├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── codespell.yml │ ├── release.yml │ └── test.yml ├── .gitignore ├── .kitchen.do.yml ├── .kitchen.dokken.yml ├── .kitchen.yml ├── .rspec ├── .rubocop.yml ├── .rubocop_todo.yml ├── Berksfile ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── attributes ├── default.rb └── sysctl.rb ├── chefignore ├── libraries ├── apt_package_extras.rb ├── cookbook_version.rb ├── gpgcheck.rb ├── helpers_param.rb └── suid_sgid.rb ├── metadata.rb ├── recipes ├── apt.rb ├── auditd.rb ├── default.rb ├── limits.rb ├── login_defs.rb ├── minimize_access.rb ├── packages.rb ├── pam.rb ├── profile.rb ├── securetty.rb ├── selinux.rb ├── suid_sgid.rb ├── sysctl.rb └── yum.rb ├── renovate.json ├── spec ├── recipes │ ├── auditd_spec.rb │ ├── default_spec.rb │ ├── limits_spec.rb │ ├── login_defs_spec.rb │ ├── minimize_access_spec.rb │ ├── pam_spec.rb │ ├── profile_spec.rb │ ├── securetty_spec.rb │ ├── suid_sgid_spec.rb │ └── sysctl_spec.rb └── spec_helper.rb ├── templates └── default │ ├── auditd.conf.erb │ ├── filesystem_blacklisting.erb │ ├── limits.conf.erb │ ├── login.defs.erb │ ├── modules.erb │ ├── pam_passwdqc.erb │ ├── pam_tally2.erb │ ├── profile.conf.erb │ ├── rhel_libuser.conf.erb │ ├── rhel_selinuxconfig.erb │ ├── rhel_sysconfig_init.erb │ ├── rhel_system_auth.erb │ └── securetty.erb └── test ├── fixtures └── cookbooks │ └── test │ ├── metadata.rb │ └── recipes │ └── default.rb └── integration ├── default ├── controls │ └── tests.rb └── inspec.yml └── selinux_enabled ├── controls └── tests.rb └── inspec.yml /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **Expected behavior** 11 | A clear and concise description of what you expected to happen. 12 | 13 | **Actual behavior** 14 | 15 | ```paste below 16 | 17 | ``` 18 | 19 | **Example code** 20 | 21 | ```paste below 22 | 23 | ``` 24 | 25 | **OS / Environment** 26 | 27 | 28 | 29 | **Chef Version** 30 | 31 | ```paste below 32 | 33 | ``` 34 | 35 | **Cookbook Version** 36 | 37 | ```paste below 38 | 39 | ``` 40 | 41 | **Additional context** 42 | Add any other context about the problem here. 43 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/workflows/codespell.yml: -------------------------------------------------------------------------------- 1 | --- 2 | name: Codespell - Spellcheck 3 | 4 | on: # yamllint disable-line rule:truthy 5 | push: 6 | branches: [master] 7 | pull_request: 8 | branches: [master] 9 | 10 | jobs: 11 | codespell: 12 | uses: "dev-sec/.github/.github/workflows/codespell.yml@main" 13 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Create a new release 2 | 3 | env: 4 | cinc_workstation_version: 23 5 | cookbook_name: os-hardening 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | version: 11 | description: 'Version number (e.g. 1.2.3)' 12 | required: true 13 | version_confirm: 14 | description: 'Version confirmation (just repeat the version)' 15 | required: true 16 | 17 | jobs: 18 | version-info: 19 | runs-on: ubuntu-latest 20 | outputs: 21 | last_tag: ${{ steps.last_tag.outputs.tag }} 22 | new_tag: ${{ steps.new_tag.outputs.tag }} 23 | steps: 24 | - name: check the new tag data 25 | run: | 26 | if [ "${{ github.event.inputs.version }}" != "${{ github.event.inputs.version_confirm }}" ]; then 27 | echo "Version and it's confirmation don't match (${{ github.event.inputs.version }} vs ${{ github.event.inputs.version_confirm }})"; 28 | exit 1; 29 | fi 30 | if [[ ! "${{ github.event.inputs.version }}" =~ ^[0-9]*\.[0-9]*\.[0-9]*$ ]]; then 31 | echo "Given version ${{ github.event.inputs.version }} doesn't match the versioning scheme 1.2.3"; 32 | exit 1; 33 | fi 34 | - name: get the new tag 35 | id: new_tag 36 | run: echo "tag=v${{ github.event.inputs.version }}" >> $GITHUB_OUTPUT 37 | - uses: actions/checkout@v4 38 | with: 39 | fetch-depth: 0 40 | - name: get last tag information 41 | id: last_tag 42 | run: echo "tag=$(git describe --tags $(git rev-list --tags --max-count=1 ))" >> $GITHUB_OUTPUT 43 | 44 | generate-changelog: 45 | runs-on: ubuntu-latest 46 | needs: version-info 47 | outputs: 48 | release_changelog: ${{ steps.release_changelog.outputs.content }} 49 | permissions: 50 | issues: read 51 | pull-requests: read 52 | contents: read 53 | steps: 54 | - name: Generate full changelog for repository 55 | uses: charmixer/auto-changelog-action@v1 56 | with: 57 | token: ${{ secrets.GITHUB_TOKEN }} 58 | future_release: ${{ needs.version-info.outputs.new_tag }} 59 | exclude_labels: duplicate,question,invalid,wontfix,release 60 | - uses: actions/upload-artifact@v4 61 | with: 62 | name: CHANGELOG.md 63 | path: CHANGELOG.md 64 | - name: Generate changelog with release information only 65 | uses: charmixer/auto-changelog-action@v1 66 | with: 67 | token: ${{ secrets.GITHUB_TOKEN }} 68 | future_release: ${{ needs.version-info.outputs.new_tag }} 69 | exclude_labels: duplicate,question,invalid,wontfix,release 70 | since_tag: ${{ needs.version-info.outputs.last_tag }} 71 | output: 'CHANGELOGRELEASE.md' 72 | - name: Read the release changelog 73 | id: release_changelog 74 | run: | 75 | OUTPUT="$(cat CHANGELOGRELEASE.md)" 76 | # https://github.com/orgs/community/discussions/26288#discussioncomment-3876281 77 | delimiter="$(openssl rand -hex 8)" 78 | echo "content<<${delimiter}" >> "$GITHUB_OUTPUT" 79 | echo "$OUTPUT" >> $GITHUB_OUTPUT 80 | echo "${delimiter}" >> "$GITHUB_OUTPUT" 81 | 82 | release-pull-request: 83 | runs-on: ubuntu-latest 84 | needs: 85 | - generate-changelog 86 | - version-info 87 | permissions: 88 | contents: write 89 | env: 90 | GITHUB_TOKEN: ${{ secrets.BOT_PAT }} 91 | steps: 92 | - name: Check out code 93 | uses: actions/checkout@v4 94 | - uses: actions/download-artifact@v4 95 | with: 96 | name: CHANGELOG.md 97 | - name: Update metadata with new version 98 | run: | 99 | sed -i "s/^version '.*'$/version '${{ github.event.inputs.version }}'/" metadata.rb 100 | - name: Commit changelog and metadata and push it 101 | id: commit-and-push 102 | run: | 103 | git checkout -b release/${{ needs.version-info.outputs.new_tag }} 104 | git config user.name "GitHub Actions" 105 | git config user.email noreply@github.com 106 | git add CHANGELOG.md metadata.rb 107 | git commit -m 'Version update ${{ needs.version-info.outputs.new_tag }}' -s 108 | echo "commit=$(git rev-parse HEAD)" >> $GITHUB_OUTPUT 109 | git push origin release/${{ needs.version-info.outputs.new_tag }} 110 | git tag ${{ needs.version-info.outputs.new_tag }} 111 | git push origin ${{ needs.version-info.outputs.new_tag }} 112 | - name: create pull request and auto merge it 113 | env: 114 | GH_TOKEN: ${{ secrets.BOT_PAT }} 115 | run: | 116 | url=$(gh pr create -b "${{ needs.generate-changelog.outputs.release_changelog }}" -t "Release ${{ needs.version-info.outputs.new_tag }}" -l release | grep -F 'https://github.com' ) 117 | gh pr merge $url --auto -m 118 | - name: create a new release 119 | uses: softprops/action-gh-release@v1 120 | with: 121 | tag_name: ${{ needs.version-info.outputs.new_tag }} 122 | body: ${{ needs.generate-changelog.outputs.release_changelog }} 123 | target_commitish: ${{ steps.commit-and-push.outputs.commit }} 124 | 125 | supermarket-upload: 126 | runs-on: ubuntu-latest 127 | needs: 128 | - version-info 129 | - release-pull-request 130 | steps: 131 | - uses: actions/cache@v3 132 | with: 133 | path: | 134 | .cache 135 | key: ${{ runner.os }}-${{ env.cinc_workstation_version }} 136 | - name: setup environment 137 | run: | 138 | mkdir -p .cache 139 | curl -L https://omnitruck.cinc.sh/install.sh | sudo bash -s -- -P cinc-workstation -d .cache -v ${{ env.cinc_workstation_version }} 140 | - name: setup knife environment 141 | run: | 142 | mkdir -p .cinc cookbooks 143 | cat > .cinc/config.rb < .cinc/key.pem < ~/.ssh/id_rsa 113 | chmod 700 ~/.ssh 114 | chmod 600 ~/.ssh/id_rsa 115 | - name: kitchen 116 | env: 117 | CINC_VERSION: ${{ matrix.cinc_version }} 118 | KITCHEN_LOCAL_YAML: .kitchen.do.yml 119 | DIGITALOCEAN_SSH_KEY_IDS: ${{ secrets.DO_SSH_KEY_ID }} 120 | DIGITALOCEAN_ACCESS_TOKEN: ${{ secrets.DO_ACCESS_TOKEN }} 121 | run: | 122 | kitchen test --color --destroy=always ${{ matrix.kitchen_distro }} 123 | 124 | pass-all-jobs: 125 | if: "!(github.repository == 'dev-sec/chef-os-hardening' && startsWith(github.head_ref, 'release/v')) && always()" 126 | needs: 127 | - cookstyle 128 | - kitchen-dokken 129 | runs-on: ubuntu-latest 130 | steps: 131 | - name: Decide whether the needed jobs succeeded or failed 132 | uses: re-actors/alls-green@release/v1 133 | with: 134 | jobs: ${{ toJSON(needs) }} 135 | 136 | pass-all-jobs-with-digitalocean: 137 | if: "(github.repository == 'dev-sec/chef-os-hardening' && !(startsWith(github.head_ref, 'release/v'))) && always()" 138 | needs: 139 | - cookstyle 140 | - kitchen-dokken 141 | - kitchen-digitalocean 142 | runs-on: ubuntu-latest 143 | steps: 144 | - name: Decide whether the needed jobs succeeded or failed 145 | uses: re-actors/alls-green@release/v1 146 | with: 147 | jobs: ${{ toJSON(needs) }} 148 | 149 | pass-all-jobs-release: 150 | if: "github.repository == 'dev-sec/chef-os-hardening' && startsWith(github.head_ref, 'release/v') && always()" 151 | runs-on: ubuntu-latest 152 | steps: 153 | - name: happy releasing 154 | run: | 155 | echo "Happy releasing :-)" 156 | # this is just a succeessfull placeholder to make release PR pass 157 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *# 3 | .#* 4 | \#*# 5 | .*.sw[a-z] 6 | *.un~ 7 | coverage 8 | exp.* 9 | pkg/ 10 | shared_test_repo/ 11 | .envrc 12 | 13 | # Berkshelf 14 | .vagrant 15 | /cookbooks 16 | Berksfile.lock 17 | 18 | # Bundler 19 | Gemfile.lock 20 | bin/* 21 | .bundle/* 22 | 23 | # Test Kitchen 24 | .kitchen/ 25 | .kitchen.local.yml 26 | 27 | # RVM 28 | /.ruby-gemset 29 | /.ruby-version 30 | -------------------------------------------------------------------------------- /.kitchen.do.yml: -------------------------------------------------------------------------------- 1 | driver: 2 | name: digitalocean 3 | size: s-1vcpu-1gb 4 | region: nyc3 5 | 6 | transport: 7 | ssh_key: '~/.ssh/id_rsa' 8 | max_wait_until_ready: 30 9 | 10 | platforms: 11 | - name: centos-7 12 | driver_config: 13 | image: centos-7-x64 14 | - name: centos-stream-8 15 | driver_config: 16 | image: centos-stream-8-x64 17 | - name: centos-stream-9 18 | driver_config: 19 | image: centos-stream-9-x64 20 | - name: almalinux-8 21 | driver_config: 22 | image: almalinux-8-x64 23 | - name: almalinux-9 24 | driver_config: 25 | image: almalinux-9-x64 26 | - name: rockylinux-8 27 | driver_config: 28 | image: rockylinux-8-x64 29 | - name: rockylinux-9 30 | driver_config: 31 | image: rockylinux-9-x64 32 | - name: fedora-37 33 | driver_config: 34 | image: fedora-37-x64 35 | - name: fedora-38 36 | driver_config: 37 | image: fedora-38-x64 38 | - name: debian-10 39 | driver_config: 40 | image: debian-10-x64 41 | lifecycle: 42 | post_create: 43 | - remote: sleep 10; while pgrep apt-get >/dev/null; do echo "Waiting for apt-get..."; sleep 5; done # let the installation of DO droplet-agent to finish and unlock dpkg 44 | - name: debian-11 45 | driver_config: 46 | image: debian-11-x64 47 | lifecycle: 48 | post_create: 49 | - remote: sleep 10; while pgrep apt-get >/dev/null; do echo "Waiting for apt-get..."; sleep 5; done # let the installation of DO droplet-agent to finish and unlock dpkg 50 | - name: ubuntu-20-04 51 | driver_config: 52 | image: ubuntu-20-04-x64 53 | lifecycle: 54 | post_create: 55 | - remote: sleep 10; while pgrep apt-get >/dev/null; do echo "Waiting for apt-get..."; sleep 5; done # let the installation of DO droplet-agent to finish and unlock dpkg 56 | -------------------------------------------------------------------------------- /.kitchen.dokken.yml: -------------------------------------------------------------------------------- 1 | # this file is used for kitchen dokken 2 | # especially for integration tests in the CI 3 | --- 4 | driver: 5 | name: dokken 6 | privileged: true # because Docker and systemd 7 | chef_image: cincproject/cinc 8 | chef_version: <%= ENV['CINC_VERSION'] || 'latest' %> 9 | 10 | provisioner: 11 | name: dokken 12 | product_name: cinc 13 | chef_binary: /opt/cinc/bin/cinc-client 14 | 15 | transport: 16 | name: dokken 17 | 18 | platforms: 19 | - name: amazonlinux-1 20 | driver: 21 | image: dokken/amazonlinux 22 | pid_one_command: /sbin/init 23 | - name: amazonlinux-2 24 | driver: 25 | image: dokken/amazonlinux-2 26 | pid_one_command: /usr/lib/systemd/systemd 27 | - name: centos-7 28 | driver: 29 | image: dokken/centos-7 30 | pid_one_command: /usr/lib/systemd/systemd 31 | - name: centos-stream-8 32 | driver: 33 | image: dokken/centos-stream-8 34 | pid_one_command: /usr/lib/systemd/systemd 35 | - name: centos-stream-9 36 | driver: 37 | image: dokken/centos-stream-9 38 | pid_one_command: /usr/lib/systemd/systemd 39 | - name: almalinux-8 40 | driver: 41 | image: dokken/almalinux-8 42 | pid_one_command: /usr/lib/systemd/systemd 43 | - name: almalinux-9 44 | driver: 45 | image: dokken/almalinux-9 46 | pid_one_command: /usr/lib/systemd/systemd 47 | - name: rockylinux-8 48 | driver: 49 | image: dokken/rockylinux-8 50 | pid_one_command: /usr/lib/systemd/systemd 51 | - name: rockylinux-9 52 | driver: 53 | image: dokken/rockylinux-9 54 | pid_one_command: /usr/lib/systemd/systemd 55 | - name: oracle-7 56 | driver: 57 | image: dokken/oraclelinux-7 58 | pid_one_command: /usr/lib/systemd/systemd 59 | - name: oracle-8 60 | driver: 61 | image: dokken/oraclelinux-8 62 | pid_one_command: /usr/lib/systemd/systemd 63 | - name: oracle-9 64 | driver: 65 | image: dokken/oraclelinux-9 66 | pid_one_command: /usr/lib/systemd/systemd 67 | - name: debian-10 68 | driver: 69 | image: dokken/debian-10 70 | intermediate_instructions: 71 | - RUN /usr/bin/apt-get update 72 | pid_one_command: /bin/systemd 73 | - name: debian-11 74 | driver: 75 | image: dokken/debian-11 76 | intermediate_instructions: 77 | - RUN /usr/bin/apt-get update 78 | pid_one_command: /bin/systemd 79 | - name: fedora-37 80 | driver: 81 | image: dokken/fedora-37 82 | pid_one_command: /usr/lib/systemd/systemd 83 | intermediate_instructions: 84 | - RUN dnf install -y yum 85 | - name: fedora-38 86 | driver: 87 | image: dokken/fedora-38 88 | pid_one_command: /usr/lib/systemd/systemd 89 | intermediate_instructions: 90 | - RUN dnf install -y yum 91 | - name: opensuse-42 92 | driver: 93 | image: dokken/opensuse-leap 94 | pid_one_command: /bin/systemd 95 | - name: ubuntu-20-04 96 | driver: 97 | image: dokken/ubuntu-20.04 98 | pid_one_command: /bin/systemd 99 | intermediate_instructions: 100 | - RUN /usr/bin/apt-get update 101 | -------------------------------------------------------------------------------- /.kitchen.yml: -------------------------------------------------------------------------------- 1 | --- 2 | driver: 3 | name: vagrant 4 | 5 | platforms: 6 | - name: ubuntu-20-04 7 | driver_config: 8 | box: bento/ubuntu-20.04 9 | - name: centos-7 10 | - name: centos-stream-8 11 | - name: centos-stream-9 12 | - name: almalinux-8 13 | - name: almalinux-9 14 | - name: rockylinux-8 15 | - name: rockylinux-9 16 | - name: oracle-7 17 | - name: oracle-8 18 | - name: oracle-9 19 | - name: debian-10 20 | - name: debian-11 21 | - name: fedora-37 22 | - name: fedora-38 23 | - name: opensuse-leap-42 24 | - name: amazonlinux-1 25 | driver_config: 26 | box: realreadme/amazon2016.09 27 | - name: amazonlinux-2 28 | driver_config: 29 | box: stakahashi/amazonlinux2 30 | 31 | provisioner: 32 | name: chef_zero 33 | product_name: cinc 34 | <% if ENV['CINC_VERSION'] %> 35 | product_version: '<%= ENV['CINC_VERSION'] %>' 36 | <% end %> 37 | 38 | verifier: 39 | name: inspec 40 | sudo: true 41 | 42 | suites: 43 | - name: default 44 | run_list: 45 | - recipe[test] 46 | - recipe[os-hardening::default] 47 | - name: modules_disabled 48 | run_list: 49 | - recipe[test] 50 | - recipe[os-hardening::default] 51 | attributes: 52 | os-hardening: 53 | security: 54 | kernel: 55 | enable_module_loading: false 56 | verifier: 57 | inspec_tests: 58 | - path: test/integration/default 59 | attributes: 60 | kernel_modules_disabled: 1 61 | -------------------------------------------------------------------------------- /.rspec: -------------------------------------------------------------------------------- 1 | --color --format documentation --require spec_helper 2 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | inherit_from: .rubocop_todo.yml 3 | 4 | AllCops: 5 | DisplayCopNames: true 6 | Exclude: 7 | - vendor/**/* 8 | - test/**/* 9 | TargetRubyVersion: 2.5 10 | Metrics/AbcSize: 11 | Max: 29 12 | Layout/LineLength: 13 | Max: 100 14 | Include: 15 | - spec/**/*.rb 16 | Metrics/MethodLength: 17 | Max: 40 18 | Style/Documentation: 19 | Enabled: false 20 | Layout/DotPosition: 21 | EnforcedStyle: trailing 22 | Layout/HashAlignment: 23 | EnforcedHashRocketStyle: table 24 | EnforcedColonStyle: table 25 | Style/NumericLiterals: 26 | MinDigits: 10 27 | Layout/SpaceAroundOperators: 28 | Exclude: 29 | - attributes/default.rb 30 | Layout/ExtraSpacing: 31 | AllowForAlignment: false 32 | Metrics/BlockLength: 33 | Exclude: 34 | - 'spec/**/*' 35 | -------------------------------------------------------------------------------- /.rubocop_todo.yml: -------------------------------------------------------------------------------- 1 | # This configuration was generated by 2 | # `rubocop --auto-gen-config` 3 | # on 2023-03-29 19:15:26 UTC using RuboCop version 1.25.1. 4 | # The point is for the user to remove these configuration records 5 | # one by one as the offenses are removed from the code base. 6 | # Note that changes in the inspected code, or installation of new 7 | # versions of RuboCop, may require this file to be generated again. 8 | 9 | # Offense count: 1 10 | # Cop supports --auto-correct. 11 | Chef/Correctness/IncorrectLibraryInjection: 12 | Exclude: 13 | - '**/metadata.rb' 14 | - '**/Berksfile' 15 | - 'recipes/sysctl.rb' 16 | 17 | # Offense count: 1 18 | # Cop supports --auto-correct. 19 | # Configuration parameters: Include. 20 | # Include: **/spec/*.rb 21 | Chef/Deprecations/ChefSpecCoverageReport: 22 | Exclude: 23 | - 'spec/spec_helper.rb' 24 | 25 | # Offense count: 1 26 | # Cop supports --auto-correct. 27 | # Configuration parameters: Include. 28 | # Include: **/metadata.rb 29 | Chef/RedundantCode/LongDescriptionMetadata: 30 | Exclude: 31 | - 'metadata.rb' 32 | 33 | # Offense count: 9 34 | # Cop supports --auto-correct. 35 | # Configuration parameters: Include. 36 | # Include: **/metadata.rb 37 | Chef/RedundantCode/RecipeMetadata: 38 | Exclude: 39 | - 'metadata.rb' 40 | 41 | # Offense count: 65 42 | # Cop supports --auto-correct. 43 | Chef/Style/CommentFormat: 44 | Enabled: false 45 | 46 | # Offense count: 2 47 | # Cop supports --auto-correct. 48 | Chef/Style/IncludeRecipeWithParentheses: 49 | Exclude: 50 | - '**/attributes/*.rb' 51 | - '**/metadata.rb' 52 | - '**/Berksfile' 53 | - 'recipes/packages.rb' 54 | 55 | # Offense count: 8 56 | # Cop supports --auto-correct. 57 | Chef/Style/UnnecessaryPlatformCaseStatement: 58 | Exclude: 59 | - '**/metadata.rb' 60 | - '**/Berksfile' 61 | - 'attributes/default.rb' 62 | - 'attributes/sysctl.rb' 63 | - 'recipes/packages.rb' 64 | - 'recipes/selinux.rb' 65 | - 'recipes/sysctl.rb' 66 | 67 | # Offense count: 7 68 | # Cop supports --auto-correct. 69 | Chef/Style/UsePlatformHelpers: 70 | Exclude: 71 | - '**/metadata.rb' 72 | - '**/libraries/*' 73 | - '**/Berksfile' 74 | - 'attributes/sysctl.rb' 75 | - 'recipes/auditd.rb' 76 | - 'recipes/default.rb' 77 | - 'recipes/minimize_access.rb' 78 | 79 | # Offense count: 12 80 | # Cop supports --auto-correct. 81 | # Configuration parameters: PreferredDelimiters. 82 | Style/PercentLiteralDelimiters: 83 | Exclude: 84 | - 'attributes/default.rb' 85 | - 'recipes/auditd.rb' 86 | - 'recipes/minimize_access.rb' 87 | - 'recipes/yum.rb' 88 | - 'spec/recipes/default_spec.rb' 89 | - 'spec/recipes/sysctl_spec.rb' 90 | 91 | # Offense count: 1 92 | # Cop supports --auto-correct. 93 | # Configuration parameters: EnforcedStyleForMultiline. 94 | # SupportedStylesForMultiline: comma, consistent_comma, no_comma 95 | Style/TrailingCommaInArrayLiteral: 96 | Exclude: 97 | - 'attributes/default.rb' 98 | 99 | # Offense count: 2 100 | # Cop supports --auto-correct. 101 | # Configuration parameters: EnforcedStyleForMultiline. 102 | # SupportedStylesForMultiline: comma, consistent_comma, no_comma 103 | Style/TrailingCommaInHashLiteral: 104 | Exclude: 105 | - 'spec/recipes/login_defs_spec.rb' 106 | - 'spec/recipes/securetty_spec.rb' 107 | 108 | # Offense count: 1 109 | # Cop supports --auto-correct. 110 | # Configuration parameters: WordRegex. 111 | # SupportedStyles: percent, brackets 112 | Style/WordArray: 113 | EnforcedStyle: percent 114 | MinSize: 6 115 | -------------------------------------------------------------------------------- /Berksfile: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | source 'https://supermarket.chef.io' 4 | 5 | group :test do 6 | cookbook 'test', path: 'test/fixtures/cookbooks/test' 7 | end 8 | 9 | metadata 10 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## [v4.2.0](https://github.com/dev-sec/chef-os-hardening/tree/v4.2.0) (2023-12-22) 4 | 5 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v4.1.2...v4.2.0) 6 | 7 | **Closed issues:** 8 | 9 | - Dependency Dashboard [\#305](https://github.com/dev-sec/chef-os-hardening/issues/305) 10 | - Support for RHEL 8 / Rocky Linux 8 [\#279](https://github.com/dev-sec/chef-os-hardening/issues/279) 11 | - Linux Baseline tests are failing for os-13 [\#272](https://github.com/dev-sec/chef-os-hardening/issues/272) 12 | - chef exec rake lint fails, foodcritic deprecated [\#265](https://github.com/dev-sec/chef-os-hardening/issues/265) 13 | 14 | **Merged pull requests:** 15 | 16 | - Update actions/upload-artifact action to v4 [\#312](https://github.com/dev-sec/chef-os-hardening/pull/312) ([renovate[bot]](https://github.com/apps/renovate)) 17 | - Update actions/download-artifact action to v4 [\#311](https://github.com/dev-sec/chef-os-hardening/pull/311) ([renovate[bot]](https://github.com/apps/renovate)) 18 | - Allow more changes to AuditD [\#310](https://github.com/dev-sec/chef-os-hardening/pull/310) ([tdekoning93](https://github.com/tdekoning93)) 19 | - CI: run for all PRs [\#309](https://github.com/dev-sec/chef-os-hardening/pull/309) ([artem-sidorenko](https://github.com/artem-sidorenko)) 20 | - Deprecation of Ubuntu 18.04 [\#308](https://github.com/dev-sec/chef-os-hardening/pull/308) ([artem-sidorenko](https://github.com/artem-sidorenko)) 21 | - CI: Update actions/checkout action to v4 [\#304](https://github.com/dev-sec/chef-os-hardening/pull/304) ([renovate[bot]](https://github.com/apps/renovate)) 22 | - Removal of Gemfile and Rakefile [\#303](https://github.com/dev-sec/chef-os-hardening/pull/303) ([artem-sidorenko](https://github.com/artem-sidorenko)) 23 | - Testing on Oraclelinux 8 and 9 [\#302](https://github.com/dev-sec/chef-os-hardening/pull/302) ([artem-sidorenko](https://github.com/artem-sidorenko)) 24 | - Testing on Almalinux and Rockylinux 8/9 [\#301](https://github.com/dev-sec/chef-os-hardening/pull/301) ([artem-sidorenko](https://github.com/artem-sidorenko)) 25 | - Testing on the CentOS Stream 8 and 9 [\#300](https://github.com/dev-sec/chef-os-hardening/pull/300) ([artem-sidorenko](https://github.com/artem-sidorenko)) 26 | - Run tests on the current fedora 37 and 38 [\#299](https://github.com/dev-sec/chef-os-hardening/pull/299) ([artem-sidorenko](https://github.com/artem-sidorenko)) 27 | - Testing on debian 10 and 11 [\#298](https://github.com/dev-sec/chef-os-hardening/pull/298) ([artem-sidorenko](https://github.com/artem-sidorenko)) 28 | - Testing on ubuntu 18.04 and 20.04 [\#297](https://github.com/dev-sec/chef-os-hardening/pull/297) ([artem-sidorenko](https://github.com/artem-sidorenko)) 29 | 30 | ## [v4.1.2](https://github.com/dev-sec/chef-os-hardening/tree/v4.1.2) (2023-06-06) 31 | 32 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v4.1.1...v4.1.2) 33 | 34 | **Merged pull requests:** 35 | 36 | - CI: run the test workflow also on the release branches [\#295](https://github.com/dev-sec/chef-os-hardening/pull/295) ([artem-sidorenko](https://github.com/artem-sidorenko)) 37 | 38 | ## [v4.1.1](https://github.com/dev-sec/chef-os-hardening/tree/v4.1.1) (2023-06-06) 39 | 40 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v4.1.0...v4.1.1) 41 | 42 | **Merged pull requests:** 43 | 44 | - Removing coveralls [\#293](https://github.com/dev-sec/chef-os-hardening/pull/293) ([artem-sidorenko](https://github.com/artem-sidorenko)) 45 | - CI: fix - we need three guard jobs [\#292](https://github.com/dev-sec/chef-os-hardening/pull/292) ([artem-sidorenko](https://github.com/artem-sidorenko)) 46 | 47 | ## [v4.1.0](https://github.com/dev-sec/chef-os-hardening/tree/v4.1.0) (2023-06-06) 48 | 49 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v4.0.0...v4.1.0) 50 | 51 | **Closed issues:** 52 | 53 | - Amazon Linux 2 Auditd fails to restart [\#270](https://github.com/dev-sec/chef-os-hardening/issues/270) 54 | - pwquality.conf defaults or suggested config [\#267](https://github.com/dev-sec/chef-os-hardening/issues/267) 55 | - Configuration conflict when using both chef-ssh-hardening and chef-os-hardening [\#264](https://github.com/dev-sec/chef-os-hardening/issues/264) 56 | - Chef warning when /bin/su is a symlink [\#262](https://github.com/dev-sec/chef-os-hardening/issues/262) 57 | - os-hardening::profile recipe creating pinerolo\_profile.sh file with .old extension on each chef-client run [\#255](https://github.com/dev-sec/chef-os-hardening/issues/255) 58 | 59 | **Merged pull requests:** 60 | 61 | - CI : release workflow with upload to supermarket [\#290](https://github.com/dev-sec/chef-os-hardening/pull/290) ([artem-sidorenko](https://github.com/artem-sidorenko)) 62 | - CI: supermarket upload workflow [\#289](https://github.com/dev-sec/chef-os-hardening/pull/289) ([artem-sidorenko](https://github.com/artem-sidorenko)) 63 | - CI: disable debian-9 dokken tests for now [\#288](https://github.com/dev-sec/chef-os-hardening/pull/288) ([artem-sidorenko](https://github.com/artem-sidorenko)) 64 | - CI: add spellchecking with codespell [\#287](https://github.com/dev-sec/chef-os-hardening/pull/287) ([schurzi](https://github.com/schurzi)) 65 | - CI: another catch-all job for runs on the main code [\#286](https://github.com/dev-sec/chef-os-hardening/pull/286) ([artem-sidorenko](https://github.com/artem-sidorenko)) 66 | - CI: tests on the real DO VMs [\#285](https://github.com/dev-sec/chef-os-hardening/pull/285) ([artem-sidorenko](https://github.com/artem-sidorenko)) 67 | - CI : Kitchen - vagrant and dokken tests [\#284](https://github.com/dev-sec/chef-os-hardening/pull/284) ([artem-sidorenko](https://github.com/artem-sidorenko)) 68 | - CI: Configure Renovate [\#283](https://github.com/dev-sec/chef-os-hardening/pull/283) ([renovate[bot]](https://github.com/apps/renovate)) 69 | - CI: run dokken jobs [\#282](https://github.com/dev-sec/chef-os-hardening/pull/282) ([artem-sidorenko](https://github.com/artem-sidorenko)) 70 | - CI: run cookstyle [\#281](https://github.com/dev-sec/chef-os-hardening/pull/281) ([artem-sidorenko](https://github.com/artem-sidorenko)) 71 | - CI: setup cinc WS in the GH actions [\#280](https://github.com/dev-sec/chef-os-hardening/pull/280) ([artem-sidorenko](https://github.com/artem-sidorenko)) 72 | - Hardening of crontabs and directories [\#273](https://github.com/dev-sec/chef-os-hardening/pull/273) ([mfortin](https://github.com/mfortin)) 73 | - Amazon Linux 2 AuditD issue [\#271](https://github.com/dev-sec/chef-os-hardening/pull/271) ([mfortin](https://github.com/mfortin)) 74 | - expose pam\_unix.so options to an attribute [\#268](https://github.com/dev-sec/chef-os-hardening/pull/268) ([bcg62](https://github.com/bcg62)) 75 | - Fix warning on managing /bin/su symlink [\#263](https://github.com/dev-sec/chef-os-hardening/pull/263) ([sean-nixon](https://github.com/sean-nixon)) 76 | - Initial \(sans Arch\) auditd management support. [\#260](https://github.com/dev-sec/chef-os-hardening/pull/260) ([b-dean](https://github.com/b-dean)) 77 | - CI: testing of Centos 8 [\#259](https://github.com/dev-sec/chef-os-hardening/pull/259) ([artem-sidorenko](https://github.com/artem-sidorenko)) 78 | - CI: testing of Debian 10 [\#258](https://github.com/dev-sec/chef-os-hardening/pull/258) ([artem-sidorenko](https://github.com/artem-sidorenko)) 79 | - Fix CI: run testing on Chef 14 and 15 [\#256](https://github.com/dev-sec/chef-os-hardening/pull/256) ([artem-sidorenko](https://github.com/artem-sidorenko)) 80 | 81 | ## [v4.0.0](https://github.com/dev-sec/chef-os-hardening/tree/v4.0.0) (2019-04-10) 82 | 83 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v3.2.1...v4.0.0) 84 | 85 | **Closed issues:** 86 | 87 | - Deprecated feature sysctl\_param used [\#230](https://github.com/dev-sec/chef-os-hardening/issues/230) 88 | 89 | **Merged pull requests:** 90 | 91 | - Update of metadata with supported distros [\#252](https://github.com/dev-sec/chef-os-hardening/pull/252) ([artem-sidorenko](https://github.com/artem-sidorenko)) 92 | - Removal of config disclaimer attribute [\#249](https://github.com/dev-sec/chef-os-hardening/pull/249) ([artem-sidorenko](https://github.com/artem-sidorenko)) 93 | - Docs: update of supported distros [\#247](https://github.com/dev-sec/chef-os-hardening/pull/247) ([artem-sidorenko](https://github.com/artem-sidorenko)) 94 | - Removal of fedora 27 as its EOL [\#246](https://github.com/dev-sec/chef-os-hardening/pull/246) ([artem-sidorenko](https://github.com/artem-sidorenko)) 95 | - Removal of Ubuntu 14.04 support [\#245](https://github.com/dev-sec/chef-os-hardening/pull/245) ([artem-sidorenko](https://github.com/artem-sidorenko)) 96 | - Removal of Debian 8 as its EOL [\#244](https://github.com/dev-sec/chef-os-hardening/pull/244) ([artem-sidorenko](https://github.com/artem-sidorenko)) 97 | - CI: improvements with handling of different chef versions [\#243](https://github.com/dev-sec/chef-os-hardening/pull/243) ([artem-sidorenko](https://github.com/artem-sidorenko)) 98 | - Updates of metadata and readme [\#242](https://github.com/dev-sec/chef-os-hardening/pull/242) ([artem-sidorenko](https://github.com/artem-sidorenko)) 99 | - Eliminating spacing for alligment [\#241](https://github.com/dev-sec/chef-os-hardening/pull/241) ([artem-sidorenko](https://github.com/artem-sidorenko)) 100 | - Update of rubocop to 0.65 [\#240](https://github.com/dev-sec/chef-os-hardening/pull/240) ([artem-sidorenko](https://github.com/artem-sidorenko)) 101 | - CI: Run unit tests on chef 14, update of some gems, small cleanup [\#239](https://github.com/dev-sec/chef-os-hardening/pull/239) ([artem-sidorenko](https://github.com/artem-sidorenko)) 102 | - Remove sysctl cookbook dependency and use new native sysctl resource [\#228](https://github.com/dev-sec/chef-os-hardening/pull/228) ([josqu4red](https://github.com/josqu4red)) 103 | 104 | ## [v3.2.1](https://github.com/dev-sec/chef-os-hardening/tree/v3.2.1) (2019-03-07) 105 | 106 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v3.2.0...v3.2.1) 107 | 108 | **Fixed bugs:** 109 | 110 | - execute\[update-pam\] resource fails on Ubuntu 14.04 on Azure [\#237](https://github.com/dev-sec/chef-os-hardening/issues/237) 111 | - exec-shield incompatible with Oracle Linux UEK [\#234](https://github.com/dev-sec/chef-os-hardening/issues/234) 112 | 113 | **Merged pull requests:** 114 | 115 | - Use full path for executing pam-auth-update [\#238](https://github.com/dev-sec/chef-os-hardening/pull/238) ([sean-nixon](https://github.com/sean-nixon)) 116 | - Do not apply exec-shield if running Oracle Linux with UEK - addresses \#234 [\#235](https://github.com/dev-sec/chef-os-hardening/pull/235) ([eyespies](https://github.com/eyespies)) 117 | 118 | ## [v3.2.0](https://github.com/dev-sec/chef-os-hardening/tree/v3.2.0) (2019-01-16) 119 | 120 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v3.1.0...v3.2.0) 121 | 122 | **Closed issues:** 123 | 124 | - PAM config prevents launching of GDM on Fedora 27 [\#206](https://github.com/dev-sec/chef-os-hardening/issues/206) 125 | - Migration to the new major sysctl cookbook version [\#198](https://github.com/dev-sec/chef-os-hardening/issues/198) 126 | 127 | **Merged pull requests:** 128 | 129 | - Update the CI settings - this fixes it again [\#231](https://github.com/dev-sec/chef-os-hardening/pull/231) ([artem-sidorenko](https://github.com/artem-sidorenko)) 130 | - Update issue templates [\#229](https://github.com/dev-sec/chef-os-hardening/pull/229) ([rndmh3ro](https://github.com/rndmh3ro)) 131 | - Fix CI: pin cucumber 3 [\#227](https://github.com/dev-sec/chef-os-hardening/pull/227) ([artem-sidorenko](https://github.com/artem-sidorenko)) 132 | - Make the daemon umask configurable [\#226](https://github.com/dev-sec/chef-os-hardening/pull/226) ([jaksi](https://github.com/jaksi)) 133 | - Ubuntu 18.04 is supported [\#223](https://github.com/dev-sec/chef-os-hardening/pull/223) ([frederikbosch](https://github.com/frederikbosch)) 134 | - Fix Fedora EOL [\#221](https://github.com/dev-sec/chef-os-hardening/pull/221) ([artem-sidorenko](https://github.com/artem-sidorenko)) 135 | - Fix fedora EOL in the CI [\#220](https://github.com/dev-sec/chef-os-hardening/pull/220) ([artem-sidorenko](https://github.com/artem-sidorenko)) 136 | - Fixing debian-9 CI tests [\#219](https://github.com/dev-sec/chef-os-hardening/pull/219) ([artem-sidorenko](https://github.com/artem-sidorenko)) 137 | - Fedora 26 is EOL, replacing with 28 [\#218](https://github.com/dev-sec/chef-os-hardening/pull/218) ([artem-sidorenko](https://github.com/artem-sidorenko)) 138 | - added ability to use template cookbook for login.defs [\#217](https://github.com/dev-sec/chef-os-hardening/pull/217) ([ekelson-bcove](https://github.com/ekelson-bcove)) 139 | - allow setting uid/gid max by attribute [\#215](https://github.com/dev-sec/chef-os-hardening/pull/215) ([mattlqx](https://github.com/mattlqx)) 140 | - Update kitchen config for more platforms [\#213](https://github.com/dev-sec/chef-os-hardening/pull/213) ([tas50](https://github.com/tas50)) 141 | - Add pam\_systemd.so to system-auth-ac [\#207](https://github.com/dev-sec/chef-os-hardening/pull/207) ([avanier](https://github.com/avanier)) 142 | 143 | ## [v3.1.0](https://github.com/dev-sec/chef-os-hardening/tree/v3.1.0) (2018-05-16) 144 | 145 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v3.0.0...v3.1.0) 146 | 147 | **Fixed bugs:** 148 | 149 | - fix metadata [\#204](https://github.com/dev-sec/chef-os-hardening/pull/204) ([chris-rock](https://github.com/chris-rock)) 150 | 151 | **Closed issues:** 152 | 153 | - earlier version [\#205](https://github.com/dev-sec/chef-os-hardening/issues/205) 154 | - Make auditd recipe optional [\#200](https://github.com/dev-sec/chef-os-hardening/issues/200) 155 | - Dependency on pinned, old version of sysctl [\#192](https://github.com/dev-sec/chef-os-hardening/issues/192) 156 | - compat\_resource deprecated [\#186](https://github.com/dev-sec/chef-os-hardening/issues/186) 157 | - Usage of azure as cloud provider for CI [\#183](https://github.com/dev-sec/chef-os-hardening/issues/183) 158 | 159 | **Merged pull requests:** 160 | 161 | - Test with Foodcritic 13 [\#212](https://github.com/dev-sec/chef-os-hardening/pull/212) ([tas50](https://github.com/tas50)) 162 | - Test on Ruby 2.4.4 [\#211](https://github.com/dev-sec/chef-os-hardening/pull/211) ([tas50](https://github.com/tas50)) 163 | - use sysctl 1.0 [\#210](https://github.com/dev-sec/chef-os-hardening/pull/210) ([dhohengassner](https://github.com/dhohengassner)) 164 | - added mail\_dir attribute and moved component attributes to attributes… [\#209](https://github.com/dev-sec/chef-os-hardening/pull/209) ([ekelson-bcove](https://github.com/ekelson-bcove)) 165 | - improve testing around amazon linux [\#202](https://github.com/dev-sec/chef-os-hardening/pull/202) ([chris-rock](https://github.com/chris-rock)) 166 | - Container support and dokken tests in travis CI [\#199](https://github.com/dev-sec/chef-os-hardening/pull/199) ([artem-sidorenko](https://github.com/artem-sidorenko)) 167 | - Lazy pin the sysctl major version [\#197](https://github.com/dev-sec/chef-os-hardening/pull/197) ([artem-sidorenko](https://github.com/artem-sidorenko)) 168 | - Feature/allow setting template source [\#196](https://github.com/dev-sec/chef-os-hardening/pull/196) ([eyespies](https://github.com/eyespies)) 169 | - Unpin sysctl dependency [\#195](https://github.com/dev-sec/chef-os-hardening/pull/195) ([artem-sidorenko](https://github.com/artem-sidorenko)) 170 | - add basic support for amazon linux [\#194](https://github.com/dev-sec/chef-os-hardening/pull/194) ([chris-rock](https://github.com/chris-rock)) 171 | - Fix fedora shadow permissions [\#190](https://github.com/dev-sec/chef-os-hardening/pull/190) ([artem-sidorenko](https://github.com/artem-sidorenko)) 172 | - Fedora 25 is EOL, replacing with 27 [\#189](https://github.com/dev-sec/chef-os-hardening/pull/189) ([artem-sidorenko](https://github.com/artem-sidorenko)) 173 | - Remove dependency on compat\_resource [\#188](https://github.com/dev-sec/chef-os-hardening/pull/188) ([bablakely](https://github.com/bablakely)) 174 | 175 | ## [v3.0.0](https://github.com/dev-sec/chef-os-hardening/tree/v3.0.0) (2017-12-21) 176 | 177 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v2.1.1...v3.0.0) 178 | 179 | **Closed issues:** 180 | 181 | - os-10 from linux-baseline is missing [\#167](https://github.com/dev-sec/chef-os-hardening/issues/167) 182 | - Removal of core dump hardening configuration if core dumps are allowed [\#165](https://github.com/dev-sec/chef-os-hardening/issues/165) 183 | - Integration testing of this cookbook in the CI [\#142](https://github.com/dev-sec/chef-os-hardening/issues/142) 184 | - Selinux enforcing support for RHEL/Centos? [\#106](https://github.com/dev-sec/chef-os-hardening/issues/106) 185 | - If I "enable" core dumps with chef-os-hardening, am I really fully enabling core dumps? [\#105](https://github.com/dev-sec/chef-os-hardening/issues/105) 186 | 187 | **Merged pull requests:** 188 | 189 | - Skip auditd tests [\#181](https://github.com/dev-sec/chef-os-hardening/pull/181) ([artem-sidorenko](https://github.com/artem-sidorenko)) 190 | - Make fedora tests pass [\#179](https://github.com/dev-sec/chef-os-hardening/pull/179) ([shoekstra](https://github.com/shoekstra)) 191 | - Control ownership of /var/log [\#178](https://github.com/dev-sec/chef-os-hardening/pull/178) ([shoekstra](https://github.com/shoekstra)) 192 | - RH family: adapt some settings, as RH has better defaults [\#177](https://github.com/dev-sec/chef-os-hardening/pull/177) ([artem-sidorenko](https://github.com/artem-sidorenko)) 193 | - Fix for fedora: lets use generic package resource [\#176](https://github.com/dev-sec/chef-os-hardening/pull/176) ([artem-sidorenko](https://github.com/artem-sidorenko)) 194 | - Kitchen: Using the same names for platforms for different drivers [\#175](https://github.com/dev-sec/chef-os-hardening/pull/175) ([artem-sidorenko](https://github.com/artem-sidorenko)) 195 | - Enable core dumps if they are enabled via attribute [\#174](https://github.com/dev-sec/chef-os-hardening/pull/174) ([artem-sidorenko](https://github.com/artem-sidorenko)) 196 | - Selinux enforcing support for RHEL/Centos [\#173](https://github.com/dev-sec/chef-os-hardening/pull/173) ([AnMoeller](https://github.com/AnMoeller)) 197 | - Kitchen: Update of testing boxes/images [\#172](https://github.com/dev-sec/chef-os-hardening/pull/172) ([artem-sidorenko](https://github.com/artem-sidorenko)) 198 | - Lets disable unused filesystems per default [\#169](https://github.com/dev-sec/chef-os-hardening/pull/169) ([artem-sidorenko](https://github.com/artem-sidorenko)) 199 | 200 | ## [v2.1.1](https://github.com/dev-sec/chef-os-hardening/tree/v2.1.1) (2017-08-21) 201 | 202 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v2.1.0...v2.1.1) 203 | 204 | **Closed issues:** 205 | 206 | - Cookbook fails on CentOS Linux release 7.2.1511 - kernel.exec-shield [\#166](https://github.com/dev-sec/chef-os-hardening/issues/166) 207 | 208 | **Merged pull requests:** 209 | 210 | - Fix: do not touch exec-shield on RHEL 7 [\#168](https://github.com/dev-sec/chef-os-hardening/pull/168) ([artem-sidorenko](https://github.com/artem-sidorenko)) 211 | 212 | ## [v2.1.0](https://github.com/dev-sec/chef-os-hardening/tree/v2.1.0) (2017-06-12) 213 | 214 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v2.0.1...v2.1.0) 215 | 216 | **Closed issues:** 217 | 218 | - Testing of chef 13 in the CI [\#155](https://github.com/dev-sec/chef-os-hardening/issues/155) 219 | - auditd package is not installed [\#145](https://github.com/dev-sec/chef-os-hardening/issues/145) 220 | - Procps conditional failing [\#48](https://github.com/dev-sec/chef-os-hardening/issues/48) 221 | 222 | **Merged pull requests:** 223 | 224 | - CI: update to ruby 2.4.1 and gem update [\#164](https://github.com/dev-sec/chef-os-hardening/pull/164) ([artem-sidorenko](https://github.com/artem-sidorenko)) 225 | - Proper testing if kernel modules are disabled [\#163](https://github.com/dev-sec/chef-os-hardening/pull/163) ([artem-sidorenko](https://github.com/artem-sidorenko)) 226 | - Proper permissions for shadow on debian family [\#162](https://github.com/dev-sec/chef-os-hardening/pull/162) ([artem-sidorenko](https://github.com/artem-sidorenko)) 227 | - Support auditd installation on different distros [\#161](https://github.com/dev-sec/chef-os-hardening/pull/161) ([artem-sidorenko](https://github.com/artem-sidorenko)) 228 | - Docs: fix the wrong kitchen URL and add inspec [\#160](https://github.com/dev-sec/chef-os-hardening/pull/160) ([artem-sidorenko](https://github.com/artem-sidorenko)) 229 | - Chef 13 and 12 CI testing and cleanup of EOL distros [\#159](https://github.com/dev-sec/chef-os-hardening/pull/159) ([artem-sidorenko](https://github.com/artem-sidorenko)) 230 | - Install auditd package [\#158](https://github.com/dev-sec/chef-os-hardening/pull/158) ([artem-sidorenko](https://github.com/artem-sidorenko)) 231 | 232 | ## [v2.0.1](https://github.com/dev-sec/chef-os-hardening/tree/v2.0.1) (2017-04-11) 233 | 234 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v2.0.0...v2.0.1) 235 | 236 | **Fixed bugs:** 237 | 238 | - \['os-hardening'\]\['desktop'\]\['enable'\] is missing in 2.0.0 [\#153](https://github.com/dev-sec/chef-os-hardening/issues/153) 239 | 240 | **Merged pull requests:** 241 | 242 | - Default value for \['os-hardening'\]\['desktop'\]\['enable'\] [\#154](https://github.com/dev-sec/chef-os-hardening/pull/154) ([artem-sidorenko](https://github.com/artem-sidorenko)) 243 | 244 | ## [v2.0.0](https://github.com/dev-sec/chef-os-hardening/tree/v2.0.0) (2017-04-06) 245 | 246 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.4.1...v2.0.0) 247 | 248 | **Implemented enhancements:** 249 | 250 | - Remove dependencies to apt and yum cookbooks. [\#132](https://github.com/dev-sec/chef-os-hardening/pull/132) ([artem-sidorenko](https://github.com/artem-sidorenko)) 251 | - Using bracket syntax to resolve deprecation message [\#131](https://github.com/dev-sec/chef-os-hardening/pull/131) ([artem-sidorenko](https://github.com/artem-sidorenko)) 252 | - remove old content [\#126](https://github.com/dev-sec/chef-os-hardening/pull/126) ([chris-rock](https://github.com/chris-rock)) 253 | - Own attribute namespace for os-hardening [\#114](https://github.com/dev-sec/chef-os-hardening/pull/114) ([joshmyers](https://github.com/joshmyers)) 254 | 255 | **Closed issues:** 256 | 257 | - pam\_passwdqc package install idempotence [\#134](https://github.com/dev-sec/chef-os-hardening/issues/134) 258 | - Openhub is not up to date [\#129](https://github.com/dev-sec/chef-os-hardening/issues/129) 259 | - login.defs.erb contains a non-ASCII character which causes a knife cookbook upload failure [\#122](https://github.com/dev-sec/chef-os-hardening/issues/122) 260 | - fixing the 4 rspec failure [\#121](https://github.com/dev-sec/chef-os-hardening/issues/121) 261 | - pam node attribute namespace error [\#118](https://github.com/dev-sec/chef-os-hardening/issues/118) 262 | - Use travis for integration testing [\#115](https://github.com/dev-sec/chef-os-hardening/issues/115) 263 | - attributes need to be localized to the `node['chef-os-hardening']` namespace [\#113](https://github.com/dev-sec/chef-os-hardening/issues/113) 264 | 265 | **Merged pull requests:** 266 | 267 | - Docs: removing obsolete sysctl hint [\#151](https://github.com/dev-sec/chef-os-hardening/pull/151) ([artem-sidorenko](https://github.com/artem-sidorenko)) 268 | - Moving the attributes with dependencies on other attributes to the recipes [\#150](https://github.com/dev-sec/chef-os-hardening/pull/150) ([artem-sidorenko](https://github.com/artem-sidorenko)) 269 | - Cleanup of sysctl dependency [\#149](https://github.com/dev-sec/chef-os-hardening/pull/149) ([artem-sidorenko](https://github.com/artem-sidorenko)) 270 | - Disable entropy testing [\#146](https://github.com/dev-sec/chef-os-hardening/pull/146) ([artem-sidorenko](https://github.com/artem-sidorenko)) 271 | - Execute integration tests in DigitalOcean [\#144](https://github.com/dev-sec/chef-os-hardening/pull/144) ([artem-sidorenko](https://github.com/artem-sidorenko)) 272 | - Update of Gemfile [\#141](https://github.com/dev-sec/chef-os-hardening/pull/141) ([artem-sidorenko](https://github.com/artem-sidorenko)) 273 | - Remove dependencies to apt and yum cookbooks. [\#140](https://github.com/dev-sec/chef-os-hardening/pull/140) ([artem-sidorenko](https://github.com/artem-sidorenko)) 274 | - Update of kitchen vagrant file [\#139](https://github.com/dev-sec/chef-os-hardening/pull/139) ([artem-sidorenko](https://github.com/artem-sidorenko)) 275 | - Fix the version in metadata.rb [\#138](https://github.com/dev-sec/chef-os-hardening/pull/138) ([artem-sidorenko](https://github.com/artem-sidorenko)) 276 | - Cleanup, update of links in readme [\#137](https://github.com/dev-sec/chef-os-hardening/pull/137) ([artem-sidorenko](https://github.com/artem-sidorenko)) 277 | - Use caching to improve spec performance [\#136](https://github.com/dev-sec/chef-os-hardening/pull/136) ([ncs-alane](https://github.com/ncs-alane)) 278 | - Add attribute to control login.defs PASS\_WARN\_AGE [\#135](https://github.com/dev-sec/chef-os-hardening/pull/135) ([ncs-alane](https://github.com/ncs-alane)) 279 | - Revert "Remove dependencies to apt and yum cookbooks." [\#133](https://github.com/dev-sec/chef-os-hardening/pull/133) ([artem-sidorenko](https://github.com/artem-sidorenko)) 280 | - Update test-kitchen settings [\#130](https://github.com/dev-sec/chef-os-hardening/pull/130) ([shortdudey123](https://github.com/shortdudey123)) 281 | - Opscode =\> Chef [\#128](https://github.com/dev-sec/chef-os-hardening/pull/128) ([shortdudey123](https://github.com/shortdudey123)) 282 | - Update Rubocop, Foodcritic, and Chefspec coverage [\#127](https://github.com/dev-sec/chef-os-hardening/pull/127) ([shortdudey123](https://github.com/shortdudey123)) 283 | - Fix links to opensource tools in README [\#125](https://github.com/dev-sec/chef-os-hardening/pull/125) ([netflash](https://github.com/netflash)) 284 | - FIX for issue \#122 non-ASCII character [\#124](https://github.com/dev-sec/chef-os-hardening/pull/124) ([atomic111](https://github.com/atomic111)) 285 | - Update rhel\_system\_auth.erb [\#120](https://github.com/dev-sec/chef-os-hardening/pull/120) ([phillym](https://github.com/phillym)) 286 | - \[pam-attr-namespace-fix\] [\#119](https://github.com/dev-sec/chef-os-hardening/pull/119) ([rljohnsn](https://github.com/rljohnsn)) 287 | - Use new InSpec integration tests [\#117](https://github.com/dev-sec/chef-os-hardening/pull/117) ([chris-rock](https://github.com/chris-rock)) 288 | - Fix issues highlighted in \#114 [\#116](https://github.com/dev-sec/chef-os-hardening/pull/116) ([chris-rock](https://github.com/chris-rock)) 289 | 290 | ## [v1.4.1](https://github.com/dev-sec/chef-os-hardening/tree/v1.4.1) (2016-05-29) 291 | 292 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.3.1...v1.4.1) 293 | 294 | **Implemented enhancements:** 295 | 296 | - Update changelog [\#103](https://github.com/dev-sec/chef-os-hardening/pull/103) ([chris-rock](https://github.com/chris-rock)) 297 | - added inspec to gemfile and inspec verifier to kitchen.yml [\#101](https://github.com/dev-sec/chef-os-hardening/pull/101) ([atomic111](https://github.com/atomic111)) 298 | 299 | **Closed issues:** 300 | 301 | - pam recipe failing with chef client \> 12.8.1 [\#112](https://github.com/dev-sec/chef-os-hardening/issues/112) 302 | - pam\_passwdqc installation fails on CentOS 7.1 [\#102](https://github.com/dev-sec/chef-os-hardening/issues/102) 303 | - tests fail in travis [\#94](https://github.com/dev-sec/chef-os-hardening/issues/94) 304 | - Fails when used in conjunction with openldap::auth recipe [\#91](https://github.com/dev-sec/chef-os-hardening/issues/91) 305 | - packages with known issues are not actually removed on debian/ubuntu [\#90](https://github.com/dev-sec/chef-os-hardening/issues/90) 306 | - Actually log martians? [\#89](https://github.com/dev-sec/chef-os-hardening/issues/89) 307 | - Archlinux doesn't have a limits.d directory by default [\#84](https://github.com/dev-sec/chef-os-hardening/issues/84) 308 | - Support Centos 7 [\#79](https://github.com/dev-sec/chef-os-hardening/issues/79) 309 | 310 | **Merged pull requests:** 311 | 312 | - Pam options and fixes [\#111](https://github.com/dev-sec/chef-os-hardening/pull/111) ([foonix](https://github.com/foonix)) 313 | - Enable martian logging for ipv4 [\#109](https://github.com/dev-sec/chef-os-hardening/pull/109) ([foonix](https://github.com/foonix)) 314 | - Initial support for CentOS/RHEL 5 [\#108](https://github.com/dev-sec/chef-os-hardening/pull/108) ([foonix](https://github.com/foonix)) 315 | - Enable pam\_pwquality in rhel-family \> 7 [\#104](https://github.com/dev-sec/chef-os-hardening/pull/104) ([boldandbusted](https://github.com/boldandbusted)) 316 | - Fix bug in execute\[update-pam\] resource in newer version of Chef. [\#100](https://github.com/dev-sec/chef-os-hardening/pull/100) ([patcon](https://github.com/patcon)) 317 | - Expose list of packages to remove as an attribute [\#99](https://github.com/dev-sec/chef-os-hardening/pull/99) ([mikemoate](https://github.com/mikemoate)) 318 | - Fix pam\_passwdqc template [\#98](https://github.com/dev-sec/chef-os-hardening/pull/98) ([chris-rock](https://github.com/chris-rock)) 319 | - Berkshelf 4 Upgrade and Ruby 1.9.3 drop [\#96](https://github.com/dev-sec/chef-os-hardening/pull/96) ([chris-rock](https://github.com/chris-rock)) 320 | - Remove packages with known issues on debian/ubuntu [\#93](https://github.com/dev-sec/chef-os-hardening/pull/93) ([mikemoate](https://github.com/mikemoate)) 321 | - Add SINGLE and PROMPT parameters. [\#92](https://github.com/dev-sec/chef-os-hardening/pull/92) ([foonix](https://github.com/foonix)) 322 | - update common kitchen.yml platforms [\#87](https://github.com/dev-sec/chef-os-hardening/pull/87) ([chris-rock](https://github.com/chris-rock)) 323 | - Allow sys uid min/max and sys gid min/max to be configured [\#86](https://github.com/dev-sec/chef-os-hardening/pull/86) ([joshgarnett](https://github.com/joshgarnett)) 324 | - fixes \#84 [\#85](https://github.com/dev-sec/chef-os-hardening/pull/85) ([chris-rock](https://github.com/chris-rock)) 325 | 326 | ## [v1.3.1](https://github.com/dev-sec/chef-os-hardening/tree/v1.3.1) (2015-07-04) 327 | 328 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.3.0...v1.3.1) 329 | 330 | **Closed issues:** 331 | 332 | - 1.3.0 release on supermarket is broken [\#83](https://github.com/dev-sec/chef-os-hardening/issues/83) 333 | 334 | ## [v1.3.0](https://github.com/dev-sec/chef-os-hardening/tree/v1.3.0) (2015-06-29) 335 | 336 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.2.0...v1.3.0) 337 | 338 | **Closed issues:** 339 | 340 | - possible incompatibility with Chef client release 12.4 [\#82](https://github.com/dev-sec/chef-os-hardening/issues/82) 341 | - ERROR: No resource or method named `File' for `Chef::Recipe "sysctl"' [\#80](https://github.com/dev-sec/chef-os-hardening/issues/80) 342 | - update tutorial.md [\#67](https://github.com/dev-sec/chef-os-hardening/issues/67) 343 | - Installation doesn't work [\#66](https://github.com/dev-sec/chef-os-hardening/issues/66) 344 | 345 | **Merged pull requests:** 346 | 347 | - Update sysctl.rb [\#81](https://github.com/dev-sec/chef-os-hardening/pull/81) ([Rockstar04](https://github.com/Rockstar04)) 348 | - feature: implement ipv6 router advertisement settings [\#78](https://github.com/dev-sec/chef-os-hardening/pull/78) ([chris-rock](https://github.com/chris-rock)) 349 | - update common Gemfile for chef11+12 [\#77](https://github.com/dev-sec/chef-os-hardening/pull/77) ([arlimus](https://github.com/arlimus)) 350 | - common files: centos7 + rubocop [\#76](https://github.com/dev-sec/chef-os-hardening/pull/76) ([arlimus](https://github.com/arlimus)) 351 | - update common kitchen.yml platforms [\#75](https://github.com/dev-sec/chef-os-hardening/pull/75) ([arlimus](https://github.com/arlimus)) 352 | - update common readme badges [\#74](https://github.com/dev-sec/chef-os-hardening/pull/74) ([arlimus](https://github.com/arlimus)) 353 | - fix SUID/SGID bit cleaning API spelling [\#72](https://github.com/dev-sec/chef-os-hardening/pull/72) ([dupuy](https://github.com/dupuy)) 354 | - RHN config check should work [\#71](https://github.com/dev-sec/chef-os-hardening/pull/71) ([rapenchukd](https://github.com/rapenchukd)) 355 | - update tutorial [\#68](https://github.com/dev-sec/chef-os-hardening/pull/68) ([chris-rock](https://github.com/chris-rock)) 356 | 357 | ## [v1.2.0](https://github.com/dev-sec/chef-os-hardening/tree/v1.2.0) (2015-01-08) 358 | 359 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.1.2...v1.2.0) 360 | 361 | **Fixed bugs:** 362 | 363 | - Chef::Exceptions::Exec: yum\_package\[xinetd\] \(os-hardening::yum line 50\) [\#57](https://github.com/dev-sec/chef-os-hardening/issues/57) 364 | 365 | **Closed issues:** 366 | 367 | - deactivate pw\_max\_age [\#58](https://github.com/dev-sec/chef-os-hardening/issues/58) 368 | - can't convert String into Integer for package 'pam-ccreds' [\#54](https://github.com/dev-sec/chef-os-hardening/issues/54) 369 | - Better error handling for cpu detection [\#42](https://github.com/dev-sec/chef-os-hardening/issues/42) 370 | - ChefSpec and Ohai/Fauxhai: cpu [\#41](https://github.com/dev-sec/chef-os-hardening/issues/41) 371 | 372 | **Merged pull requests:** 373 | 374 | - updating common files [\#65](https://github.com/dev-sec/chef-os-hardening/pull/65) ([arlimus](https://github.com/arlimus)) 375 | - Idempotency [\#64](https://github.com/dev-sec/chef-os-hardening/pull/64) ([rmoriz](https://github.com/rmoriz)) 376 | - Badges [\#63](https://github.com/dev-sec/chef-os-hardening/pull/63) ([chris-rock](https://github.com/chris-rock)) 377 | - make uid\_min and gid\_min of login.defs configurable [\#62](https://github.com/dev-sec/chef-os-hardening/pull/62) ([bkw](https://github.com/bkw)) 378 | - standalone installation needs ohai cookbook as dep [\#61](https://github.com/dev-sec/chef-os-hardening/pull/61) ([aschmidt75](https://github.com/aschmidt75)) 379 | - updating common files [\#59](https://github.com/dev-sec/chef-os-hardening/pull/59) ([arlimus](https://github.com/arlimus)) 380 | - fix chefspec depreciation warning about `should` [\#56](https://github.com/dev-sec/chef-os-hardening/pull/56) ([bkw](https://github.com/bkw)) 381 | - improve cpu detection and implement intel fallback [\#55](https://github.com/dev-sec/chef-os-hardening/pull/55) ([chris-rock](https://github.com/chris-rock)) 382 | - updating common files [\#53](https://github.com/dev-sec/chef-os-hardening/pull/53) ([arlimus](https://github.com/arlimus)) 383 | - chefspec test for limites [\#52](https://github.com/dev-sec/chef-os-hardening/pull/52) ([chris-rock](https://github.com/chris-rock)) 384 | - Introduce Chef Spec [\#51](https://github.com/dev-sec/chef-os-hardening/pull/51) ([chris-rock](https://github.com/chris-rock)) 385 | - improvement: switch to site location in berkshelf [\#50](https://github.com/dev-sec/chef-os-hardening/pull/50) ([chris-rock](https://github.com/chris-rock)) 386 | - bugfix: fix failing conditional for procps [\#49](https://github.com/dev-sec/chef-os-hardening/pull/49) ([arlimus](https://github.com/arlimus)) 387 | - Drop procps service [\#47](https://github.com/dev-sec/chef-os-hardening/pull/47) ([bkw](https://github.com/bkw)) 388 | 389 | ## [v1.1.2](https://github.com/dev-sec/chef-os-hardening/tree/v1.1.2) (2014-09-08) 390 | 391 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.1.1...v1.1.2) 392 | 393 | **Closed issues:** 394 | 395 | - sysctl dependency [\#44](https://github.com/dev-sec/chef-os-hardening/issues/44) 396 | 397 | **Merged pull requests:** 398 | 399 | - Sysctl update to 0.6.0 [\#46](https://github.com/dev-sec/chef-os-hardening/pull/46) ([arlimus](https://github.com/arlimus)) 400 | - Lint [\#43](https://github.com/dev-sec/chef-os-hardening/pull/43) ([chris-rock](https://github.com/chris-rock)) 401 | - add more documentation about test run [\#40](https://github.com/dev-sec/chef-os-hardening/pull/40) ([chris-rock](https://github.com/chris-rock)) 402 | 403 | ## [v1.1.1](https://github.com/dev-sec/chef-os-hardening/tree/v1.1.1) (2014-07-28) 404 | 405 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/v1.1.0...v1.1.1) 406 | 407 | ## [v1.1.0](https://github.com/dev-sec/chef-os-hardening/tree/v1.1.0) (2014-07-28) 408 | 409 | [Full Changelog](https://github.com/dev-sec/chef-os-hardening/compare/7edf75f30f33563d7544089a24da2b470cb68dcd...v1.1.0) 410 | 411 | **Implemented enhancements:** 412 | 413 | - Conservative package update [\#10](https://github.com/dev-sec/chef-os-hardening/issues/10) 414 | 415 | **Closed issues:** 416 | 417 | - Tagged Release [\#34](https://github.com/dev-sec/chef-os-hardening/issues/34) 418 | - passwordless users not able to log in [\#32](https://github.com/dev-sec/chef-os-hardening/issues/32) 419 | - remove ntp [\#19](https://github.com/dev-sec/chef-os-hardening/issues/19) 420 | - Tests for suid bits [\#15](https://github.com/dev-sec/chef-os-hardening/issues/15) 421 | - forwarding isn't configured [\#9](https://github.com/dev-sec/chef-os-hardening/issues/9) 422 | - properly handle sysctl again [\#8](https://github.com/dev-sec/chef-os-hardening/issues/8) 423 | - enforce security updates [\#7](https://github.com/dev-sec/chef-os-hardening/issues/7) 424 | - enable\_sysrq-check is faulty [\#6](https://github.com/dev-sec/chef-os-hardening/issues/6) 425 | - Validate suid-bit removal from /bin/screen [\#5](https://github.com/dev-sec/chef-os-hardening/issues/5) 426 | 427 | **Merged pull requests:** 428 | 429 | - updated kitchen images to current batch \(mysql-equivalent\) [\#39](https://github.com/dev-sec/chef-os-hardening/pull/39) ([arlimus](https://github.com/arlimus)) 430 | - intend fix [\#38](https://github.com/dev-sec/chef-os-hardening/pull/38) ([chris-rock](https://github.com/chris-rock)) 431 | - fix wrong class definition [\#37](https://github.com/dev-sec/chef-os-hardening/pull/37) ([arlimus](https://github.com/arlimus)) 432 | - add common lint task. fix issues [\#35](https://github.com/dev-sec/chef-os-hardening/pull/35) ([ehaselwanter](https://github.com/ehaselwanter)) 433 | - update with common run\_all\_linters task [\#33](https://github.com/dev-sec/chef-os-hardening/pull/33) ([ehaselwanter](https://github.com/ehaselwanter)) 434 | - add Gemfile.lock to ignore list and remove it from tree [\#31](https://github.com/dev-sec/chef-os-hardening/pull/31) ([ehaselwanter](https://github.com/ehaselwanter)) 435 | - streamline .rubocop config [\#30](https://github.com/dev-sec/chef-os-hardening/pull/30) ([ehaselwanter](https://github.com/ehaselwanter)) 436 | - bugfix: make sysctl arp restrictions apply to all [\#29](https://github.com/dev-sec/chef-os-hardening/pull/29) ([arlimus](https://github.com/arlimus)) 437 | - Lint [\#28](https://github.com/dev-sec/chef-os-hardening/pull/28) ([chris-rock](https://github.com/chris-rock)) 438 | - various rubocop style fixes [\#27](https://github.com/dev-sec/chef-os-hardening/pull/27) ([ehaselwanter](https://github.com/ehaselwanter)) 439 | - fix FC019: Access node attributes in a consistent manner, use single quotes [\#26](https://github.com/dev-sec/chef-os-hardening/pull/26) ([ehaselwanter](https://github.com/ehaselwanter)) 440 | - make kitchen run optional, ignore shred test repo [\#25](https://github.com/dev-sec/chef-os-hardening/pull/25) ([ehaselwanter](https://github.com/ehaselwanter)) 441 | - changed the log\_martians value to 0 in attributes/sysctl.rb [\#24](https://github.com/dev-sec/chef-os-hardening/pull/24) ([atomic111](https://github.com/atomic111)) 442 | - improvement: clarify SUID/SGID options in readme [\#23](https://github.com/dev-sec/chef-os-hardening/pull/23) ([arlimus](https://github.com/arlimus)) 443 | - be more forgiving and relax rubocop [\#22](https://github.com/dev-sec/chef-os-hardening/pull/22) ([ehaselwanter](https://github.com/ehaselwanter)) 444 | - add linting, spec, guard infrastructure as well as config files [\#21](https://github.com/dev-sec/chef-os-hardening/pull/21) ([ehaselwanter](https://github.com/ehaselwanter)) 445 | - remove ntp [\#20](https://github.com/dev-sec/chef-os-hardening/pull/20) ([arlimus](https://github.com/arlimus)) 446 | - new gem release for sharing just the integration folder [\#18](https://github.com/dev-sec/chef-os-hardening/pull/18) ([ehaselwanter](https://github.com/ehaselwanter)) 447 | - Use shared test-repo [\#17](https://github.com/dev-sec/chef-os-hardening/pull/17) ([ehaselwanter](https://github.com/ehaselwanter)) 448 | - improvement: move /usr/bin/screen to SGID whitelisting [\#14](https://github.com/dev-sec/chef-os-hardening/pull/14) ([arlimus](https://github.com/arlimus)) 449 | - Packages [\#12](https://github.com/dev-sec/chef-os-hardening/pull/12) ([chris-rock](https://github.com/chris-rock)) 450 | - sysctl fixes [\#11](https://github.com/dev-sec/chef-os-hardening/pull/11) ([arlimus](https://github.com/arlimus)) 451 | - Contributing guide [\#4](https://github.com/dev-sec/chef-os-hardening/pull/4) ([arlimus](https://github.com/arlimus)) 452 | - Bugfix: broken link for debian wheezy vagrant box in .kitchen.yml and also broken link for NSA RedHat security guide in README.md [\#3](https://github.com/dev-sec/chef-os-hardening/pull/3) ([atomic111](https://github.com/atomic111)) 453 | - add license and improve styling [\#2](https://github.com/dev-sec/chef-os-hardening/pull/2) ([chris-rock](https://github.com/chris-rock)) 454 | - Fix: markdown fix in TUTORIAL.md [\#1](https://github.com/dev-sec/chef-os-hardening/pull/1) ([atomic111](https://github.com/atomic111)) 455 | 456 | 457 | 458 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 459 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributor Guideline 2 | 3 | This document provides an overview of how you can participate in improving this project or extending it. We are grateful for all your help: bug reports and fixes, code contributions, documentation or ideas. Feel free to join, we appreciate your support!! 4 | 5 | ## Communication 6 | 7 | ### GitHub repositories 8 | 9 | Much of the issues, goals and ideas are tracked in the respective projects in GitHub. Please use this channel to report bugs and post ideas. 10 | 11 | ## git and GitHub 12 | 13 | In order to contribute code please: 14 | 15 | 1. Fork the repository 16 | 2. Clone the project 17 | 3. Create a named feature branch (like `feature/add_component_x`) 18 | 4. Do your changes (do not forget the tests) 19 | 5. Run the tests, ensuring they all pass (and you are not decreasing the test coverage) 20 | 6. [Rebase][rebase-squash] it to the latest master (to ensure your changes do apply) 21 | 7. [Squash][rebase-squash] your commits to a small amount of logical separated commits (e.g. to avoid commits with something like "reverted or fixed last commit" in the commit chain) 22 | 8. Submit a Merge Request to the master branch of this repository 23 | 24 | To have your code merged, see the expectations listed below. 25 | 26 | You can find a well-written guide [here](https://help.github.com/articles/fork-a-repo). 27 | 28 | Please follow common commit best-practices. Be explicit, have a short summary, a well-written description and references. This is especially important for the merge-request. 29 | 30 | Some great guidelines can be found [here](https://wiki.openstack.org/wiki/GitCommitMessages) and [here](http://robots.thoughtbot.com/5-useful-tips-for-a-better-commit-message). 31 | 32 | ## Expectations 33 | 34 | ### Don't reinvent the wheel 35 | 36 | This hardening project doesn't intend to reinvent the configuration stack for services. Aim to use official configuration projects first and provide hardening as a layer on top. The goal is remove the need for a user to configure all aspects of services and maintain security configuration. This way, the user can still configure a service using the interface provided by the official project. 37 | 38 | * For Chef refer to the official [Chef community cookbooks](https://supermarket.chef.io/cookbooks). 39 | * For Puppet head to the [Puppet Forge](https://forge.puppetlabs.com/) and take a node of the Puppet supported modules. 40 | 41 | These projects are generally hosted on GitHub as well. 42 | 43 | In some cases, we in fact create the full rollout stack, but this is generally the exception ([os-hardening](https://github.com/dev-sec/chef-os-hardening), [ssh-hardening](https://github.com/dev-sec/chef-ssh-hardening)). 44 | 45 | 46 | ### Be explicit 47 | 48 | * Please avoid using nonsensical property and variable names 49 | * Use self-describing attribute names for user configuration 50 | * In case of failures, communicate what happened and why a failure occurs to the user. Make it easy to track the code or action that produced the error. Try to catch and handle errors if possible to provide improved failure messages. 51 | 52 | 53 | ### Add tests 54 | 55 | The security review of this project is done using integration tests. 56 | 57 | Whenever you add a new security configuration, please start by writing a test that checks for this configuration. For example: If you want to set a new attribute in a configuration file, write a test that expects the value to be set first. Then implement your change. 58 | 59 | You may add a new feature request by creating a test for whatever value you need. 60 | 61 | All tests will be reviewed internally for their validity and overall project direction. 62 | 63 | 64 | ### Document your code 65 | 66 | As code is more often read than written, please provide documentation in all projects. 67 | 68 | Adhere to the respective guidelines for documentation: 69 | 70 | * Chef generally documents code based explicit readme files. For code documentation please use [yard-chef](https://github.com/rightscale/yard-chef) 71 | * [Puppet module documentation](http://docs.puppetlabs.com/puppet/latest/reference/modules_documentation.html) 72 | 73 | 74 | ### Follow coding styles 75 | 76 | We generally include test for coding guidelines: 77 | 78 | * Chef follows [Foodcritic](http://acrmp.github.io/foodcritic/) 79 | * Puppet is checked with [puppet-lint](http://puppet-lint.com/checks/) 80 | 81 | Remember: Code is generally read much more often than written. 82 | 83 | 84 | ### Use Markdown 85 | 86 | Wherever possible, please refrain from any other formats and stick to simple markdown. 87 | 88 | [rebase-squash]: https://github.com/edx/edx-platform/wiki/How-to-Rebase-a-Pull-Request 89 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # os-hardening (Chef cookbook) 2 | 3 | [![Supermarket](http://img.shields.io/cookbook/v/os-hardening.svg)][1] 4 | [![Tests](https://github.com/dev-sec/chef-os-hardening/actions/workflows/test.yml/badge.svg)][2] 5 | 6 | ## Description 7 | 8 | This cookbook provides numerous security-related configurations, providing all-round base protection. 9 | 10 | It configures: 11 | 12 | * Configures package management e.g. allows only signed packages 13 | * Remove packages with known issues 14 | * Configures `pam` and `pam_limits` module 15 | * Shadow password suite configuration 16 | * Configures system path permissions 17 | * Disable core dumps via soft limits 18 | * Restrict Root Logins to System Console 19 | * Set SUIDs 20 | * Configures kernel parameters via sysctl 21 | 22 | It will not: 23 | 24 | * Update system packages 25 | * Install security patches 26 | 27 | ## Requirements 28 | 29 | * Chef >= 14.13.11 30 | 31 | ### Platform 32 | 33 | - Debian 10, 11 34 | - Ubuntu 18.04, 20.04 35 | - RHEL 7, 8, 9 36 | - CentOS 7 37 | - CentOS Stream 8, 9 38 | - Oracle Linux 7, 8, 9 39 | - AlmaLinux 8, 9 40 | - Rocky Linux 8, 9 41 | - Fedora 37, 38 42 | - OpenSuse Leap 42 43 | - Amazon Linux 1, 2 44 | 45 | ## Attributes 46 | 47 | * `['os-hardening']['components'][COMPONENT_NAME]` - allows the fine control over which components should be executed via default recipe. See below for more details 48 | * `['os-hardening']['desktop']['enable'] = false` 49 | true if this is a desktop system, ie Xorg, KDE/GNOME/Unity/etc 50 | * `['os-hardening']['network']['forwarding'] = false` 51 | true if this system requires packet forwarding (eg Router), false otherwise 52 | * `['os-hardening']['network']['ipv6']['enable'] = false` 53 | * `['os-hardening']['network']['arp']['restricted'] = true` 54 | true if you want the behavior of announcing and replying to ARP to be restricted, false otherwise 55 | * `['os-hardening']['env']['extra_user_paths'] = []` 56 | add additional paths to the user's `PATH` variable (default is empty). 57 | * `['os-hardening']['env']['umask'] = "027"` 58 | * `['os-hardening']['env']['root_path'] = "/"` 59 | where root is mounted 60 | * `['os-hardening']['auth']['pw_max_age'] = 60` 61 | maximum password age 62 | * `['os-hardening']['auth']['pw_min_age'] = 7` 63 | minimum password age (before allowing any other password change) 64 | * `['os-hardening']['auth']['pw_warn_age'] = 7` 65 | number of days before maximum password age occurs to warn of impending 66 | change 67 | * `['os-hardening']['auth']['uid_min'] = 1000` 68 | lower bound of UIDs assigned by useradd 69 | * `['os-hardening']['auth']['uid_max'] = 60000` 70 | upper bound of UIDs assigned by useradd 71 | * `['os-hardening']['auth']['gid_min'] = 1000` 72 | lower bound of GIDs assigned by groupadd 73 | * `['os-hardening']['auth']['gid_max'] = 60000` 74 | upper bound of GIDs assigned by groupadd 75 | * `['os-hardening']['auth']['retries'] = 5` 76 | the maximum number of authentication attempts, before the account is locked for some time 77 | * `['os-hardening']['auth']['lockout_time'] = 600` 78 | time in seconds that needs to pass, if the account was locked due to too many failed authentication attempts 79 | * `['os-hardening']['auth']['timeout'] = 60` 80 | authentication timeout in seconds, so login will exit if this time passes 81 | * `['os-hardening']['auth']['allow_homeless'] = false` 82 | true if to allow users without home to login 83 | * `['os-hardening']['auth']['pam']['passwdqc']['enable'] = true` 84 | true if you want to use strong password checking in PAM using passwdqc 85 | * `['os-hardening']['auth']['pam']['passwdqc']['options'] = "min=disabled,disabled,16,12,8"` 86 | set to any option line (as a string) that you want to pass to passwdqc 87 | * `['os-hardening']['auth']['pam']['passwdqc']['template_cookbook'] = 'os-hardening'` 88 | set to the name of the cookbook from which the template is obtained for the `/usr/share/pam-configs/passwdqc` file 89 | * `['os-hardening']['auth']['pam']['tally2']['template_cookbook'] = 'os-hardening'` 90 | set to the name of the cookbook from which the template is obtained for the `/usr/share/pam-configs/tally2` file 91 | * `['os-hardening']['auth']['pam']['system-auth']['template_cookbook'] = 'os-hardening'` 92 | set to the name of the cookbook from which the template is obtained for the `/etc/pam.d/system-auth-ac` file 93 | * `['os-hardening']['security']['users']['allow'] = []` 94 | list of things, that a user is allowed to do. May contain: `change_user` 95 | * `['os-hardening']['security']['kernel']['enable_module_loading'] = true` 96 | true if you want to allowed to change kernel modules once the system is running (eg `modprobe`, `rmmod`) 97 | * `['os-hardening']['security']['kernel']['disable_filesystems'] = ['cramfs', 'freevxfs', 'jffs2', 'hfs', 'hfsplus', 'squashfs', 'udf', 'vfat']` 98 | list of kernel file system modules, which are blacklisted for loading (e.g. they are unused and can be disabled). Set this to `[]` to completely avoid this blacklisting 99 | * `['os-hardening']['security']['kernel']['enable_sysrq'] = false` 100 | * `['os-hardening']['security']['kernel']['enable_core_dump'] = false` 101 | * `['os-hardening']['security']['suid_sgid']['enforce'] = true` 102 | true if you want to reduce SUID/SGID bits. There is already a list of items which are searched for configured, but you can also add your own 103 | * `['os-hardening']['security']['suid_sgid']['blacklist'] = []` 104 | a list of paths which should have their SUID/SGID bits removed 105 | * `['os-hardening']['security']['suid_sgid']['whitelist'] = []` 106 | a list of paths which should not have their SUID/SGID bits altered 107 | * `['os-hardening']['security']['suid_sgid']['remove_from_unknown'] = false` 108 | true if you want to remove SUID/SGID bits from any file, that is not explicitly configured in a `blacklist`. This will make every Chef run search through the mounted filesystems looking for SUID/SGID bits that are not configured in the default and user blacklist. If it finds an SUID/SGID bit, it will be removed, unless this file is in your `whitelist`. 109 | * `['os-hardening']['security']['suid_sgid']['dry_run_on_unknown'] = false` 110 | like `remove_from_unknown` above, only that SUID/SGID bits aren't removed. 111 | It will still search the filesystems to look for SUID/SGID bits but it will only print them in your log. This option is only ever recommended, when you first configure `remove_from_unknown` for SUID/SGID bits, so that you can see the files that are being changed and make adjustments to your `whitelist` and `blacklist`. 112 | * `['os-hardening']['security']['packages']['clean'] = true` 113 | removes packages with known issues. 114 | * `['os-hardening']['security']['packages']['list'] = ['xinetd','inetd','ypserv','telnet-server','rsh-server']` 115 | list of packages to remove, by default we remove the following packages: 116 | * xinetd ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.1) 117 | * inetd ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.1) 118 | * tftp-server ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.5) 119 | * ypserv ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.4) 120 | * telnet-server ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.2) 121 | * rsh-server ([NSA](http://www.nsa.gov/ia/_files/os/redhat/rhel5-guide-i731.pdf), Chapter 3.2.3) 122 | * `['os-hardening']['security']['selinux_mode'] = 'unmanaged'` 123 | set to `unmanaged` if you want to let selinux configuration as it is. Set to `enforcing` to enforce or `permissive` to permissive SELinux. 124 | 125 | ### Controlling the included components 126 | 127 | `default.rb` includes other components based on the ohai autodetection attributes of your system. E.g. do not execute selinux on non-RHEL systems. You can override this behavior and force components to be executed or not via setting attributes in `node['os-hardening']['components']` on the override level. Example 128 | 129 | ```ruby 130 | # some attribute file 131 | # do not include sysctl and auditd 132 | override['os-hardening']['components']['sysctl'] = false 133 | override['os-hardening']['components']['auditd'] = false 134 | 135 | # force selinux to be included 136 | override['os-hardening']['components']['selinux'] = true 137 | ``` 138 | 139 | In the current implementation different components are located in the different recipes. See the available recipes or `default.rb` for possible component names. 140 | 141 | ## Usage 142 | 143 | Add the recipes to the `run_list`, it should be last: 144 | 145 | "recipe[os-hardening]" 146 | 147 | Configure attributes: 148 | 149 | "security" : { 150 | "kernel" : { 151 | "enable_module_loading" : true 152 | } 153 | }, 154 | 155 | ## Local Testing 156 | 157 | ### Local testing 158 | 159 | Please install [chef-dk](https://downloads.chef.io/chefdk), [VirtualBox](https://www.virtualbox.org/) or VMware Workstation and [Vagrant](https://www.vagrantup.com/). 160 | 161 | Linting is checked with [rubocop](https://github.com/bbatsov/rubocop) and [foodcritic](http://www.foodcritic.io/): 162 | 163 | ```bash 164 | $ chef exec rake lint 165 | ..... 166 | ``` 167 | 168 | Unit/spec tests are done with [chefspec](https://github.com/sethvargo/chefspec): 169 | 170 | ```bash 171 | $ chef exec rake spec 172 | ..... 173 | ``` 174 | 175 | Integration tests are done with [test-kitchen](http://kitchen.ci/) and [inspec](https://www.inspec.io/): 176 | 177 | ```bash 178 | $ chef exec rake kitchen 179 | ..... 180 | # or you can use the kitchen directly 181 | $ kitchen test 182 | ``` 183 | 184 | ### CI testing of forks 185 | 186 | You can enable testing of your fork in [Travis CI](http://travis-ci.org/). By default you will get linting, spec tests and integration tests with [kitchen-dokken]. 187 | 188 | Integration tests with [kitchen-dokken] do not cover everything as they run in the container environment. 189 | Full integration tests can be executed using [DigitalOcean](http://digitalocean.com/). 190 | 191 | If you want to have full integration tests for your fork, you will have to add following [environment variables](https://docs.travis-ci.com/user/environment-variables/#Defining-Variables-in-Repository-Settings) in the settings of your fork: 192 | - `DIGITALOCEAN_ACCESS_TOKEN` - [access token for DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2) 193 | - `CI_SSH_KEY` - private part of some ssh key, available on DigitalOcean for your instances, in base64 encoded form (e.g. `cat id_rsa | base64 -w0 ; echo`) 194 | - `DIGITALOCEAN_SSH_KEY_IDS` - ID in DigitalOcean of `CI_SSH_KEY`, see [this](https://github.com/test-kitchen/kitchen-digitalocean#installation-and-setup) for more information 195 | 196 | ## Contributors + Kudos 197 | 198 | * Dominik Richter [arlimus](https://github.com/arlimus) 199 | * Bernhard Weisshuhn [bkw](https://github.com/bkw) 200 | * Christoph Hartmann [chris-rock](https://github.com/chris-rock) 201 | * Edmund Haselwanter [ehaselwanter](https://github.com/ehaselwanter) 202 | * Patrick Meier [atomic111](https://github.com/atomic111) 203 | * Artem Sidorenko [artem-sidorenko](https://github.com/artem-sidorenko) 204 | 205 | This cookbook is mostly based on guides by: 206 | 207 | * [Arch Linux wiki, Sysctl hardening](https://wiki.archlinux.org/index.php/Sysctl) 208 | * [Ubuntu Security/Features](https://wiki.ubuntu.com/Security/Features) 209 | * [NSA: Guide to the Secure Configuration of Red Hat Enterprise Linux 5](https://www.iad.gov/iad/library/ia-guidance/security-configuration/operating-systems/guide-to-the-secure-configuration-of-red-hat-enterprise.cfm) 210 | * [Deutsche Telekom, Group IT Security, Security Requirements (German)](https://www.telekom.com/psa) 211 | 212 | 213 | Thanks to all of you!! 214 | 215 | ## Contributing 216 | 217 | See [contributor guideline](CONTRIBUTING.md). 218 | 219 | ## License and Author 220 | 221 | * Author:: Dominik Richter 222 | * Author:: Deutsche Telekom AG 223 | 224 | Licensed under the Apache License, Version 2.0 (the "License"); 225 | you may not use this file except in compliance with the License. 226 | You may obtain a copy of the License at 227 | 228 | http://www.apache.org/licenses/LICENSE-2.0 229 | 230 | Unless required by applicable law or agreed to in writing, software 231 | distributed under the License is distributed on an "AS IS" BASIS, 232 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 233 | See the License for the specific language governing permissions and 234 | limitations under the License. 235 | 236 | [1]: https://supermarket.getchef.com/cookbooks/os-hardening 237 | [2]: https://github.com/dev-sec/chef-os-hardening/actions/workflows/test.yml 238 | [3]: https://coveralls.io/r/dev-sec/chef-os-hardening 239 | [kitchen-dokken]: https://github.com/someara/kitchen-dokken 240 | -------------------------------------------------------------------------------- /attributes/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Attributes:: default 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | 22 | # rubocop:disable Metrics/BlockLength 23 | 24 | default['os-hardening'].tap do |os_hardening| 25 | # components of this cookbook 26 | %w[packages limits login_defs minimize_access pam profile securetty].each do |cp| 27 | os_hardening['components'][cp] = true 28 | end 29 | 30 | # Define the packages based on operating system 31 | os_hardening['packages'].tap do |packages| 32 | case node['platform_family'] 33 | when 'rhel', 'fedora', 'amazon' 34 | packages['pam_ccreds'] = 'pam_ccreds' 35 | packages['pam_passwdqc'] = 'pam_passwdqc' 36 | packages['pam_cracklib'] = 'pam_cracklib' 37 | packages['pam_pwquality'] = 'libpwquality' 38 | packages['auditd'] = 'audit' 39 | when 'debian' 40 | packages['pam_ccreds'] = 'libpam-ccreds' 41 | packages['pam_passwdqc'] = 'libpam-passwdqc' 42 | packages['pam_cracklib'] = 'libpam-cracklib' 43 | packages['auditd'] = 'auditd' 44 | when 'arch' 45 | packages['pam_ccreds'] = 'pam_ccreds' 46 | packages['pam_passwdqc'] = 'pam_passwdqc' 47 | packages['pam_cracklib'] = 'pam_cracklib' 48 | packages['auditd'] = 'audit' 49 | else 50 | packages['pam_ccreds'] = 'pam_ccreds' 51 | packages['pam_passwdqc'] = 'pam_passwdqc' 52 | packages['pam_cracklib'] = 'pam_cracklib' 53 | packages['auditd'] = 'audit' 54 | end 55 | end 56 | 57 | # rhel, centos autoconf configuration 58 | os_hardening['authconfig']['shadow']['enable'] = true 59 | os_hardening['authconfig']['md5']['enable'] = true 60 | 61 | os_hardening['desktop']['enable'] = false 62 | os_hardening['network']['forwarding'] = false 63 | os_hardening['network']['ipv6']['enable'] = false 64 | os_hardening['network']['arp']['restricted'] = true 65 | 66 | os_hardening['env']['extra_user_paths'] = [] 67 | os_hardening['env']['root_path'] = '/' 68 | 69 | os_hardening['auth'].tap do |auth| 70 | auth['pw_max_age'] = 60 71 | auth['pw_min_age'] = 7 # discourage password cycling 72 | auth['pw_warn_age'] = 7 73 | auth['retries'] = 5 74 | auth['lockout_time'] = 600 # 10min 75 | auth['maildir'] = '/var/mail' 76 | auth['timeout'] = 60 77 | auth['allow_homeless'] = false 78 | auth['login_defs']['template_cookbook'] = 'os-hardening' 79 | auth['root_ttys'] = %w[console tty1 tty2 tty3 tty4 tty5 tty6] 80 | auth['uid_min'] = 1000 81 | auth['uid_max'] = 60000 82 | auth['gid_min'] = 1000 83 | auth['gid_max'] = 60000 84 | auth['sys_uid_max'] = 999 85 | auth['sys_gid_max'] = 999 86 | 87 | # PAM settings 88 | auth['pam'].tap do |pam| 89 | case node['platform_family'] 90 | when 'rhel', 'fedora', 'amazon' 91 | if node['platform_version'].to_f < 7 92 | pam['passwdqc']['enable'] = true 93 | pam['pwquality']['enable'] = false 94 | else 95 | pam['passwdqc']['enable'] = false 96 | pam['pwquality']['enable'] = true 97 | end 98 | end 99 | 100 | pam['passwdqc']['options'] = 'min=disabled,disabled,16,12,8' 101 | pam['cracklib']['options'] = 'try_first_pass retry=3 type=' 102 | pam['pwquality']['options'] = 'try_first_pass retry=3 type=' 103 | pam['unix']['options'] = 'shadow nullok try_first_pass use_authtok remember=5' 104 | pam['tally2']['template_cookbook'] = 'os-hardening' 105 | pam['passwdqc']['template_cookbook'] = 'os-hardening' 106 | pam['system-auth']['template_cookbook'] = 'os-hardening' 107 | pam['pam_systemd']['enable'] = node['os-hardening']['desktop']['enable'] 108 | end 109 | end 110 | 111 | # RH has a bit different defaults on some places 112 | case node['platform_family'] 113 | when 'rhel', 'amazon' 114 | os_hardening['env']['umask'] = '077' 115 | os_hardening['auth']['sys_uid_min'] = 201 116 | os_hardening['auth']['sys_gid_min'] = 201 117 | else 118 | os_hardening['env']['umask'] = '027' 119 | os_hardening['auth']['sys_uid_min'] = 100 120 | os_hardening['auth']['sys_gid_min'] = 100 121 | end 122 | 123 | os_hardening['security'].tap do |security| 124 | # may contain: change_user 125 | security['users']['allow'] = [] 126 | security['kernel']['enable_module_loading'] = true 127 | security['kernel']['disable_filesystems'] = %w[cramfs freevxfs jffs2 hfs hfsplus squashfs udf vfat] 128 | security['kernel']['enable_sysrq'] = false 129 | security['kernel']['enable_core_dump'] = false 130 | security['suid_sgid']['enforce'] = true 131 | # user-defined blacklist and whitelist 132 | security['suid_sgid']['blacklist'] = [] 133 | security['suid_sgid']['whitelist'] = [] 134 | # if this is true, remove any suid/sgid bits from files that were not in the 135 | # whitelist 136 | security['suid_sgid']['remove_from_unknown'] = false 137 | security['suid_sgid']['dry_run_on_unknown'] = false 138 | 139 | # Allow interactive startup (rhel, centos) 140 | security['init']['prompt'] = true 141 | # Require root password for single user mode. (rhel, centos) 142 | security['init']['single'] = false 143 | security['init']['daemon_umask'] = '027' 144 | 145 | # remove packages with known issues 146 | security['packages']['clean'] = true 147 | # list of packages with known issues 148 | security['packages']['list'] = [ 149 | 'xinetd', 150 | 'inetd', 151 | 'ypserv', 152 | 'telnet-server', 153 | 'rsh-server' 154 | ] 155 | 156 | # SELinux enforcing (enforcing, permissive, unmanaged) 157 | security['selinux_mode'] = 'unmanaged' 158 | 159 | # SYSTEM CONFIGURATION 160 | # ==================== 161 | # These are not meant to be modified by the user 162 | 163 | # misc 164 | security['kernel']['secure_sysrq'] = 4 + 16 + 32 + 64 + 128 165 | 166 | # suid and sgid blacklists and whitelists 167 | # --------------------------------------- 168 | # don't change values in the system_blacklist/whitelist 169 | # adjust values for blacklist/whitelist instead, they can override system_blacklist/whitelist 170 | 171 | # list of suid/sgid entries that must be removed 172 | security['suid_sgid']['system_blacklist'] = [ 173 | # blacklist as provided by NSA 174 | '/usr/bin/rcp', '/usr/bin/rlogin', '/usr/bin/rsh', 175 | # sshd must not use host-based authentication (see ssh cookbook) 176 | '/usr/libexec/openssh/ssh-keysign', 177 | '/usr/lib/openssh/ssh-keysign', 178 | # misc others 179 | '/sbin/netreport', # not normally required for user 180 | '/usr/sbin/usernetctl', # modify interfaces via functional accounts 181 | # connecting to ... 182 | '/usr/sbin/userisdnctl', # no isdn... 183 | '/usr/sbin/pppd', # no ppp / dsl ... 184 | # lockfile 185 | '/usr/bin/lockfile', 186 | '/usr/bin/mail-lock', 187 | '/usr/bin/mail-unlock', 188 | '/usr/bin/mail-touchlock', 189 | '/usr/bin/dotlockfile', 190 | # need more investigation, blacklist for now 191 | '/usr/bin/arping', 192 | '/usr/sbin/uuidd', 193 | '/usr/bin/mtr', # investigate current state... 194 | '/usr/lib/evolution/camel-lock-helper-1.2', # investigate current state... 195 | '/usr/lib/pt_chown', # pseudo-tty, needed? 196 | '/usr/lib/eject/dmcrypt-get-device', 197 | '/usr/lib/mc/cons.saver' # midnight commander screensaver 198 | ] 199 | 200 | # list of suid/sgid entries that can remain untouched 201 | security['suid_sgid']['system_whitelist'] = [ 202 | # whitelist as provided by NSA 203 | '/bin/mount', '/bin/ping', '/bin/su', '/bin/umount', '/sbin/pam_timestamp_check', 204 | '/sbin/unix_chkpwd', '/usr/bin/at', '/usr/bin/gpasswd', '/usr/bin/locate', 205 | '/usr/bin/newgrp', '/usr/bin/passwd', '/usr/bin/ssh-agent', '/usr/libexec/utempter/utempter', '/usr/sbin/lockdev', 206 | '/usr/sbin/sendmail.sendmail', '/usr/bin/expiry', 207 | # whitelist ipv6 208 | '/bin/ping6', '/usr/bin/traceroute6.iputils', 209 | # whitelist nfs 210 | '/sbin/mount.nfs', '/sbin/umount.nfs', 211 | # whitelist nfs4 212 | '/sbin/mount.nfs4', '/sbin/umount.nfs4', 213 | # whitelist cron 214 | '/usr/bin/crontab', 215 | # whitelist consolemssaging 216 | '/usr/bin/wall', '/usr/bin/write', 217 | # whitelist: only SGID with utmp group for multi-session access 218 | # impact is limited; installation/usage has some remaining risk 219 | '/usr/bin/screen', 220 | # whitelist locate 221 | '/usr/bin/mlocate', 222 | # whitelist usermanagement 223 | '/usr/bin/chage', '/usr/bin/chfn', '/usr/bin/chsh', 224 | # whitelist fuse 225 | '/bin/fusermount', 226 | # whitelist pkexec 227 | '/usr/bin/pkexec', 228 | # whitelist sudo 229 | '/usr/bin/sudo', '/usr/bin/sudoedit', 230 | # whitelist postfix 231 | '/usr/sbin/postdrop', '/usr/sbin/postqueue', 232 | # whitelist apache 233 | '/usr/sbin/suexec', 234 | # whitelist squid 235 | '/usr/lib/squid/ncsa_auth', '/usr/lib/squid/pam_auth', 236 | # whitelist kerberos 237 | '/usr/kerberos/bin/ksu', 238 | # whitelist pam_caching 239 | '/usr/sbin/ccreds_validate', 240 | # whitelist Xorg 241 | '/usr/bin/Xorg', # xorg 242 | '/usr/bin/X', # xorg 243 | '/usr/lib/dbus-1.0/dbus-daemon-launch-helper', # freedesktop ipc 244 | '/usr/lib/vte/gnome-pty-helper', # gnome 245 | '/usr/lib/libvte9/gnome-pty-helper', # gnome 246 | '/usr/lib/libvte-2.90-9/gnome-pty-helper' # gnome 247 | ] 248 | 249 | # set default cpu vendor 250 | security['cpu_vendor'] = 'intel' 251 | end 252 | end 253 | # rubocop:enable Metrics/BlockLength 254 | 255 | # auditd config 256 | default['os-hardening']['auditd']['log_file'] = '/var/log/audit/audit.log' 257 | default['os-hardening']['auditd']['log_format'] = 'RAW' 258 | default['os-hardening']['auditd']['max_log_file_action'] = 'keep_logs' 259 | default['os-hardening']['auditd']['space_left'] = 75 260 | default['os-hardening']['auditd']['action_mail_acct'] = 'root' 261 | default['os-hardening']['auditd']['space_left_action'] = 'SYSLOG' 262 | default['os-hardening']['auditd']['admin_space_left'] = 50 263 | default['os-hardening']['auditd']['admin_space_left_action'] = 'SUSPEND' 264 | default['os-hardening']['auditd']['disk_full_action'] = 'SUSPEND' 265 | default['os-hardening']['auditd']['disk_error_action'] = 'SUSPEND' 266 | default['os-hardening']['auditd']['flush'] = 'INCREMENTAL' 267 | default['os-hardening']['auditd']['log_group'] = 'root' 268 | default['os-hardening']['auditd']['priority_boost'] = '4' 269 | default['os-hardening']['auditd']['freq'] = '20' 270 | default['os-hardening']['auditd']['num_logs'] = '5' 271 | default['os-hardening']['auditd']['disp_qos'] = 'lossy' 272 | default['os-hardening']['auditd']['dispatcher'] = '/sbin/audispd' 273 | default['os-hardening']['auditd']['name_format'] = 'NONE' 274 | default['os-hardening']['auditd']['max_log_file'] = '6' 275 | default['os-hardening']['auditd']['tcp_listen_queue'] = '5' 276 | default['os-hardening']['auditd']['tcp_max_per_addr'] = '1' 277 | default['os-hardening']['auditd']['tcp_client_max_idle'] = '0' 278 | default['os-hardening']['auditd']['enable_krb5'] = 'no' 279 | default['os-hardening']['auditd']['krb5_principal'] = 'auditd' 280 | -------------------------------------------------------------------------------- /attributes/sysctl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Attributes:: sysctl 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | 21 | # Enable RFC-recommended source validation feature. It should not be used for 22 | # routers on complex networks, but is helpful for end hosts and routers serving 23 | # small networks. 24 | default['sysctl']['params']['net']['ipv4']['conf']['all']['rp_filter'] = 1 25 | default['sysctl']['params']['net']['ipv4']['conf']['default']['rp_filter'] = 1 26 | 27 | # Reduce the surface on SMURF attacks. Make sure to ignore ECHO broadcasts, 28 | # which are only required in broad network analysis. 29 | default['sysctl']['params']['net']['ipv4']['icmp_echo_ignore_broadcasts'] = 1 30 | 31 | # There is no reason to accept bogus error responses from ICMP, so ignore them 32 | # instead. 33 | default['sysctl']['params']['net']['ipv4']['icmp_ignore_bogus_error_responses'] = 1 34 | 35 | # Limit the amount of traffic the system uses for ICMP. 36 | default['sysctl']['params']['net']['ipv4']['icmp_ratelimit'] = 100 37 | 38 | # Adjust the ICMP ratelimit to include: ping, dst unreachable, source quench, 39 | # time exceed, param problem, timestamp reply, information reply 40 | default['sysctl']['params']['net']['ipv4']['icmp_ratemask'] = 88089 41 | 42 | # Protect against wrapping sequence numbers at gigabit speeds: 43 | default['sysctl']['params']['net']['ipv4']['tcp_timestamps'] = 0 44 | 45 | # RFC 1337 fix F1 46 | default['sysctl']['params']['net']['ipv4']['tcp_rfc1337'] = 1 47 | 48 | # Syncookies is used to prevent SYN-flooding attacks. 49 | default['sysctl']['params']['net']['ipv4']['tcp_syncookies'] = 1 50 | 51 | default['sysctl']['params']['net']['ipv4']['conf']['all']['shared_media'] = 1 52 | default['sysctl']['params']['net']['ipv4']['conf']['default']['shared_media'] = 1 53 | 54 | # Accepting source route can lead to malicious networking behavior, so disable 55 | # it if not needed. 56 | default['sysctl']['params']['net']['ipv4']['conf']['all']['accept_source_route'] = 0 57 | default['sysctl']['params']['net']['ipv4']['conf']['default']['accept_source_route'] = 0 58 | 59 | # Accepting redirects can lead to malicious networking behavior, so disable 60 | # it if not needed. 61 | default['sysctl']['params']['net']['ipv4']['conf']['all']['accept_redirects'] = 0 62 | default['sysctl']['params']['net']['ipv4']['conf']['default']['accept_redirects'] = 0 63 | default['sysctl']['params']['net']['ipv6']['conf']['all']['accept_redirects'] = 0 64 | default['sysctl']['params']['net']['ipv6']['conf']['default']['accept_redirects'] = 0 65 | default['sysctl']['params']['net']['ipv4']['conf']['all']['secure_redirects'] = 0 66 | default['sysctl']['params']['net']['ipv4']['conf']['default']['secure_redirects'] = 0 67 | 68 | # For non-routers: don't send redirects, these settings are 0 69 | default['sysctl']['params']['net']['ipv4']['conf']['all']['send_redirects'] = 0 70 | default['sysctl']['params']['net']['ipv4']['conf']['default']['send_redirects'] = 0 71 | 72 | # log martian packets 73 | default['sysctl']['params']['net']['ipv4']['conf']['all']['log_martians'] = 1 74 | default['sysctl']['params']['net']['ipv4']['conf']['default']['log_martians'] = 1 75 | 76 | # ipv6 config 77 | # NSA 2.5.3.2.5 Limit Network-Transmitted Configuration 78 | default['sysctl']['params']['net']['ipv6']['conf']['default']['router_solicitations'] = 0 79 | default['sysctl']['params']['net']['ipv6']['conf']['default']['accept_ra_rtr_pref'] = 0 80 | default['sysctl']['params']['net']['ipv6']['conf']['default']['accept_ra_pinfo'] = 0 81 | default['sysctl']['params']['net']['ipv6']['conf']['default']['accept_ra_defrtr'] = 0 82 | default['sysctl']['params']['net']['ipv6']['conf']['default']['autoconf'] = 0 83 | default['sysctl']['params']['net']['ipv6']['conf']['default']['dad_transmits'] = 0 84 | default['sysctl']['params']['net']['ipv6']['conf']['default']['max_addresses'] = 1 85 | 86 | # Disable acceptance of router advertisements 87 | # 88 | # * **0** - do not accept router advertisements 89 | # * **1** - accept router advertisements if forwarding is disabled 90 | # * **2** - accept router advertisements even if forwarding is enabled 91 | default['sysctl']['params']['net']['ipv6']['conf']['all']['accept_ra'] = 0 92 | default['sysctl']['params']['net']['ipv6']['conf']['default']['accept_ra'] = 0 93 | 94 | # ExecShield protection against buffer overflows 95 | case node['platform_family'] 96 | when 'rhel', 'fedora' 97 | # on Oracle Linux with UEK it is not available; this helps address UEK on Oracle Linux 6 98 | is_oracle_uek = (node['platform'] == 'oracle' && node['kernel']['release'] =~ /^4\..*uek/) 99 | 100 | # on RHEL 7 its enabled per default and can't be disabled 101 | if node['platform_version'].to_f < 7 && !is_oracle_uek 102 | default['sysctl']['params']['kernel']['exec-shield'] = 1 103 | end 104 | end 105 | 106 | # Virtual memory regions protection 107 | default['sysctl']['params']['kernel']['randomize_va_space'] = 2 108 | -------------------------------------------------------------------------------- /chefignore: -------------------------------------------------------------------------------- 1 | # Put files/directories that should be ignored in this file when uploading 2 | # to a chef-server or supermarket. 3 | # Lines that start with '# ' are comments. 4 | 5 | # OS generated files # 6 | ###################### 7 | .DS_Store 8 | Icon? 9 | nohup.out 10 | ehthumbs.db 11 | Thumbs.db 12 | 13 | # SASS # 14 | ######## 15 | .sass-cache 16 | 17 | # EDITORS # 18 | ########### 19 | \#* 20 | .#* 21 | *~ 22 | *.sw[a-z] 23 | *.bak 24 | REVISION 25 | TAGS* 26 | tmtags 27 | *_flymake.* 28 | *_flymake 29 | *.tmproj 30 | .project 31 | .settings 32 | mkmf.log 33 | 34 | ## COMPILED ## 35 | ############## 36 | a.out 37 | *.o 38 | *.pyc 39 | *.so 40 | *.com 41 | *.class 42 | *.dll 43 | *.exe 44 | */rdoc/ 45 | 46 | # Testing # 47 | ########### 48 | .watchr 49 | .rspec 50 | spec/* 51 | spec/fixtures/* 52 | test/* 53 | features/* 54 | examples/* 55 | Guardfile 56 | Procfile 57 | .kitchen* 58 | kitchen.yml* 59 | .rubocop.yml 60 | spec/* 61 | Rakefile 62 | .travis.yml 63 | .foodcritic 64 | .codeclimate.yml 65 | 66 | # SCM # 67 | ####### 68 | .git 69 | */.git 70 | .gitignore 71 | .gitmodules 72 | .gitconfig 73 | .gitattributes 74 | .svn 75 | */.bzr/* 76 | */.hg/* 77 | */.svn/* 78 | 79 | # Berkshelf # 80 | ############# 81 | Berksfile 82 | Berksfile.lock 83 | cookbooks/* 84 | tmp 85 | 86 | # Bundler # 87 | ########### 88 | vendor/* 89 | 90 | # Policyfile # 91 | ############## 92 | Policyfile.rb 93 | Policyfile.lock.json 94 | 95 | # Cookbooks # 96 | ############# 97 | CONTRIBUTING* 98 | CHANGELOG* 99 | TESTING* 100 | 101 | # Vagrant # 102 | ########### 103 | .vagrant 104 | Vagrantfile 105 | 106 | # Others # 107 | ########## 108 | .github/* 109 | coverage/* 110 | Gemfile 111 | Gemfile.lock 112 | chefignore 113 | .envrc 114 | -------------------------------------------------------------------------------- /libraries/apt_package_extras.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Library:: apt_package_extras 6 | # 7 | # Copyright 2008, Chef Software, Inc. 8 | # Copyright 2015, Hardening Framework Team 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | class Chef 24 | class Recipe 25 | class AptPackageExtras 26 | def self.virtual_package?(package_name) 27 | # This functionality is based on that in the apt package provider 28 | # See https://github.com/chef/chef/blob/master/lib/chef/provider/package/apt.rb 29 | # The provider functionality isn't easily exposed for consumption in other recipes 30 | 31 | policy = Mixlib::ShellOut.new("apt-cache policy '#{package_name}'") 32 | policy.run_command 33 | policy.error! 34 | 35 | policy.stdout.each_line do |line| 36 | case line 37 | when /^\s{2}Candidate: (.+)$/ 38 | candidate_version = Regexp.last_match[1] 39 | if candidate_version == '(none)' 40 | # This may not be an appropriate assumption, but is the same as that used by the apt package provider 41 | Chef::Log.info("#{package_name} is a virtual package, no candidate version.") 42 | return true 43 | else 44 | Chef::Log.info("#{package_name} is not a virtual package, candidate version is #{candidate_version}.") 45 | return false 46 | end 47 | end 48 | end 49 | end 50 | 51 | def self.get_providing_packages(package_name) 52 | # This functionality is based on that in the apt package provider 53 | # See https://github.com/chef/chef/blob/master/lib/chef/provider/package/apt.rb 54 | # The provider functionality isn't easily exposed for consumption in other recipes 55 | 56 | unless virtual_package?(package_name) 57 | raise "#{package_name} is not a virtual package, cannot remove providing packages." 58 | end 59 | 60 | showpkg = Mixlib::ShellOut.new("apt-cache showpkg '#{package_name}'") 61 | showpkg.run_command 62 | showpkg.error! 63 | 64 | providers = {} 65 | 66 | # Disable rubocop warning to get a build 67 | showpkg.stdout.rpartition(/Reverse Provides: ?#{$/}/)[2].each_line do |line| # rubocop:disable Style/SpecialGlobalVars 68 | provider, version = line.split 69 | providers[provider] = version 70 | Chef::Log.info("Package #{provider} #{version} provides virtual package #{package_name}") 71 | end 72 | 73 | if providers.length <= 0 74 | Chef::Log.warn("There are no providing packages for virtual package #{package_name}.") 75 | end 76 | 77 | providers.keys 78 | end 79 | end 80 | end 81 | end 82 | -------------------------------------------------------------------------------- /libraries/cookbook_version.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Library:: cookbook_version 6 | # 7 | # Copyright 2014, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | class Chef 24 | class Recipe 25 | def cookbook_version(cookbook_name, version_contraint) 26 | cb = run_context.cookbook_collection[cookbook_name] 27 | raise "Can't find cookbook #{cookbook_name}! Can't determine its version." if cb.nil? 28 | 29 | v = cb.metadata.version 30 | Chef::VersionConstraint::Platform.new(version_contraint).include?(v) 31 | end 32 | end 33 | end 34 | -------------------------------------------------------------------------------- /libraries/gpgcheck.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Library:: gpgcheck 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | class Chef 24 | class Recipe 25 | class GPGCheck 26 | def self.check(file) 27 | pattern = /gpgcheck\s*=\s*0/ 28 | 29 | return unless File.file?(file) 30 | 31 | File.open(file) do |f| 32 | f.each_line do |line| 33 | next unless pattern.match(line) 34 | 35 | Chef::Log.warn file + ': gpgcheck=1 not properly configured' 36 | end 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /libraries/helpers_param.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Library:: gpgcheck 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | module SysctlCookbook 24 | module SysctlHelpers 25 | module Param 26 | def coerce_attributes(attr, out = nil) 27 | case attr 28 | when Array 29 | "#{out}=#{attr.join(' ')}" 30 | when String, Integer 31 | "#{out}=#{attr}" 32 | when Hash 33 | out += '.' unless out.nil? 34 | attr.map { |k, v| coerce_attributes(v, "#{out}#{k}") }.flatten.sort 35 | end 36 | end 37 | end 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /libraries/suid_sgid.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name:: os-hardening 5 | # Library:: suid_sgid 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | class Chef 24 | class Recipe 25 | class SuidSgid 26 | def self.remove_suid_sgid_from(file) 27 | unless File.exist?(file) 28 | Chef::Log.info "suid_sgid: Couldn't find file '#{file}'" 29 | return 30 | end 31 | 32 | chmod = Mixlib::ShellOut.new("chmod -s '#{file}'") 33 | chmod.run_command 34 | chmod.error! 35 | end 36 | 37 | def self.find_all_suid_sgid_files(start_at = '/') 38 | # "find / -xdev \( -perm -4000 -o -perm -2000 \) -type f -print 2>/dev/null" 39 | # don't limit to one filesystem, go nuts recursively: (ie without -xdev) 40 | findcmd = "find #{start_at} -path /proc -prune -o \\( -perm -4000 -o -perm -2000 \\) -type f -print 2>/dev/null" 41 | Chef::Log.info "suid_sgid: findcmd #{findcmd}" 42 | find = Mixlib::ShellOut.new(findcmd) 43 | find.run_command 44 | find.error! 45 | find.stdout.split("\n") 46 | end 47 | 48 | def self.remove_suid_sgid_from_blacklist(blacklist) 49 | blacklist. 50 | select { |file| File.exist?(file) }. 51 | each do |file| 52 | Chef::Log.info "suid_sgid: Blacklist SUID/SGID for '#{file}', removing bit..." 53 | remove_suid_sgid_from(file) 54 | end 55 | end 56 | 57 | def self.remove_suid_sgid_from_unknown(whitelist = [], root = '/', dry_run = false) 58 | all_suid_sgid_files = find_all_suid_sgid_files(root).reject do |file| 59 | in_whitelist = whitelist.include?(file) 60 | Chef::Log.info "suid_sgid: Whitelisted file '#{file}', not altering SUID/SGID bit" if in_whitelist && !dry_run 61 | in_whitelist 62 | end 63 | 64 | all_suid_sgid_files.each do |file| 65 | Chef::Log.info "suid_sgid: SUID/SGID on '#{file}'" + dry_run ? ' (dry_run)' : ', removing bit...' 66 | remove_suid_sgid_from(file) unless dry_run 67 | end 68 | end 69 | end 70 | end 71 | end 72 | -------------------------------------------------------------------------------- /metadata.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | name 'os-hardening' 20 | maintainer 'Artem Sidorenko' 21 | maintainer_email 'artem@posteo.de' 22 | license 'Apache-2.0' 23 | description 'Installs and configures operating system hardening' 24 | long_description IO.read(File.join(File.dirname(__FILE__), 'README.md')) 25 | version '4.2.0' 26 | source_url 'https://github.com/dev-sec/chef-os-hardening' 27 | issues_url 'https://github.com/dev-sec/chef-os-hardening/issues' 28 | 29 | chef_version '>= 14' 30 | 31 | supports 'amazon' 32 | supports 'ubuntu', '>= 16.04' 33 | supports 'debian', '>= 9.0' 34 | supports 'centos', '>= 6.0' 35 | supports 'redhat', '>= 6.0' 36 | supports 'oracle', '>= 6.4' 37 | supports 'fedora', '>= 28.0' 38 | supports 'suse' 39 | supports 'opensuseleap', '>= 42.1' 40 | 41 | recipe 'os-hardening::default', 'harden the operating system (all recipes)' 42 | recipe 'os-hardening::limits', 'prevent core dumps' 43 | recipe 'os-hardening::login_defs', 'harden /etc/login.defs' 44 | recipe 'os-hardening::minimize_access', 'enforce minimal file permissions' 45 | recipe 'os-hardening::pam', 'configure sane values for PAM' 46 | recipe 'os-hardening::profile', 'harden settings in /etc/profile.d' 47 | recipe 'os-hardening::securetty', 'limit the allowed TTYs for root login' 48 | recipe 'os-hardening::suid_sgid', 'reduce SUID and SGID bits in the filesystem' 49 | recipe 'os-hardening::sysctl', 'set sane sysctl values' 50 | -------------------------------------------------------------------------------- /recipes/apt.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: apt.rb 6 | # 7 | # Copyright 2015, Hardening Framework Team 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # apt-get and aptitude check package signatures by default. 23 | # TODO: could check apt.conf to make sure this hasn't been disabled. 24 | 25 | if node['os-hardening']['security']['packages']['clean'] 26 | # remove packages and handle virtual packages correctly. 27 | # this is the same package list as used for the redhat distro family 28 | node['os-hardening']['security']['packages']['list'].each do |pkg| 29 | if !AptPackageExtras.virtual_package?(pkg) 30 | package pkg do 31 | action :purge 32 | end 33 | else 34 | AptPackageExtras.get_providing_packages(pkg).each do |provider| 35 | package provider do 36 | action :purge 37 | end 38 | end 39 | end 40 | end 41 | end 42 | -------------------------------------------------------------------------------- /recipes/auditd.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: auditd.rb 6 | # 7 | # Copyright 2017, Artem Sidorenko 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | package node['os-hardening']['packages']['auditd'] 23 | 24 | service 'auditd' do 25 | supports %i[start stop restart reload status] 26 | if (node['platform_family'] == 'rhel' && node['platform_version'].to_f >= 7) || 27 | (node['platform_family'] == 'fedora' && node['platform_version'].to_f >= 27) || 28 | (node['platform_family'] == 'amazon' && node['platform_version'].to_f >= 2) 29 | restart_command 'service auditd restart' 30 | end 31 | action [:enable] 32 | end 33 | 34 | unless node['os-hardening']['auditd']['flush'].match(/^INCREMENTAL|INCREMENTAL_ASYNC$/) || 35 | node['os-hardening']['auditd']['flush'].empty? 36 | Chef::Log.fatal('If specifying a value for auditd flush parameter, must be one of INCREMENTAL or INCREMENTAL_ASYNC') 37 | raise 38 | end 39 | 40 | template '/etc/audit/auditd.conf' do 41 | source 'auditd.conf.erb' 42 | mode '0400' 43 | owner 'root' 44 | group 'root' 45 | variables( 46 | log_file: node['os-hardening']['auditd']['log_file'], 47 | log_format: node['os-hardening']['auditd']['log_format'], 48 | max_log_file_action: node['os-hardening']['auditd']['max_log_file_action'], 49 | space_left: node['os-hardening']['auditd']['space_left'], 50 | action_mail_acct: node['os-hardening']['auditd']['action_mail_acct'], 51 | space_left_action: node['os-hardening']['auditd']['space_left_action'], 52 | admin_space_left: node['os-hardening']['auditd']['admin_space_left'], 53 | admin_space_left_action: node['os-hardening']['auditd']['admin_space_left_action'], 54 | disk_full_action: node['os-hardening']['auditd']['disk_full_action'], 55 | disk_error_action: node['os-hardening']['auditd']['disk_error_action'], 56 | flush: node['os-hardening']['auditd']['flush'], 57 | log_group: node['os-hardening']['auditd']['log_group'], 58 | priority_boost: node['os-hardening']['auditd']['priority_boost'], 59 | freq: node['os-hardening']['auditd']['freq'], 60 | num_logs: node['os-hardening']['auditd']['num_logs'], 61 | disp_qos: node['os-hardening']['auditd']['disp_qos'], 62 | dispatcher: node['os-hardening']['auditd']['dispatcher'], 63 | name_format: node['os-hardening']['auditd']['name_format'], 64 | max_log_file: node['os-hardening']['auditd']['max_log_file'], 65 | tcp_listen_queue: node['os-hardening']['auditd']['tcp_listen_queue'], 66 | tcp_max_per_addr: node['os-hardening']['auditd']['tcp_max_per_addr'], 67 | tcp_client_max_idle: node['os-hardening']['auditd']['tcp_client_max_idle'], 68 | enable_krb5: node['os-hardening']['auditd']['enable_krb5'], 69 | krb5_principal: node['os-hardening']['auditd']['krb5_principal'] 70 | ) 71 | notifies :restart, 'service[auditd]' 72 | action :create 73 | end 74 | -------------------------------------------------------------------------------- /recipes/default.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: default 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | # here we try to determine which components should be included. 24 | # You can control the behaviour via setting the node['os-hardening']['components'][recipe_name] 25 | # to true (to include it) or to false (to skip it) on the override level, e.g. 26 | # 27 | # override['os-hardening']['components']['sysctl'] = false 28 | # 29 | 30 | node.default['os-hardening']['components']['suid_sgid'] = node['os-hardening']['security']['suid_sgid']['enforce'] 31 | 32 | # components which are not suitable for containers 33 | unless node['virtualization']['system'] =~ /^(lxc|docker)$/ && node['virtualization']['role'] == 'guest' 34 | node.default['os-hardening']['components']['sysctl'] = true 35 | node.default['os-hardening']['components']['auditd'] = true 36 | 37 | # selinux should be included only on RH based systems 38 | node.default['os-hardening']['components']['selinux'] = 39 | node['platform_family'] == 'rhel' || node['platform_family'] == 'fedora' 40 | end 41 | 42 | # include all required components 43 | node['os-hardening']['components'].each do |component, state| 44 | include_recipe "#{cookbook_name}::#{component}" if state 45 | end 46 | -------------------------------------------------------------------------------- /recipes/limits.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: limits.rb 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | directory '/etc/security/limits.d' do 23 | owner 'root' 24 | group 'root' 25 | mode '0755' 26 | recursive true 27 | end 28 | 29 | template '/etc/security/limits.d/10.hardcore.conf' do 30 | source 'limits.conf.erb' 31 | mode '0440' 32 | owner 'root' 33 | group 'root' 34 | action :delete if node['os-hardening']['security']['kernel']['enable_core_dump'] 35 | end 36 | -------------------------------------------------------------------------------- /recipes/login_defs.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: login_defs.rb 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | template '/etc/login.defs' do 23 | source 'login.defs.erb' 24 | cookbook node['os-hardening']['auth']['login_defs']['template_cookbook'] 25 | mode '0444' 26 | owner 'root' 27 | group 'root' 28 | variables( 29 | additional_user_paths: node['os-hardening']['env']['extra_user_paths'].join(':'), # :/usr/local/games:/usr/games 30 | umask: node['os-hardening']['env']['umask'], 31 | password_max_age: node['os-hardening']['auth']['pw_max_age'], 32 | password_min_age: node['os-hardening']['auth']['pw_min_age'], 33 | password_warn_age: node['os-hardening']['auth']['pw_warn_age'], 34 | login_retries: node['os-hardening']['auth']['retries'], 35 | login_timeout: node['os-hardening']['auth']['timeout'], 36 | chfn_restrict: '', # "rwh" 37 | allow_login_without_home: node['os-hardening']['auth']['allow_homeless'], 38 | uid_min: node['os-hardening']['auth']['uid_min'], 39 | uid_max: node['os-hardening']['auth']['uid_max'], 40 | gid_min: node['os-hardening']['auth']['gid_min'], 41 | gid_max: node['os-hardening']['auth']['gid_max'], 42 | sys_uid_min: node['os-hardening']['auth']['sys_uid_min'], 43 | sys_uid_max: node['os-hardening']['auth']['sys_uid_max'], 44 | sys_gid_min: node['os-hardening']['auth']['sys_gid_min'], 45 | sys_gid_max: node['os-hardening']['auth']['sys_gid_max'], 46 | mail_dir: node['os-hardening']['auth']['maildir'] 47 | ) 48 | end 49 | -------------------------------------------------------------------------------- /recipes/minimize_access.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: minimize_access 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # remove write permissions from path folders ($PATH) for all regular users 23 | # this prevents changing any system-wide command from normal users 24 | paths = %w[/usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin] + node['os-hardening']['env']['extra_user_paths'] 25 | paths.each do |folder| 26 | execute "remove write permission from #{folder}" do 27 | command "chmod go-w -R #{folder}" 28 | not_if "find #{folder} -perm -go+w -type f | wc -l | egrep '^0$'" 29 | end 30 | end 31 | 32 | # limit access to shadow. On debian family group shadow should be able to read it 33 | # (otherwise screensavers might break etc) 34 | file '/etc/shadow' do 35 | owner 'root' 36 | case node['platform_family'] 37 | when 'rhel', 'fedora', 'amazon' 38 | group 'root' 39 | mode '0000' 40 | when 'debian' 41 | group 'shadow' 42 | mode '0640' 43 | else 44 | group 'root' 45 | mode '0600' 46 | end 47 | end 48 | 49 | # su must only be accessible to user and group root 50 | file '/bin/su' do 51 | owner 'root' 52 | group 'root' 53 | mode '0750' 54 | manage_symlink_source true 55 | not_if { node['os-hardening']['security']['users']['allow'].include?('change_user') } 56 | end 57 | 58 | # /var/log should restricted to root or syslog on ubuntu systems 59 | directory '/var/log' do 60 | owner 'root' 61 | # ubuntu with containers does not have rsyslog installed and syslog group does not exist 62 | if node['platform'] == 'ubuntu' && node['packages']['rsyslog'] 63 | group 'syslog' 64 | else 65 | group 'root' 66 | end 67 | end 68 | 69 | # Cron files and folders should not be readable or writable by groups or others 70 | file '/etc/crontab' do 71 | mode '0600' 72 | only_if { ::File.exist?('/etc/crontab') } 73 | end 74 | 75 | cron_directories = %w[/etc/cron.hourly /etc/cron.daily /etc/cron.weekly /etc/cron.monthly /etc/cron.d] 76 | cron_directories.each do |cron_path| 77 | next unless ::Dir.exist?(cron_path) 78 | 79 | directory cron_path.to_s do 80 | mode '0700' 81 | end 82 | end 83 | -------------------------------------------------------------------------------- /recipes/packages.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: packages.rb 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # do package config for ubuntu 23 | case node['platform_family'] 24 | when 'debian' 25 | include_recipe('os-hardening::apt') 26 | end 27 | 28 | # do package config for rhel-family 29 | case node['platform_family'] 30 | when 'rhel', 'fedora', 'amazon' 31 | include_recipe('os-hardening::yum') 32 | end 33 | -------------------------------------------------------------------------------- /recipes/pam.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: pam.rb 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | # remove ccreds if not necessary 24 | package 'pam-ccreds' do 25 | package_name node['os-hardening']['packages']['pam_ccreds'] 26 | action :remove 27 | end 28 | 29 | case node['platform_family'] 30 | # do pam config for ubuntu 31 | when 'debian' 32 | 33 | passwdqc_path = '/usr/share/pam-configs/passwdqc' 34 | tally2_path = '/usr/share/pam-configs/tally2' 35 | 36 | # See NSA 2.3.3.1.2 37 | if node['os-hardening']['auth']['pam']['passwdqc']['enable'] 38 | 39 | # remove pam_cracklib, because it does not play nice with passwdqc 40 | package 'pam-cracklib' do 41 | package_name node['os-hardening']['packages']['pam_cracklib'] 42 | action :remove 43 | end 44 | 45 | # get the package for strong password checking 46 | package 'pam-passwdqc' do 47 | package_name node['os-hardening']['packages']['pam_passwdqc'] 48 | end 49 | 50 | # configure passwdqc via central module: 51 | template passwdqc_path do 52 | source 'pam_passwdqc.erb' 53 | cookbook node['os-hardening']['auth']['pam']['passwdqc']['template_cookbook'] 54 | mode '0640' 55 | owner 'root' 56 | group 'root' 57 | end 58 | 59 | # deactivate passwdqc 60 | else 61 | 62 | # delete passwdqc file on ubuntu and debian 63 | file passwdqc_path do 64 | action :delete 65 | end 66 | 67 | # make sure the package is not on the system, 68 | # if this feature is not wanted 69 | package 'pam-passwdqc' do 70 | package_name node['os-hardening']['packages']['pam_passwdqc'] 71 | action :remove 72 | end 73 | end 74 | 75 | # configure tally2 76 | if node['os-hardening']['auth']['retries'].positive? 77 | # tally2 is needed for pam 78 | package 'libpam-modules' 79 | 80 | template tally2_path do 81 | source 'pam_tally2.erb' 82 | cookbook node['os-hardening']['auth']['pam']['tally2']['template_cookbook'] 83 | mode '0640' 84 | owner 'root' 85 | group 'root' 86 | end 87 | else 88 | 89 | file tally2_path do 90 | action :delete 91 | end 92 | end 93 | 94 | execute 'update-pam' do 95 | command '/usr/sbin/pam-auth-update --package' 96 | end 97 | 98 | # do config for rhel-family 99 | when 'rhel', 'fedora' 100 | 101 | # we do not allow to use authconfig, because it does not use the /etc/sysconfig/authconfig as a basis 102 | # therefore we edit /etc/pam.d/system-auth-ac/ 103 | # @see http://serverfault.com/questions/292406/puppet-configuration-using-augeas-fails-if-combined-with-notify 104 | 105 | if node['platform_version'].to_f < 7 106 | # remove pam_cracklib, because it does not play nice with passwdqc in versions less than 7 107 | package 'pam-cracklib' do 108 | package_name node['os-hardening']['packages']['pam_cracklib'] 109 | action node['os-hardening']['auth']['pam']['passwdqc']['enable'] ? :remove : :nothing 110 | end 111 | 112 | package 'pam-passwdqc' do 113 | package_name node['os-hardening']['packages']['pam_passwdqc'] 114 | action node['os-hardening']['auth']['pam']['passwdqc']['enable'] ? :install : :remove 115 | end 116 | else 117 | # In RH-family distros > 7, 'pam_pwquality' obsoletes both pam_cracklib and pam_passwdqc 118 | # See https://linux.web.cern.ch/linux/rhel/releasenotes/RELEASE-NOTES-7.0-x86_64/ 119 | package 'pam_pwquality' do 120 | package_name node['os-hardening']['packages']['pam_pwquality'] 121 | end 122 | end 123 | 124 | # configure passwdqc and tally via central system-auth confic: 125 | template '/etc/pam.d/system-auth-ac' do 126 | source 'rhel_system_auth.erb' 127 | cookbook node['os-hardening']['auth']['pam']['system-auth']['template_cookbook'] 128 | mode '0640' 129 | owner 'root' 130 | group 'root' 131 | end 132 | 133 | # NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512 134 | template '/etc/libuser.conf' do 135 | source 'rhel_libuser.conf.erb' 136 | mode '0640' 137 | owner 'root' 138 | group 'root' 139 | end 140 | end 141 | -------------------------------------------------------------------------------- /recipes/profile.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: profile.rb 6 | # 7 | # Copyright 2013, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | template '/etc/profile.d/pinerolo_profile.sh' do 23 | source 'profile.conf.erb' 24 | mode '0755' 25 | owner 'root' 26 | group 'root' 27 | action :delete if node['os-hardening']['security']['kernel']['enable_core_dump'] 28 | end 29 | -------------------------------------------------------------------------------- /recipes/securetty.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: securetty 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | # See NSA 2.3.1.1 Restrict Root Logins to System Console 24 | template '/etc/securetty' do 25 | source 'securetty.erb' 26 | mode '0400' 27 | owner 'root' 28 | group 'root' 29 | variables( 30 | ttys: node['os-hardening']['auth']['root_ttys'].join("\n") 31 | ) 32 | end 33 | -------------------------------------------------------------------------------- /recipes/selinux.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: selinux.rv 6 | # 7 | # Copyright 2017, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # SELinux enforcing support 23 | 24 | case node['platform_family'] 25 | when 'rhel', 'fedora', 'amazon' 26 | unless node['os-hardening']['security']['selinux_mode'] == 'unmanaged' 27 | semode = case node['os-hardening']['security']['selinux_mode'] 28 | when 'enforcing' 29 | 'Enforcing' 30 | when 'permissive' 31 | 'Permissive' 32 | else 33 | raise "Unsupported selinuxmode #{node['os-hardening']['security']['selinux_mode']}" 34 | end 35 | 36 | execute "Set selinux mode to #{semode}" do 37 | command "setenforce #{semode}" 38 | not_if "getenforce | grep -F #{semode}" 39 | end 40 | 41 | template '/etc/selinux/config' do 42 | source 'rhel_selinuxconfig.erb' 43 | mode '0644' 44 | owner 'root' 45 | group 'root' 46 | variables selinux_mode: node['os-hardening']['security']['selinux_mode'] 47 | end 48 | end 49 | else 50 | raise "Selinux recipe is not supported on the platform family #{node['platform_family']}" 51 | end 52 | -------------------------------------------------------------------------------- /recipes/suid_sgid.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: suid_sgid 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | # make user-defined blacklist/whitelist override our default lists 24 | sb = node['os-hardening']['security']['suid_sgid']['system_blacklist'] 25 | sw = node['os-hardening']['security']['suid_sgid']['system_whitelist'] 26 | b = node['os-hardening']['security']['suid_sgid']['blacklist'] 27 | w = node['os-hardening']['security']['suid_sgid']['whitelist'] 28 | 29 | blacklist = (sb - w + b).uniq 30 | whitelist = (sw - b + w).uniq 31 | 32 | # root = "/" 33 | dry_run = node['os-hardening']['security']['suid_sgid']['dry_run_on_unknown'] 34 | root = node['os-hardening']['env']['root_path'] 35 | 36 | # walk the blacklist and remove suid and sgid bits from these items 37 | ruby_block 'remove_suid_from_blacklists' do 38 | block do 39 | SuidSgid.remove_suid_sgid_from_blacklist(blacklist) 40 | end 41 | end 42 | 43 | # remove suid bits from unknown, if desired 44 | ruby_block 'remove_suid_from_unknown' do 45 | block do 46 | SuidSgid.remove_suid_sgid_from_unknown(whitelist, root, dry_run) 47 | end 48 | only_if do 49 | node['os-hardening']['security']['suid_sgid']['remove_from_unknown'] || 50 | node['os-hardening']['security']['suid_sgid']['dry_run_on_unknown'] 51 | end 52 | end 53 | -------------------------------------------------------------------------------- /recipes/sysctl.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: sysctl 6 | # 7 | # Copyright 2012, Dominik Richter 8 | # Copyright 2014, Deutsche Telekom AG 9 | # 10 | # Licensed under the Apache License, Version 2.0 (the "License"); 11 | # you may not use this file except in compliance with the License. 12 | # You may obtain a copy of the License at 13 | # 14 | # http://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License. 21 | # 22 | 23 | ::Chef::Recipe.send(:include, SysctlCookbook::SysctlHelpers::Param) 24 | 25 | # cleanup of old sysctl related configurations. This can be removed at some point in the future 26 | # https://github.com/dev-sec/chef-os-hardening/issues/166#issuecomment-322433264 27 | # https://github.com/sous-chefs/sysctl/pull/61/files#diff-25e5d4a4446ae12a0d6f1162b6160375 28 | old_sysctl_conf_file = '/etc/sysctl.conf' 29 | if platform_family?('arch', 'debian', 'rhel', 'fedora', 'amazon', 'suse') 30 | old_sysctl_conf_file = if platform_family?('suse') && node['platform_version'].to_f < 12.0 31 | '/etc/sysctl.conf' 32 | else 33 | '/etc/sysctl.d/99-chef-attributes.conf' 34 | end 35 | end 36 | 37 | file 'cleanup of old sysctl settings' do 38 | path old_sysctl_conf_file 39 | action :delete 40 | end 41 | 42 | # default attributes 43 | # We can not set this kind of defaults in the attribute files 44 | # as we react on value of other attributes 45 | # https://github.com/dev-sec/chef-ssh-hardening/issues/140#issuecomment-267779720 46 | 47 | # Only enable IP traffic forwarding, if required. 48 | node.default['sysctl']['params']['net']['ipv4']['ip_forward'] = 49 | node['os-hardening']['network']['forwarding'] ? 1 : 0 50 | node.default['sysctl']['params']['net']['ipv6']['conf']['all']['forwarding'] = 51 | node['os-hardening']['network']['ipv6']['enable'] && node['os-hardening']['network']['forwarding'] ? 1 : 0 52 | 53 | # Disable or Enable IPv6 as it is needed. 54 | node.default['sysctl']['params']['net']['ipv6']['conf']['all']['disable_ipv6'] = 55 | node['os-hardening']['network']['ipv6']['enable'] ? 0 : 1 56 | 57 | # Define different modes for sending replies in response to received ARP requests that resolve local target IP addresses: 58 | # 59 | # * **0** - (default): reply for any local target IP address, configured on 60 | # any interface 61 | # * **1** - reply only if the target IP address is local address configured 62 | # on the incoming interface 63 | # * **2** - reply only if the target IP address is local address configured 64 | # on the incoming interface and both with the sender's IP address are 65 | # part from same subnet on this interface 66 | # * **3** - do not reply for local addresses configured with scope host, only 67 | # resolutions for global and link addresses are replied 68 | # * **4-7** - reserved 69 | # * **8** - do not reply for all local addresses 70 | node.default['sysctl']['params']['net']['ipv4']['conf']['all']['arp_ignore'] = 71 | node['os-hardening']['network']['arp']['restricted'] ? 1 : 0 72 | 73 | # Define different restriction levels for announcing the local source IP 74 | # address from IP packets in ARP requests sent on interface: 75 | # 76 | # * **0** - (default) Use any local address, configured on any interface 77 | # * **1** - Try to avoid local addresses that are not in the target's subnet 78 | # for this interface. This mode is useful when target hosts reachable 79 | # via this interface require the source IP address in ARP requests to 80 | # be part of their logical network configured on the receiving 81 | # interface. When we generate the request we will check all our 82 | # subnets that include the target IP and will preserve the source 83 | # address if it is from such subnet. If there is no such subnet we 84 | # select source address according to the rules for level 2. 85 | # * **2** - Always use the best local address for this target. In this mode 86 | # we ignore the source address in the IP packet and try to select 87 | # local address that we prefer for talks with the target host. Such 88 | # local address is selected by looking for primary IP addresses on 89 | # all our subnets on the outgoing interface that include the target 90 | # IP address. If no suitable local address is found we select the 91 | # first local address we have on the outgoing interface or on all 92 | # other interfaces, with the hope we will receive reply for our 93 | # request and even sometimes no matter the source IP address we 94 | # announce. 95 | # 96 | node.default['sysctl']['params']['net']['ipv4']['conf']['all']['arp_announce'] = 97 | node['os-hardening']['network']['arp']['restricted'] ? 2 : 0 98 | 99 | # This setting controls how the kernel behaves towards module changes at 100 | # runtime. Setting to 1 will disable module loading at runtime. 101 | # Setting it to 0 is actually never supported. 102 | unless node['os-hardening']['security']['kernel']['enable_module_loading'] 103 | node.default['sysctl']['params']['kernel']['modules_disabled'] = 1 104 | end 105 | 106 | # Magic Sysrq should be disabled, but can also be set to a safe value if so 107 | # desired for physical machines. It can allow a safe reboot if the system hangs 108 | # and is a 'cleaner' alternative to hitting the reset button. 109 | # The following values are permitted: 110 | # 111 | # * **0** - disable sysrq 112 | # * **1** - enable sysrq completely 113 | # * **>1** - bitmask of enabled sysrq functions: 114 | # * **2** - control of console logging level 115 | # * **4** - control of keyboard (SAK, unraw) 116 | # * **8** - debugging dumps of processes etc. 117 | # * **16** - sync command 118 | # * **32** - remount read-only 119 | # * **64** - signalling of processes (term, kill, oom-kill) 120 | # * **128** - reboot/poweroff 121 | # * **256** - nicing of all RT tasks 122 | node.default['sysctl']['params']['kernel']['sysrq'] = 123 | node['os-hardening']['security']['kernel']['enable_sysrq'] ? node['os-hardening']['security']['kernel']['secure_sysrq'] : 0 124 | 125 | # Prevent core dumps with SUID. These are usually only needed by developers and 126 | # may contain sensitive information. 127 | node.default['sysctl']['params']['fs']['suid_dumpable'] = 128 | node['os-hardening']['security']['kernel']['enable_core_dump'] ? 2 : 0 129 | 130 | if node.attribute?('sysctl') && node['sysctl'].attribute?('params') 131 | coerce_attributes(node['sysctl']['params']).each do |x| 132 | k, v = x.split('=') 133 | sysctl k do 134 | value v 135 | end 136 | end 137 | end 138 | 139 | # try to determine the real cpu vendor 140 | begin 141 | cpu_vendor = node['cpu']['0']['vendor_id']. 142 | sub(/^.*GenuineIntel.*$/, 'intel'). 143 | sub(/^.*AuthenticAMD.*$/, 'amd') 144 | node.default['os-hardening']['security']['cpu_vendor'] = cpu_vendor 145 | rescue # rubocop:disable Style/RescueStandardError 146 | log 'WARNING: Could not properly determine the cpu vendor. Fallback to intel cpu.' do 147 | level :warn 148 | end 149 | end 150 | 151 | # protect sysctl.conf 152 | file '/etc/sysctl.conf' do 153 | mode '0440' 154 | owner 'root' 155 | group 'root' 156 | end 157 | 158 | # NSA 2.2.4.1 Set Daemon umask 159 | # do config for rhel-family 160 | case node['platform_family'] 161 | when 'rhel', 'fedora', 'amazon' 162 | template '/etc/sysconfig/init' do 163 | source 'rhel_sysconfig_init.erb' 164 | mode '0544' 165 | owner 'root' 166 | group 'root' 167 | variables( 168 | prompt: node['os-hardening']['security']['init']['prompt'], 169 | single: node['os-hardening']['security']['init']['single'], 170 | umask: node['os-hardening']['security']['init']['daemon_umask'] 171 | ) 172 | end 173 | end 174 | 175 | # do initramfs config for ubuntu and debian 176 | case node['platform_family'] 177 | when 'debian' 178 | 179 | # rebuild initramfs with starting pack of modules, 180 | # if module loading at runtime is disabled 181 | unless node['os-hardening']['security']['kernel']['enable_module_loading'] 182 | template '/etc/initramfs-tools/modules' do 183 | source 'modules.erb' 184 | mode '0440' 185 | owner 'root' 186 | group 'root' 187 | variables( 188 | x86_64: !(node['kernel']['machine'] =~ /x86_64/).nil?, 189 | cpuVendor: node['os-hardening']['security']['cpu_vendor'] 190 | ) 191 | end 192 | 193 | execute 'update-initramfs' do 194 | command 'update-initramfs -u' 195 | action :run 196 | end 197 | end 198 | end 199 | 200 | # CIS requirement: disable unused filesystems 201 | if node['os-hardening']['security']['kernel']['disable_filesystems'].empty? 202 | file '/etc/modprobe.d/dev-sec.conf' do 203 | action :delete 204 | end 205 | else 206 | template '/etc/modprobe.d/dev-sec.conf' do 207 | source 'filesystem_blacklisting.erb' 208 | mode '0440' 209 | owner 'root' 210 | group 'root' 211 | variables filesystems: node['os-hardening']['security']['kernel']['disable_filesystems'] 212 | end 213 | end 214 | -------------------------------------------------------------------------------- /recipes/yum.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Cookbook Name: os-hardening 5 | # Recipe: pack_yum.rb 6 | # 7 | # Copyright 2014, Deutsche Telekom AG 8 | # 9 | # Licensed under the Apache License, Version 2.0 (the "License"); 10 | # you may not use this file except in compliance with the License. 11 | # You may obtain a copy of the License at 12 | # 13 | # http://www.apache.org/licenses/LICENSE-2.0 14 | # 15 | # Unless required by applicable law or agreed to in writing, software 16 | # distributed under the License is distributed on an "AS IS" BASIS, 17 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | # See the License for the specific language governing permissions and 19 | # limitations under the License. 20 | # 21 | 22 | # NSA chapter: NSA 2.1.2.3.3 23 | # verify package signatures 24 | # search /etc/yum.conf gpgcheck=1 25 | ruby_block 'check package signature in repo files' do 26 | block do 27 | # TODO: harmonize with latter function 28 | config_file = '/etc/yum.conf' 29 | GPGCheck.check(config_file) 30 | 31 | Dir.glob('/etc/yum.repos.d/*').each do |file| 32 | GPGCheck.check(file) 33 | end 34 | 35 | rhn_conf = '/etc/yum/pluginconf.d/rhnplugin.conf' 36 | File.file?(rhn_conf) do 37 | GPGCheck.check(rhn_conf) 38 | end 39 | end 40 | action :run 41 | end 42 | 43 | if node['os-hardening']['security']['packages']['clean'] 44 | 45 | # remove unused repos 46 | %w[CentOS-Debuginfo CentOS-Media CentOS-Vault].each do |repo| 47 | yum_repository repo do 48 | action :remove 49 | end 50 | end 51 | 52 | # remove packages 53 | node['os-hardening']['security']['packages']['list'].each do |pkg| 54 | package pkg do 55 | action :purge 56 | end 57 | end 58 | 59 | end 60 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": [ 4 | "config:base", 5 | ":gitSignOff" 6 | ], 7 | "dependencyDashboard": true, 8 | "dependencyDashboardAutoclose": true, 9 | "packageRules": [ 10 | { 11 | "matchUpdateTypes": ["patch", "minor"], 12 | "automerge": true 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /spec/recipes/auditd_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2017, Artem Sidorenko 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::auditd' do 20 | cached(:chef_run) do 21 | ChefSpec::SoloRunner.new.converge(described_recipe) 22 | end 23 | 24 | subject { chef_run } 25 | 26 | it 'should install auditd' do 27 | is_expected.to install_package('auditd') 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/recipes/default_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::default' do 20 | # converge 21 | cached(:chef_run) do 22 | ChefSpec::ServerRunner.new do |node| 23 | # sysctl/attributes/default.rb will set the config dir 24 | # on rhel and debian, but apply requires it for notification 25 | # therefore we set it manually here 26 | node.normal['sysctl']['conf_dir'] = '/etc/sysctl.d' 27 | node.normal['cpu']['0']['vendor_id'] = 'GenuineIntel' 28 | node.normal['env']['extra_user_paths'] = [] 29 | 30 | paths = %w[ 31 | /usr/local/sbin /usr/local/bin /usr/sbin /usr/bin /sbin /bin 32 | ] + node['env']['extra_user_paths'] 33 | paths.each do |folder| 34 | stub_command( 35 | "find #{folder} -perm -go+w -type f | wc -l | egrep '^0$'" 36 | ).and_return(false) 37 | end 38 | end.converge(described_recipe) 39 | end 40 | 41 | subject { chef_run } 42 | 43 | # check that the recipes are executed 44 | it 'default should include os-hardening recipes by default' do 45 | is_expected.to include_recipe 'os-hardening::packages' 46 | is_expected.to include_recipe 'os-hardening::limits' 47 | is_expected.to include_recipe 'os-hardening::login_defs' 48 | is_expected.to include_recipe 'os-hardening::minimize_access' 49 | is_expected.to include_recipe 'os-hardening::pam' 50 | is_expected.to include_recipe 'os-hardening::profile' 51 | is_expected.to include_recipe 'os-hardening::securetty' 52 | is_expected.to include_recipe 'os-hardening::sysctl' 53 | is_expected.to include_recipe 'os-hardening::auditd' 54 | end 55 | end 56 | -------------------------------------------------------------------------------- /spec/recipes/limits_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::limits' do 20 | cached(:chef_run) do 21 | ChefSpec::ServerRunner.new.converge(described_recipe) 22 | end 23 | 24 | subject { chef_run } 25 | 26 | it 'creates /etc/security/limits.d directory' do 27 | is_expected.to create_directory('/etc/security/limits.d').with( 28 | user: 'root', 29 | group: 'root', 30 | mode: '0755', 31 | recursive: true 32 | ) 33 | end 34 | 35 | describe 'core dump setting' do 36 | let(:enable_core_dump) { nil } 37 | let(:chef_run) do 38 | ChefSpec::ServerRunner.new do |node| 39 | node.override['os-hardening']['security']['kernel']['enable_core_dump'] = enable_core_dump if enable_core_dump # rubocop:disable Metrics/LineLength 40 | end.converge(described_recipe) 41 | end 42 | 43 | context 'enable_core_dump has its default value' do 44 | it 'should create the settings file' do 45 | is_expected.to create_template( 46 | '/etc/security/limits.d/10.hardcore.conf' 47 | ).with( 48 | user: 'root', 49 | group: 'root', 50 | mode: '0440' 51 | ) 52 | end 53 | end 54 | 55 | context 'enable_core_dump is disabled' do 56 | let(:enable_core_dump) { false } 57 | 58 | it 'should create the settings file' do 59 | is_expected.to create_template( 60 | '/etc/security/limits.d/10.hardcore.conf' 61 | ).with( 62 | user: 'root', 63 | group: 'root', 64 | mode: '0440' 65 | ) 66 | end 67 | end 68 | 69 | context 'enable_core_dump is enabled' do 70 | let(:enable_core_dump) { true } 71 | 72 | it 'should remove the settings file' do 73 | is_expected.to delete_template( 74 | '/etc/security/limits.d/10.hardcore.conf' 75 | ) 76 | end 77 | end 78 | end 79 | end 80 | -------------------------------------------------------------------------------- /spec/recipes/login_defs_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::login_defs' do 20 | cached(:chef_run) do 21 | ChefSpec::ServerRunner.new do |node| 22 | node.normal['os-hardening']['auth']['uid_min'] = 5000 23 | node.normal['os-hardening']['auth']['uid_max'] = 6000 24 | node.normal['os-hardening']['auth']['gid_min'] = 5000 25 | node.normal['os-hardening']['auth']['gid_max'] = 6000 26 | end.converge(described_recipe) 27 | end 28 | 29 | subject { chef_run } 30 | 31 | it 'creates /etc/login.defs' do 32 | is_expected.to create_template('/etc/login.defs').with( 33 | source: 'login.defs.erb', 34 | mode: '0444', 35 | owner: 'root', 36 | group: 'root', 37 | variables: { 38 | additional_user_paths: '', 39 | umask: '027', 40 | password_max_age: 60, 41 | password_min_age: 7, 42 | password_warn_age: 7, 43 | login_retries: 5, 44 | login_timeout: 60, 45 | chfn_restrict: '', 46 | allow_login_without_home: false, 47 | uid_min: 5000, 48 | uid_max: 6000, 49 | gid_min: 5000, 50 | gid_max: 6000, 51 | sys_uid_min: 100, 52 | sys_uid_max: 999, 53 | sys_gid_min: 100, 54 | sys_gid_max: 999, 55 | mail_dir: '/var/mail' 56 | } 57 | ) 58 | end 59 | 60 | it 'uses uid_min and gid_min in /etc/login.defs' do 61 | is_expected.to render_file('/etc/login.defs'). 62 | with_content(/^PASS_WARN_AGE\s+7$/). 63 | with_content(/^UID_MIN\s+5000$/). 64 | with_content(/^UID_MAX\s+6000$/). 65 | with_content(/^GID_MIN\s+5000$/). 66 | with_content(/^GID_MAX\s+6000$/) 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /spec/recipes/minimize_access_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::minimize_access' do 20 | before do 21 | stub_command( 22 | "find /usr/local/sbin -perm -go+w -type f | wc -l | egrep '^0$'" 23 | ).and_return(false) 24 | stub_command( 25 | "find /usr/local/bin -perm -go+w -type f | wc -l | egrep '^0$'" 26 | ).and_return(false) 27 | stub_command( 28 | "find /usr/sbin -perm -go+w -type f | wc -l | egrep '^0$'" 29 | ).and_return(false) 30 | stub_command( 31 | "find /usr/bin -perm -go+w -type f | wc -l | egrep '^0$'" 32 | ).and_return(false) 33 | stub_command( 34 | "find /sbin -perm -go+w -type f | wc -l | egrep '^0$'" 35 | ).and_return(false) 36 | stub_command( 37 | "find /bin -perm -go+w -type f | wc -l | egrep '^0$'" 38 | ).and_return(false) 39 | end 40 | 41 | cached(:chef_run) do 42 | ChefSpec::ServerRunner.new.converge(described_recipe) 43 | end 44 | 45 | subject { chef_run } 46 | 47 | it 'remove write permission from /usr/local/sbin' do 48 | is_expected.to run_execute( 49 | 'remove write permission from /usr/local/sbin' 50 | ).with(command: 'chmod go-w -R /usr/local/sbin') 51 | end 52 | 53 | it 'remove write permission from /usr/local/bin' do 54 | is_expected.to run_execute( 55 | 'remove write permission from /usr/local/bin' 56 | ).with(command: 'chmod go-w -R /usr/local/bin') 57 | end 58 | 59 | it 'remove write permission from /usr/sbin' do 60 | is_expected.to run_execute('remove write permission from /usr/sbin').with( 61 | command: 'chmod go-w -R /usr/sbin' 62 | ) 63 | end 64 | 65 | it 'remove write permission from /usr/bin' do 66 | is_expected.to run_execute('remove write permission from /usr/bin').with( 67 | command: 'chmod go-w -R /usr/bin' 68 | ) 69 | end 70 | 71 | it 'remove write permission from /sbin' do 72 | is_expected.to run_execute('remove write permission from /sbin').with( 73 | command: 'chmod go-w -R /sbin' 74 | ) 75 | end 76 | 77 | it 'remove write permission from /bin' do 78 | is_expected.to run_execute('remove write permission from /bin').with( 79 | command: 'chmod go-w -R /bin' 80 | ) 81 | end 82 | 83 | it 'creates /etc/shadow' do 84 | is_expected.to create_file('/etc/shadow').with( 85 | user: 'root', 86 | group: 'shadow', 87 | mode: '0640' 88 | ) 89 | end 90 | 91 | it 'creates /etc/su' do 92 | is_expected.to create_file('/bin/su').with( 93 | user: 'root', 94 | group: 'root', 95 | mode: '0750' 96 | ) 97 | end 98 | end 99 | -------------------------------------------------------------------------------- /spec/recipes/pam_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::pam' do 20 | cached(:chef_run) do 21 | ChefSpec::ServerRunner.new.converge(described_recipe) 22 | end 23 | 24 | subject { chef_run } 25 | 26 | it 'remove pam-ccreds' do 27 | is_expected.to remove_package('pam-ccreds') 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/recipes/profile_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::profile' do 20 | let(:enable_core_dump) { nil } 21 | let(:chef_run) do 22 | ChefSpec::ServerRunner.new do |node| 23 | node.override['os-hardening']['security']['kernel']['enable_core_dump'] = enable_core_dump if enable_core_dump # rubocop:disable Metrics/LineLength 24 | end.converge(described_recipe) 25 | end 26 | 27 | subject { chef_run } 28 | 29 | context 'enable_core_dump has its default value' do 30 | it 'create /etc/profile.d/pinerolo_profile.sh' do 31 | is_expected.to create_template('/etc/profile.d/pinerolo_profile.sh').with( 32 | source: 'profile.conf.erb', 33 | mode: '0755', 34 | owner: 'root', 35 | group: 'root' 36 | ) 37 | end 38 | end 39 | 40 | context 'enable_core_dump is disabled' do 41 | let(:enable_core_dump) { false } 42 | 43 | it 'create /etc/profile.d/pinerolo_profile.sh' do 44 | is_expected.to create_template('/etc/profile.d/pinerolo_profile.sh').with( 45 | source: 'profile.conf.erb', 46 | mode: '0755', 47 | owner: 'root', 48 | group: 'root' 49 | ) 50 | end 51 | end 52 | 53 | context 'enable_core_dump is enabled' do 54 | let(:enable_core_dump) { true } 55 | 56 | it 'should remove the settings file' do 57 | is_expected.to delete_template( 58 | '/etc/profile.d/pinerolo_profile.sh' 59 | ) 60 | end 61 | end 62 | end 63 | -------------------------------------------------------------------------------- /spec/recipes/securetty_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::securetty' do 20 | cached(:chef_run) do 21 | ChefSpec::ServerRunner.new.converge(described_recipe) 22 | end 23 | 24 | subject { chef_run } 25 | 26 | it 'creates /etc/securetty' do 27 | is_expected.to create_template('/etc/securetty').with( 28 | source: 'securetty.erb', 29 | user: 'root', 30 | group: 'root', 31 | mode: '0400', 32 | variables: { 33 | ttys: "console\ntty1\ntty2\ntty3\ntty4\ntty5\ntty6" 34 | } 35 | ) 36 | end 37 | end 38 | -------------------------------------------------------------------------------- /spec/recipes/suid_sgid_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::suid_sgid' do 20 | cached(:chef_run) do 21 | ChefSpec::ServerRunner.new.converge(described_recipe) 22 | end 23 | 24 | subject { chef_run } 25 | 26 | it 'run remove_suid_from_blacklists ruby_block' do 27 | is_expected.to run_ruby_block('remove_suid_from_blacklists') 28 | end 29 | end 30 | -------------------------------------------------------------------------------- /spec/recipes/sysctl_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | describe 'os-hardening::sysctl' do 20 | context 'intel' do 21 | cached(:intel_run) do 22 | ChefSpec::ServerRunner.new do |node| 23 | node.normal['sysctl']['conf_dir'] = '/etc/sysctl.d' 24 | node.normal['cpu']['0']['vendor_id'] = 'GenuineIntel' 25 | end.converge(described_recipe) 26 | end 27 | 28 | describe 'attributes' do 29 | subject { intel_run.node['os-hardening']['security']['cpu_vendor'] } 30 | 31 | it 'should detect intel cpu' do 32 | is_expected.to eq('intel') 33 | end 34 | end 35 | 36 | describe 'chef run' do 37 | subject { intel_run } 38 | 39 | it 'creates /etc/sysctl.conf' do 40 | is_expected.to create_file('/etc/sysctl.conf').with( 41 | user: 'root', 42 | group: 'root', 43 | mode: '0440' 44 | ) 45 | end 46 | 47 | it 'not write log for cpu_vendor fallback' do 48 | is_expected.to_not write_log( 49 | 'WARNING: Could not properly determine the cpu vendor. Fallback to ' \ 50 | 'intel cpu.' 51 | ).with( 52 | level: :warn 53 | ) 54 | end 55 | end 56 | end 57 | 58 | context 'amd' do 59 | cached(:amd_run) do 60 | ChefSpec::ServerRunner.new do |node| 61 | node.normal['sysctl']['conf_dir'] = '/etc/sysctl.d' 62 | node.normal['cpu']['0']['vendor_id'] = 'AuthenticAMD' 63 | end.converge(described_recipe) 64 | end 65 | 66 | describe 'attributes' do 67 | subject { amd_run.node['os-hardening']['security']['cpu_vendor'] } 68 | 69 | it 'should detect amd cpu' do 70 | is_expected.to eq('amd') 71 | end 72 | end 73 | 74 | describe 'chef run' do 75 | subject { amd_run } 76 | 77 | it 'creates /etc/sysctl.conf' do 78 | is_expected.to create_file('/etc/sysctl.conf').with( 79 | user: 'root', 80 | group: 'root', 81 | mode: '0440' 82 | ) 83 | end 84 | 85 | it 'not write log for cpu_vendor fallback' do 86 | is_expected.to_not write_log( 87 | 'WARNING: Could not properly determine the cpu vendor. Fallback to ' \ 88 | 'intel cpu.' 89 | ).with( 90 | level: :warn 91 | ) 92 | end 93 | end 94 | end 95 | 96 | context 'fallback' do 97 | cached(:fallback_run) do 98 | ChefSpec::ServerRunner.new do |node| 99 | node.normal['sysctl']['conf_dir'] = '/etc/sysctl.d' 100 | end.converge(described_recipe) 101 | end 102 | 103 | describe 'attributes' do 104 | subject { fallback_run.node['os-hardening']['security']['cpu_vendor'] } 105 | 106 | it 'should detect intel cpu' do 107 | is_expected.to eq('intel') 108 | end 109 | end 110 | 111 | describe 'chef run' do 112 | subject { fallback_run } 113 | 114 | it 'creates /etc/sysctl.conf' do 115 | is_expected.to create_file('/etc/sysctl.conf').with( 116 | user: 'root', 117 | group: 'root', 118 | mode: '0440' 119 | ) 120 | end 121 | 122 | it 'not write log for cpu_vendor fallback' do 123 | is_expected.to write_log( 124 | 'WARNING: Could not properly determine the cpu vendor. Fallback to ' \ 125 | 'intel cpu.' 126 | ).with( 127 | level: :warn 128 | ) 129 | end 130 | end 131 | end 132 | 133 | describe 'sysctl flags' do 134 | let(:ipv6_enable) { false } 135 | let(:network_forwarding) { false } 136 | let(:arp_restricted) { true } 137 | let(:enable_module_loading) { true } 138 | let(:enable_sysrq) { true } 139 | let(:enable_core_dump) { true } 140 | let(:chef_run) do 141 | ChefSpec::SoloRunner.new do |node| 142 | node.normal['os-hardening']['network']['forwarding'] = 143 | network_forwarding 144 | node.normal['os-hardening']['network']['ipv6']['enable'] = ipv6_enable 145 | node.normal['os-hardening']['network']['arp']['restricted'] = 146 | arp_restricted 147 | node.normal['os-hardening']['security']['kernel']['enable_module_loading'] = # rubocop:disable Metrics/LineLength 148 | enable_module_loading 149 | node.normal['os-hardening']['security']['kernel']['enable_sysrq'] = 150 | enable_sysrq 151 | node.normal['os-hardening']['security']['kernel']['enable_core_dump'] = 152 | enable_core_dump 153 | end.converge(described_recipe) 154 | end 155 | 156 | describe 'IPv4 forwarding' do 157 | context 'when forwarding is enabled' do 158 | let(:network_forwarding) { true } 159 | 160 | it 'should enable IPv4 forwarding in sysctl attributes' do 161 | expect(chef_run).to apply_sysctl('net.ipv4.ip_forward').with( 162 | value: '1' 163 | ) 164 | end 165 | end 166 | 167 | context 'when forwarding is disabled' do 168 | let(:network_forwarding) { false } 169 | 170 | it 'should disable IPv4 forwarding in sysctl attributes' do 171 | expect(chef_run).to apply_sysctl('net.ipv4.ip_forward').with( 172 | value: '0' 173 | ) 174 | end 175 | end 176 | end 177 | 178 | describe 'IPv6 forwarding' do 179 | RSpec.shared_examples 'IPv6 forwarding in sysctl attributes' do |state| 180 | it "should #{state == 1 ? 'enable' : 'disable'} IPv6 forwarding in sysctl attributes" do # rubocop:disable Metrics/LineLength 181 | expect(chef_run).to apply_sysctl('net.ipv6.conf.all.forwarding').with( 182 | value: state.to_s 183 | ) 184 | end 185 | end 186 | 187 | context 'when IPv6 is enabled' do 188 | let(:ipv6_enable) { true } 189 | 190 | context 'when forwarding is enabled' do 191 | let(:network_forwarding) { true } 192 | 193 | include_examples 'IPv6 forwarding in sysctl attributes', 1 194 | end 195 | context 'when forwarding is disabled' do 196 | let(:network_forwarding) { false } 197 | 198 | include_examples 'IPv6 forwarding in sysctl attributes', 0 199 | end 200 | end 201 | 202 | context 'when IPv6 is disabled' do 203 | let(:ipv6_enable) { false } 204 | 205 | context 'when forwarding is enabled' do 206 | let(:network_forwarding) { true } 207 | 208 | include_examples 'IPv6 forwarding in sysctl attributes', 0 209 | end 210 | 211 | context 'when forwarding is disabled' do 212 | let(:network_forwarding) { false } 213 | 214 | include_examples 'IPv6 forwarding in sysctl attributes', 0 215 | end 216 | end 217 | end 218 | 219 | describe 'Control IPv6' do 220 | context 'when IPv6 is enabled' do 221 | let(:ipv6_enable) { true } 222 | 223 | it 'should not disable IPv6' do 224 | expect(chef_run).to apply_sysctl('net.ipv4.ip_forward').with( 225 | value: '0' 226 | ) 227 | end 228 | end 229 | 230 | context 'when IPv6 is disabled' do 231 | let(:ipv6_enable) { false } 232 | 233 | it 'should not disable IPv6' do 234 | expect(chef_run).to apply_sysctl('net.ipv6.conf.all.forwarding').with( 235 | value: '0' 236 | ) 237 | end 238 | end 239 | end 240 | 241 | describe 'ARP restrictions' do 242 | RSpec.shared_examples 'ARP restrictions in sysctl attributes' do |arp_ignore, arp_announce| # rubocop:disable Metrics/LineLength 243 | describe 'arp_ignore' do 244 | it "should be set to #{arp_ignore}" do 245 | expect(chef_run).to apply_sysctl('net.ipv4.conf.all.arp_ignore').with( 246 | value: arp_ignore.to_s 247 | ) 248 | end 249 | end 250 | 251 | describe 'arp_announce' do 252 | it "should be set to #{arp_announce}" do 253 | expect(chef_run).to apply_sysctl('net.ipv4.conf.all.arp_announce').with( 254 | value: arp_announce.to_s 255 | ) 256 | end 257 | end 258 | end 259 | 260 | context 'when ARP is restricted' do 261 | let(:arp_restricted) { true } 262 | 263 | include_examples 'ARP restrictions in sysctl attributes', 1, 2 264 | end 265 | 266 | context 'when ARP is not restricted' do 267 | let(:arp_restricted) { false } 268 | 269 | include_examples 'ARP restrictions in sysctl attributes', 0, 0 270 | end 271 | end 272 | 273 | describe 'Module loading' do 274 | context 'when module loading is enabled' do 275 | let(:enable_module_loading) { true } 276 | 277 | it 'should not set the sysctl flag' do 278 | expect(chef_run).to_not apply_sysctl('kernel.modules_disabled') 279 | end 280 | 281 | describe 'rebuild of initramfs' do 282 | subject { chef_run } 283 | 284 | it 'should not create initramfs module file' do 285 | is_expected.not_to create_template('/etc/initramfs-tools/modules') 286 | end 287 | 288 | it 'should not rebuild initramfs' do 289 | is_expected.not_to run_execute('update-initramfs') 290 | end 291 | end 292 | end 293 | 294 | context 'when module loading is disabled' do 295 | let(:enable_module_loading) { false } 296 | 297 | it 'should disable module loading via sysctl flag' do 298 | expect(chef_run).to apply_sysctl('kernel.modules_disabled').with( 299 | value: '1' 300 | ) 301 | end 302 | 303 | describe 'rebuild of initramfs' do 304 | subject { chef_run } 305 | 306 | it 'should create initramfs module file' do 307 | is_expected.to create_template('/etc/initramfs-tools/modules') 308 | end 309 | 310 | it 'should rebuild initramfs' do 311 | is_expected.to run_execute('update-initramfs') 312 | end 313 | end 314 | end 315 | end 316 | 317 | describe 'Control magic SysRq' do 318 | context 'when sysrq is enabled' do 319 | let(:enable_sysrq) { true } 320 | 321 | it 'should enable sysrq with safe value' do 322 | expect(chef_run).to apply_sysctl('kernel.sysrq').with( 323 | value: '244' 324 | ) 325 | end 326 | end 327 | 328 | context 'when sysrq is disabled' do 329 | let(:enable_sysrq) { false } 330 | 331 | it 'should disable sysrq' do 332 | expect(chef_run).to apply_sysctl('kernel.sysrq').with( 333 | value: '0' 334 | ) 335 | end 336 | end 337 | end 338 | 339 | describe 'Core dumps with SUID' do 340 | context 'when core dumps are enabled' do 341 | let(:enable_core_dump) { true } 342 | 343 | it 'should set suid_dumpable to safe value' do 344 | expect(chef_run).to apply_sysctl('fs.suid_dumpable').with( 345 | value: '2' 346 | ) 347 | end 348 | end 349 | 350 | context 'when core dumps are disabled' do 351 | let(:enable_core_dump) { false } 352 | 353 | it 'should set suid_dumpable to default value' do 354 | expect(chef_run).to apply_sysctl('fs.suid_dumpable').with( 355 | value: '0' 356 | ) 357 | end 358 | end 359 | end 360 | end 361 | 362 | describe 'filesystems' do 363 | let(:disable_filesystems) { nil } 364 | let(:chef_run) do 365 | ChefSpec::SoloRunner.new do |node| 366 | if disable_filesystems 367 | node.normal['os-hardening']['security']['kernel']['disable_filesystems'] = 368 | disable_filesystems 369 | end 370 | end.converge(described_recipe) 371 | end 372 | 373 | describe 'when unused filesystems are disabled with default values' do 374 | it 'should render the proper modprobe file' do 375 | %w[cramfs freevxfs jffs2 hfs hfsplus squashfs udf vfat].each do |fs| 376 | expect(chef_run).to render_file('/etc/modprobe.d/dev-sec.conf'). 377 | with_content("install #{fs} /bin/true") 378 | end 379 | end 380 | end 381 | 382 | describe 'when only some filesystems are disabled' do 383 | let(:disable_filesystems) { %w[vfat udf] } 384 | 385 | it 'should render the proper modprobe file' do 386 | %w[udf vfat].each do |fs| 387 | expect(chef_run).to render_file('/etc/modprobe.d/dev-sec.conf'). 388 | with_content("install #{fs} /bin/true") 389 | end 390 | 391 | expect(chef_run).not_to render_file('/etc/modprobe.d/dev-sec.conf'). 392 | with_content('install cramfs /bin/true') 393 | end 394 | end 395 | 396 | describe 'when unused filesystems are not disabled' do 397 | let(:disable_filesystems) { %w[] } 398 | 399 | it 'should delete the modprobe file' do 400 | expect(chef_run).to delete_file('/etc/modprobe.d/dev-sec.conf') 401 | end 402 | end 403 | end 404 | end 405 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # 4 | # Copyright 2014, Deutsche Telekom AG 5 | # 6 | # Licensed under the Apache License, Version 2.0 (the "License"); 7 | # you may not use this file except in compliance with the License. 8 | # You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | # 18 | 19 | require 'chefspec' 20 | require 'chefspec/berkshelf' 21 | 22 | RSpec.configure do |config| 23 | # OS and version for mocking of ohai data, needed by chefspec 24 | config.platform = 'ubuntu' 25 | config.version = '16.04' 26 | 27 | config.before(:each) do 28 | # we have to stub this, as its executed by the sysctl cookbook 29 | # dependency as native ruby code 30 | # see http://stackoverflow.com/questions/24270887/stub-file-open-in-chefspec 31 | allow(::File).to receive(:exist?).and_call_original 32 | allow(::File).to receive(:exist?).with('/etc/sysctl.conf').and_return false 33 | end 34 | end 35 | -------------------------------------------------------------------------------- /templates/default/auditd.conf.erb: -------------------------------------------------------------------------------- 1 | <% node['config_disclaimer'].to_s.split("\n").each do |l| %> 2 | # <%= l %> 3 | <% end %> 4 | # 5 | #-- 6 | 7 | # Specified by linux-baseline 8 | log_file = <%= @log_file %> 9 | log_format = <%= @log_format %> 10 | flush = <%= @flush %> 11 | max_log_file_action = <%= @max_log_file_action %> 12 | space_left = <%= @space_left %> 13 | action_mail_acct = <%= @action_mail_acct %> 14 | space_left_action = <%= @space_left_action %> 15 | admin_space_left = <%= @admin_space_left %> 16 | admin_space_left_action = <%= @admin_space_left_action %> 17 | disk_full_action = <%= @disk_full_action %> 18 | disk_error_action = <%= @disk_error_action %> 19 | 20 | # Unspecified, auditd defaults unless overwritten 21 | log_group = <%= @log_group %> 22 | priority_boost = <%= @priority_boost %> 23 | freq = <%= @freq %> 24 | num_logs = <%= @num_logs %> 25 | disp_qos = <%= @disp_qos %> 26 | dispatcher = <%= @dispatcher %> 27 | name_format = <%= @name_format %> 28 | max_log_file = <%= @max_log_file %> 29 | tcp_listen_queue = <%= @tcp_listen_queue %> 30 | tcp_max_per_addr = <%= @tcp_max_per_addr %> 31 | tcp_client_max_idle = <%= @tcp_client_max_idle %> 32 | enable_krb5 = <%= @enable_krb5 %> 33 | krb5_principal = <%= @krb5_principal %> 34 | -------------------------------------------------------------------------------- /templates/default/filesystem_blacklisting.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | <% @filesystems.each do |fs| %> 8 | install <%= fs %> /bin/true 9 | <% end %> 10 | -------------------------------------------------------------------------------- /templates/default/limits.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # Prevent core dumps for all users. These are usually only needed by developers and may contain sensitive information. 8 | * hard core 0 9 | -------------------------------------------------------------------------------- /templates/default/login.defs.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # Configuration control definitions for the login package. 8 | # 9 | # Three items must be defined: `MAIL_DIR`, `ENV_SUPATH`, and `ENV_PATH`. If unspecified, some arbitrary (and possibly incorrect) value will be assumed. All other items are optional - if not specified then the described action or option will be inhibited. 10 | # 11 | # Comment lines (lines beginning with `#`) and blank lines are ignored. 12 | # 13 | #-- Modified for Linux. --marekm 14 | 15 | # *REQUIRED for useradd/userdel/usermod* 16 | # 17 | # Directory where mailboxes reside, _or_ name of file, relative to the home directory. If you _do_ define `MAIL_DIR` and `MAIL_FILE`, `MAIL_DIR` takes precedence. 18 | # Essentially: 19 | # 20 | # * `MAIL_DIR` defines the location of users mail spool files (for mbox use) by appending the username to `MAIL_DIR` as defined below. 21 | # * `MAIL_FILE` defines the location of the users mail spool files as the fully-qualified filename obtained by prepending the user home directory before `$MAIL_FILE` 22 | # 23 | # *NOTE*: This is no more used for setting up users MAIL environment variable which is, starting from shadow 4.0.12-1 in Debian, entirely the job of the pam_mail PAM modules. 24 | # 25 | # See default PAM configuration files provided for login, su, etc. 26 | # This is a temporary situation: setting these variables will soon move to `/etc/default/useradd` and the variables will then be no more supported 27 | MAIL_DIR <%= @mail_dir %> 28 | #MAIL_FILE .mail 29 | 30 | # Enable logging and display of `/var/log/faillog` login failure info. This option conflicts with the `pam_tally` PAM module. 31 | FAILLOG_ENAB yes 32 | 33 | # Enable display of unknown usernames when login failures are recorded. 34 | # 35 | # *WARNING*: Unknown usernames may become world readable. See #290803 and #298773 for details about how this could become a security concern 36 | LOG_UNKFAIL_ENAB no 37 | 38 | # Enable logging of successful logins 39 | LOG_OK_LOGINS yes 40 | 41 | # Enable "syslog" logging of su activity - in addition to sulog file logging. 42 | SYSLOG_SU_ENAB yes 43 | 44 | # Enable "syslog" logging of newgrp and sg. 45 | SYSLOG_SG_ENAB yes 46 | 47 | # If defined, all su activity is logged to this file. 48 | #SULOG_FILE /var/log/sulog 49 | 50 | # If defined, file which maps tty line to `TERM` environment parameter. Each line of the file is in a format something like "vt100 tty01". 51 | #TTYTYPE_FILE /etc/ttytype 52 | 53 | # If defined, login failures will be logged here in a utmp format last, when invoked as lastb, will read `/var/log/btmp`, so... 54 | FTMP_FILE /var/log/btmp 55 | 56 | # If defined, the command name to display when running "su -". For # example, if this is defined as "su" then a "ps" will display the command is "-su". If not defined, then "ps" would display the name of the shell actually being run, e.g. something like "-sh". 57 | SU_NAME su 58 | 59 | # If defined, file which inhibits all the usual chatter during the login sequence. If a full pathname, then hushed mode will be enabled if the user's name or shell are found in the file. If not a full pathname, then hushed mode will be enabled if the file exists in the user's home directory. 60 | #HUSHLOGIN_FILE /etc/hushlogins 61 | HUSHLOGIN_FILE .hushlogin 62 | 63 | # *REQUIRED*: The default PATH settings, for superuser and normal users. (they are minimal, add the rest in the shell startup files) 64 | ENV_SUPATH PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin 65 | ENV_PATH PATH=/usr/local/bin:/usr/bin:/bin<% if not @additional_user_paths.empty? %><%= @additional_user_paths %><% end %> 66 | 67 | # Terminal permissions 68 | # -------------------- 69 | 70 | # Login tty will be assigned this group ownership. 71 | # If you have a "write" program which is "setgid" to a special group which owns the terminals, define `TTYGROUP` to the group number and `TTYPERM` to `0620`. Otherwise leave `TTYGROUP` commented out and assign `TTYPERM` to either `622` or `600`. 72 | TTYGROUP tty 73 | 74 | # Login tty will be set to this permission. 75 | # In Debian `/usr/bin/bsd-write` or similar programs are setgid tty. However, the default and recommended value for `TTYPERM` is still `0600` to not allow anyone to write to anyone else console or terminal 76 | # Users can still allow other people to write them by issuing the `mesg y` command. 77 | TTYPERM 0600 78 | 79 | # Login conf initializations 80 | # -------------------------- 81 | 82 | # Terminal ERASE character ('\010' = backspace). Only used on System V. 83 | ERASECHAR 0177 84 | 85 | # Terminal KILL character ('\025' = CTRL/U). Only used on System V. 86 | KILLCHAR 025 87 | 88 | # The default umask value for `pam_umask` and is used by useradd and newusers to set the mode of the new home directories. 89 | # If `USERGROUPS_ENAB` is set to `yes`, that will modify this `UMASK` default value for private user groups, i. e. the uid is the same as gid, and username is the same as the primary group name: for these, the user permissions will be used as group permissions, e. g. `022` will become `002`. 90 | # Prefix these values with `0` to get octal, `0x` to get hexadecimal. 91 | # `022` is the "historical" value in Debian for UMASK 92 | # `027`, or even `077`, could be considered better for privacy. 93 | UMASK <%= @umask %> 94 | 95 | # Enable setting of the umask group bits to be the same as owner bits (examples: `022` -> `002`, `077` -> `007`) for non-root users, if the uid is the same as gid, and username is the same as the primary group name. 96 | # If set to yes, userdel will remove the user's group if it contains no more members, and useradd will create by default a group with the name of the user. 97 | USERGROUPS_ENAB yes 98 | 99 | 100 | # Password aging controls 101 | # ----------------------- 102 | 103 | # Maximum number of days a password may be used. 104 | PASS_MAX_DAYS <%= @password_max_age.to_s %> 105 | 106 | # Minimum number of days allowed between password changes. 107 | PASS_MIN_DAYS <%= @password_min_age.to_s %> 108 | 109 | # Number of days warning given before a password expires. 110 | PASS_WARN_AGE <%= @password_warn_age.to_s %> 111 | 112 | # Min/max values for automatic uid selection in useradd 113 | UID_MIN <%= @uid_min.to_s %> 114 | UID_MAX <%= @uid_max.to_s %> 115 | <% unless node['platform_family'] == 'rhel' and node['platform_version'].to_f < 6.0 %> 116 | # System accounts 117 | SYS_UID_MIN <%= @sys_uid_min.to_s %> 118 | SYS_UID_MAX <%= @sys_uid_max.to_s %> 119 | <% end %> 120 | 121 | # Min/max values for automatic gid selection in groupadd 122 | GID_MIN <%= @gid_min.to_s %> 123 | GID_MAX <%= @gid_max.to_s %> 124 | <% unless node['platform_family'] == 'rhel' and node['platform_version'].to_f < 6.0 %> 125 | # System accounts 126 | SYS_GID_MIN <%= @sys_gid_min.to_s %> 127 | SYS_GID_MAX <%= @sys_gid_max.to_s %> 128 | <% end %> 129 | 130 | # Max number of login retries if password is bad. This will most likely be overridden by PAM, since the default pam_unix module has it's own built in of 3 retries. However, this is a safe fallback in case you are using an authentication module that does not enforce PAM_MAXTRIES. 131 | LOGIN_RETRIES <%= @login_retries.to_s %> 132 | 133 | # Max time in seconds for login 134 | LOGIN_TIMEOUT <%= @login_timeout.to_s %> 135 | 136 | # Which fields may be changed by regular users using chfn - use any combination of letters "frwh" (full name, room number, work phone, home phone). If not defined, no changes are allowed. 137 | # For backward compatibility, "yes" = "rwh" and "no" = "frwh". 138 | <% if not @chfn_restrict.empty? %> 139 | CHFN_RESTRICT <%= @chfn_restrict %> 140 | <% end %> 141 | 142 | # Should login be allowed if we can't cd to the home directory? 143 | DEFAULT_HOME <%= @allow_login_without_home ? "yes" : "no" %> 144 | 145 | # If defined, this command is run when removing a user. 146 | # It should remove any at/cron/print jobs etc. owned by 147 | # the user to be removed (passed as the first argument). 148 | #USERDEL_CMD /usr/sbin/userdel_local 149 | 150 | # Instead of the real user shell, the program specified by this parameter will be launched, although its visible name (`argv[0]`) will be the shell's. The program may do whatever it wants (logging, additional authentication, banner, ...) before running the actual shell. 151 | #FAKE_SHELL /bin/fakeshell 152 | 153 | # If defined, either full pathname of a file containing device names or a ":" delimited list of device names. Root logins will be allowed only upon these devices. 154 | # This variable is used by login and su. 155 | #CONSOLE /etc/consoles 156 | #CONSOLE console:tty01:tty02:tty03:tty04 157 | 158 | # List of groups to add to the user's supplementary group set when logging in on the console (as determined by the `CONSOLE` setting). Default is none. 159 | # Use with caution - it is possible for users to gain permanent access to these groups, even when not logged in on the console. How to do it is left as an exercise for the reader... 160 | # This variable is used by login and su. 161 | #CONSOLE_GROUPS floppy:audio:cdrom 162 | 163 | # If set to `MD5`, MD5-based algorithm will be used for encrypting password 164 | # If set to `SHA256`, SHA256-based algorithm will be used for encrypting password 165 | # If set to `SHA512`, SHA512-based algorithm will be used for encrypting password 166 | # If set to `DES`, DES-based algorithm will be used for encrypting password (default) 167 | # Overrides the MD5_CRYPT_ENAB option 168 | # 169 | # Note: It is recommended to use a value consistent with 170 | # the PAM modules configuration. 171 | MD5_CRYPT_ENAB no 172 | ENCRYPT_METHOD SHA512 173 | 174 | # Only used if `ENCRYPT_METHOD` is set to `SHA256` or `SHA512`: Define the number of SHA rounds. 175 | # With a lot of rounds, it is more difficult to brute forcing the password. But note also that it more CPU resources will be needed to authenticate users. 176 | # If not specified, the libc will choose the default number of rounds (5000). The values must be inside the 1000-999999999 range. If only one of the MIN or MAX values is set, then this value will be used. 177 | # If MIN > MAX, the highest value will be used. 178 | #SHA_CRYPT_MIN_ROUNDS 5000 179 | #SHA_CRYPT_MAX_ROUNDS 5000 180 | 181 | 182 | # Obsoleted by PAM 183 | # ================ 184 | # These options are now handled by PAM. Please edit the appropriate file in `/etc/pam.d/` to enable the equivalents of them. 185 | #MOTD_FILE 186 | #DIALUPS_CHECK_ENAB 187 | #LASTLOG_ENAB 188 | #MAIL_CHECK_ENAB 189 | #OBSCURE_CHECKS_ENAB 190 | #PORTTIME_CHECKS_ENAB 191 | #SU_WHEEL_ONLY 192 | #CRACKLIB_DICTPATH 193 | #PASS_CHANGE_TRIES 194 | #PASS_ALWAYS_WARN 195 | #ENVIRON_FILE 196 | #NOLOGINS_FILE 197 | #ISSUE_FILE 198 | #PASS_MIN_LEN 199 | #PASS_MAX_LEN 200 | #ULIMIT 201 | #ENV_HZ 202 | #CHFN_AUTH 203 | #CHSH_AUTH 204 | #FAIL_DELAY 205 | 206 | # Obsoleted 207 | # ========= 208 | # These options are no more handled by shadow. 209 | # Shadow utilities will display a warning if they still appear. 210 | #CLOSE_SESSIONS 211 | #LOGIN_STRING 212 | #NO_PASSWORD_CONSOLE 213 | #QMAIL_DIR 214 | 215 | # If set to `yes`, new passwords will be encrypted using the MD5-based algorithm compatible with the one used by recent releases of FreeBSD. It supports passwords of unlimited length and longer salt strings. 216 | # Set to `no` if you need to copy encrypted passwords to other systems which don't understand the new algorithm. Default is `no`. 217 | # This variable is deprecated. You should use ENCRYPT_METHOD. 218 | # 219 | #MD5_CRYPT_ENAB no 220 | -------------------------------------------------------------------------------- /templates/default/modules.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # This file contains the names of kernel modules that should be loaded at boot time, one per line. Lines beginning with "#" are ignored. 8 | # 9 | # A list of all available kernel modules kann be found with `find /lib/modules/$(uname -r)/kernel/` 10 | # We will sort by folder. 11 | 12 | 13 | # Arch 14 | # ---- 15 | # 16 | # Modules for certains builds, contains support modules and some CPU-specific optimizations. 17 | 18 | <% if @x86_64 == true %> 19 | # Optimize for x86_64 cryptographic features 20 | twofish-x86_64-3way 21 | twofish-x86_64 22 | aes-x86_64 23 | salsa20-x86_64 24 | blowfish-x86_64 25 | <% end %> 26 | 27 | <% if @cpuVendor == "intel" %> 28 | # Intel-specific optimizations 29 | ghash-clmulni-intel 30 | aesni-intel 31 | kvm-intel 32 | <% end %> 33 | 34 | <% if @cpuVendor == "amd" %> 35 | # AMD-specific optimizations 36 | kvm-amd 37 | <% end %> 38 | 39 | kvm 40 | 41 | 42 | # Crypto 43 | # ------ 44 | 45 | # Some core modules which comprise strong cryptography. 46 | blowfish_common 47 | blowfish_generic 48 | ctr 49 | cts 50 | lrw 51 | lzo 52 | rmd160 53 | rmd256 54 | rmd320 55 | serpent 56 | sha512_generic 57 | twofish_common 58 | twofish_generic 59 | xts 60 | zlib 61 | 62 | 63 | # Drivers 64 | # ------- 65 | 66 | # Basics 67 | lp 68 | rtc 69 | loop 70 | 71 | # Filesystems 72 | ext2 73 | btrfs 74 | 75 | <% if @node['os-hardening']['desktop']['enable'] %> 76 | # Desktop 77 | psmouse 78 | snd 79 | snd_ac97_codec 80 | snd_intel8x0 81 | snd_page_alloc 82 | snd_pcm 83 | snd_timer 84 | soundcore 85 | usbhid 86 | <% end %> 87 | 88 | # Lib 89 | # --- 90 | xz 91 | 92 | 93 | # Net 94 | # --- 95 | 96 | # All packets needed for netfilter rules (ie iptables, ebtables). 97 | ip_tables 98 | x_tables 99 | iptable_filter 100 | iptable_nat 101 | 102 | # Targets 103 | ipt_LOG 104 | ipt_REJECT 105 | 106 | # Modules 107 | xt_connlimit 108 | xt_tcpudp 109 | xt_recent 110 | xt_limit 111 | xt_conntrack 112 | nf_conntrack 113 | nf_conntrack_ipv4 114 | nf_defrag_ipv4 115 | xt_state 116 | nf_nat 117 | 118 | # Addons 119 | xt_pknock 120 | -------------------------------------------------------------------------------- /templates/default/pam_passwdqc.erb: -------------------------------------------------------------------------------- 1 | Name: passwdqc password strength enforcement 2 | Default: yes 3 | Priority: 1024 4 | Conflicts: cracklib 5 | Password-Type: Primary 6 | Password: 7 | requisite pam_passwdqc.so <%= node['os-hardening']['auth']['pam']['passwdqc']['options'] %> 8 | -------------------------------------------------------------------------------- /templates/default/pam_tally2.erb: -------------------------------------------------------------------------------- 1 | Name: tally2 lockout after failed attempts enforcement 2 | Default: yes 3 | Priority: 1024 4 | Conflicts: cracklib 5 | Auth-Type: Primary 6 | Auth-Initial: 7 | required pam_tally2.so deny=<%= node['os-hardening']['auth']['retries'] %> onerr=fail unlock_time=<%= node['os-hardening']['auth']['lockout_time'] %> 8 | Account-Type: Primary 9 | Account-Initial: 10 | required pam_tally2.so 11 | -------------------------------------------------------------------------------- /templates/default/profile.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # Disable core dumps via soft limits for all users. Compliance to this setting is voluntary and can be modified by users up to a hard limit. This setting is a sane default. 8 | ulimit -S -c 0 > /dev/null 2>&1 9 | -------------------------------------------------------------------------------- /templates/default/rhel_libuser.conf.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | [import] 8 | # Data from these files is used when libuser.conf does not define a value. 9 | # The mapping is documented in the man page. 10 | login_defs = /etc/login.defs 11 | default_useradd = /etc/default/useradd 12 | 13 | [defaults] 14 | # The default (/usr/lib*/libuser) is usually correct 15 | # moduledir = /your/custom/directory 16 | 17 | # The following variables are usually imported: 18 | # skeleton = /etc/skel 19 | # mailspooldir = /var/mail 20 | 21 | # NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512 22 | crypt_style = sha512 23 | 24 | modules = files shadow 25 | create_modules = files shadow 26 | # modules = files shadow ldap 27 | # create_modules = ldap 28 | 29 | [userdefaults] 30 | LU_USERNAME = %n 31 | # LU_UIDNUMBER = 500 32 | LU_GIDNUMBER = %u 33 | # LU_USERPASSWORD = !! 34 | # LU_GECOS = %n 35 | # LU_HOMEDIRECTORY = /home/%n 36 | # LU_LOGINSHELL = /bin/bash 37 | 38 | # LU_SHADOWNAME = %n 39 | # LU_SHADOWPASSWORD = !! 40 | # LU_SHADOWLASTCHANGE = %d 41 | # LU_SHADOWMIN = 0 42 | # LU_SHADOWMAX = 99999 43 | # LU_SHADOWWARNING = 7 44 | # LU_SHADOWINACTIVE = -1 45 | # LU_SHADOWEXPIRE = -1 46 | # LU_SHADOWFLAG = -1 47 | 48 | [groupdefaults] 49 | LU_GROUPNAME = %n 50 | # LU_GIDNUMBER = 500 51 | # LU_GROUPPASSWORD = !! 52 | # LU_MEMBERUID = 53 | # LU_ADMINISTRATORUID = 54 | 55 | [files] 56 | # This is useful for the case where some master files are used to 57 | # populate a different NSS mechanism which this workstation uses. 58 | # directory = /etc 59 | 60 | [shadow] 61 | # This is useful for the case where some master files are used to 62 | # populate a different NSS mechanism which this workstation uses. 63 | # directory = /etc 64 | 65 | [ldap] 66 | # Setting these is always necessary. 67 | # server = ldap 68 | # basedn = dc=example,dc=com 69 | 70 | # Setting these is rarely necessary, since it's usually correct. 71 | # userBranch = ou=People 72 | # groupBranch = ou=Group 73 | 74 | # Set only if your administrative user uses simple bind operations to 75 | # connect to the server. 76 | # binddn = cn=Manager,dc=example,dc=com 77 | 78 | # Set this only if the default user (as determined by SASL) is incorrect 79 | # for SASL bind operations. Usually, it's correct, so you'll rarely need 80 | # to set these. 81 | # user = Manager 82 | # authuser = Manager 83 | 84 | [sasl] 85 | # Set these only if your sasldb is only used by a particular application, and 86 | # in a particular domain. The default (all applications, all domains) is 87 | # probably correct for most installations. 88 | # appname = imap 89 | # domain = EXAMPLE.COM 90 | -------------------------------------------------------------------------------- /templates/default/rhel_selinuxconfig.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # This file controls the state of SELinux on the system. 8 | # SELINUX= can take one of these three values: 9 | # enforcing - SELinux security policy is enforced. 10 | # permissive - SELinux prints warnings instead of enforcing. 11 | # disabled - No SELinux policy is loaded. 12 | SELINUX=<%= @selinux_mode %> 13 | # SELINUXTYPE= can take one of these three values: 14 | # targeted - Targeted processes are protected, 15 | # minimum - Modification of targeted policy. Only selected processes are protected. 16 | # mls - Multi Level Security protection. 17 | SELINUXTYPE=targeted 18 | -------------------------------------------------------------------------------- /templates/default/rhel_sysconfig_init.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # color => new RH6.0 bootup 8 | # verbose => old-style bootup 9 | # anything else => new style bootup without ANSI colors or positioning 10 | BOOTUP=color 11 | # column to start "[ OK ]" label in 12 | RES_COL=60 13 | # terminal sequence to move to that column. You could change this 14 | # to something like "tput hpa ${RES_COL}" if your terminal supports it 15 | MOVE_TO_COL="echo -en \\033[${RES_COL}G" 16 | # terminal sequence to set color to a 'success' color (currently: green) 17 | SETCOLOR_SUCCESS="echo -en \\033[0;32m" 18 | # terminal sequence to set color to a 'failure' color (currently: red) 19 | SETCOLOR_FAILURE="echo -en \\033[0;31m" 20 | # terminal sequence to set color to a 'warning' color (currently: yellow) 21 | SETCOLOR_WARNING="echo -en \\033[0;33m" 22 | # terminal sequence to reset to the default color. 23 | SETCOLOR_NORMAL="echo -en \\033[0;39m" 24 | # Set to anything other than 'no' to allow hotkey interactive startup... 25 | PROMPT=<%= @prompt ? 'yes' : 'no' %> 26 | # Set to 'yes' to allow probing for devices with swap signatures 27 | AUTOSWAP=no 28 | # What ttys should gettys be started on? 29 | ACTIVE_CONSOLES=/dev/tty[1-6] 30 | # Set to '/sbin/sulogin' to prompt for password on single-user mode 31 | # Set to '/sbin/sushell' otherwise 32 | SINGLE=<%= @single ? '/sbin/sulogin' : '/sbin/sushell' %> 33 | 34 | # NSA 2.2.4.1 Set Daemon umask 35 | umask <%= @umask %> 36 | -------------------------------------------------------------------------------- /templates/default/rhel_system_auth.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | #%PAM-1.0 8 | <% if node['os-hardening']['auth']['retries'] > 0 %> 9 | auth required pam_tally2.so deny=<%= node['os-hardening']['auth']['retries'] %> onerr=fail unlock_time=<%= node['os-hardening']['auth']['lockout_time'] %> 10 | <% end %> 11 | auth required pam_env.so 12 | auth sufficient pam_unix.so nullok try_first_pass 13 | auth requisite pam_succeed_if.so uid >= 500 quiet 14 | auth required pam_deny.so 15 | 16 | <% if node['os-hardening']['auth']['retries'] > 0 %> 17 | account required pam_tally2.so 18 | <% end %> 19 | account required pam_unix.so 20 | account sufficient pam_localuser.so 21 | account sufficient pam_succeed_if.so uid < 500 quiet 22 | account required pam_permit.so 23 | 24 | <% if node['os-hardening']['auth']['pam']['passwdqc']['enable'] %> 25 | password requisite pam_passwdqc.so <%= node['os-hardening']['auth']['pam']['passwdqc']['options'] %> 26 | <% elsif node['os-hardening']['auth']['pam']['pwquality']['enable'] %> 27 | password requisite pam_pwquality.so <%= node['os-hardening']['auth']['pam']['pwquality']['options'] %> 28 | <% else %> 29 | password requisite pam_cracklib.so <%= node['os-hardening']['auth']['pam']['cracklib']['options'] %> 30 | <% end %> 31 | 32 | # NSA 2.3.3.5 Upgrade Password Hashing Algorithm to SHA-512 33 | # NSA 2.3.3.6 Limit Password Reuse 34 | password sufficient pam_unix.so sha512 <%= node['os-hardening']['auth']['pam']['unix']['options'] %> 35 | password required pam_deny.so 36 | 37 | session optional pam_keyinit.so revoke 38 | session required pam_limits.so 39 | <% if node['os-hardening']['auth']['pam']['pam_systemd']['enable'] %> 40 | session optional pam_systemd.so 41 | <% end %> 42 | session [success=1 default=ignore] pam_succeed_if.so service in crond quiet use_uid 43 | session required pam_unix.so 44 | -------------------------------------------------------------------------------- /templates/default/securetty.erb: -------------------------------------------------------------------------------- 1 | # 2 | # This file is generated by Chef for <%= node['fqdn'] %> 3 | # 4 | # Local changes will be overwritten 5 | # 6 | 7 | # A list of TTYs, from which root can log in 8 | # see `man securetty` for reference 9 | <%= @ttys %> 10 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/metadata.rb: -------------------------------------------------------------------------------- 1 | name 'test' 2 | maintainer 'Artem Sidorenko' 3 | maintainer_email 'artem@posteo.de' 4 | license 'Apache-2.0' 5 | description 'Test preparation cookbook' 6 | long_description 'Test preparation cookbook' 7 | version '0.1.0' 8 | -------------------------------------------------------------------------------- /test/fixtures/cookbooks/test/recipes/default.rb: -------------------------------------------------------------------------------- 1 | # 2 | # Cookbook Name:: test 3 | # Recipe:: default 4 | # 5 | 6 | # We use this test cookbook to initialize the test environment 7 | 8 | if node['platform_family'] == 'debian' 9 | # Run apt-get update if we are on debian, some images/boxes do not have full package lists 10 | execute 'apt update' do 11 | command 'apt-get update' 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /test/integration/default/controls/tests.rb: -------------------------------------------------------------------------------- 1 | include_controls 'linux-baseline' do 2 | # TODO: check and align with following tests 3 | skip_control 'os-14' 4 | skip_control 'os-15' 5 | skip_control 'os-16' 6 | skip_control 'sysctl-21' 7 | skip_control 'sysctl-26' 8 | skip_control 'sysctl-34' 9 | # skip entropy test, as our short living test VMs usually do not 10 | # have enough 11 | skip_control 'os-08' 12 | # skip CPU vulnerability testing, in the DO VMs sometimes (ubuntu) kernel reports missing microcode 13 | skip_control 'os-12' 14 | end 15 | -------------------------------------------------------------------------------- /test/integration/default/inspec.yml: -------------------------------------------------------------------------------- 1 | name: os-hardening-integration-tests 2 | version: 1.0.0 3 | depends: 4 | - name: linux-baseline 5 | url: https://github.com/dev-sec/linux-baseline 6 | -------------------------------------------------------------------------------- /test/integration/selinux_enabled/controls/tests.rb: -------------------------------------------------------------------------------- 1 | include_controls 'os-hardening-integration-tests' 2 | 3 | control 'SELinux-01' do 4 | impact 1.0 5 | title 'Verify SELinux enforcing' 6 | desc 'Verify SELinux enforcing' 7 | 8 | describe file('/etc/selinux/config') do 9 | its('content') { should include 'SELINUX=enforcing' } 10 | end 11 | 12 | describe command('getenforce') do 13 | its('stdout') { should eq "Enforcing\n" } 14 | its('stderr') { should eq '' } 15 | end 16 | end 17 | -------------------------------------------------------------------------------- /test/integration/selinux_enabled/inspec.yml: -------------------------------------------------------------------------------- 1 | name: os-hardening-integration-tests-selinux 2 | version: 1.0.0 3 | depends: 4 | - name: os-hardening-integration-tests 5 | path: test/integration/default 6 | --------------------------------------------------------------------------------