diff --git a/.config/.secrets.baseline b/.config/.secrets.baseline deleted file mode 100644 index 65908eb9..00000000 --- a/.config/.secrets.baseline +++ /dev/null @@ -1,119 +0,0 @@ -{ - "version": "1.4.0", - "plugins_used": [ - { - "name": "ArtifactoryDetector" - }, - { - "name": "AWSKeyDetector" - }, - { - "name": "AzureStorageKeyDetector" - }, - { - "name": "Base64HighEntropyString", - "limit": 4.5 - }, - { - "name": "BasicAuthDetector" - }, - { - "name": "CloudantDetector" - }, - { - "name": "DiscordBotTokenDetector" - }, - { - "name": "GitHubTokenDetector" - }, - { - "name": "HexHighEntropyString", - "limit": 3.0 - }, - { - "name": "IbmCloudIamDetector" - }, - { - "name": "IbmCosHmacDetector" - }, - { - "name": "JwtTokenDetector" - }, - { - "name": "KeywordDetector", - "keyword_exclude": "" - }, - { - "name": "MailchimpDetector" - }, - { - "name": "NpmDetector" - }, - { - "name": "PrivateKeyDetector" - }, - { - "name": "SendGridDetector" - }, - { - "name": "SlackDetector" - }, - { - "name": "SoftlayerDetector" - }, - { - "name": "SquareOAuthDetector" - }, - { - "name": "StripeDetector" - }, - { - "name": "TwilioKeyDetector" - } - ], - "filters_used": [ - { - "path": "detect_secrets.filters.allowlist.is_line_allowlisted" - }, - { - "path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies", - "min_level": 2 - }, - { - "path": "detect_secrets.filters.heuristic.is_indirect_reference" - }, - { - "path": "detect_secrets.filters.heuristic.is_likely_id_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_lock_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_potential_uuid" - }, - { - "path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign" - }, - { - "path": "detect_secrets.filters.heuristic.is_sequential_string" - }, - { - "path": "detect_secrets.filters.heuristic.is_swagger_file" - }, - { - "path": "detect_secrets.filters.heuristic.is_templated_secret" - }, - { - "path": "detect_secrets.filters.regex.should_exclude_file", - "pattern": [ - ".config/.gitleaks-report.json", - "tasks/parse_etc_password.yml" - ] - } - ], - "results": {}, - "generated_at": "2023-09-25T16:05:28Z" -} diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 39af625a..07eae733 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -1,138 +1,159 @@ --- - name: Devel pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: ubuntu-latest - - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + name: Devel pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - devel + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + # Allow manual running of workflow + workflow_dispatch: + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This will create messages for first time contributers and direct them to the Discord server + welcome: + runs-on: self-hosted + + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} - - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION: "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git Clone the Lockdown Repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu Init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu Validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu Apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep - Allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run Ansible Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 8ded7018..08433d90 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -1,127 +1,156 @@ --- - name: Main pipeline - - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' - - # A workflow run is made up of one or more jobs - # that can run sequentially or in parallel - jobs: - - # This workflow contains a single job that tests the playbook - playbook-test: - # The type of runner that the job will run on - runs-on: ubuntu-latest - env: - ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} - # Imported as a variable by terraform - TF_VAR_repository: ${{ github.event.repository.name }} - defaults: - run: - shell: bash - working-directory: .github/workflows/github_linux_IaC - - steps: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + name: Main pipeline + + on: # yamllint disable-line rule:truthy + pull_request_target: + types: [opened, reopened, synchronize] + branches: + - main + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + + # A workflow run is made up of one or more jobs + # that can run sequentially or in parallel + jobs: + # This will create messages for first time contributers and direct them to the Discord server + welcome: + runs-on: self-hosted + + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} - - # Pull in terraform code for linux servers - - name: Clone GitHub IaC plan - uses: actions/checkout@v4 - with: - repository: ansible-lockdown/github_linux_IaC - path: .github/workflows/github_linux_IaC - - - name: Add_ssh_key - working-directory: .github/workflows - env: - SSH_AUTH_SOCK: /tmp/ssh_agent.sock - PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}" - run: | - mkdir .ssh - chmod 700 .ssh - echo $PRIVATE_KEY > .ssh/github_actions.pem - chmod 600 .ssh/github_actions.pem - - - name: DEBUG - Show IaC files - if: env.ENABLE_DEBUG == 'true' - run: | - echo "OSVAR = $OSVAR" - echo "benchmark_type = $benchmark_type" - pwd - ls - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Init - id: init - run: terraform init - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Validate - id: validate - run: terraform validate - env: - # Imported from GitHub variables this is used to load the relevant OS.tfvars file - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - - name: Terraform_Apply - id: apply - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform apply -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false - - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml - - # Aws deployments taking a while to come up insert sleep or playbook fails - - - name: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} - - # Run the Ansible playbook - - name: Run_Ansible_Playbook - uses: arillso/action.playbook@master - with: - playbook: site.yml - inventory: .github/workflows/github_linux_IaC/hosts.yml - galaxy_file: collections/requirements.yml - private_key: ${{ secrets.SSH_PRV_KEY }} - # verbose: 3 - env: - ANSIBLE_HOST_KEY_CHECKING: "false" - ANSIBLE_DEPRECATION_WARNINGS: "false" - - # Remove test system - User secrets to keep if necessary - - - name: Terraform_Destroy - if: always() && env.ENABLE_DEBUG == 'false' - env: - AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} - AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} - OSVAR: ${{ vars.OSVAR }} - TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} - run: terraform destroy -var-file "github_vars.tfvars" -var-file "${OSVAR}.tfvars" --auto-approve -input=false + repo-token: ${{ secrets.GITHUB_TOKEN }} + pr-message: |- + Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! + Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. + + # This workflow contains a single job that tests the playbook + playbook-test: + # The type of runner that the job will run on + runs-on: self-hosted + env: + ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} + # Imported as a variable by terraform + TF_VAR_repository: ${{ github.event.repository.name }} + AWS_REGION : "us-east-1" + ANSIBLE_VERSION: ${{ vars.ANSIBLE_RUNNER_VERSION }} + defaults: + run: + shell: bash + working-directory: .github/workflows/github_linux_IaC + # working-directory: .github/workflows + + steps: + + - name: Git Clone the Lockdown Repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} + + - name: If a variable for IAC_BRANCH is set use that branch + working-directory: .github/workflows + run: | + if [ ${{ vars.IAC_BRANCH }} != '' ]; then + echo "IAC_BRANCH=${{ vars.IAC_BRANCH }}" >> $GITHUB_ENV + echo "Pipeline using the following IAC branch ${{ vars.IAC_BRANCH }}" + else + echo IAC_BRANCH=main >> $GITHUB_ENV + fi + + # Pull in terraform code for linux servers + - name: Clone GitHub IaC plan + uses: actions/checkout@v4 + with: + repository: ansible-lockdown/github_linux_IaC + path: .github/workflows/github_linux_IaC + ref: ${{ env.IAC_BRANCH }} + + # Uses dedicated restricted role and policy to enable this only for this task + # No credentials are part of github for AWS auth + - name: Configure AWS Credentials + uses: aws-actions/configure-aws-credentials@main + with: + role-to-assume: ${{ secrets.AWS_ASSUME_ROLE }} + role-session-name: ${{ secrets.AWS_ROLE_SESSION }} + aws-region: ${{ env.AWS_REGION }} + + - name: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + echo "PRIVSUBNET_ID = $AWS_PRIVSUBNET_ID" + echo "VPC_ID" = $AWS_VPC_SECGRP_ID" + pwd + ls + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} + PRIVSUBNET_ID: ${{ secrets.AWS_PRIVSUBNET_ID }} + VPC_ID: ${{ secrets.AWS_VPC_SECGRP_ID }} + + - name: Tofu Init + id: init + run: tofu init + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu Validate + id: validate + run: tofu validate + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + + - name: Tofu Apply + id: apply + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu apply -var-file "${OSVAR}.tfvars" --auto-approve -input=false + +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml + + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep - Allow system to come up + run: sleep ${{ vars.BUILD_SLEEPTIME }} + + # Run the Ansible playbook + - name: Run Ansible Playbook + env: + ANSIBLE_HOST_KEY_CHECKING: "false" + ANSIBLE_DEPRECATION_WARNINGS: "false" + run: | + /opt/ansible_${{ env.ANSIBLE_VERSION }}_venv/bin/ansible-playbook -i hosts.yml --private-key ~/.ssh/le_runner ../../../site.yml + + # Remove test system - User secrets to keep if necessary + + - name: Tofu Destroy + if: always() && env.ENABLE_DEBUG == 'false' + env: + OSVAR: ${{ vars.OSVAR }} + TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }} + TF_VAR_privsubnet_id: ${{ secrets.AWS_PRIVSUBNET_ID }} + TF_VAR_vpc_secgrp_id: ${{ secrets.AWS_VPC_SECGRP_ID }} + run: tofu destroy -var-file "${OSVAR}.tfvars" --auto-approve -input=false diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0368cf3e..e3bd1700 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.5.0 + rev: v4.6.0 hooks: # Safety - id: detect-aws-credentials @@ -30,21 +30,17 @@ repos: # Scan for passwords - repo: https://github.com/Yelp/detect-secrets - rev: v1.4.0 + rev: v1.5.0 hooks: - id: detect-secrets - args: ['--baseline', '.config/.secrets.baseline'] - exclude: package.lock.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.2 + rev: v8.18.4 hooks: - id: gitleaks - args: ['--baseline-path', '.config/.gitleaks-report.json'] - exclude: .config/.secrets.baseline - repo: https://github.com/ansible-community/ansible-lint - rev: v24.2.0 + rev: v24.7.0 hooks: - id: ansible-lint name: Ansible-lint diff --git a/Changelog.md b/Changelog.md index 20a34030..b1e5a0c9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,36 +1,38 @@ # Changes to rhel8CIS -## 1.5.16 - Based on CIS v2.0.0 +## 2.0 based on CIS 3.0.0 -- updated min ansibleversion to 2.11.1 +### This is not an upgrade for CIS v2.0.0 due to the number of changes treat as a new baseline -- changes to 5.6.1.[ 1, 2, 3] - - ability to change current users - - variables added to defaults/main.yml to enable +### Changes and improvements (March24) -- ability to choose remove for mask for nfs,rpc and rsync +Changes to variable naming for those variables discovered +some lint updates -## 1.5.15 - based on CIS v2.0.0 - -### Audit +thanks to @bbaassssiiee -- ability to run audit_only - - var audit_only: true - - tidy up of audit variables to var/audit.yml and some in defaults/main.ym -- goss version increased to 0.3.23 - Doesn't run with latest version 0.4+ +- #353 +- #354 +- #359 +- #360 +- #361 +- #363 +- #364 +- #365 -- updated 5.4.1 and 5.4.2 for authselect +Audit and audit_only changed to run prior to any significant changes -- Update to 2.1.2. sysconfig for chronyd +#### Initial -- Added optional control thanks to @bbaassssiiee - - #273 - ability to use crypto Future with options - optional control added - - #329 - pam remove nullok - optional control added +Inline with new CIS baseline +Rewrite and ordering of nearly all controls +Many new controls added +Authselect is now used to setup pam options +Min ansible version now 2.11.1 -- update to audit thanks you @aaosopra - - #336 - - #337 - - #338 +- variable audit_only - ability to run audit only without remediate +- New ansible-lint layout +- New variable rhel8cis_disruption_high - found in defaults/main.yml default false ## 1.5.14 based on CIS v2.0.0 diff --git a/README.md b/README.md index 4c3ba530..75f086db 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL/Rocky/AlmaLinux 8 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant -### Based on [ CIS RedHat Enterprise Linux 8 Benchmark v2.0.0 - 02-23-2022 ](https://www.cisecurity.org/cis-benchmarks/) +### Based on [ CIS RedHat Enterprise Linux 8 Benchmark v3.0.0 - 11-10-2023 ](https://www.cisecurity.org/cis-benchmarks/) --- @@ -47,11 +47,19 @@ Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to a This role **will make changes to the system** which may have unintended consequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted. -Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL8-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. +- Testing is the most important thing you can do. -This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed. +- Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL8-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. -To use release version please point to main branch and relevant release for the cis benchmark you wish to work with. +- This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed. + +- To use release version please point to main branch and relevant release/tag for the cis benchmark you wish to work with. + +- If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade. + +- Containers references vars/is_container.yml this is an example and to be updated for your requirements + +- Did we mention testing?? --- @@ -133,8 +141,8 @@ RHEL/AlmaLinux/Rocky/Oracle 8 - Other versions are not supported. - AlmaLinux/Rocky Has been tested on 8.8(enabling crypto (sections 1.10 & 1.11) breaks updating or installs : July 01 2021 - Access to download or add the goss binary and content to the system if using auditing (other options are available on how to get the content to the system.) -- Python3 -- Ansible 2.10+ +- Python3.8 +- Ansible 2.11+ - python-def (should be included in RHEL 8) - libselinux-python @@ -175,6 +183,8 @@ rhel8cis_rule_1_1_3_3 [bug 1839899](https://bugs.launchpad.net/cloud-init/+bug/1839899) +Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow repo_gpgcheck on rule_1.2.3 this will cause issues during the playbook unless or a workaround is found. + ## Pipeline Testing uses: diff --git a/defaults/main.yml b/defaults/main.yml index a52598f8..9507a83d 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -21,7 +21,9 @@ rhel8cis_level_1: true rhel8cis_level_2: true rhel8cis_selinux_disable: false -rhel8cis_legacy_boot: false + +# Some tests can have a heavy impact on systen e.g. find on all filesystems etc +rhel8cis_disruption_high: false ## Python Binary ## This is used for python3 Installations where python2 OS modules are used in ansible @@ -30,32 +32,38 @@ python2_bin: /bin/python2.7 ## Benchmark name used by audting control role # The audit variable found at the base benchmark: RHEL8-CIS -benchmark_version: v2.0.0 +benchmark_version: v3.0.0 # Whether to skip the reboot skip_reboot: true +# Modify behavior of changed_when if reboot is pending and skipped to allow idempotency to succeed +reboot_warning_changed_when: true + ### ### Settings for associated Audit role using Goss ### -########################################## +########################################### ### Goss is required on the remote host ### -## Refer to vars/auditd.yml for any other settings ## +### vars/auditd.yml for other settings ### # Allow audit to setup the requirements including installing git (if option chosen and downloading and adding goss binary to system) setup_audit: false # enable audits to run - this runs the audit and get the latest content run_audit: false +# Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system +audit_run_heavy_tests: true -# Only run Audit do not remediate +## Only run Audit do not remediate audit_only: false -# As part of audit_only -# This will enable files to be copied back to control node +### As part of audit_only ### +# This will enable files to be copied back to control node in audit_only mode fetch_audit_files: false -# Path to copy the files to will create dir structure +# Path to copy the files to will create dir structure in audit_only mode audit_capture_files_dir: /some/location to copy to on control node +############################# # How to retrieve audit binary # Options are copy or download - detailed settings at the bottom of this file @@ -68,20 +76,24 @@ get_audit_binary_method: download audit_bin_copy_location: /some/accessible/path # how to get audit files onto host options -# options are git/copy/get_url other e.g. if you wish to run from already downloaded conf +# options are git/copy/archive/get_url other e.g. if you wish to run from already downloaded conf audit_content: git -# archive or copy: -audit_conf_copy: "some path to copy from" +# If using either archive, copy, get_url: +## Note will work with .tar files - zip will require extra configuration +### If using get_url this is expecting github url in tar.gz format e.g. +### https://github.com/ansible-lockdown/UBUNTU22-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz +audit_conf_source: "some path or url to copy from" -# get_url: -audit_files_url: "some url maybe s3?" +# Destination for the audit content to be placed on managed node +# note may not need full path e.g. /opt with the directory being the {{ benchmark }}-Audit directory +audit_conf_dest: "/opt" -# Run heavy tests - some tests can have more impact on a system enabling these can have greater impact on a system -audit_run_heavy_tests: true +# Where the audit logs are stored +audit_log_dir: '/opt' -### End Goss enablements #### -#### Detailed settings found at the end of this document #### +### Goss Settings ## +####### END ######## # These variables correspond with the CIS rule IDs or paragraph numbers defined in # the CIS benchmark documents. @@ -91,76 +103,112 @@ audit_run_heavy_tests: true rhel8cis_rule_1_1_1_1: true rhel8cis_rule_1_1_1_2: true rhel8cis_rule_1_1_1_3: true -rhel8cis_rule_1_1_2_1: true -rhel8cis_rule_1_1_2_2: true -rhel8cis_rule_1_1_2_3: true -rhel8cis_rule_1_1_2_4: true -rhel8cis_rule_1_1_3_1: true -rhel8cis_rule_1_1_3_2: true -rhel8cis_rule_1_1_3_3: true -rhel8cis_rule_1_1_3_4: true -rhel8cis_rule_1_1_4_1: true -rhel8cis_rule_1_1_4_2: true -rhel8cis_rule_1_1_4_3: true -rhel8cis_rule_1_1_4_4: true -rhel8cis_rule_1_1_5_1: true -rhel8cis_rule_1_1_5_2: true -rhel8cis_rule_1_1_5_3: true -rhel8cis_rule_1_1_5_4: true -rhel8cis_rule_1_1_6_1: true -rhel8cis_rule_1_1_6_2: true -rhel8cis_rule_1_1_6_3: true -rhel8cis_rule_1_1_6_4: true -rhel8cis_rule_1_1_7_1: true -rhel8cis_rule_1_1_7_2: true -rhel8cis_rule_1_1_7_3: true -rhel8cis_rule_1_1_7_4: true -rhel8cis_rule_1_1_7_5: true -rhel8cis_rule_1_1_8_1: true -rhel8cis_rule_1_1_8_2: true -rhel8cis_rule_1_1_8_3: true -rhel8cis_rule_1_1_9: true -rhel8cis_rule_1_1_10: true +rhel8cis_rule_1_1_1_4: true +rhel8cis_rule_1_1_1_5: true +rhel8cis_rule_1_1_1_6: true +rhel8cis_rule_1_1_1_7: true +rhel8cis_rule_1_1_1_8: true + +# /tmp +rhel8cis_rule_1_1_2_1_1: true +rhel8cis_rule_1_1_2_1_2: true +rhel8cis_rule_1_1_2_1_3: true +rhel8cis_rule_1_1_2_1_4: true + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: true +rhel8cis_rule_1_1_2_2_2: true +rhel8cis_rule_1_1_2_2_3: true +rhel8cis_rule_1_1_2_2_4: true + +# /home +rhel8cis_rule_1_1_2_3_1: true +rhel8cis_rule_1_1_2_3_2: true +rhel8cis_rule_1_1_2_3_3: true + +# /var +rhel8cis_rule_1_1_2_4_1: true +rhel8cis_rule_1_1_2_4_2: true +rhel8cis_rule_1_1_2_4_3: true + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: true +rhel8cis_rule_1_1_2_5_2: true +rhel8cis_rule_1_1_2_5_3: true +rhel8cis_rule_1_1_2_5_4: true + +# /var/log +rhel8cis_rule_1_1_2_6_1: true +rhel8cis_rule_1_1_2_6_2: true +rhel8cis_rule_1_1_2_6_3: true +rhel8cis_rule_1_1_2_6_4: true + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: true +rhel8cis_rule_1_1_2_7_2: true +rhel8cis_rule_1_1_2_7_3: true +rhel8cis_rule_1_1_2_7_4: true + +# DNF - Patching rhel8cis_rule_1_2_1: true rhel8cis_rule_1_2_2: true rhel8cis_rule_1_2_3: true rhel8cis_rule_1_2_4: true +rhel8cis_rule_1_2_5: true + +# bootloader grub rhel8cis_rule_1_3_1: true rhel8cis_rule_1_3_2: true + +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: true rhel8cis_rule_1_4_2: true rhel8cis_rule_1_4_3: true -rhel8cis_rule_1_5_1: true -rhel8cis_rule_1_5_2: true -rhel8cis_rule_1_5_3: true +rhel8cis_rule_1_4_4: true + +# SElinux +rhel8cis_rule_1_5_1_1: true +rhel8cis_rule_1_5_1_2: true +rhel8cis_rule_1_5_1_3: true +rhel8cis_rule_1_5_1_4: true +rhel8cis_rule_1_5_1_5: true +rhel8cis_rule_1_5_1_6: true +rhel8cis_rule_1_5_1_7: true +rhel8cis_rule_1_5_1_8: true + +# Crypto Policies rhel8cis_rule_1_6_1: true rhel8cis_rule_1_6_2: true -rhel8cis_rule_1_6_1_1: true -rhel8cis_rule_1_6_1_2: true -rhel8cis_rule_1_6_1_3: true -rhel8cis_rule_1_6_1_4: true -rhel8cis_rule_1_6_1_5: true -rhel8cis_rule_1_6_1_6: true -rhel8cis_rule_1_6_1_7: true -rhel8cis_rule_1_6_1_8: true +rhel8cis_rule_1_6_3: true +rhel8cis_rule_1_6_4: true + +# MOTD and messages rhel8cis_rule_1_7_1: true rhel8cis_rule_1_7_2: true rhel8cis_rule_1_7_3: true rhel8cis_rule_1_7_4: true rhel8cis_rule_1_7_5: true rhel8cis_rule_1_7_6: true + +# Gnome desktop rhel8cis_rule_1_8_1: true rhel8cis_rule_1_8_2: true rhel8cis_rule_1_8_3: true rhel8cis_rule_1_8_4: true rhel8cis_rule_1_8_5: true -rhel8cis_rule_1_9: true -rhel8cis_rule_1_10: true -rhel8cis_rule_1_11: true +rhel8cis_rule_1_8_6: true +rhel8cis_rule_1_8_7: true +rhel8cis_rule_1_8_8: true +rhel8cis_rule_1_8_9: true +rhel8cis_rule_1_8_10: true # Section 2 rules +# time sync rhel8cis_rule_2_1_1: true rhel8cis_rule_2_1_2: true +rhel8cis_rule_2_1_3: true + +# Server services rhel8cis_rule_2_2_1: true rhel8cis_rule_2_2_2: true rhel8cis_rule_2_2_3: true @@ -181,21 +229,29 @@ rhel8cis_rule_2_2_17: true rhel8cis_rule_2_2_18: true rhel8cis_rule_2_2_19: true rhel8cis_rule_2_2_20: true +rhel8cis_rule_2_2_21: true +rhel8cis_rule_2_2_22: true + +# Client services rhel8cis_rule_2_3_1: true rhel8cis_rule_2_3_2: true rhel8cis_rule_2_3_3: true rhel8cis_rule_2_3_4: true rhel8cis_rule_2_3_5: true -rhel8cis_rule_2_3_6: true -rhel8cis_rule_2_4: true # Section 3 rules +# network connectivity wifi/bluetooth/ipv6 rhel8cis_rule_3_1_1: true rhel8cis_rule_3_1_2: true rhel8cis_rule_3_1_3: true -rhel8cis_rule_3_1_4: true + +# Network Kernel module rhel8cis_rule_3_2_1: true rhel8cis_rule_3_2_2: true +rhel8cis_rule_3_2_3: true +rhel8cis_rule_3_2_4: true + +# Network Kernel Params rhel8cis_rule_3_3_1: true rhel8cis_rule_3_3_2: true rhel8cis_rule_3_3_3: true @@ -205,144 +261,206 @@ rhel8cis_rule_3_3_6: true rhel8cis_rule_3_3_7: true rhel8cis_rule_3_3_8: true rhel8cis_rule_3_3_9: true +rhel8cis_rule_3_3_10: true +rhel8cis_rule_3_3_11: true + +# Firewall rhel8cis_rule_3_4_1_1: true rhel8cis_rule_3_4_1_2: true -rhel8cis_rule_3_4_1_3: true -rhel8cis_rule_3_4_1_4: true -rhel8cis_rule_3_4_1_5: true -rhel8cis_rule_3_4_1_6: true -rhel8cis_rule_3_4_1_7: true + +# Firewall rules rhel8cis_rule_3_4_2_1: true rhel8cis_rule_3_4_2_2: true rhel8cis_rule_3_4_2_3: true rhel8cis_rule_3_4_2_4: true rhel8cis_rule_3_4_2_5: true -rhel8cis_rule_3_4_2_6: true -rhel8cis_rule_3_4_2_7: true -rhel8cis_rule_3_4_2_8: true -rhel8cis_rule_3_4_2_9: true -rhel8cis_rule_3_4_2_10: true -rhel8cis_rule_3_4_2_11: true -rhel8cis_rule_3_4_3_1_1: true -rhel8cis_rule_3_4_3_1_2: true -rhel8cis_rule_3_4_3_1_3: true -rhel8cis_rule_3_4_3_2_1: true -rhel8cis_rule_3_4_3_2_2: true -rhel8cis_rule_3_4_3_2_3: true -rhel8cis_rule_3_4_3_2_4: true -rhel8cis_rule_3_4_3_2_5: true -rhel8cis_rule_3_4_3_2_6: true -rhel8cis_rule_3_4_3_3_1: true -rhel8cis_rule_3_4_3_3_2: true -rhel8cis_rule_3_4_3_3_3: true -rhel8cis_rule_3_4_3_3_4: true -rhel8cis_rule_3_4_3_3_5: true -rhel8cis_rule_3_4_3_3_6: true - -# Section 4 rules + +## +## Section 4 rules +## +# cron rhel8cis_rule_4_1_1_1: true rhel8cis_rule_4_1_1_2: true rhel8cis_rule_4_1_1_3: true rhel8cis_rule_4_1_1_4: true +rhel8cis_rule_4_1_1_5: true +rhel8cis_rule_4_1_1_6: true +rhel8cis_rule_4_1_1_7: true +rhel8cis_rule_4_1_1_8: true + +# at rhel8cis_rule_4_1_2_1: true -rhel8cis_rule_4_1_2_2: true -rhel8cis_rule_4_1_2_3: true -rhel8cis_rule_4_1_3_1: true -rhel8cis_rule_4_1_3_2: true -rhel8cis_rule_4_1_3_3: true -rhel8cis_rule_4_1_3_4: true -rhel8cis_rule_4_1_3_5: true -rhel8cis_rule_4_1_3_6: true -rhel8cis_rule_4_1_3_7: true -rhel8cis_rule_4_1_3_8: true -rhel8cis_rule_4_1_3_9: true -rhel8cis_rule_4_1_3_10: true -rhel8cis_rule_4_1_3_11: true -rhel8cis_rule_4_1_3_12: true -rhel8cis_rule_4_1_3_13: true -rhel8cis_rule_4_1_3_14: true -rhel8cis_rule_4_1_3_15: true -rhel8cis_rule_4_1_3_16: true -rhel8cis_rule_4_1_3_17: true -rhel8cis_rule_4_1_3_18: true -rhel8cis_rule_4_1_3_19: true -rhel8cis_rule_4_1_3_20: true -rhel8cis_rule_4_1_3_21: true -rhel8cis_rule_4_2_1_1: true -rhel8cis_rule_4_2_1_2: true -rhel8cis_rule_4_2_1_3: true -rhel8cis_rule_4_2_1_4: true -rhel8cis_rule_4_2_1_5: true -rhel8cis_rule_4_2_1_6: true -rhel8cis_rule_4_2_1_7: true -rhel8cis_rule_4_2_2_1_1: true -rhel8cis_rule_4_2_2_1_2: true -rhel8cis_rule_4_2_2_1_3: true -rhel8cis_rule_4_2_2_1_4: true -rhel8cis_rule_4_2_2_2: true -rhel8cis_rule_4_2_2_3: true -rhel8cis_rule_4_2_2_4: true -rhel8cis_rule_4_2_2_5: true -rhel8cis_rule_4_2_2_6: true -rhel8cis_rule_4_2_2_7: true + +# sshd +rhel8cis_rule_4_2_1: true +rhel8cis_rule_4_2_2: true rhel8cis_rule_4_2_3: true -rhel8cis_rule_4_3: true +rhel8cis_rule_4_2_4: true +rhel8cis_rule_4_2_5: true +rhel8cis_rule_4_2_6: true +rhel8cis_rule_4_2_7: true +rhel8cis_rule_4_2_8: true +rhel8cis_rule_4_2_9: true +rhel8cis_rule_4_2_10: true +rhel8cis_rule_4_2_12: true +rhel8cis_rule_4_2_11: true +rhel8cis_rule_4_2_13: true +rhel8cis_rule_4_2_14: true +rhel8cis_rule_4_2_15: true +rhel8cis_rule_4_2_16: true +rhel8cis_rule_4_2_17: true +rhel8cis_rule_4_2_18: true +rhel8cis_rule_4_2_19: true +rhel8cis_rule_4_2_20: true +rhel8cis_rule_4_2_21: true +rhel8cis_rule_4_2_22: true + +# sudo +rhel8cis_rule_4_3_1: true +rhel8cis_rule_4_3_2: true +rhel8cis_rule_4_3_3: true +rhel8cis_rule_4_3_4: true +rhel8cis_rule_4_3_5: true +rhel8cis_rule_4_3_6: true +rhel8cis_rule_4_3_7: true + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: true +rhel8cis_rule_4_4_1_2: true + +# authselect +rhel8cis_rule_4_4_2_1: true +rhel8cis_rule_4_4_2_2: true +rhel8cis_rule_4_4_2_3: true +rhel8cis_rule_4_4_2_4: true +rhel8cis_rule_4_4_2_5: true + +# pam faillock +rhel8cis_rule_4_4_3_1_1: true +rhel8cis_rule_4_4_3_1_2: true +rhel8cis_rule_4_4_3_1_3: true + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: true +rhel8cis_rule_4_4_3_2_2: true +rhel8cis_rule_4_4_3_2_3: true +rhel8cis_rule_4_4_3_2_4: true +rhel8cis_rule_4_4_3_2_5: true +rhel8cis_rule_4_4_3_2_6: true +rhel8cis_rule_4_4_3_2_7: true + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: true +rhel8cis_rule_4_4_3_3_2: true +rhel8cis_rule_4_4_3_3_3: true + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: true +rhel8cis_rule_4_4_3_4_2: true +rhel8cis_rule_4_4_3_4_3: true +rhel8cis_rule_4_4_3_4_4: true + +# Shadow user settings +rhel8cis_rule_4_5_1_1: true +rhel8cis_rule_4_5_1_2: true +rhel8cis_rule_4_5_1_3: true +rhel8cis_rule_4_5_1_4: true +rhel8cis_rule_4_5_1_5: true + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: true +rhel8cis_rule_4_5_2_2: true +rhel8cis_rule_4_5_2_3: true +rhel8cis_rule_4_5_2_4: true +rhel8cis_rule_4_5_2_5: true + +# User enviroment +rhel8cis_rule_4_5_3_1: true +rhel8cis_rule_4_5_3_2: true +rhel8cis_rule_4_5_3_3: true -# Section 5 rules -rhel8cis_rule_5_1_1: true -rhel8cis_rule_5_1_2: true +## +## Section 5 rules +## + +# Rsyslog +rhel8cis_rule_5_1_1_1: true +rhel8cis_rule_5_1_1_2: true +rhel8cis_rule_5_1_1_3: true +rhel8cis_rule_5_1_1_4: true +rhel8cis_rule_5_1_1_5: true +rhel8cis_rule_5_1_1_6: true +rhel8cis_rule_5_1_1_7: true + +# Journald +rhel8cis_rule_5_1_2_1_1: true +rhel8cis_rule_5_1_2_1_2: true +rhel8cis_rule_5_1_2_1_3: true +rhel8cis_rule_5_1_2_1_4: true +rhel8cis_rule_5_1_2_2: true +rhel8cis_rule_5_1_2_3: true +rhel8cis_rule_5_1_2_4: true +rhel8cis_rule_5_1_2_5: true +rhel8cis_rule_5_1_2_6: true rhel8cis_rule_5_1_3: true rhel8cis_rule_5_1_4: true -rhel8cis_rule_5_1_5: true -rhel8cis_rule_5_1_6: true -rhel8cis_rule_5_1_7: true -rhel8cis_rule_5_1_8: true -rhel8cis_rule_5_1_9: true -rhel8cis_rule_5_2_1: true -rhel8cis_rule_5_2_2: true -rhel8cis_rule_5_2_3: true -rhel8cis_rule_5_2_4: true -rhel8cis_rule_5_2_5: true -rhel8cis_rule_5_2_6: true -rhel8cis_rule_5_2_7: true -rhel8cis_rule_5_2_8: true -rhel8cis_rule_5_2_9: true -rhel8cis_rule_5_2_10: true -rhel8cis_rule_5_2_12: true -rhel8cis_rule_5_2_11: true -rhel8cis_rule_5_2_13: true -rhel8cis_rule_5_2_14: true -rhel8cis_rule_5_2_15: true -rhel8cis_rule_5_2_16: true -rhel8cis_rule_5_2_17: true -rhel8cis_rule_5_2_18: true -rhel8cis_rule_5_2_19: true -rhel8cis_rule_5_2_20: true + +# Auditd +rhel8cis_rule_5_2_1_1: true +rhel8cis_rule_5_2_1_2: true +rhel8cis_rule_5_2_1_3: true +rhel8cis_rule_5_2_1_4: true +rhel8cis_rule_5_2_2_1: true +rhel8cis_rule_5_2_2_2: true +rhel8cis_rule_5_2_2_3: true +rhel8cis_rule_5_2_2_4: true + +# auditd rules +rhel8cis_rule_5_2_3_1: true +rhel8cis_rule_5_2_3_2: true +rhel8cis_rule_5_2_3_3: true +rhel8cis_rule_5_2_3_4: true +rhel8cis_rule_5_2_3_5: true +rhel8cis_rule_5_2_3_6: true +rhel8cis_rule_5_2_3_7: true +rhel8cis_rule_5_2_3_8: true +rhel8cis_rule_5_2_3_9: true +rhel8cis_rule_5_2_3_10: true +rhel8cis_rule_5_2_3_11: true +rhel8cis_rule_5_2_3_12: true +rhel8cis_rule_5_2_3_13: true +rhel8cis_rule_5_2_3_14: true +rhel8cis_rule_5_2_3_15: true +rhel8cis_rule_5_2_3_16: true +rhel8cis_rule_5_2_3_17: true +rhel8cis_rule_5_2_3_18: true +rhel8cis_rule_5_2_3_19: true +rhel8cis_rule_5_2_3_20: true +rhel8cis_rule_5_2_3_21: true + +# auditd log perms +rhel8cis_rule_5_2_4_1: true +rhel8cis_rule_5_2_4_2: true +rhel8cis_rule_5_2_4_3: true +rhel8cis_rule_5_2_4_4: true +rhel8cis_rule_5_2_4_5: true +rhel8cis_rule_5_2_4_6: true +rhel8cis_rule_5_2_4_7: true +rhel8cis_rule_5_2_4_8: true +rhel8cis_rule_5_2_4_9: true +rhel8cis_rule_5_2_4_10: true + +# AIDE + rhel8cis_rule_5_3_1: true rhel8cis_rule_5_3_2: true rhel8cis_rule_5_3_3: true -rhel8cis_rule_5_3_4: true -rhel8cis_rule_5_3_5: true -rhel8cis_rule_5_3_6: true -rhel8cis_rule_5_3_7: true -rhel8cis_rule_5_4_1: true -rhel8cis_rule_5_4_2: true -rhel8cis_rule_5_5_1: true -rhel8cis_rule_5_5_2: true -rhel8cis_rule_5_5_3: true -rhel8cis_rule_5_5_4: true -rhel8cis_rule_5_5_5: true -rhel8cis_rule_5_6_1_1: true -rhel8cis_rule_5_6_1_2: true -rhel8cis_rule_5_6_1_3: true -rhel8cis_rule_5_6_1_4: true -rhel8cis_rule_5_6_1_5: true -rhel8cis_rule_5_6_2: true -rhel8cis_rule_5_6_3: true -rhel8cis_rule_5_6_4: true -rhel8cis_rule_5_6_5: true - -# Section 6 rules + +## +## Section 6 rules +## + +# System file perms rhel8cis_rule_6_1_1: true rhel8cis_rule_6_1_2: true rhel8cis_rule_6_1_3: true @@ -357,7 +475,8 @@ rhel8cis_rule_6_1_11: true rhel8cis_rule_6_1_12: true rhel8cis_rule_6_1_13: true rhel8cis_rule_6_1_14: true -rhel8cis_rule_6_1_15: true + +# local and usergroup rhel8cis_rule_6_2_1: true rhel8cis_rule_6_2_2: true rhel8cis_rule_6_2_3: true @@ -369,56 +488,10 @@ rhel8cis_rule_6_2_8: true rhel8cis_rule_6_2_9: true rhel8cis_rule_6_2_10: true rhel8cis_rule_6_2_11: true -rhel8cis_rule_6_2_12: true -rhel8cis_rule_6_2_13: true -rhel8cis_rule_6_2_14: true -rhel8cis_rule_6_2_15: true -rhel8cis_rule_6_2_16: true - -# Service configuration booleans set true to keep service - -# Server Services -rhel8cis_avahi_server: false -rhel8cis_bind: false -rhel8cis_cups_server: false -rhel8cis_dhcp_server: false -rhel8cis_dns_server: false -rhel8cis_dovecot_cyrus_server: false -rhel8cis_ftp_server: false -rhel8cis_httpd_server: false -rhel8cis_is_mail_server: false -rhel8cis_net_snmp_server: false -# Ability to choose between remove or mask(default) -rhel8cis_nfs_server: false -rhel8cis_nfs_mask: true -rhel8cis_nginx_server: false -rhel8cis_nis_server: false -# Ability to choose between remove or mask(default) -rhel8cis_rpc_server: false -rhel8cis_rpc_mask: true -# Ability to choose between remove or mask(default) -rhel8cis_rsync_server: false -rhel8cis_rsync_mask: true -rhel8cis_samba_server: false -rhel8cis_squid_server: false -rhel8cis_telnet_server: false -rhel8cis_tftp_server: false -rhel8cis_vsftpd_server: false -rhel8cis_xinetd_server: false - -# Client Services - -rhel8cis_ypbind_required: false -rhel8cis_rsh_required: false -rhel8cis_talk_required: false -rhel8cis_telnet_required: false -rhel8cis_openldap_clients_required: false -rhel8cis_tftp_client: false - -rhel8cis_allow_autofs: false +## ## Section 1 vars - +## # 1.1.2.2 # 1.1.2.3 # 1.1.2.4 @@ -428,36 +501,124 @@ rhel8cis_allow_autofs: false # If set true uses the tmp.mount service else using fstab configuration rhel8cis_tmp_svc: false -# 1.2.1 -# This is the login information for your RedHat Subscription -# DO NOT USE PLAIN TEXT PASSWORDS!!!!! -# The intent here is to use a password utility like Ansible Vault here -rhel8cis_rh_sub_user: user -rhel8cis_rh_sub_password: password # pragma: allowlist secret - -# 1.2.2 -# Do you require rhnsd -# RedHat Satellite Subscription items -rhel8cis_rhnsd_required: false - -# xinetd required -rhel8cis_xinetd_required: false +# 1.2 patch system +rhel8cis_apply_installed_kernel_limit: false +rhel8cis_installed_kernel_limit: 2 -# 1.4.1 Bootloader password +# 1.3 Bootloader password rhel8cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret rhel8cis_bootloader_password: random # pragma: allowlist secret rhel8cis_set_boot_pass: false -# 1.9 patch system -rhel8cis_apply_installed_kernel_limit: false -rhel8cis_installed_kernel_limit: 2 +# 1.5 SELinux policy +rhel8cis_selinux_state: enforcing +# Configure SELinux to meet or exceed the default targeted policy, which constrains daemons and system software only. +# Valid Inputs: targeted or mls +rhel8cis_selinux_policy: targeted -# 1.10/1.11 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) -# Control 1.10 states do not use LEGACY and control 1.11 says to use FUTURE or FIPS. +# 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) rhel8cis_crypto_policy: 'DEFAULT' -# Added module to be allowed as default setting (Allowed options in vars/main.yml) + +# 1.6.1 Allowed crypto-policy modules +rhel8cis_allowed_crypto_policies_modules: + - 'AD-SUPPORT' + - 'NO-SHA1' + - 'OSPP' + +# Added module to be loaded rhel8cis_crypto_policy_module: '' +# 1.7 +# Warning Banner Content (issue, issue.net, motd) +rhel8cis_warning_banner: | + Authorized uses only. All activity may be monitored and reported. +# End Banner + +# 1.8 Gnome Desktop +# Whether or not to run tasks related to auditing/patching the desktop environment +rhel8cis_gui: false +rhel8cis_dconf_db_name: local +rhel8cis_screensaver_idle_delay: 900 # Set max value for idle-delay in seconds (between 1 and 900) +rhel8cis_screensaver_lock_delay: 5 # Set max value for lock-delay in seconds (between 0 and 5) +## +## Section 2 vars +## +# 2.1.1 Time Synchronization - Either chrony or ntp +rhel8cis_time_synchronization: chrony + +# Time Synchronization servers - used in template file chrony.conf.j2 +rhel8cis_time_synchronization_servers: + - 0.pool.ntp.org + - 1.pool.ntp.org + - 2.pool.ntp.org + - 3.pool.ntp.org + +rhel8cis_chrony_server_options: "minpoll 8" +rhel8cis_ntp_server_options: "iburst" + +# Service configuration +# Options are +# true to leave installed if exists not changes take place +# false - this removes the package +# mask - if a dependancy for product so cannot be removed +# Server Services +rhel8cis_autofs_services: false +rhel8cis_autofs_mask: true +rhel8cis_avahi_server: false +rhel8cis_avahi_mask: false +rhel8cis_dhcp_server: false +rhel8cis_dhcp_mask: false +rhel8cis_dns_server: false +rhel8cis_dns_mask: false +rhel8cis_dnsmasq_server: false +rhel8cis_dnsmasq_mask: false +rhel8cis_samba_server: false +rhel8cis_samba_mask: false +rhel8cis_ftp_server: false +rhel8cis_ftp_mask: false +rhel8cis_message_server: false # This is for messaging dovecot and cyrus-imap +rhel8cis_message_mask: false +rhel8cis_nfs_server: true +rhel8cis_nfs_mask: true +rhel8cis_nis_server: true # set to mask if nis client required +rhel8cis_nis_mask: false +rhel8cis_print_server: false # replaces cups +rhel8cis_print_mask: false +rhel8cis_rpc_server: true +rhel8cis_rpc_mask: true +rhel8cis_rsync_server: false +rhel8cis_rsync_mask: false +rhel8cis_net_snmp_server: false +rhel8cis_net_snmp_mask: false +rhel8cis_telnet_server: false +rhel8cis_telnet_mask: false +rhel8cis_tftp_server: false +rhel8cis_tftp_mask: false +rhel8cis_squid_server: false +rhel8cis_squid_mask: false +rhel8cis_httpd_server: false +rhel8cis_httpd_mask: false +rhel8cis_nginx_server: false +rhel8cis_nginx_mask: false +rhel8cis_xinetd_server: false +rhel8cis_xinetd_mask: false +rhel8cis_xwindow_server: false # will remove mask not an option +rhel8cis_is_mail_server: false + +# Client Services +rhel8cis_ftp_client: false +rhel8cis_openldap_clients_required: false +rhel8cis_ypbind_required: false # Same package as NIS server +rhel8cis_telnet_required: false +rhel8cis_tftp_client: false + +## +## Section 3 vars +## + +rhel8cis_bluetooth_service: false +rhel8cis_bluetooth_mask: false + # System network parameters (host only OR host and router) rhel8cis_is_router: false @@ -466,7 +627,7 @@ rhel8cis_ipv6_required: true rhel8cis_ipv6_sysctl_force: true -## Optional - Understand the impact of making the following controls to true +## Optional - Understand the impact of making the following two control to true # By default, we do not disable IPv6 on localhost, as it's important for multiple # components. If you want to disable it anyway, change the following # value to true refer https://access.redhat.com/solutions/8709 @@ -477,258 +638,208 @@ rhel8cis_ipv6_disable_localhost: false rhel8cis_ipv6_sshd_disable: false # disable chrony on ipv6 rhel8cis_ipv6_chrony_disable: false -## -# Pam Change remove null ok from system/password-auth files manual change for 5.4.1 if not using authselect -rhel8cis_remove_nullok: true -# Allow override of crypto polices tyo enable some alternate repos etc when policy is FIPS or FUTURE -rhel8cis_optional_crypto_module: false -rhel8cis_optional_key_exchange: 'ECDHE RSA DHE DHE-RSA PSK DHE-PSK ECDHE-PSK ECDHE-GSS DHE-GSS' -rhel8cis_optional_rsa_size: 2048 - -# AIDE -rhel8cis_config_aide: true -# AIDE cron settings -rhel8cis_aide_cron: - cron_user: root - cron_file: /etc/cron.d/cis_aide - aide_job: '/usr/sbin/aide --check' - aide_minute: 0 - aide_hour: 5 - aide_day: '*' - aide_month: '*' - aide_weekday: '*' - -# SELinux policy - -# SELinux can run in one of three modes: disabled, permissive, or enforcing: -# CIS strongly discourages disabled -# NOTE: -# Section 1.6.1.5 forces Enforcing to be set. So If rhel8cis_rule_1_6_1_3: true -# make sure enforcing is set below for idempotency for taks 1.6.1.3 - 5 -rhel8cis_selinux_state: enforcing -# Configure SELinux to meet or exceed the default targeted policy, which constrains daemons and system software only. -# Valid Inputs: targeted or mls -rhel8cis_selinux_policy: targeted - -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel8cis_gui: false # Set to 'true' if X Windows is needed in your environment rhel8cis_xwindows_required: false -# 2.1.1 Time Synchronization - Either chrony or ntp -rhel8cis_time_synchronization: chrony - -# 2.2.1.2 Time Synchronization servers - used in template file chrony.conf.j2 -rhel8cis_time_synchronization_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - - 3.pool.ntp.org - -# rhel8cis_ansible_chrony_managed uses the template built into this remediation to be copied to /etc/chrony.conf -# If you are using your own self managed /etc/chrony.conf set this to false. -rhel8cis_chrony_ansible_managed: true - -rhel8cis_chrony_server_options: "minpoll 8" -rhel8cis_ntp_server_options: "iburst" - ## Section3 vars # default location for the sysctl overrides. rhel8cis_sysctl_file: /etc/sysctl.d/99_cis.conf -# Firewall Service - either firewalld, iptables, or nftables -rhel8cis_firewall: firewalld +# Firewall Service - either firewalld or nftables +rhel8cis_firewall: 'firewalld' -# 3.4.1.5 Default zone setting rhel8cis_default_zone: public -# 3.4.2.5 Zone and Interface setting -rhel8cis_int_zone: customezone -rhel8cis_interface: eth0 - -rhel8cis_firewall_services: - - cockpit - - dhcpv6-client - - ssh - -# 3.4.2.5 Set nftables new table create -# 3.4.2.6 -# 3.4.2.7 -# 3.4.2.8 -# 3.4.2.9 -# 3.4.2.11 rhel8cis_nft_tables_autonewtable: true rhel8cis_nft_tables_tablename: filter # 3.4.2.6 Set nftables new chain create rhel8cis_nft_tables_autochaincreate: true -# Warning Banner Content (issue, issue.net, motd) -rhel8cis_warning_banner: | - Authorized uses only. All activity may be monitored and reported. -# End Banner - -## Section4 vars - -update_audit_template: false - -rhel8cis_auditd: - space_left_action: email - action_mail_acct: root - admin_space_left_action: halt - max_log_file_action: keep_logs - -# This can be used to configure other keys in auditd.conf -rhel8cis_auditd_extra_conf: {} -# Example: -# rhel8cis_auditd_extra_conf: -# admin_space_left: '10%' - -rhel8cis_logrotate: "daily" - -# The audit_back_log_limit value should never be below 8192 -rhel8cis_audit_back_log_limit: 8192 - -# The max_log_file parameter should be based on your sites policy -rhel8cis_max_log_file_size: 10 - -# OS logging system - either rsyslog or journald or other if 3rd party tool -rhel8cis_syslog: rsyslog -rhel8cis_rsyslog_ansiblemanaged: true - -# RHEL-08-4.2.1.4/4.2.1.5 remote and destination log server name -rhel8cis_remote_log_server: logagg.example.com - -# 4.2.1.5, 4.2.2.1.3, 4.2.2.1.4 -rhel8cis_system_is_log_server: false - -# 4.2.2.1.2 -# rhel8cis_journal_upload_url is the ip address to upload the journal entries to -rhel8cis_journal_upload_url: 192.168.50.42 -# The paths below have the default paths/files, but allow user to create custom paths/filenames -rhel8cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" -rhel8cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" -rhel8cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" - -# 4.2.2.1 -# The variables below related to journald, please set these to your site specific values -# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use -rhel8cis_journald_systemmaxuse: 10M -# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free -rhel8cis_journald_systemkeepfree: 100G -rhel8cis_journald_runtimemaxuse: 10M -rhel8cis_journald_runtimekeepfree: 100G -# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks -rhel8cis_journald_maxfilesec: 1month - -# 4.2.3 logrotate configuration -# change to true if you wish to change logrotate.d conf files -allow_logrotate_conf_umask_updates: false - +####### ## Section5 vars - +###### +## If using the allow/deny user groups options +rhel8cis_sshd_limited: false rhel8cis_sshd: - clientalivecountmax: 0 - clientaliveinterval: 900 + clientalivecountmax: 3 + clientaliveinterval: 15 logingracetime: 60 + loglevel: INFO + macs: '-hmac-md5,hmac-md5-96,hmac-ripemd160,hmac-sha1-96,umac-64@openssh.com,hmac-md5-etm@openssh.com,hmac-md5-96-etm@openssh.com,hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com,umac-64-etm@openssh.com' + maxauthtries: 4 + maxsessions: 10 + maxstartups: "10:30:60" + ciphers: '-3des-cbc,aes128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se' + kex: '-diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha1' # WARNING: make sure you understand the precedence when working with these values!! + ## Only runs if value rhel8cis_sshd_limited is true # allowusers: # allowgroups: systems dba # denyusers: # denygroups: + +# 4.3. sudo +rhel8cis_sudolog_location: "/var/log/sudo.log" +rhel8cis_sudo_timestamp_timeout: 15 + +## PAM +# 4.4.2.x +# Do not use authselect if: +# Your host is part of Linux Identity Management. +# Joining your host to an IdM domain with the ipa-client-install command automatically configures SSSD authentication on your host. +# Your host is part of Active Directory via SSSD. +# Calling the realm join command to join your host to an Active Directory domain automatically configures SSSD authentication on your host. +rhel8cis_allow_authselect_updates: false +## +rhel8cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install +rhel8cis_authselect_custom_profile_create: false +rhel8cis_authselect_custom_profile_select: false +rhel8cis_authselect: + custom_profile_name: 'cis_example_profile' + default_file_to_copy: "sssd --symlink-meta" + options: with-sudo with-faillock without-nullok with-pwhistory + rhel8cis_pam_faillock: attempts: 5 + deny: 5 interval: 900 unlock_time: 900 - fail_for_root: 'no' - remember: 5 - pwhash: sha512 + root_unlock_time: 60 + # Choose options below for root options + root_option: even_deny_root + # root_option: "root_unlock_time = {{ root_unlock_time }}" + +rhel8cis_pam_pwquality: + difok: 2 + maxrepeat: 3 + maxseq: 3 + minlen: 14 + minclass: 4 -# 5.2.5 SSH LogLevel setting. Options are INFO or VERBOSE -rhel8cis_ssh_loglevel: INFO +rhel8cis_pam_pwhistory: + remember: 24 -# 5.2.19 SSH MaxSessions setting. Must be 10 or less -rhel8cis_ssh_maxsessions: 10 +rhel8cis_pam_pwhash: sha512 -# 5.3.1 Enable automation to create custom profile settings, using the settings above -rhel8cis_authselect_custom_profile_create: false +rhel8cis_pass: + inactive: 30 + max_days: 365 # Max 365 + min_days: 7 + warn_age: 7 -# 5.3.2 Enable automation to select custom profile options, using the settings above -rhel8cis_authselect_custom_profile_select: false +## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['max_days'] +rhel8cis_set_max_expiry: false -# 5.3.3 sudo log location variable -rhel8cis_sudolog_location: "/var/log/sudo.log" +## Add users to be skipped if required +rhel8cis_user_skip_list: + root -# 5.3.6 rhel8cis_sudo_timestamp_timeout is the timeout set to authentication in minutes -# To conform to CIS standards this needs to be 15 minutes or less -rhel8cis_sudo_timestamp_timeout: 15 +rhel8cis_root_umask: '0027' # 0027 or more restrictive -# 5.3.7 +rhel8cis_shell_session_timeout: + file: /etc/profile.d/tmout.sh + timeout: 900 + +# sugroup rhel8cis_sugroup: sugroup # wheel users list rhel8cis_sugroup_users: "root" -# 5.4.1/5.4.2 Custom authselect profile settings. Settings in place now will fail, they are place holders from the control example -# Due to the way many multiple options and ways to configure this control needs to be enabled and settings adjusted to minimise risk -rhel8cis_use_authconfig: false -rhel8cis_authselect: - custom_profile_name: custom-profile - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok - # Its not provider recommended to run changes to pam files manually that affects authentication # This control needs to be set to ACCEPT this so that the changes do take place # Any other value does nothing rhel8cis_pamd_manual_risks: NEVER -# 5.6.1.x -rhel8cis_pass: - max_days: 365 - min_days: 7 - warn_age: 7 +rhel8cis_inactivelock: + lock_days: 30 -# 5.6.1.1 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['max_days'] -rhel8cis_5_6_1_1_set_max_expiry: false +# Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords +rhel8cis_futurepwchgdate_autofix: true -## Add users to be skipped if required -rhel8cis_5_6_1_1_user_skip_list: - root +rhel8uid_uid_start: 1000 +rhel8uid_uid_stop: 60000 -# 5.6.1.2 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['min_days'] -rhel8cis_5_6_1_1_set_min_days_change: false +## Section5 vars -# 5.6.1.3 -## Set the following to true if you wish to adjust accounts greater than rhel8cis_pass['warn_age'] -rhel8cis_5_6_1_3_set_warn_age_change: false +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +rhel8cis_syslog: rsyslog +rhel8cis_rsyslog_ansiblemanaged: true +# Set if system is the log server +rhel8cis_system_is_log_server: false -# 5.6.1.4 -rhel8cis_inactivelock: - lock_days: 30 +#### remote and destination log server name +rhel8cis_remote_log_server: false +rhel8cis_remote_log_host: logagg.example.com +rhel8cis_remote_log_port: 514 +rhel8cis_remote_log_protocol: tcp +rhel8cis_remote_log_retrycount: 100 +rhel8cis_remote_log_queuesize: 1000 -# 5.6.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords -rhel8cis_futurepwchgdate_autofix: true +update_audit_template: false -## PAM -rhel8cis_pam_password: - minlen: 14 - minclass: 4 +rhel8cis_auditd: + disk_error_action: halt + disk_full_action: halt + action_mail_acct: root + space_left_action: email + admin_space_left_action: email + max_log_file_action: keep_logs -# This is a dynamic check but can be overridden here marking it as false and uncomment -rhel8uid_info_dynamic: true -# rhel8uid_interactive_uid_start: 1000 -# rhel8uid_interactive_uid_stop: 60000 +# This can be used to configure other keys in auditd.conf +rhel8cis_auditd_extra_conf: {} +# Example: +# rhel8cis_auditd_extra_conf: +# admin_space_left: '10%' -# 5.6.3 -# Session timeout setting file (TMOUT setting can be set in multiple files) -# Timeout value is in seconds. (60 seconds * 10 = 600) -rhel8cis_shell_session_timeout: - file: /etc/profile.d/tmout.sh - timeout: 900 +rhel8cis_logrotate: "daily" + +# Journald +# rhel8cis_journal_upload_url is the ip address to upload the journal entries to +rhel8cis_journal_upload_url: 192.168.50.42 +# The paths below have the default paths/files, but allow user to create custom paths/filenames +rhel8cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" +rhel8cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" +rhel8cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" + +# The variables below related to journald, please set these to your site specific values +# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use +rhel8cis_journald_systemmaxuse: 10M +# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free +rhel8cis_journald_systemkeepfree: 100G +rhel8cis_journald_runtimemaxuse: 10M +rhel8cis_journald_runtimekeepfree: 100G +# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +rhel8cis_journald_maxfilesec: 1month + +# logrotate configuration +# change to true if you wish to change logrotate.d conf files +allow_logrotate_conf_umask_updates: false + +# The audit_back_log_limit value should never be below 8192 +rhel8cis_audit_back_log_limit: 8192 + +# The max_log_file parameter should be based on your sites policy +rhel8cis_max_log_file_size: 10 + +# AIDE +# aide setup via - cron, timer +rhel8cis_aide_scan: cron +rhel8cis_config_aide: true +# AIDE cron settings +rhel8cis_aide_cron: + cron_user: root + cron_file: /etc/cron.d/cis_aide + aide_job: '/usr/sbin/aide --check' + aide_minute: 0 + aide_hour: 5 + aide_day: '*' + aide_month: '*' + aide_weekday: '*' ## Section6 vars @@ -739,11 +850,12 @@ rhel8cis_rpm_audit_file: /var/tmp/rpm_file_check rhel8cis_no_world_write_adjust: true rhel8cis_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}" -# 6.2.9 - adjusting symlinks in home directories -# Default in ansible is true this causes lots of issues for many users -# set as variable so can be overridden but default is not to follow. +## 6.1.12 adjust files if ungrouped +rhel8cis_ungrouped_adjust: false -rhel_08_6_2_9_follow_home_symlinks: false +## 6.1.13 Remove suid/sgid from files +rhel8cis_suid_adjust: false +rhel8cis_sgid_adjust: false # 6.2.12 rhel8cis_dotperm_ansiblemanaged: true diff --git a/files/etc/systemd/system/tmp.mount b/files/etc/systemd/system/tmp.mount new file mode 100644 index 00000000..47ca6625 --- /dev/null +++ b/files/etc/systemd/system/tmp.mount @@ -0,0 +1,25 @@ +# This file is part of systemd. +# +# systemd is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. + +[Unit] +Description=Temporary Directory +Documentation=man:hier(7) +Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems +ConditionPathIsSymbolicLink=!/tmp +DefaultDependencies=no +Conflicts=umount.target +Before=local-fs.target umount.target + +[Mount] +What=tmpfs +Where=/tmp +Type=tmpfs +Options=mode=1777,strictatime,noexec,nodev,nosuid + +# Make 'systemctl enable tmp.mount' work: +[Install] +WantedBy=local-fs.target diff --git a/handlers/main.yml b/handlers/main.yml index f2e6e8f1..49d3d7ed 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,7 +1,24 @@ --- # handlers file for RHEL8-CIS -- name: sysctl flush ipv4 route table +- name: Update_authselect + ansible.builtin.shell: authselect apply-changes + +- name: Remount_tmp + ansible.builtin.shell: mount -o remount /tmp + +- name: Systemd_restart_tmp.mount + ansible.builtin.systemd: + name: tmp.mount + daemon_reload: true + enabled: true + masked: false + state: reloaded + +- name: Reload_sysctl + ansible.builtin.shell: sysctl --system + +- name: Sysctl_flush_ipv4_routes ansible.posix.sysctl: name: net.ipv4.route.flush value: '1' @@ -9,10 +26,8 @@ ignore_errors: true # noqa ignore-errors when: - not system_is_container - tags: - - skip_ansible_lint -- name: sysctl flush ipv6 route table +- name: Sysctl_flush_ipv6_routes ansible.posix.sysctl: name: net.ipv6.route.flush value: '1' @@ -21,117 +36,76 @@ when: - not system_is_container -- name: systemd restart tmp.mount - ansible.builtin.systemd: - name: tmp.mount - daemon_reload: true - enabled: true - masked: false - state: reloaded - -- name: systemd restart var-tmp.mount - ansible.builtin.systemd: - name: var-tmp.mount - daemon_reload: true - enabled: true - masked: false - state: reloaded - -- name: Systemd_daemon_reload - ansible.builtin.systemd: - daemon-reload: true - -- name: remount tmp - ansible.builtin.shell: mount -o remount /tmp - -- name: restart firewalld - ansible.builtin.service: - name: firewalld - state: restarted - -- name: restart xinetd - ansible.builtin.service: - name: xinetd - state: restarted - -- name: restart sshd +- name: Restart_sshd ansible.builtin.service: name: sshd state: restarted -- name: restart chronyd +- name: Restart_chronyd ansible.builtin.service: name: chronyd state: restarted -- name: restart postfix +- name: Restart_postfix ansible.builtin.service: name: postfix state: restarted -- name: reload dconf +- name: Reload_dconf ansible.builtin.shell: dconf update -- name: update auditd +- name: Update_auditd_rules ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 0600 - notify: restart auditd + mode: '0600' + notify: Restart_auditd -- name: restart auditd - ansible.builtin.shell: /sbin/service auditd restart - changed_when: false - check_mode: false - failed_when: false - -- name: restart journald +- name: Restart_journald ansible.builtin.service: name: systemd-journald state: restarted -- name: restart systemd_journal_upload +- name: Restart_systemd_journal_upload ansible.builtin.service: name: systemd-journal-upload state: restarted -- name: rhel8cis_grub2cfg - ansible.builtin.shell: "grub2-mkconfig -o {{ grub_cfg.stat.lnk_source }}" +- name: Rebuild_grub + ansible.builtin.shell: "grub2-mkconfig -o {{ discovered_grub_cfg.stat.lnk_source }}" ignore_errors: true # noqa ignore-errors - notify: change_requires_reboot + notify: Change_requires_reboot tags: - skip_ansible_lint -- name: restart rsyslog +- name: Restart_rsyslog ansible.builtin.service: name: rsyslog state: restarted -- name: systemd_daemon_reload +- name: Systemd_daemon_reload ansible.builtin.systemd: daemon-reload: true ## Auditd tasks note order for handlers to run -- name: auditd_immutable_check +- name: Auditd_immutable_check ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules changed_when: false - register: auditd_immutable_check + register: discovered_auditd_immutable_check -- name: audit_immutable_fact +- name: Audit_immutable_fact ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" - notify: change_requires_reboot + notify: Change_requires_reboot when: - - auditd_immutable_check.stdout == '1' + - discovered_auditd_immutable_check.stdout == '1' -- name: restart auditd - ansible.builtin.shell: service auditd restart - tags: - - skip_ansible_lint +- name: Restart_auditd + ansible.builtin.shell: /sbin/service auditd restart -- name: change_requires_reboot +- name: Change_requires_reboot ansible.builtin.set_fact: - change_requires_reboot: true + reboot_required: true diff --git a/meta/main.yml b/meta/main.yml index 2ffe148d..c2e2402f 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -10,7 +10,7 @@ galaxy_info: platforms: - name: EL versions: - - 8 + - '8' galaxy_tags: - system - security @@ -22,6 +22,7 @@ galaxy_info: - redhat - rhel - compliance + - complianceascode collections: - community.general - community.crypto diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7ef94b4a..70674142 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -3,16 +3,18 @@ - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit + when: ansible_facts.machine == "x86_64" ansible.builtin.set_fact: audit_pkg_arch_name: AMD64 - when: ansible_facts.machine == "x86_64" - name: Pre Audit Setup | Set audit package name | ARM64 + when: ansible_facts.machine == "arm64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 - when: ansible_facts.machine == "arm64" - name: Pre Audit Setup | Download audit binary + when: + - get_audit_binary_method == 'download' ansible.builtin.get_url: url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" dest: "{{ audit_bin }}" @@ -20,15 +22,13 @@ group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" mode: '0555' - when: - - get_audit_binary_method == 'download' - name: Pre Audit Setup | Copy audit binary + when: + - get_audit_binary_method == 'copy' ansible.builtin.copy: src: "{{ audit_bin_copy_location }}" dest: "{{ audit_bin }}" mode: '0555' owner: root group: root - when: - - get_audit_binary_method == 'copy' diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 864f5bbe..d34b90f0 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,28 +1,28 @@ --- - name: Audit_Only | Create local Directories for hosts + when: fetch_audit_files ansible.builtin.file: mode: '0755' path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" recurse: true state: directory - when: fetch_audit_files delegate_to: localhost become: false - name: Audit_only | Get audits from systems and put in group dir + when: fetch_audit_files ansible.builtin.fetch: dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" flat: true mode: '0644' src: "{{ pre_audit_outfile }}" - when: fetch_audit_files - name: Audit_only | Show Audit Summary when: - audit_only ansible.builtin.debug: - msg: "The Audit results are: {{ pre_audit_summary }}." + msg: "{{ audit_results.split('\n') }}" - name: Audit_only | Stop Playbook Audit Only selected when: diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 1b5b4aaf..00ed3ecc 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -1,14 +1,13 @@ --- -- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added +- name: POST | AUDITD | Apply auditd template will for section 5.2.3 - only required rules will be added ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 0600 - register: audit_rules_updated + mode: '0600' notify: - - auditd_immutable_check - - audit_immutable_fact - - restart auditd + - Auditd_immutable_check + - Audit_immutable_fact + - Restart_auditd diff --git a/tasks/main.yml b/tasks/main.yml index 126c0e6b..c47d8485 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,52 +2,75 @@ # tasks file for RHEL8-CIS - name: Check OS version and family - ansible.builtin.assert: - that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('8', '==') - fail_msg: "This role can only be run against Supported OSs. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported." - success_msg: "This role is running against a supported OS {{ ansible_distribution }} {{ ansible_distribution_major_version }}" when: - os_check - - not system_is_ec2 tags: - always + ansible.builtin.assert: + that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('8', '==') + fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." + success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_distribution_major_version }}" - name: Check ansible version + tags: + - always ansible.builtin.assert: that: ansible_version.full is version_compare(min_ansible_version, '>=') fail_msg: "You must use Ansible {{ min_ansible_version }} or greater" success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}" - tags: - - always - name: Check crypto-policy input - ansible.builtin.assert: - that: rhel8cis_crypto_policy in rhel8cis_allowed_crypto_policies when: - - rhel8cis_rule_1_10 + - rhel8cis_rule_1_6_1 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel8cis_crypto_policy in rhel8cis_allowed_crypto_policies - name: Check crypto-policy module input - ansible.builtin.assert: - that: rhel8cis_crypto_policy_module in rhel8cis_allowed_crypto_policies_modules when: - - rhel8cis_rule_1_10 + - rhel8cis_rule_1_6_1 - rhel8cis_crypto_policy_module | length > 0 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel8cis_crypto_policy_module in rhel8cis_allowed_crypto_policies_modules - name: Check rhel8cis_bootloader_password_hash variable has been changed + when: + - rhel8cis_set_boot_pass + - rhel8cis_rule_1_4_1 + tags: + - always ansible.builtin.assert: that: rhel8cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel8cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret msg: "This role will not be able to run single user password commands as rhel8cis_bootloader_password_hash variable has not been set correctly" # pragma: allowlist secret + +- name: Ensure root password is set when: - - rhel8cis_set_boot_pass - - rhel8cis_rule_1_4_1 + - rhel8cis_rule_4_5_2_4 tags: - always + block: + - name: Ensure root password is set + ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked|root\s(LK|L)\s)" + changed_when: false + failed_when: false + register: discovered_root_passwd_set + + - name: Ensure root password is set + ansible.builtin.assert: + that: discovered_root_passwd_set.rc == 0 + fail_msg: "You have rule 4.5.2.4 enabled this requires that you have a root password set" + success_msg: "You have a root password set" - name: Setup rules if container + when: + - ansible_connection == 'docker' or + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + tags: + - container_discovery + - always block: - name: Discover and set container variable if required ansible.builtin.set_fact: @@ -58,153 +81,142 @@ file: "{{ container_vars_file }}" - name: Output if discovered is a container - ansible.builtin.debug: - msg: system has been discovered as a container when: - system_is_container - when: - - ansible_connection == 'docker' or - ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] - tags: - - container_discovery - - always + ansible.builtin.debug: + msg: system has been discovered as a container - name: "Check password set for {{ ansible_user }}" + when: + - ansible_env.SUDO_USER is defined + - not system_is_ec2 + - not audit_only + - rhel8cis_rule_4_3_4 block: - name: Capture current password state of connecting user" ansible.builtin.shell: "grep {{ ansible_env.SUDO_USER }} /etc/shadow | awk -F: '{print $2}'" changed_when: false failed_when: false check_mode: false - register: ansible_user_password_set + register: discovered_ansible_user_password_set - name: "Assert that password set for {{ ansible_env.SUDO_USER }} and account not locked" ansible.builtin.assert: - that: ansible_user_password_set.stdout | length != 0 and ansible_user_password_set.stdout != "!!" + that: discovered_ansible_user_password_set.stdout | length != 0 and discovered_ansible_user_password_set.stdout != "!!" fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access" success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user" vars: - sudo_password_rule: rhel8cis_rule_5_3_4 # pragma: allowlist secret - when: - - rhel8cis_rule_5_3_4 - - ansible_env.SUDO_USER is defined - - not system_is_ec2 - tags: - - user_passwd + sudo_password_rule: rhel8cis_rule_4_3_4 # pragma: allowlist secret -- name: Include preliminary steps - ansible.builtin.import_tasks: prelim.yml +- name: Include prelim tasks tags: - prelim_tasks - - always - -- name: Include audit specific variables - ansible.builtin.include_vars: audit.yml - when: - - run_audit or audit_only - - setup_audit - tags: - - setup_audit - - run_audit - -- name: Include pre-remediation audit tasks - ansible.builtin.import_tasks: pre_remediation_audit.yml - when: - - run_audit or audit_only - - setup_audit - tags: - run_audit + ansible.builtin.import_tasks: + file: prelim.yml - name: Gather the package facts after prelim - ansible.builtin.package_facts: - manager: auto tags: - always + ansible.builtin.package_facts: + manager: auto - name: Include OS specific variables - ansible.builtin.include_vars: "{{ ansible_distribution }}.yml" tags: - always + ansible.builtin.include_vars: + file: "{{ ansible_distribution }}.yml" - name: Capture /etc/password variables - ansible.builtin.import_tasks: parse_etc_password.yml when: - rhel8cis_section5 or rhel8cis_section6 tags: - always + ansible.builtin.import_tasks: + file: parse_etc_password.yml - name: Run Section 1 tasks - ansible.builtin.import_tasks: section_1/main.yml when: - rhel8cis_section1 tags: - rhel8cis_section1 + ansible.builtin.import_tasks: + file: section_1/main.yml - name: Run Section 2 tasks - ansible.builtin.import_tasks: section_2/main.yml when: - rhel8cis_section2 tags: - rhel8cis_section2 + ansible.builtin.import_tasks: + file: section_2/main.yml - name: Run Section 3 tasks - ansible.builtin.import_tasks: section_3/main.yml when: - rhel8cis_section3 tags: - rhel8cis_section3 + ansible.builtin.import_tasks: + file: section_3/main.yml - name: Run Section 4 tasks - ansible.builtin.import_tasks: section_4/main.yml when: - rhel8cis_section4 tags: - rhel8cis_section4 + ansible.builtin.import_tasks: + file: section_4/main.yml - name: run Section 5 tasks - ansible.builtin.import_tasks: section_5/main.yml when: - rhel8cis_section5 tags: - rhel8cis_section5 + ansible.builtin.import_tasks: + file: section_5/main.yml - name: Run Section 6 tasks - ansible.builtin.import_tasks: section_6/main.yml when: - rhel8cis_section6 tags: - rhel8cis_section6 + ansible.builtin.import_tasks: + file: section_6/main.yml - name: Run auditd logic - ansible.builtin.import_tasks: auditd.yml when: - update_audit_template tags: - always + ansible.builtin.import_tasks: + file: auditd.yml -- name: run post remediation tasks - ansible.builtin.import_tasks: post.yml +- name: Run post remediation tasks tags: - post_tasks - always - -- name: Run post audit ansible.builtin.import_tasks: - file: post_remediation_audit.yml + file: post.yml + +- name: Run post_remediation audit when: - run_audit + tags: + - run_audit + ansible.builtin.import_tasks: + file: post_remediation_audit.yml - name: Show Audit Summary - ansible.builtin.debug: - msg: "{{ audit_results.split('\n') }}" when: - run_audit tags: - run_audit + ansible.builtin.debug: + msg: "{{ audit_results.split('\n') }}" - name: Output Warning count and control IDs affected - ansible.builtin.debug: - msg: "You have {{ warn_count }} warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" tags: - always + ansible.builtin.debug: + msg: "You have {{ warn_count }} warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}" diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 3c791695..7878ae20 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -6,16 +6,16 @@ ansible.builtin.shell: cat /etc/passwd changed_when: false check_mode: false - register: rhel8cis_passwd_file_audit + register: discovered_passwd_file_audit - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" ansible.builtin.set_fact: - rhel8cis_passwd: "{{ rhel8cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - with_items: "{{ rhel8cis_passwd_file_audit.stdout_lines }}" + rhel8cis_passwd: "{{ discovered_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + with_items: "{{ discovered_passwd_file_audit.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) - ld_passwd_yaml: | + ld_passwd_yaml: | # pragma: allowlist secret id: >-4 \g password: >-4 diff --git a/tasks/post.yml b/tasks/post.yml index 22f542bc..88618abd 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -12,31 +12,32 @@ - name: POST | reboot system if changes require it and not skipped block: - name: POST | Reboot system if changes require it and not skipped - ansible.builtin.reboot: when: - - change_requires_reboot + - reboot_required - not skip_reboot + ansible.builtin.reboot: - name: POST | Warning a reboot required but skip option set - ansible.builtin.debug: - msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" - changed_when: true when: - - change_requires_reboot + - reboot_required - skip_reboot + ansible.builtin.debug: + msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results" + changed_when: reboot_warning_changed_when - name: "POST | Warning a reboot required but skip option set | warning count" - ansible.builtin.import_tasks: warning_facts.yml when: - - change_requires_reboot + - reboot_required - skip_reboot + ansible.builtin.import_tasks: + file: warning_facts.yml vars: warn_control_id: Reboot_required tags: - always - name: If Warning count is 0 set fact - ansible.builtin.set_fact: - control_number: "Congratulation None Found" when: - warn_count == '0' + ansible.builtin.set_fact: + control_number: "Congratulation None Found" diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 2c51bbb0..ea72759c 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,14 +1,14 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users +- name: Post Audit | Ensure audit files readable by users ansible.builtin.file: path: "{{ item }}" mode: '0644' @@ -21,26 +21,24 @@ when: - audit_format == "json" block: - - name: capture data {{ post_audit_outfile }} - ansible.builtin.shell: cat {{ post_audit_outfile }} - register: post_audit + - name: Post Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 + register: post_audit_summary changed_when: false - - name: Capture post-audit result + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: summary."summary-line" + post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format when: - audit_format == "documentation" block: - - name: Post Audit | capture data {{ post_audit_outfile }} - ansible.builtin.shell: tail -2 {{ post_audit_outfile }} - register: post_audit + - name: Post Audit | Capture audit data if documentation format + ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + register: post_audit_summary changed_when: false - - name: Post Audit | Capture post-audit result + - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: - post_audit_summary: "{{ post_audit.stdout_lines }}" + post_audit_results: "{{ post_audit_summary.stdout }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index e3a261e7..c72136d2 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -5,7 +5,8 @@ - setup_audit tags: - setup_audit - ansible.builtin.include_tasks: LE_audit_setup.yml + ansible.builtin.include_tasks: + file: LE_audit_setup.yml - name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists ansible.builtin.file: @@ -32,23 +33,25 @@ when: - audit_content == 'copy' ansible.builtin.copy: - src: "{{ audit_local_copy }}" + src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server when: - - audit_content == 'archived' + - audit_content == 'archive' ansible.builtin.unarchive: - src: "{{ audit_conf_copy }}" - dest: "{{ audit_conf_dir }}" + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url when: - audit_content == 'get_url' - ansible.builtin.get_url: - url: "{{ audit_files_url }}" - dest: "{{ audit_conf_dir }}" + ansible.builtin.unarchive: + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit" + remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}" + extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}" - name: Pre Audit Setup | Check Goss is available when: @@ -66,53 +69,52 @@ msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" - name: Pre Audit Setup | Copy ansible default vars values to test audit + when: + - run_audit tags: - goss_template - run_audit - when: - - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" mode: '0600' - name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" + AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format when: - audit_format == "json" block: - - name: capture data {{ pre_audit_outfile }} - ansible.builtin.shell: cat {{ pre_audit_outfile }} - register: pre_audit + - name: Pre Audit | Capture audit data if json format + ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 + register: pre_audit_summary changed_when: false - - name: Pre Audit | Capture pre-audit result + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}" - vars: - summary: summary."summary-line" + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format when: - audit_format == "documentation" block: - - name: Pre Audit | capture data {{ pre_audit_outfile }} | documentation format - ansible.builtin.shell: tail -2 {{ pre_audit_outfile }} - register: pre_audit + - name: Pre Audit | Capture audit data if documentation format + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + register: pre_audit_summary changed_when: false - - name: Pre Audit | Capture pre-audit result | documentation format + - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: - pre_audit_summary: "{{ pre_audit.stdout_lines }}" + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only when: - audit_only - ansible.builtin.import_tasks: audit_only.yml + ansible.builtin.import_tasks: + file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 3b672b1b..d35cf848 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -1,268 +1,393 @@ --- # Preliminary tasks that should always be run -- name: "PRELIM | Add the required packages" +- name: "PRELIM | PATCH | Add the required packages" + tags: + - always ansible.builtin.package: name: - python3-libselinux - python3-rpm state: present + +- name: "PRELIM | AUDIT | Interactive Users" tags: - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }' + changed_when: false + register: discovered_interactive_usernames -- name: "PRELIM | Gather the package facts before prelim" - ansible.builtin.package_facts: - manager: auto +- name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - always - -# List users in order to look files inside each home directory -- name: "PRELIM | List users accounts" - ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $6 }' changed_when: false - check_mode: false - register: users + register: discovered_interactive_users_home + +- name: "PRELIM | AUDIT | Interactive UIDs" tags: - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }' + changed_when: false + register: discovered_interactive_uids -- name: "PRELIM | Gather interactive user ID min and max" +- name: "PRELIM | AUDIT | Set facts based on boot type" + tags: + - always block: - - name: "PRELIM | Gather interactive user ID min" - ansible.builtin.shell: grep ^UID_MIN /etc/login.defs | awk '{print $2}' - changed_when: false - failed_when: false - register: rhel8cis_min_uid + - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" + ansible.builtin.stat: + path: /sys/firmware/efi + register: discovered_efi_boot - - name: "PRELIM | Gather interactive user ID max" - ansible.builtin.shell: grep ^UID_MAX /etc/login.defs | awk '{print $2}' - changed_when: false - failed_when: false - register: rhel8cis_max_uid + - name: "PRELIM | AUDIT | set legacy boot and grub path fact | Bios" + when: not discovered_efi_boot.stat.exists + ansible.builtin.set_fact: + rhel8cis_legacy_boot: true + grub2_path: /etc/grub2.cfg + rhel8cis_boot_path: /boot/grub2/ - - name: "PRELIM | Setting the fact" + - name: "PRELIM | AUDIT | set grub fact | UEFI" + when: discovered_efi_boot.stat.exists ansible.builtin.set_fact: - rhel8uid_interactive_uid_start: "{{ rhel8cis_min_uid.stdout | string }}" - rhel8uid_interactive_uid_stop: "{{ rhel8cis_max_uid.stdout | string }}" - when: - - rhel8uid_info_dynamic + grub2_path: /etc/grub2-efi.cfg + rhel8cis_boot_path: "/boot/efi/EFI/{{ansible_facts.distribution | lower }}/" + +- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats" tags: - always - -- name: "PRELIM | Gather accounts with empty password fields" - ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" + ansible.builtin.stat: + path: "{{ grub2_path }}" changed_when: false - check_mode: false - register: empty_password_accounts + register: discovered_grub_cfg + +- name: "PRELIM | AUDIT | Gather the package facts before prelim" + tags: + - always + ansible.builtin.package_facts: + manager: auto + +- name: Include audit specific variables when: - - rhel8cis_rule_6_2_1 + - run_audit or audit_only + - setup_audit + tags: + - setup_audit + - run_audit + ansible.builtin.include_vars: + file: audit.yml + +- name: Include pre-remediation audit tasks + when: + - run_audit or audit_only + - setup_audit + tags: + - run_audit + ansible.builtin.import_tasks: + file: pre_remediation_audit.yml + +##### Section requirements ##### +- name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" tags: - always + ansible.builtin.set_fact: + mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" -- name: "PRELIM | Gather UID 0 accounts other than root" - ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" +- name: "PRELIM | AUDIT | Ensure /dev/shm is a separate partition | discover" + when: + - rhel8cis_rule_1_1_2_2_1 or + rhel8cis_rule_1_1_2_2_2 or + rhel8cis_rule_1_1_2_2_3 or + rhel8cis_rule_1_1_2_2_4 + tags: + - always + ansible.builtin.shell: findmnt -kn /dev/shm changed_when: false - check_mode: false - register: rhel8cis_uid_zero_accounts_except_root + failed_when: discovered_dev_shm_present.rc not in [ 0, 1 ] + register: discovered_dev_shm_present + +- name: "PRELIM | AUDIT | systemd coredump file check" when: - - rhel8cis_rule_6_2_8 + - rhel8cis_rule_1_4_4 tags: - always + ansible.builtin.stat: + path: /etc/systemd/coredump.conf + register: discovered_systemd_coredump -- name: "PRELIM | Ensure crypto-policies-scripts package is installed" +- name: "PRELIM | AUDIT | Ensure crypto-policies-scripts package is installed" + when: "'crypto-policies-scripts' not in ansible_facts.packages" + tags: + - always ansible.builtin.package: name: crypto-policies-scripts state: installed - when: - - rhel8cis_rule_1_10 + +- name: "PRELIM | AUDIT | Gather system-wide crypto-policy settings" tags: - always - -- name: "PRELIM | Gather system-wide crypto-policy settings" block: - - name: "PRELIM | Gather system-wide crypto-policy settings" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy settings" ansible.builtin.shell: 'update-crypto-policies --show' changed_when: false check_mode: false - register: rhel8cis_system_wide_crypto_policy + register: discovered_system_wide_crypto_policy - - name: "PRELIM | Gather system-wide crypto-policy | set fact for crypto policy" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy | set fact for crypto policy" ansible.builtin.set_fact: - current_crypto_policy: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[0] }}" + current_crypto_policy: "{{ discovered_system_wide_crypto_policy.stdout.split(':')[0] }}" - - name: "PRELIM | Gather system-wide crypto-policy module | set fact for crypto submodule" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy module | set fact for crypto submodule" + when: "':' in discovered_system_wide_crypto_policy.stdout" ansible.builtin.set_fact: - current_crypto_module: "{{ rhel8cis_system_wide_crypto_policy.stdout.split(':')[1] }}" - when: "':' in rhel8cis_system_wide_crypto_policy.stdout" - when: - - rhel8cis_rule_1_10 - tags: - - always + current_crypto_module: "{{ discovered_system_wide_crypto_policy.stdout.split(':')[1] }}" -- name: "PRELIM | if systemd coredump" - ansible.builtin.stat: - path: /etc/systemd/coredump.conf - register: systemd_coredump - when: - - rhel8cis_rule_1_5_1 - tags: - - always - -- name: "PRELIM | Section 1.1 | Create list of mount points" - ansible.builtin.set_fact: - mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}" - tags: - - always - -- name: "PRELIM | Install dconf" - ansible.builtin.package: - name: dconf - state: present +- name: "PRELIM | PATCH | Install dconf if gui" when: - "'gdm' in ansible_facts.packages" - "'dconf' not in ansible_facts.packages" - - rhel8cis_rule_1_8_2 or - rhel8cis_rule_1_8_3 or - rhel8cis_rule_1_8_5 + - rhel8cis_gui tags: - always - -- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: - name: audit + name: dconf state: present - when: rhel8cis_level_2 + +- name: "PRELIM | PATCH | Cron Package" + when: "'cronie' not in ansible_facts.packages" tags: - always - -- name: "PRELIM | Section 5.1 | Configure cron" ansible.builtin.package: name: cronie state: present + +- name: "PRELIM | AUDIT | Find all sudoers files." + when: + - rhel8cis_rule_4_3_4 or + rhel8cis_rule_4_3_5 tags: - always - -- name: "PRELIM | Find all sudoers files." ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" changed_when: false failed_when: false check_mode: false - register: rhel8cis_sudoers_files - when: - - rhel8cis_rule_5_3_4 or - rhel8cis_rule_5_3_5 + register: discovered_sudoers_files + +- name: "PRELIM | AUDIT | Check authselect package versions" tags: - always + - authselect + vars: + warn_control_id: 'authselect_pkg_version_too_low' + authselect_pkg_version: 1.2.6 + block: + - name: "PRELIM | AUDIT | Check authselect package versions | set fact" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '>=') + ansible.builtin.set_fact: + authselect_version: OK -- name: "PRELIM | Install authconfig" - ansible.builtin.package: - name: authconfig - state: present - when: - - rhel8cis_use_authconfig - - rhel8cis_rule_5_3_1 or - rhel8cis_rule_5_3_2 or - rhel8cis_rule_5_3_3 + - name: "PRELIM | WARNING | Check authselect package versions | Warning" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') + ansible.builtin.debug: + msg: "Warning!! Authselect controls won't run as authselect pkg version too low" + + - name: "PRELIM | WARNING | Check authselect package versions | Warning" + when: ansible_facts.packages.authselect[0].version is version(authselect_pkg_version, '<') + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "PRELIM | AUDIT | Check pam package versions" tags: - always + vars: + warn_control_id: 'pam_pkg_version_too_low' + pam_pkg_version: 1.3.1 + pam_pkg_release: 25 + block: + - name: "PRELIM | AUDIT | Check pam package versions | set fact" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '>=') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '>=') + ansible.builtin.set_fact: + pam_version: OK + + - name: "PRELIM | WARNING | Check pam package versions | Warning" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') + ansible.builtin.debug: + msg: "Warning!! Authselect controls won't run as pam package version too low" -- name: "PRELIM | Set facts based on boot type" + - name: "PRELIM | WARNING | Check pam package versions | Warning" + when: + - ansible_facts.packages.pam[0].version is version(pam_pkg_version, '<') + - ansible_facts.packages.pam[0].release is version (pam_pkg_release, '<') + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "PRELIM | AUDIT | Check authselect profile is selected" + when: + - rhel8cis_allow_authselect_updates + - rhel8cis_rule_4_4_2_1 or + rhel8cis_rule_4_4_2_2 or + rhel8cis_rule_4_4_2_3 or + rhel8cis_rule_4_4_2_4 or + rhel8cis_rule_4_4_2_5 or + rhel8cis_rule_4_4_3_1_1 or + rhel8cis_rule_4_4_3_1_2 or + rhel8cis_rule_4_4_3_1_3 + tags: + - always block: - - name: "PRELIM | Check whether machine is UEFI-based" + - name: "PRELIM | AUDIT | Check authselect profile name has been updated" + ansible.builtin.assert: + that: rhel8cis_authselect['custom_profile_name'] != 'cis_example_profile' + fail_msg: "You still have the default name for your authselect profile" + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + when: not rhel8cis_authselect_custom_profile_create + ansible.builtin.shell: authselect current + changed_when: false + failed_when: discovered_authselect_running_config.rc not in [ 0, 1 ] + register: discovered_authselect_running_config + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.assert: + that: not rhel8cis_authselect_custom_profile_create and "'example' not in rhel8cis_authselect['custom_profile_name']" or discovered_authselect_running_config is defined + success_msg: "Authselect is running and profile is selected" + fail_msg: Authselect updates have been selected there are issues with profile selection" + + - name: "PRELIM | AUDIT | Check profile exists if not created" ansible.builtin.stat: - path: /sys/firmware/efi - register: rhel_08_efi_boot + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + register: discovered_authselect_profile - - name: "PRELIM | AUDIT | set legacy boot and grub path | Bios" - ansible.builtin.set_fact: - rhel8cis_legacy_boot: true - grub2_path: /etc/grub2.cfg - when: not rhel_08_efi_boot.stat.exists + - name: "PRELIM | AUDIT | Check authselect profile exists if not created" + when: discovered_authselect_profile.stat.exists + ansible.builtin.assert: + that: not rhel8cis_authselect_custom_profile_create + success_msg: "Authselect is running and profile is selected" + fail_msg: Authselect updates have been selected but you have stated create and profile already exists" - - name: "PRELIM | set grub fact | UEFI" - ansible.builtin.set_fact: - grub2_path: /etc/grub2-efi.cfg - when: rhel_08_efi_boot.stat.exists +- name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - always + ansible.builtin.shell: > + grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }' + changed_when: false + register: discovered_interactive_users_home -- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats" - ansible.builtin.stat: - path: "{{ grub2_path }}" +- name: "PRELIM | PATCH | Section 5.1 | Configure System Accounting (auditd)" + when: + - rhel8cis_level_2 + - "'audit' not in ansible_facts.packages" + tags: + - always + ansible.builtin.package: + name: audit + state: present + +- name: "PRELIM | AUDIT | 5.2.4.x | Ensure audit log files are mode 0640 or less permissive | discover file" + ansible.builtin.shell: "grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'" changed_when: false - register: grub_cfg + failed_when: discovered_audit_logfile.rc not in [0, 1] + register: discovered_audit_logfile + when: + - rhel8cis_rule_5_2_4_1 + - rhel8cis_rule_5_2_4_2 + - rhel8cis_rule_5_2_4_3 + - rhel8cis_rule_5_2_4_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.1 + - rule_5.2.4.2 + - rule_5.2.4.3 + - rule_5.2.4.4 + +- name: "PRELIM | AUDIT | 5.2.4.5/6/7 | Audit conf and rules files | list files" + when: + - rhel8cis_rule_5_2_4_5 or + rhel8cis_rule_5_2_4_6 or + rhel8cis_rule_5_2_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.5 + - rule_5.2.4.6 + - rule_5.2.4.7 + ansible.builtin.find: + path: /etc/audit + file_type: file + recurse: true + patterns: '*.conf,*.rules' + register: discovered_auditd_conf_files + +- name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" + when: + - rhel8cis_rule_6_2_8 tags: - always + ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'" + changed_when: false + check_mode: false + register: discovered_uid_zero_accounts_except_root + +##### Optional ##### - name: "PRELIM | Optional | If IPv6 disable to stop ssh listening" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: ^AddressFamily - line: AddressFamily inet - notify: restart sshd when: - rhel8cis_ipv6_sshd_disable - not rhel8cis_ipv6_required tags: - always + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: ^AddressFamily + line: AddressFamily inet + notify: Restart_sshd - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" - ansible.builtin.lineinfile: - path: /etc/sysconfig/chronyd - regexp: ^OPTIONS="(.*)" - line: OPTIONS="\1 -4" - backrefs: true - notify: restart chronyd when: - rhel8cis_ipv6_chrony_disable - not rhel8cis_ipv6_required tags: - always + notify: Restart_chronyd + block: + - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening | Check existence" + ansible.builtin.shell: grep -E "OPTIONS=.*-4" /etc/sysconfig/chronyd + changed_when: false + failed_when: discovered_chrony_ipv6_exists.rc not in [ 0, 1] + register: discovered_chrony_ipv6_exists + + - name: "PRELIM | Optional | If IPv6 disable to stop chronyd listening" + when: discovered_chrony_ipv6_exists.stdout | length == 0 + ansible.builtin.lineinfile: + path: /etc/sysconfig/chronyd + regexp: '^OPTIONS="(?!.* -4.*)(.*)"' + line: OPTIONS="\1 -4" + backrefs: true # Optional extra keys to extend auditd not part of CIS but can influence a system # e.g. admin_space_left: '10%' - name: PRELIM | Optional | Configure other keys for auditd.conf - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^{{ item }}( |=)" - line: "{{ item }} = {{ rhel8cis_auditd_extra_conf[item] }}" - notify: restart auditd - loop: "{{ rhel8cis_auditd_extra_conf.keys() }}" when: - rhel8cis_auditd_extra_conf.keys() | length > 0 - rhel8cis_level_2 tags: - always - -# Not assigned directly to any control but a requirement - manual change for 5.4.1 if not using authselect -- name: "PRELIM | Optional | Remove the ability to login without a password" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '\snullok' - replace: '' - loop: - - /etc/pam.d/system-auth - - /etc/pam.d/password-auth - when: rhel8cis_remove_nullok - -# Allow other keys to be used while setting FUTURE or FIPS in crypto Policy -# These settings may need to be changed to personal preference -- name: "PRELIM | Optional | Override Ciphers/Keys/Macs if required on some crypto policies" - block: - - name: "PRELIM | Optional | Add Override file Ciphers/Keys/Macs if required on some crypto policies" - ansible.builtin.template: - src: crypto_policy_RSA.j2 - dest: /etc/crypto-policies/policies/modules/RSA-2048 - mode: '0440' - owner: root - group: root - register: rhel8cis_crypto_override_added - - - name: "PRELIM | Optional | Add fact to append crypto_update_command" - ansible.builtin.set_fact: - rhel8cis_crypto_override: true - when: rhel8cis_crypto_override_added is defined - when: - - rhel8cis_optional_crypto_module - - rhel8cis_crypto_policy == 'FIPS' or rhel8cis_crypto_policy == 'FUTURE' - - rhel8cis_rule_1_10 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^{{ item }}( |=)" + line: "{{ item }} = {{ rhel8cis_auditd_extra_conf[item] }}" + notify: Restart_auditd + loop: "{{ rhel8cis_auditd_extra_conf.keys() }}" diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 01fbdc78..5072c81b 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -1,103 +1,281 @@ --- -- name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled" +- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.1 + - NIST800-53R5_CM-7 + - cramfs block: - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Edit modprobe config" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install cramfs(\\s|$)" line: "install cramfs /bin/true" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | blacklist" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Disable cramfs" + - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" + when: + - not system_is_container community.general.modprobe: name: cramfs state: absent + +- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.2 + - NIST800-53R5_CM-7 + - freevxfs + block: + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install freevxfs(\\s|$)" + line: "install freevxfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist freevxfs(\\s|$)" + line: "blacklist freevxfs" + create: true + mode: '0600' + + - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs" + community.general.modprobe: + name: freevxfs + state: absent when: - not system_is_container + +- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available" when: - - rhel8cis_rule_1_1_1_1 + - rhel8cis_rule_1_1_1_3 tags: - level1-server - level1-workstation - automated - patch - - rule_1.1.1.1 - - cramfs + - rule_1.1.1.3 + - NIST800-53R5_CM-7 + - hfs + block: + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfs(\\s|$)" + line: "install hfs /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfs(\\s|$)" + line: "blacklist hfs" + create: true + mode: '0600' + + - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs" + when: + - not system_is_container + community.general.modprobe: + name: hfs + state: absent + +- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available" + when: + - rhel8cis_rule_1_1_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.4 + - NIST800-53R5_CM-7 + - hfsplus + block: + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install hfsplus(\\s|$)" + line: "install hfsplus /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist hfsplus(\\s|$)" + line: "blacklist hfsplus" + create: true + mode: '0600' -- name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled" + - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus" + when: + - not system_is_container + community.general.modprobe: + name: hfsplus + state: absent + +- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available" + when: + - rhel8cis_rule_1_1_1_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.1.1.5 + - NIST800-53R5_CM-7 + - jffs2 block: - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | Edit modprobe config" + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install jffs2(\\s|$)" + line: "install jffs2 /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist jffs2(\\s|$)" + line: "blacklist jffs2" + create: true + mode: '0600' + + - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2" + when: + - not system_is_container + community.general.modprobe: + name: jffs2 + state: absent + +- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available" + when: + - rhel8cis_rule_1_1_1_6 + tags: + - level2-server + - level2-workstation + - automated + - patch + - rule_1.1.1.6 + - NIST800-53R5_CM-7 + - squashfs + block: + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install squashfs(\\s|$)" line: "install squashfs /bin/true" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist" + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist squashfs(\\s|$)" line: "blacklist squashfs" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.2 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs" + - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs" + when: + - not system_is_container community.general.modprobe: name: squashfs state: absent - when: - - not system_is_container + +- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available" when: - - rhel8cis_rule_1_1_1_2 + - rhel8cis_rule_1_1_1_7 tags: - level2-server - level2-workstation - automated - patch - - rule_1.1.1.2 - - squashfs - -- name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disabled" + - rule_1.1.1.7 + - NIST800-53R5_CM-7 + - udf block: - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disable | Edit modprobe config" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: path: /etc/modprobe.d/CIS.conf regexp: "^(#)?install udf(\\s|$)" line: "install udf /bin/true" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf regexp: "^(#)?blacklist udf(\\s|$)" line: "blacklist udf" create: true - mode: 0600 + mode: '0600' - - name: "1.1.1.3 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf" + - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf" + when: + - not system_is_container community.general.modprobe: name: udf state: absent - when: - - not system_is_container + +- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available" when: - - rhel8cis_rule_1_1_1_3 + - rhel8cis_rule_1_1_1_8 tags: - - level2-server + - level1-server - level2-workstation - automated - patch - - rule_1.1.1.3 - - udf + - rule_1.1.1.8 + - NIST800-53R5_SI-3 + - usb + block: + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Edit modprobe config" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install usb-storage(\\s|$)" + line: "install usb-storage /bin/true" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist usb-storage(\\s|$)" + line: "blacklist usb-storage" + create: true + mode: '0600' + + - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb" + when: + - not system_is_container + community.general.modprobe: + name: usb-storage + state: absent diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml new file mode 100644 index 00000000..ac5ef2b4 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -0,0 +1,90 @@ +--- + +- name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" + when: + - rhel8cis_rule_1_1_2_1_1 + - "'/tmp' not in mount_names" + tags: + - level1-server + - level1-workstation + - automated + - audit + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.1 + vars: + warn_control_id: '1.1.2.1.1' + required_mount: '/tmp' + block: + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# via fstab +- name: | + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - item.mount == "/tmp" + - not rhel8cis_tmp_svc + - rhel8cis_rule_1_1_2_1_2 or + rhel8cis_rule_1_1_2_1_3 or + rhel8cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + ansible.posix.mount: + name: /tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_1_4 %}noexec{% endif %} + notify: Remount_tmp + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + +# via systemd +- name: | + "1.1.2.1.1 | PATCH | Ensure /tmp is configured" + "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" + "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - rhel8cis_tmp_svc + - rhel8cis_rule_1_1_2_1_1 or + rhel8cis_rule_1_1_2_1_2 or + rhel8cis_rule_1_1_2_1_3 or + rhel8cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.1.1 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + notify: Systemd_restart_tmp.mount + ansible.builtin.template: + src: etc/systemd/system/tmp.mount.j2 + dest: /etc/systemd/system/tmp.mount + owner: root + group: root + mode: '0644' diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml new file mode 100644 index 00000000..42c04a0d --- /dev/null +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -0,0 +1,56 @@ +--- + +- name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition" + when: + - rhel8cis_rule_1_1_2_2_1 + - "'/tmp' not in mount_names" + tags: + - level1-server + - level1-workstation + - automated + - audit + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.2.1 + vars: + warn_control_id: '1.1.2.2.1' + required_mount: '/dev/shm' + block: + + - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Absent" + when: discovered_dev_shm_present is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition | Present" + when: discovered_dev_shm_present is undefined + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: | + "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition + 1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition + 1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" + when: + - discovered_dev_shm_present is defined + - rhel8cis_rule_1_1_2_2_2 or + rhel8cis_rule_1_1_2_2_3 or + rhel8cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.1.2.2.1 + - rule_1.1.2.2.2 + - rule_1.1.2.2.3 + notify: Change_requires_reboot + ansible.posix.mount: + name: /dev/shm + src: tmpfs + fstype: tmpfs + state: mounted + opts: defaults,{% if rhel8cis_rule_1_1_2_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_2_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_2_4 %}noexec{% endif %} diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml new file mode 100644 index 00000000..ee6d924a --- /dev/null +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -0,0 +1,57 @@ +--- + +- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" + when: + - rhel8cis_rule_1_1_2_3_1 + - "'/home' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.3.1 + - NIST800-53R5_CM-7 + - skip_ansible_lint + vars: + warn_control_id: '1.1.2.3.1' + required_mount: '/home' + block: + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: discovered_home_mount_absent + changed_when: discovered_home_mount_absent.skipped is undefined + + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + ansible.builtin.import_tasks: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition + 1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition + when: + - "'/home' in mount_names" + - item.mount == "/home" + - rhel8cis_rule_1_1_2_3_2 or + rhel8cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - rule_1.1.2.3.2 + - rule_1.1.2.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /home + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_3_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_3_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml new file mode 100644 index 00000000..0dff27d6 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -0,0 +1,58 @@ +--- + +- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" + block: + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: discovered_var_mount_absent + changed_when: discovered_var_mount_absent.skipped is undefined + + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + vars: + warn_control_id: '1.1.2.4.1' + required_mount: '/var' + when: + - "'/var' not in mount_names" + - rhel8cis_rule_1_1_2_4_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.4.1 + +# skips if mount is absent +- name: | + "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" + "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" + when: + - "'/var' in mount_names" + - item.mount == "/var" + - rhel8cis_rule_1_1_2_4_2 or + rhel8cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.4.2 + - rule_1.1.2.4.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_4_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_4_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml new file mode 100644 index 00000000..49b913f3 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -0,0 +1,62 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" + when: + - rhel8cis_rule_1_1_2_5_1 + - "'/var/tmp' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - NIST800-53R5_CM-7 + - rule_1.1.2.5.1 + vars: + warn_control_id: '1.1.2.5.1' + required_mount: '/var/tmp' + block: + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: discovered_var_tmp_mount_absent + changed_when: discovered_var_tmp_mount_absent.skipped is undefined + + - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition" + "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" + "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" + when: + - "'/var/tmp' in mount_names" + - item.mount == "/var/tmp" + - rhel8cis_rule_1_1_2_5_2 or + rhel8cis_rule_1_1_2_5_3 or + rhel8cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.5.2 + - rule_1.1.2.5.3 + - rule_1.1.2.5.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_5_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_5_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_5_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml new file mode 100644 index 00000000..390fc415 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -0,0 +1,61 @@ +--- + +- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" + when: + - rhel8cis_rule_1_1_2_6_1 + - "'/var/log' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.6.1 + - NIST800-53R5_CM-7 + vars: + warn_control_id: '1.1.2.6.1' + required_mount: '/var/log' + block: + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: discovered_var_log_mount_absent + changed_when: discovered_var_log_mount_absent.skipped is undefined + + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition" + "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" + "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" + when: + - "'/var/log' in mount_names" + - item.mount == "/var/log" + - rhel8cis_rule_1_1_2_6_2 or + rhel8cis_rule_1_1_2_6_3 or + rhel8cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - skip_ansible_lint + - rule_1.1.2.6.2 + - rule_1.1.2.6.3 + - rule_1.1.2.6.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/log + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_6_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_6_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_6_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml new file mode 100644 index 00000000..6ebbfdb7 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -0,0 +1,60 @@ +--- + +- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" + when: + - rhel8cis_rule_1_1_2_7_1 + - "'/var/log/audit' not in mount_names" + tags: + - level2-server + - level2-workstation + - automated + - audit + - mounts + - rule_1.1.2.7.1 + - NIST800-53R5_CM-7 + vars: + warn_control_id: '1.1.2.7.1' + required_mount: '/var/log/audit' + block: + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn if partition is absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + register: discovered_var_log_audit_mount_absent + changed_when: discovered_var_log_audit_mount_absent.skipped is undefined + + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# skips if mount is absent +- name: | + "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" + "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" + "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" + when: + - "'/var/log/audit' in mount_names" + - item.mount == "/var/log/audit" + - rhel8cis_rule_1_1_2_7_2 or + rhel8cis_rule_1_1_2_7_3 or + rhel8cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - mounts + - rule_1.1.2.7.2 + - rule_1.1.2.7.3 + - rule_1.1.2.7.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + notify: Change_requires_reboot + ansible.posix.mount: + name: /var/log/audit + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel8cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_7_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml deleted file mode 100644 index c77a25a2..00000000 --- a/tasks/section_1/cis_1.1.2.x.yml +++ /dev/null @@ -1,84 +0,0 @@ ---- - -- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition" - block: - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.2.1' - required_mount: '/tmp' - when: - - rhel8cis_rule_1_1_2_1 - - "'/tmp' not in mount_names" - tags: - - level1-server - - level1-workstation - - automated - - audit - - mounts - - rule_1.1.2.1 - -# via fstab -- name: | - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.posix.mount: - name: /tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_2_4 %}nosuid{% endif %} - notify: remount tmp - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - item.mount == "/tmp" - - not rhel8cis_tmp_svc - - rhel8cis_rule_1_1_2_2 or - rhel8cis_rule_1_1_2_3 or - rhel8cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 - -# via systemd -- name: | - "1.1.2.1 | PATCH | Ensure /tmp is configured" - "1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition" - "1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition" - "1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition" - ansible.builtin.template: - src: etc/systemd/system/tmp.mount.j2 - dest: /etc/systemd/system/tmp.mount - owner: root - group: root - mode: 0644 - notify: systemd restart tmp.mount - when: - - rhel8cis_tmp_svc - - rhel8cis_rule_1_1_2_1 or - rhel8cis_rule_1_1_2_2 or - rhel8cis_rule_1_1_2_3 or - rhel8cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.2.1 - - rule_1.1.2.2 - - rule_1.1.2.3 - - rule_1.1.2.4 diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml deleted file mode 100644 index 9a7b7f4f..00000000 --- a/tasks/section_1/cis_1.1.3.x.yml +++ /dev/null @@ -1,59 +0,0 @@ ---- - -- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var" - block: - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_mount_absent - changed_when: var_mount_absent.skipped is undefined - - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.3.1' - required_mount: '/var' - when: - - "'/var' not in mount_names" - - rhel8cis_rule_1_1_3_1 - tags: - - level2-server - - level2-workstation - - automated - - patch - - mounts - - rule_1.1.3.1 - -# skips if mount is absent -- name: | - "1.1.3.2 | PATCH | Ensure nodev option set on /var partition" - "1.1.3.3 | PATCH | Ensure noexec option set on /var partition" - "1.1.3.4 | PATCH | Ensure nosuid option set on /var partition" - ansible.posix.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_3_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_3_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var' in mount_names" - - item.mount == "/var" - - rhel8cis_rule_1_1_3_1 # This is required so the check takes place - - rhel8cis_rule_1_1_3_2 or - rhel8cis_rule_1_1_3_3 or - rhel8cis_rule_1_1_3_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.3.2 - - rule_1.1.3.3 - - rule_1.1.3.4 diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml deleted file mode 100644 index 454318f3..00000000 --- a/tasks/section_1/cis_1.1.4.x.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- - -# Skips if mount is absent -- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp" - block: - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_tmp_mount_absent - changed_when: var_tmp_mount_absent.skipped is undefined - - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.1.4.1' - required_mount: '/var/tmp' - when: - - rhel8cis_rule_1_1_4_1 - - "'/var/tmp' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.4.1 - -# skips if mount is absent -- name: | - "1.1.4.2 | PATCH | Ensure noexec option set on /var/tmp partition" - "1.1.4.3 | PATCH | Ensure nosuid option set on /var/tmp partition" - "1.1.4.4 | PATCH | Ensure nodev option set on /var/tmp partition" - ansible.posix.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_4_4 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_4_3 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/tmp' in mount_names" - - item.mount == "/var/tmp" - - rhel8cis_rule_1_1_4_1 # This is required so the check takes place - - rhel8cis_rule_1_1_4_2 or - rhel8cis_rule_1_1_4_3 or - rhel8cis_rule_1_1_4_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.4.2 - - rule_1.1.4.3 - - rule_1.1.4.4 diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml deleted file mode 100644 index 2614cc1e..00000000 --- a/tasks/section_1/cis_1.1.5.x.yml +++ /dev/null @@ -1,61 +0,0 @@ ---- - -- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log" - block: - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_mount_absent - changed_when: var_log_mount_absent.skipped is undefined - - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.5.1' - required_mount: '/var/log' - when: - - rhel8cis_rule_1_1_5_1 - - "'/var/log' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.5.1 - - skip_ansible_lint - -# skips if mount is absent -- name: | - "1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition" - "1.1.5.3 | PATCH | Ensure noexec option set on /var/log partition" - "1.1.5.4 | PATCH | Ensure nosuid option set on /var/log partition" - ansible.posix.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_5_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/log' in mount_names" - - item.mount == "/var/log" - - rhel8cis_rule_1_1_5_1 # This is required so the check takes place - - rhel8cis_rule_1_1_5_2 or - rhel8cis_rule_1_1_5_3 or - rhel8cis_rule_1_1_5_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.5.2 - - rule_1.1.5.3 - - rule_1.1.5.4 diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml deleted file mode 100644 index 8cb7fac3..00000000 --- a/tasks/section_1/cis_1.1.6.x.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- - -- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit" - block: - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: var_log_audit_mount_absent - changed_when: var_log_audit_mount_absent.skipped is undefined - - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.6.1' - required_mount: '/var/log/audit' - when: - - rhel8cis_rule_1_1_6_1 - - "'/var/log/audit' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.6.1 - -# skips if mount is absent -- name: | - "1.1.6.2 | PATCH | Ensure noexec option set on /var/log/audit partition" - "1.1.6.3 | PATCH | Ensure nodev option set on /var/log/audit partition" - "1.1.6.4 | PATCH | Ensure nosuid option set on /var/log/audit partition" - ansible.posix.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_6_4 %}nosuid{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/var/log/audit' in mount_names" - - item.mount == "/var/log/audit" - - rhel8cis_rule_1_1_6_1 # This is required so the check takes place - - rhel8cis_rule_1_1_6_2 or - rhel8cis_rule_1_1_6_3 or - rhel8cis_rule_1_1_6_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - skip_ansible_lint - - rule_1.1.6.2 - - rule_1.1.6.3 - - rule_1.1.6.4 diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml deleted file mode 100644 index 63d2240d..00000000 --- a/tasks/section_1/cis_1.1.7.x.yml +++ /dev/null @@ -1,63 +0,0 @@ ---- - -- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home" - block: - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Warn if partition is absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - register: home_mount_absent - changed_when: home_mount_absent.skipped is undefined - - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: warning_facts.yml - - vars: - warn_control_id: '1.1.7.1' - required_mount: '/home' - when: - - rhel8cis_rule_1_1_7_1 - - "'/home' not in mount_names" - tags: - - level2-server - - level2-workstation - - automated - - audit - - mounts - - rule_1.1.7.1 - - skip_ansible_lint - -# skips if mount is absent -- name: | - "1.1.7.2 | PATCH | Ensure nodev option set on /home partition - 1.1.7.3 | PATCH | Ensure nosuid option set on /home partition - 1.1.7.4 | PATCH | Ensure usrquota option set on /home partition - 1.1.7.5 | PATCH | Ensure grpquota option set on /home partition" - ansible.posix.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel8cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_7_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_7_4 %}usrquota,{% endif %}{% if rhel8cis_rule_1_1_7_5 %}grpquota{% endif %} - notify: change_requires_reboot - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - "'/home' in mount_names" - - item.mount == "/home" - - rhel8cis_rule_1_1_7_1 - - rhel8cis_rule_1_1_7_2 or - rhel8cis_rule_1_1_7_3 or - rhel8cis_rule_1_1_7_4 or - rhel8cis_rule_1_1_7_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.7.2 - - rule_1.1.7.3 - - rule_1.1.7.4 - - skip_ansible_lint diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml deleted file mode 100644 index 4bdbd8f5..00000000 --- a/tasks/section_1/cis_1.1.8.x.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- - -# Skips if mount is absent -- name: | - "1.1.8.1 | PATCH | Ensure nodev option set on /dev/shm partition - 1.1.8.2 | PATCH | Ensure nosuid option set on /dev/shm partition - 1.1.8.3 | PATCH | Ensure noexec option set on /dev/shm partition" - block: - - name: | - "1.1.8.1 | AUDIT | Ensure nodev option set on /dev/shm partition | Check for /dev/shm existence - 1.1.8.2 | AUDIT | Ensure nosuid option set on /dev/shm partition | Check for /dev/shm existence - 1.1.8.3 | AUDIT | Ensure noexec option set on /dev/shm partition | Check for /dev/shm existence" - ansible.builtin.shell: mount -l | grep -E '\s/dev/shm\s' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_1_1_8_x_dev_shm_status - - - name: | - "1.1.8.1 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option - 1.1.8.2 | PATCH | Ensure noexec option set on /dev/shm partition | Set nosuid option - 1.1.8.3 | PATCH | Ensure nosuid option set on /dev/shm partition | Set noexec option" - ansible.posix.mount: - name: /dev/shm - src: tmpfs - fstype: tmpfs - state: mounted - opts: defaults,{% if rhel8cis_rule_1_1_8_2 %}noexec,{% endif %}{% if rhel8cis_rule_1_1_8_1 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_8_3 %}nosuid{% endif %} - when: "'dev/shm' in rhel8cis_1_1_8_x_dev_shm_status.stdout" - notify: change_requires_reboot - when: - - rhel8cis_rule_1_1_8_1 or - rhel8cis_rule_1_1_8_2 or - rhel8cis_rule_1_1_8_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - mounts - - rule_1.1.8.1 - - rule_1.1.8.2 - - rule_1.1.8.3 diff --git a/tasks/section_1/cis_1.1.x.yml b/tasks/section_1/cis_1.1.x.yml deleted file mode 100644 index 1131f810..00000000 --- a/tasks/section_1/cis_1.1.x.yml +++ /dev/null @@ -1,53 +0,0 @@ ---- - -- name: "1.1.9 | PATCH | Disable Automounting" - ansible.builtin.service: - name: autofs - enabled: false - when: - - not rhel8cis_allow_autofs - - "'autofs' in ansible_facts.packages" - - rhel8cis_rule_1_1_9 - tags: - - level1-server - - level2-workstation - - automated - - patch - - mounts - - automounting - - rule_1.1.9 - -- name: "1.1.10 | PATCH | Disable USB Storage" - block: - - name: "1.1.10 | PATCH | Disable USB Storage | Edit modprobe config" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install usb-storage(\\s|$)" - line: "install usb-storage /bin/true" - create: true - owner: root - group: root - mode: 0600 - - - name: "1.1.10 | PATCH | Disable USB Storage | | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist usb-storage(\\s|$)" - line: "blacklist usb-storage" - create: true - mode: 0600 - - - name: "1.1.10 | PATCH | Disable USB Storage | Edit modprobe config" - community.general.modprobe: - name: usb-storage - state: absent - when: - - rhel8cis_rule_1_1_10 - tags: - - level1-server - - level2-workstation - - automated - - patch - - mounts - - removable_storage - - rule_1.1.10 diff --git a/tasks/section_1/cis_1.10.yml b/tasks/section_1/cis_1.10.yml deleted file mode 100644 index 765b5241..00000000 --- a/tasks/section_1/cis_1.10.yml +++ /dev/null @@ -1,24 +0,0 @@ ---- - -- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - block: - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact" - ansible.builtin.set_fact: - rhel8cis_full_crypto_policy: "{{ rhel8cis_crypto_policy }}{% if rhel8cis_crypto_policy_module | length > 0 %}:{{ rhel8cis_crypto_policy_module }}{% endif %}" - - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}{% if rhel8cis_crypto_override %}:RSA-2048{% endif %}" - update-crypto-policies - notify: change_requires_reboot - when: - - rhel8cis_system_wide_crypto_policy.stdout != rhel8cis_full_crypto_policy - when: - - rhel8cis_rule_1_10 - tags: - - level1-server - - level1-workstation - - automated - - no system_is_ec2 - - patch - - rule_1.10 diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index d43e4b03..4cfa9470 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -1,92 +1,152 @@ --- -- name: "1.2.1 | PATCH | Ensure Red Hat Subscription Manager connection is configured" - community.general.redhat_subscription: - state: present - username: "{{ rhel8cis_rh_sub_user }}" - password: "{{ rhel8cis_rh_sub_password }}" - auto_attach: true - no_log: true +- name: "1.2.1 | AUDIT | Ensure GPG keys are configured" when: - - ansible_distribution == "RedHat" - - rhel8cis_rhnsd_required - rhel8cis_rule_1_2_1 + - ansible_distribution == "RedHat" or + ansible_distribution == "Rocky" or + ansible_distribution == "AlmaLinux" or + ansible_distribution == "Oracle Linux" tags: - level1-server - level1-workstation - manual - patch + - NIST800-53R5_SI-2 - rule_1.2.1 - - skip_ansible_lint # Added as no_log still errors on ansible-lint -- name: "1.2.2 | AUDIT | Ensure GPG keys are configured" ansible.builtin.shell: "PKG=`rpm -qf {{ rpm_gpg_key }}` && rpm -q --queryformat \"%{PACKAGER} %{SIGPGP:pgpsig}\\n\" \"${PKG}\" | grep \"^{{ rpm_packager }}.*Key.ID.{{ rpm_key }}\"" changed_when: false + +- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated" when: - rhel8cis_rule_1_2_2 - - ansible_distribution == "RedHat" or - ansible_distribution == "Rocky" or - ansible_distribution == "AlmaLinux" or - ansible_distribution == "OracleLinux" tags: - level1-server - level1-workstation - - manual + - automated - patch + - NIST800-53R5_SI-2 - rule_1.2.2 - -- name: "1.2.3 | PATCH | Ensure gpgcheck is globally activated" block: - - name: "1.2.3 | AUDIT | Ensure gpgcheck is globally activated | Find repos" + - name: "1.2.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" - register: yum_repos + register: discovered_yum_repos changed_when: false - - name: "1.2.3 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" + - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" ansible.builtin.replace: name: "{{ item.path }}" regexp: "^gpgcheck=0" replace: "gpgcheck=1" - with_items: - - "{{ yum_repos.files }}" + loop: "{{ discovered_yum_repos.files }}" loop_control: label: "{{ item.path }}" + + - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^(#|)gpgcheck= + line: gpgcheck=1 + +- name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated" when: - rhel8cis_rule_1_2_3 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - patch + - NIST800-53R5_SI-2 - rule_1.2.3 + block: + - name: "1.2.3 | AUDIT | Ensure repo_gpgcheck is globally activated | Find repos" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: discovered_yum_repos + changed_when: false + + - name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated | Update yum.repos" + ansible.builtin.replace: + name: "{{ item.path }}" + regexp: "^repo_gpgcheck=0" + replace: "repo_gpgcheck=1" + loop: "{{ discovered_yum_repos.files }}" + loop_control: + label: "{{ item.path }}" + + - name: "1.2.3 | PATCH | Ensure repo_gpgcheck is globally activated | Update dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^(#|)repo_gpgcheck= + line: repo_gpgcheck=1 - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured" + when: + - rhel8cis_rule_1_2_4 + tags: + - level1-server + - level1-workstation + - manual + - audit + - NIST800-53R5_SI-2 + - rule_1.2.4 + vars: + warn_control_id: '1.2.4' block: - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Get repo list" ansible.builtin.shell: dnf repolist changed_when: false failed_when: false - register: dnf_configured + register: discovered_dnf_configured check_mode: false - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Display repo list" ansible.builtin.debug: msg: - "Warning!! Below are the configured repos. Please review and make sure all align with site policy" - - "{{ dnf_configured.stdout_lines }}" + - "{{ discovered_dnf_configured.stdout_lines }}" - name: "1.2.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '1.2.4' + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed" when: - - rhel8cis_rule_1_2_4 + - rhel8cis_rule_1_2_5 + - not system_is_ec2 tags: - level1-server - level1-workstation - - manual - - audit - - rule_1.2.4 - - skip_ansible_lint + - automated + - patch + - rule_1.2_5 + notify: Change_requires_reboot + block: + - name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | Patch" + ansible.builtin.package: + name: "*" + state: latest + + - name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | update_facts" + ansible.builtin.package_facts: + manager: auto + +- name: "1.2.5 | PATCH | Ensure updates, patches, and additional security software are installed | limit kernels" + when: + - rhel8cis_rule_1_2_5 + - rhel8cis_apply_installed_kernel_limit + tags: + - level1-server + - level1-workstation + - automated + - patch + - kernel_limit + - rule_1.2.5 + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: ^installonly_limit= + line: installonly_limit={{ rhel8cis_installed_kernel_limit }} diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml index a3916384..9c82fe44 100644 --- a/tasks/section_1/cis_1.3.x.yml +++ b/tasks/section_1/cis_1.3.x.yml @@ -1,51 +1,71 @@ --- -- name: "1.3.1 | PATCH | Ensure AIDE is installed" - block: - - name: "1.3.1 | PATCH | Ensure AIDE is installed | Install AIDE" - ansible.builtin.package: - name: aide - state: present - - - name: "1.3.1 | PATCH | Ensure AIDE is installed | Configure AIDE" - ansible.builtin.shell: /usr/sbin/aide --init -B 'database_out=file:/var/lib/aide/aide.db.gz' - changed_when: false - failed_when: false - async: 45 - poll: 0 - args: - creates: /var/lib/aide/aide.db.gz - when: not ansible_check_mode +- name: "1.3.1 | PATCH | Ensure bootloader password is set" + ansible.builtin.copy: + dest: "{{ rhel8cis_boot_path }}user.cfg" # noqa template-instead-of-copy + content: "GRUB2_PASSWORD={{ rhel8cis_bootloader_password_hash }}" + owner: root + group: root + mode: '0600' + notify: Rebuild_grub when: - - rhel8cis_config_aide + - rhel8cis_set_boot_pass - rhel8cis_rule_1_3_1 tags: - level1-server - level1-workstation - automated - - aide + - grub - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.3.1 -- name: "1.3.2 | PATCH | Ensure filesystem integrity is regularly checked" - ansible.builtin.cron: - name: Run AIDE integrity check - cron_file: "{{ rhel8cis_aide_cron['cron_file'] }}" - user: "{{ rhel8cis_aide_cron['cron_user'] }}" - minute: "{{ rhel8cis_aide_cron['aide_minute'] | default('0') }}" - hour: "{{ rhel8cis_aide_cron['aide_hour'] | default('5') }}" - day: "{{ rhel8cis_aide_cron['aide_day'] | default('*') }}" - month: "{{ rhel8cis_aide_cron['aide_month'] | default('*') }}" - weekday: "{{ rhel8cis_aide_cron['aide_weekday'] | default('*') }}" - job: "{{ rhel8cis_aide_cron['aide_job'] }}" +- name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured" when: - rhel8cis_rule_1_3_2 - - not system_is_ec2 + - discovered_grub_cfg.stat.exists + - discovered_grub_cfg.stat.islnk tags: - level1-server - level1-workstation - automated - - aide - - file_integrity + - grub - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.3.2 + block: + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | BIOS" + when: rhel8cis_legacy_boot + ansible.builtin.file: + path: "{{ rhel8cis_boot_path }}" + owner: root + group: root + mode: '0600' + recurse: true + + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | EFI" + when: not rhel8cis_legacy_boot + ansible.builtin.file: + path: "{{ rhel8cis_boot_path }}" + owner: root + group: root + mode: '0700' + recurse: true + + - name: "1.3.2 | PATCH | Ensure permissions on bootloader config are configured | UEFI" + when: + - not rhel8cis_legacy_boot + - item.mount == "/boot/efi" + notify: Change_requires_reboot + ansible.posix.mount: + name: /boot/efi + src: "UUID={{ item.uuid }}" + fstype: vfat + state: present + opts: defaults,umask=0027,fmask=0077,uid=0,gid=0 + passno: '0' + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 5a2c487e..818b5eba 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -1,74 +1,80 @@ --- -- name: "1.4.1 | PATCH | Ensure bootloader password is set" - ansible.builtin.copy: - dest: /boot/grub2/user.cfg # noqa template-instead-of-copy - content: "GRUB2_PASSWORD={{ rhel8cis_bootloader_password_hash }}" - owner: root - group: root - mode: 0600 - notify: rhel8cis_grub2cfg +- name: "1.4.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" when: - - rhel8cis_set_boot_pass - rhel8cis_rule_1_4_1 tags: - level1-server - level1-workstation - automated - - grub - patch + - sysctl + - NIST800-53R5_CM-6 - rule_1.4.1 + notify: Reload_sysctl + ansible.builtin.lineinfile: + path: /etc/sysctl.d/60-kernel_sysctl.conf + regexp: kernel.randomize_va_space + line: kernel.randomize_va_space = 2 + create: true -- name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - block: - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - ansible.builtin.file: - path: "{{ grub_cfg.stat.lnk_source }}" - owner: root - group: root - mode: 0600 - - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | UEFI" - ansible.posix.mount: - name: /boot/efi - src: "UUID={{ item.uuid }}" - fstype: vfat - state: present - opts: defaults,umask=0027,fmask=0077,uid=0,gid=0 - passno: '0' - with_items: - - "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" - when: - - not rhel8cis_legacy_boot - - item.mount == "/boot/efi" +- name: "1.4.2 | PATCH | Ensure ptrace_scope is restricted" when: - rhel8cis_rule_1_4_2 - - grub_cfg.stat.exists - - grub_cfg.stat.islnk tags: - level1-server - level1-workstation - automated - - grub - patch + - sysctl + - NIST800-53R5_CM-6 - rule_1.4.2 + notify: Reload_sysctl + block: + - name: Ensure ptrace_scope is restricted | Set file + ansible.builtin.lineinfile: + path: /etc/sysctl.d/60-kernel_sysctl.conf + regexp: kernel.yama.ptrace_scope + line: kernel.yama.ptrace_scope = 1 + create: true + + - name: Ensure ptrace_scope is restricted | comment out other entry + ansible.builtin.lineinfile: + path: /lib/sysctl.d/10-default-yama-scope.conf + backrefs: true + regexp: ^(\s*kernel.yama.ptrace_scope.*) + line: '# \1' + create: true -- name: "1.4.3 | PATCH | Ensure authentication is required when booting into rescue mode" +- name: "1.4.3 | PATCH | Ensure core dump backtraces are disabled" + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_CM-6 + - rule_1.4.3 ansible.builtin.lineinfile: - path: /etc/systemd/system/rescue.service.d/00-require-auth.conf - regexp: '^ExecStart=' - line: "ExecStart=-/usr/lib/systemd/systemd-sulogin-shell rescue" + path: /etc/systemd/coredump.conf + regexp: 'ProcessSizeMax=' + line: 'ProcessSizeMax=0' create: true - owner: root - group: root - mode: 0644 when: - rhel8cis_rule_1_4_3 + +- name: "1.4.4 | PATCH | Ensure core dump storage is disabled" + when: + - rhel8cis_rule_1_4_4 + - discovered_systemd_coredump.stat.exists tags: - level1-server - level1-workstation - automated - patch - - rule_1.4.3 + - rule_1.4.4 + notify: Systemd_daemon_reload + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: 'Storage=' + line: 'Storage=none' diff --git a/tasks/section_1/cis_1.5.1.x.yml b/tasks/section_1/cis_1.5.1.x.yml new file mode 100644 index 00000000..971c336c --- /dev/null +++ b/tasks/section_1/cis_1.5.1.x.yml @@ -0,0 +1,152 @@ +--- + +- name: "1.5.1.1 | PATCH | Ensure SELinux is installed" + when: + - rhel8cis_rule_1_5_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.1 + ansible.builtin.package: + name: libselinux + state: present + +- name: "1.5.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" + when: + - rhel8cis_rule_1_5_1_2 + tags: + - level1-server + - level1-workstation + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.2 + notify: Rebuild_grub + ansible.builtin.replace: + path: /etc/default/grub + regexp: '(selinux|enforcing)\s*=\s*0\s*' + replace: '' + +# State set to enforcing because control 1.5.1.5 requires enforcing to be set +- name: "1.5.1.3 | PATCH | Ensure SELinux policy is configured" + when: + - rhel8cis_rule_1_5_1_3 + tags: + - level1-server + - level1-workstation + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.3 + notify: Change_requires_reboot + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: "{{ rhel8cis_selinux_state }}" + +# State set to enforcing because control 1.6.1.5 requires enforcing to be set +- name: "1.5.1.4 | PATCH | Ensure the SELinux mode is not disabled" + when: + - rhel8cis_rule_1_5_1_4 + tags: + - level1-server + - level1-workstation + - auotmated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.4 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: "{{ rhel8cis_selinux_state }}" + +- name: "1.5.1.5 | PATCH | Ensure the SELinux state is enforcing" + when: + - rhel8cis_rule_1_5_1_5 + tags: + - level2-server + - level2-workstation + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.5 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel8cis_selinux_policy }}" + state: enforcing + +- name: "1.5.1.6 | AUDIT | Ensure no unconfined services exist" + when: + - rhel8cis_rule_1_5_1_6 + tags: + - level1-server + - level1-workstation + - automated + - audit + - services + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.6 + vars: + warn_control_id: '1.5.1.6' + block: + - name: "1.5.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' + register: discovered_unconf_services + failed_when: false + changed_when: false + + - name: "1.5.1.6 | WARNING | Ensure no unconfined services exist | Message on unconfined services" + when: + - discovered_unconf_services is defined + - discovered_unconf_services.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! You have unconfined services: {{ discovered_unconf_services.stdout_lines }}" + + - name: "1.5.1.6 | WARNING | Ensure no unconfined services exist | warning count" + when: + - discovered_unconf_services is defined + - discovered_unconf_services.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.5.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" + when: + - rhel8cis_rule_1_5_1_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.7 + ansible.builtin.package: + name: mcstrans + state: absent + +- name: "1.5.1.8 | PATCH | Ensure SETroubleshoot is not installed" + ansible.builtin.package: + name: setroubleshoot + state: absent + when: + - rhel8cis_rule_1_5_1_8 + - "'setroubleshoot' in ansible_facts.packages" + tags: + - level1-server + - automated + - selinux + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_1.5.1.8 diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml deleted file mode 100644 index f035f682..00000000 --- a/tasks/section_1/cis_1.5.x.yml +++ /dev/null @@ -1,48 +0,0 @@ ---- - -- name: "1.5.1 | PATCH | Ensure core dump storage is disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: 'Storage=' - line: 'Storage=none' - notify: systemd_daemon_reload - when: - - rhel8cis_rule_1_5_1 - - systemd_coredump.stat.exists - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.5.1 - -- name: "1.5.2 | PATCH | Ensure core dump backtraces are disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: 'ProcessSizeMax=' - line: 'ProcessSizeMax=0' - when: - - rhel8cis_rule_1_5_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sysctl - - rule_1.5.2 - -- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.posix.sysctl: - name: kernel.randomize_va_space - value: '2' - sysctl_set: true - ignoreerrors: true - when: - - rhel8cis_rule_1_5_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sysctl - - rule_1.5.3 diff --git a/tasks/section_1/cis_1.6.1.x.yml b/tasks/section_1/cis_1.6.1.x.yml deleted file mode 100644 index fde021c7..00000000 --- a/tasks/section_1/cis_1.6.1.x.yml +++ /dev/null @@ -1,135 +0,0 @@ ---- - -- name: "1.6.1.1 | PATCH | Ensure SELinux is installed" - ansible.builtin.package: - name: libselinux - state: present - when: - - rhel8cis_rule_1_6_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.6.1.1 - -- name: "1.6.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" - ansible.builtin.replace: - path: /etc/default/grub - regexp: '(selinux|enforcing)\s*=\s*0\s*' - replace: '' - register: selinux_grub_patch - ignore_errors: true # noqa ignore-errors - notify: rhel8cis_grub2cfg - when: - - rhel8cis_rule_1_6_1_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.6.1.2 - -# State set to enforcing because control 1.6.1.5 requires enforcing to be set -- name: "1.6.1.3 | PATCH | Ensure SELinux policy is configured" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: "{{ rhel8cis_selinux_state }}" - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_3 - tags: - - level1-server - - level1-workstation - - automated - - selinux - - patch - - rule_1.6.1.3 - -# State set to enforcing because control 1.6.1.5 requires enforcing to be set -- name: "1.6.1.4 | PATCH | Ensure the SELinux mode is not disabled" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: "{{ rhel8cis_selinux_state }}" - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_4 - tags: - - level1-server - - level1-workstation - - automated - - selinux - - patch - - rule_1.6.1.4 - -- name: "1.6.1.5 | PATCH | Ensure the SELinux state is enforcing" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel8cis_selinux_policy }}" - state: enforcing - when: - - not rhel8cis_selinux_disable - - rhel8cis_rule_1_6_1_5 - tags: - - level2-server - - level2-workstation - - automated - - selinux - - patch - - rule_1.6.1.5 - -- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist" - block: - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services" - ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' - register: rhelcis_1_6_1_6_unconf_services - failed_when: false - changed_when: false - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" - ansible.builtin.debug: - msg: "Warning!! You have unconfined services: {{ rhelcis_1_6_1_6_unconf_services.stdout_lines }}" - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - - - name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | warning count" - ansible.builtin.import_tasks: warning_facts.yml - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - vars: - warn_control_id: '1.6.1.6' - when: - - rhel8cis_rule_1_6_1_6 - tags: - - level1-server - - level1-workstation - - automated - - audit - - services - - rule_1.6.1.6 - -- name: "1.6.1.7 | PATCH | Ensure SETroubleshoot is not installed" - ansible.builtin.package: - name: setroubleshoot - state: absent - when: - - rhel8cis_rule_1_6_1_7 - - "'setroubleshoot' in ansible_facts.packages" - tags: - - level1-server - - automated - - selinux - - patch - - rule_1.6.1.7 - -- name: "1.6.1.8 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" - ansible.builtin.package: - name: mcstrans - state: absent - when: - - rhel8cis_rule_1_6_1_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_1.6.1.8 diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml new file mode 100644 index 00000000..4e619c49 --- /dev/null +++ b/tasks/section_1/cis_1.6.x.yml @@ -0,0 +1,87 @@ +--- + +- name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" + when: + - rhel8cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_SC-8 + - rule_1.6.1 + notify: Change_requires_reboot + block: + - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact" + ansible.builtin.set_fact: + rhel8cis_full_crypto_policy: "{{ rhel8cis_crypto_policy }}{% if rhel8cis_crypto_policy_module | length > 0 %}:{{ rhel8cis_crypto_policy_module }}{% endif %}" + + - name: "1.6.1 | PATCH | Ensure system-wide crypto policy is not legacy" + when: + - rhel8cis_full_crypto_policy not in discovered_system_wide_crypto_policy.stdout + ansible.builtin.shell: | + update-crypto-policies --set "{{ rhel8cis_full_crypto_policy }}" + update-crypto-policies + +- name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" + when: + - rhel8cis_rule_1_6_2 + - "'NO-SHA1' not in discovered_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_SC-8 + - rule_1.6.2 + notify: Change_requires_reboot + block: + - name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod + src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 + + - name: "1.6.2 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:NO-SHA1" + +- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh" + when: + - rhel8cis_rule_1_6_3 + - "'NO-SSHCBC' not in discovered_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_SC-8 + - rule_1.6.3 + notify: Change_requires_reboot + block: + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod + src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 + + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables cbc for ssh | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:{% if rhel8cis_rule_1_6_2 %}NO-SHA1:{% endif %}NO-SSHCBC" + +- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" + when: + - rhel8cis_rule_1_6_4 + - "'NO-WEAKMAC' not in discovered_system_wide_crypto_policy.stdout" + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_SC-8 + - rule_1.6.4 + notify: Change_requires_reboot + block: + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables cbc for ssh | crypto_file" + ansible.builtin.template: + dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod + src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 + + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables cbc for ssh | set crypto policy" + ansible.builtin.shell: "update-crypto-policies --set {{ rhel8cis_full_crypto_policy }}:{% if rhel8cis_rule_1_6_2 %}NO-SHA1:{% endif %}{% if rhel8cis_rule_1_6_3 %}NO-SSHCBC:{% endif %}NO-WEAKMAC" diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index c4745540..9c240b4e 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -1,12 +1,6 @@ --- - name: "1.7.1 | PATCH | Ensure message of the day is configured properly" - ansible.builtin.template: - src: etc/motd.j2 - dest: /etc/motd - owner: root - group: root - mode: 0644 when: - rhel8cis_rule_1_7_1 tags: @@ -15,15 +9,18 @@ - automated - banner - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.1 - -- name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" ansible.builtin.template: - src: etc/issue.j2 - dest: /etc/issue + src: etc/motd.j2 + dest: /etc/motd owner: root group: root - mode: 0644 + mode: go-rx + +- name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" when: - rhel8cis_rule_1_7_2 tags: @@ -31,15 +28,18 @@ - level1-workstation - automated - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.2 - -- name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" ansible.builtin.template: - src: etc/issue.net.j2 - dest: /etc/issue.net + src: etc/issue.j2 + dest: /etc/issue owner: root group: root - mode: 0644 + mode: go-rx + +- name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" when: - rhel8cis_rule_1_7_3 tags: @@ -48,15 +48,18 @@ - automated - banner - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 - rule_1.7.3 - -- name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured" - ansible.builtin.file: - path: /etc/motd - state: file + ansible.builtin.template: + src: etc/issue.net.j2 + dest: /etc/issue.net owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.4 | PATCH | Ensure access to /etc/motd is configured" when: - rhel8cis_rule_1_7_4 tags: @@ -65,15 +68,17 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.4 - -- name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured" ansible.builtin.file: - path: /etc/issue + path: /etc/motd state: file owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.5 | PATCH | Ensure access to /etc/issue is configured" when: - rhel8cis_rule_1_7_5 tags: @@ -82,15 +87,17 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.5 - -- name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured" ansible.builtin.file: - path: /etc/issue.net + path: /etc/issue state: file owner: root group: root - mode: 0644 + mode: go-wx + +- name: "1.7.6 | PATCH | Ensure access to /etc/issue.net is configured" when: - rhel8cis_rule_1_7_6 tags: @@ -99,4 +106,12 @@ - automated - perms - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_1.7.6 + ansible.builtin.file: + path: /etc/issue.net + state: file + owner: root + group: root + mode: go-wx diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index 877a5756..dcc2f2aa 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -1,9 +1,6 @@ --- - name: "1.8.1 | PATCH | Ensure GNOME Display Manager is removed" - ansible.builtin.package: - name: gdm - state: absent when: - rhel8cis_rule_1_8_1 - "'gdm' in ansible_facts.packages" @@ -15,8 +12,22 @@ - gui - gdm - rule_1.8.1 + ansible.builtin.package: + name: gdm + state: absent - name: "1.8.2 | PATCH | Ensure GDM login banner is configured" + when: + - rhel8cis_rule_1_8_2 + - rhel8cis_gui + tags: + - level1-server + - level1-workstation + - automated + - patch + - gui + - gdm + - rule_1.8.2 ansible.builtin.lineinfile: path: "{{ item.file }}" regexp: "{{ item.regexp }}" @@ -24,17 +35,36 @@ create: true owner: root group: root - mode: 0644 - notify: reload dconf - with_items: + mode: '0644' + notify: Reload_dconf + loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-enable', line: 'banner-message-enable=true' } - { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-text', line: "banner-message-text='{{ rhel8cis_warning_banner | replace('\n', ' ') }}' " } + +- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" + ansible.builtin.lineinfile: + path: "{{ item.file }}" + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + notify: Reload_dconf + loop: + - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } + - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } + - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } + - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } + +- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" when: - - rhel8cis_rule_1_8_2 + - rhel8cis_rule_1_8_3 - rhel8cis_gui tags: - level1-server @@ -42,10 +72,7 @@ - automated - patch - gui - - gdm - - rule_1.8.2 - -- name: "1.8.3 | PATCH | Ensure last logged in user display is disabled" + - rule_1.8.3 ansible.builtin.lineinfile: path: "{{ item.file }}" regexp: "{{ item.regexp }}" @@ -53,16 +80,18 @@ create: true owner: root group: root - mode: 0644 - notify: reload dconf - with_items: + mode: '0644' + notify: Reload_dconf + loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } - { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' } - { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'} - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' } - { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' } + +- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle" when: - - rhel8cis_rule_1_8_3 + - rhel8cis_rule_1_8_4 - rhel8cis_gui tags: - level1-server @@ -70,45 +99,179 @@ - automated - patch - gui - - rule_1.8.3 + - rule_1.8.4 + notify: Reload_dconf + block: + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile" + ansible.builtin.lineinfile: + path: /etc/dconf/profile/user + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + loop: + - { regexp: '^user-db', line: 'user-db: user' } + - { regexp: '^system-db', line: 'system-db: local' } -- name: "1.8.4 | PATCH | Ensure XDMCP is not enabled" - ansible.builtin.lineinfile: - path: /etc/gdm/custom.conf - regexp: 'Enable=true' - state: absent + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-screensaver.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-screensaver" + owner: root + group: root + mode: '0644' + +- name: "1.8.5 PATCH | Ensure GDM screen locks cannot be overridden" when: - - rhel8cis_rule_1_8_4 + - rhel8cis_rule_1_8_5 - rhel8cis_gui tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch - gui - - rule_1.8.4 + - rule_1.8.5 + block: + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory -- name: "1.8.5 | PATCH | Ensure automatic mounting of removable media is disabled" - ansible.builtin.lineinfile: - path: /etc/dconf/db/local.d/00-media-automount - regexp: "{{ item.regex }}" - line: "{{ item.line }}" - create: true + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/locks/00-screensaver_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-screensaver" + owner: root + group: root + mode: '0644' + +- name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled" + when: + - rhel8cis_rule_1_8_6 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.6 + notify: Reload_dconf + ansible.builtin.template: + src: etc/dconf/db/00-media-automount.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-media-automount" owner: root group: root - mode: 0640 - notify: reload dconf - with_items: - - { regex: '\[org\/gnome\/desktop\/media-handling\]', line: '[org/gnome/desktop/media-handling]' } - - { regex: 'automount=', line: 'automount=false' } - - { regex: 'automount-open=', line: 'automount-open=false'} + mode: '0644' + +- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden" when: - - rhel8cis_rule_1_8_5 + - rhel8cis_rule_1_8_7 - rhel8cis_gui tags: - level1-server - level2-workstation - - automated - patch - gui - - rule_1.8.5 + - rule_1.8.7 + notify: Reload_dconf + block: + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/locks/00-automount_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-automount_lock" + owner: root + group: root + mode: '0644' + +- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled" + when: + - rhel8cis_rule_1_8_8 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.8 + notify: Reload_dconf + block: + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file" + ansible.builtin.template: + src: etc/dconf/db/00-media-autorun.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/00-media-autorun" + owner: root + group: root + mode: '0644' + +- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden" + when: + - rhel8cis_rule_1_8_9 + - rhel8cis_gui + tags: + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.9 + notify: Reload_dconf + block: + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile" + ansible.builtin.template: + src: etc/dconf/db/locks/00-autorun_lock.j2 + dest: "/etc/dconf/db/{{ rhel8cis_dconf_db_name }}.d/locks/00-autorun_lock" + owner: root + group: root + mode: '0644' + +- name: "1.8.10 | PATCH | Ensure XDMCP is not enabled" + when: + - rhel8cis_rule_1_8_10 + - rhel8cis_gui + tags: + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.10 + ansible.builtin.lineinfile: + path: /etc/gdm/custom.conf + regexp: 'Enable=true' + state: absent diff --git a/tasks/section_1/cis_1.9.yml b/tasks/section_1/cis_1.9.yml index f2bafe43..76113d6c 100644 --- a/tasks/section_1/cis_1.9.yml +++ b/tasks/section_1/cis_1.9.yml @@ -1,33 +1,18 @@ --- -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed" - ansible.builtin.package: - name: "*" - state: latest - notify: change_requires_reboot +- name: "1.1.9 | PATCH | Disable Automounting" + ansible.builtin.service: + name: autofs + enabled: false when: - - rhel8cis_rule_1_9 - - not system_is_ec2 + - not rhel8cis_allow_autofs + - "'autofs' in ansible_facts.packages" + - rhel8cis_rule_1_1_9 tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch - - rule_1.9 - - skip_ansible_lint - -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed | limit kernels" - ansible.builtin.lineinfile: - path: /etc/dnf/dnf.conf - regexp: ^installonly_limit= - line: installonly_limit={{ rhel8cis_installed_kernel_limit }} - when: - - rhel8cis_rule_1_9 - - rhel8cis_apply_installed_kernel_limit - tags: - - level1-server - - level1-workstation - - automated - - patch - - kernel_limit - - rule_1.9 + - mounts + - automounting + - rule_1.1.9 diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 8cdde142..ba9d119a 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -1,59 +1,63 @@ --- - name: "SECTION | 1.1.1.x | Disable unused filesystems" - ansible.builtin.import_tasks: cis_1.1.1.x.yml + ansible.builtin.import_tasks: + file: cis_1.1.1.x.yml -- name: "SECTION | 1.1.2.x | Configure /tmp" - ansible.builtin.import_tasks: cis_1.1.2.x.yml +- name: "SECTION | 1.1.2.1.x | Configure /tmp" + ansible.builtin.import_tasks: + file: cis_1.1.2.1.x.yml -- name: "SECTION | 1.1.3.x | Configure /var" - ansible.builtin.import_tasks: cis_1.1.3.x.yml +- name: "SECTION | 1.1.2.2.x | Configure /dev/shm" + ansible.builtin.import_tasks: + file: cis_1.1.2.2.x.yml -- name: "SECTION | 1.1.4.x | Configure /var/tmp" - ansible.builtin.import_tasks: cis_1.1.4.x.yml +- name: "SECTION | 1.1.2.3.x | Configure /home" + ansible.builtin.import_tasks: + file: cis_1.1.2.3.x.yml -- name: "SECTION | 1.1.5.x | Configure /var/log" - ansible.builtin.import_tasks: cis_1.1.5.x.yml +- name: "SECTION | 1.1.2.4.x | Configure /var" + ansible.builtin.import_tasks: + file: cis_1.1.2.4.x.yml -- name: "SECTION | 1.1.6.x | Configure /var/log/audit" - ansible.builtin.import_tasks: cis_1.1.6.x.yml +- name: "SECTION | 1.1.2.5.x | Configure /var/tmp" + ansible.builtin.import_tasks: + file: cis_1.1.2.5.x.yml -- name: "SECTION | 1.1.7.x | Configure /home" - ansible.builtin.import_tasks: cis_1.1.7.x.yml +- name: "SECTION | 1.1.2.6.x | Configure /var/log" + ansible.builtin.import_tasks: + file: cis_1.1.2.6.x.yml -- name: "SECTION | 1.1.8.x | Configure /dev/shm" - ansible.builtin.import_tasks: cis_1.1.8.x.yml +- name: "SECTION | 1.1.2.7.x | Configure /var/log/audit" + ansible.builtin.import_tasks: + file: cis_1.1.2.7.x.yml -- name: "SECTION | 1.1.x | Disable various mounting" - ansible.builtin.import_tasks: cis_1.1.x.yml +- name: "SECTION | 1.2 | DNF and updates" + ansible.builtin.import_tasks: + file: cis_1.2.x.yml -- name: "SECTION | 1.2 | Configure Software Updates" - ansible.builtin.import_tasks: cis_1.2.x.yml +- name: "SECTION | 1.3 | Bootloader" + ansible.builtin.import_tasks: + file: cis_1.3.x.yml -- name: "SECTION | 1.3 | Filesystem Integrity Checking" - ansible.builtin.import_tasks: cis_1.3.x.yml - when: rhel8cis_config_aide +- name: "SECTION | 1.4 | sysctl kernel" + ansible.builtin.import_tasks: + file: cis_1.4.x.yml -- name: "SECTION | 1.4 | Secure Boot Settings" - ansible.builtin.import_tasks: cis_1.4.x.yml - -- name: "SECTION | 1.5 | Additional Process Hardening" - ansible.builtin.import_tasks: cis_1.5.x.yml - -- name: "SECTION | 1.6 | Mandatory Access Control" - ansible.builtin.import_tasks: cis_1.6.1.x.yml +- name: "SECTION | 1.5 | SELinux" when: not rhel8cis_selinux_disable + ansible.builtin.import_tasks: + file: cis_1.5.1.x.yml + +- name: "SECTION | 1.6 | Crypto" + ansible.builtin.import_tasks: + file: cis_1.6.x.yml - name: "SECTION | 1.7 | Command Line Warning Banners" - ansible.builtin.import_tasks: cis_1.7.x.yml + ansible.builtin.import_tasks: + file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" - ansible.builtin.import_tasks: cis_1.8.x.yml - -- name: "SECTION | 1.9 | Updates and Patches" - ansible.builtin.import_tasks: cis_1.9.yml - -- name: "SECTION | 1.10 | Crypto policies" - ansible.builtin.import_tasks: cis_1.10.yml - when: - - not system_is_ec2 + when: rhel8cis_gui + ansible.builtin.import_tasks: + file: cis_1.8.x.yml diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 33143d23..9738e6bf 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -1,9 +1,6 @@ --- - name: "2.1.1 | PATCH | Ensure time synchronization is in use" - ansible.builtin.package: - name: "{{ rhel8cis_time_synchronization }}" - state: present when: - rhel8cis_rule_2_1_1 - not system_is_container @@ -13,27 +10,11 @@ - automated - patch - rule_2.1.1 + ansible.builtin.package: + name: "{{ rhel8cis_time_synchronization }}" + state: present - name: "2.1.2 | PATCH | Ensure chrony is configured" - block: - - name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration" - ansible.builtin.template: - src: chrony.conf.j2 - dest: /etc/chrony.conf - owner: root - group: root - mode: 0644 - when: rhel8cis_chrony_ansible_managed - - - name: "2.1.2 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd" - ansible.builtin.lineinfile: - path: /etc/sysconfig/chronyd - regexp: OPTIONS=\"(.*)(?!-u chrony)(.*)" - line: OPTIONS="\1\2 -u chrony" - create: true - backrefs: true - mode: '0644' - when: - rhel8cis_time_synchronization == "chrony" - rhel8cis_rule_2_1_2 @@ -42,4 +23,31 @@ - level1-server - level1-workstation - patch + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 - rule_2.1.2 + ansible.builtin.template: + src: chrony.conf.j2 + dest: /etc/chrony.conf + owner: root + group: root + mode: '0644' + +- name: "2.1.3 | PATCH | Ensure chrony is not run as the root user" + when: + - rhel8cis_time_synchronization == "chrony" + - rhel8cis_rule_2_1_3 + - not system_is_container + tags: + - level1-server + - level1-workstation + - patch + - rule_2.1.3 + ansible.builtin.lineinfile: + path: /etc/sysconfig/chronyd + regexp: '^OPTIONS="(?!.* -u chrony.*)(.*)"' + line: OPTIONS="\1 -u chrony" + create: true + backrefs: true + mode: '0644' + notify: Restart_chronyd diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 5b759b26..3860862a 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -1,106 +1,208 @@ --- -- name: "2.2.1 | PATCH | Ensure xinetd is not installed" - ansible.builtin.package: - name: xinetd - state: absent +- name: "2.2.1 | PATCH | Ensure autofs services are not in use" when: - rhel8cis_rule_2_2_1 - - not rhel8cis_xinetd_server - - "'xinetd' in ansible_facts.packages" + - "'autofs' in ansible_facts.packages" tags: - level1-server - - level1-workstation + - level2-workstation - automated - patch + - NIST800-53R5_SI-3 + - NIST800-53R5_MP-7 - rule_2.2.1 + block: + - name: "2.2.1 | PATCH | Ensure autofs services are not in use | Remove Package" + when: + - not rhel8cis_autofs_services + - not rhel8cis_autofs_mask + ansible.builtin.package: + name: autofs + state: absent -- name: "2.2.2 | PATCH | Ensure xorg-x11-server-common is not installed" - ansible.builtin.package: - name: xorg-x11-server-common - state: absent + - name: "2.2.1 | PATCH | Ensure autofs services are not in use | Mask service" + when: + - not rhel8cis_autofs_services + - rhel8cis_autofs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: autofs + enabled: false + state: stopped + masked: true + +- name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use" when: - rhel8cis_rule_2_2_2 - - "'xorg-x11-server-common' in ansible_facts.packages" - - not rhel8cis_xwindows_required or not rhel8cis_gui + - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" tags: - level1-server + - level2-workstation - automated - patch - - x11 + - avahi + - NIST800-53R5_SI-4 - rule_2.2.2 + block: + - name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use | Remove package" + when: + - not rhel8cis_avahi_server + - not rhel8cis_avahi_mask + ansible.builtin.package: + name: + - avahi-autoipd + - avahi + state: absent -- name: "2.2.3 | PATCH | Ensure Avahi Server is not installed" - ansible.builtin.package: - name: - - avahi-autoipd - - avahi - state: absent + - name: "2.2.2 | PATCH | Ensure avahi daemon services are not in use | Mask service" + when: + - not rhel8cis_avahi_server + - rhel8cis_avahi_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - avahi-daemon.socket + - avahi-daemon.service + +- name: "2.2.3 | PATCH | Ensure dhcp server services are not in use" when: + - "'dhcp-server' in ansible_facts.packages" - rhel8cis_rule_2_2_3 - - not rhel8cis_avahi_server - - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" tags: - level1-server - - level2-workstation + - level1-workstation - automated - patch - - avahi + - dhcp + - NIST800-53R5_CM-7 - rule_2.2.3 + block: + - name: "2.2.3 | PATCH | Ensure dhcp server services are not in use | Remove package" + when: + - not rhel8cis_dhcp_server + - not rhel8cis_dhcp_mask + ansible.builtin.package: + name: dhcp-server + state: absent -- name: "2.2.4 | PATCH | Ensure CUPS is not installed" - ansible.builtin.package: - name: cups - state: absent + - name: "2.2.3 | PATCH | Ensure dhcp server services are not in use | Mask service" + when: + - not rhel8cis_dhcp_server + - rhel8cis_dhcp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - dhcpd.service + - dhcpd6.service + +- name: "2.2.4 | PATCH | Ensure dns server services are not in use" when: - - not rhel8cis_cups_server - - "'cups' in ansible_facts.packages" - - rhel8cis_rule_2_2_3 + - "'bind' in ansible_facts.packages" + - rhel8cis_rule_2_2_4 tags: - level1-server + - level1-workstation - automated - patch - - cups + - dns + - NIST800-53R5_CM-7 - rule_2.2.4 + block: + - name: "2.2.4 | PATCH | Ensure dns server services are not in use | Remove package" + when: + - not rhel8cis_dns_server + - not rhel8cis_dns_mask + ansible.builtin.package: + name: bind + state: absent -- name: "2.2.5 | PATCH | Ensure DHCP Server is not installed" - ansible.builtin.package: - name: dhcp-server - state: absent + - name: "2.2.4 | PATCH | Ensure dns server services are not in use | Mask service" + when: + - not rhel8cis_dns_server + - rhel8cis_dns_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: named.service + enabled: false + state: stopped + masked: true + +- name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use" when: - - not rhel8cis_dhcp_server - - "'dhcp-server' in ansible_facts.packages" + - "'dnsmasq' in ansible_facts.packages" - rhel8cis_rule_2_2_5 tags: - level1-server - level1-workstation - - audtomated + - automated - patch - - dhcp + - dns + - NIST800-53R5_CM-7 - rule_2.2.5 + block: + - name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use | Remove package" + when: + - not rhel8cis_dnsmasq_server + - not rhel8cis_dnsmasq_mask + ansible.builtin.package: + name: dnsmasq + state: absent -- name: "2.2.6 | PATCH | Ensure DNS Server is not installed" - ansible.builtin.package: - name: bind - state: absent + - name: "2.2.5 | PATCH | Ensure dnsmasq server services are not in use | Mask service" + when: + - not rhel8cis_dnsmasq_server + - rhel8cis_dnsmasq_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: dnsmasq.service + enabled: false + state: stopped + masked: true + +- name: "2.2.6 | PATCH | Ensure samba file server services are not in use" when: - - not rhel8cis_dns_server - - "'bind' in ansible_facts.packages" + - "'samba' in ansible_facts.packages" - rhel8cis_rule_2_2_6 tags: - level1-server - level1-workstation - automated - patch - - dns + - samba + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.6 + block: + - name: "2.2.6 | PATCH | Ensure samba file server services are not in use | Remove package" + when: + - not rhel8cis_samba_server + - not rhel8cis_samba_mask + ansible.builtin.package: + name: samba + state: absent -- name: "2.2.7 | PATCH | Ensure FTP Server is not installed" - ansible.builtin.package: - name: ftp - state: absent + - name: "2.2.6 | PATCH | Ensure samba file server services are not in use | Mask service" + when: + - not rhel8cis_samba_server + - rhel8cis_samba_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: smb.service + enabled: false + state: stopped + masked: true + +- name: "2.2.7 | PATCH | Ensure ftp server services are not in use" when: - - not rhel8cis_ftp_server - "'ftp' in ansible_facts.packages" - rhel8cis_rule_2_2_7 tags: @@ -109,127 +211,243 @@ - automation - patch - ftp + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.7 + block: + - name: "2.2.7 | PATCH | Ensure ftp server services are not in use | Remove package" + when: + - not rhel8cis_ftp_server + - not rhel8cis_ftp_mask + ansible.builtin.package: + name: vsftpd + state: absent -- name: "2.2.8 | PATCH | Ensure VSFTP Server is not installed" - ansible.builtin.package: - name: vsftpd - state: absent + - name: "2.2.7 | PATCH | Ensure ftp server services are not in use | Mask service" + when: + - not rhel8cis_ftp_server + - rhel8cis_ftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: vsftpd.service + enabled: false + state: stopped + masked: true + +- name: "2.2.8 | PATCH | Ensure message access server services are not in use" when: - - not rhel8cis_vsftpd_server - - "'vsftpd' in ansible_facts.packages" + - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" - rhel8cis_rule_2_2_8 tags: - level1-server - level1-workstation - automated - patch - - vsftpd + - dovecot + - imap + - pop3 + - NIST800-53R5_CM-7 - rule_2.2.8 + block: + - name: "2.2.8 | PATCH | Ensure message access server services are not in use | Remove package" + when: + - not rhel8cis_message_server + - not rhel8cis_message_mask + ansible.builtin.package: + name: + - dovecot + - cyrus-imapd + state: absent -- name: "2.2.9 | PATCH | Ensure TFTP Server is not installed" - ansible.builtin.package: - name: tftp-server - state: absent + - name: "2.2.8 | PATCH | Ensure message access server services are not in use | Mask service" + when: + - not rhel8cis_message_server + - rhel8cis_message_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - "dovecot.socket" + - "dovecot.service" + - "cyrus-imapd.service" + +- name: "2.2.9 | PATCH | Ensure network file system services are not in use" when: - - not rhel8cis_tftp_server - - "'tftp-server' in ansible_facts.packages" + - "'nfs-utils' in ansible_facts.packages" - rhel8cis_rule_2_2_9 tags: - level1-server - level1-workstation - automated - patch - - tftp + - nfs + - services + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.9 - -- name: "2.2.10 | PATCH | Ensure a web server is not installed" block: - - name: "2.2.10 | PATCH | Ensure a web server is not installed | Remove httpd server" - ansible.builtin.package: - name: httpd - state: absent + - name: "2.2.9 | PATCH | Ensure network file system services are not in use | Remove package" when: - - not rhel8cis_httpd_server - - "'httpd' in ansible_facts.packages" - - - name: "2.2.10 | PATCH | Ensure a web server is not installed | Remove nginx server" + - not rhel8cis_nfs_server + - not rhel8cis_nfs_mask ansible.builtin.package: - name: nginx + name: nfs-utils state: absent + + - name: "2.2.9 | PATCH | Ensure network file system services are not in use | Mask service" when: - - not rhel8cis_nginx_server - - "'nginx' in ansible_facts.packages" + - not rhel8cis_nfs_server + - rhel8cis_nfs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: nfs-server.service + enabled: false + state: stopped + masked: true + +- name: "2.2.10 | PATCH | Ensure nis server services are not in use" when: + - "'ypserv' in ansible_facts.packages" - rhel8cis_rule_2_2_10 tags: - level1-server - level1-workstation - automated - patch - - httpd - - nginx - - webserver + - nis + - NIST800-53R5_CM-7 - rule_2.2.10 + notify: Systemd_daemon_reload + block: + - name: "2.2.10 | PATCH | Ensure nis server services are not in use | Remove package" + when: + - not rhel8cis_nis_server + - not rhel8cis_nis_mask + ansible.builtin.package: + name: ypserv + state: absent -- name: "2.2.11 | PATCH | Ensure IMAP and POP3 server is not installed" - ansible.builtin.package: - name: - - dovecot - - cyrus-imapd - state: absent + - name: "2.2.10 | PATCH | Ensure nis server services are not in use | Mask service" + when: + - not rhel8cis_nis_server + - rhel8cis_nis_mask + ansible.builtin.systemd: + name: ypserv.service + enabled: false + state: stopped + masked: true + +- name: "2.2.11 | PATCH | Ensure print server services are not in use" when: - - not rhel8cis_dovecot_cyrus_server - - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" + - "'cups' in ansible_facts.packages" - rhel8cis_rule_2_2_11 tags: - level1-server - - level1-workstation - automated - patch - - dovecot - - imap - - pop3 + - cups + - NIST800-53R5_CM-7 - rule_2.2.11 + block: + - name: "2.2.11 | PATCH | Ensure print server services are not in use | Remove package" + when: + - not rhel8cis_print_server + - not rhel8cis_print_mask + ansible.builtin.package: + name: cups + state: absent -- name: "2.2.12 | PATCH | Ensure Samba is not enabled" - ansible.builtin.package: - name: samba - state: absent + - name: "2.2.11 | PATCH | Ensure print server services are not in use | Mask service" + when: + - not rhel8cis_print_server + - rhel8cis_print_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - "cups.socket" + - "cups.service" + +- name: "2.2.12 | PATCH | Ensure rpcbind services are not in use" when: - - not rhel8cis_samba_server - - "'samba' in ansible_facts.packages" + - "'rpcbind' in ansible_facts.packages" - rhel8cis_rule_2_2_12 tags: - level1-server - level1-workstation - automated - patch - - samba + - rpc + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.12 + block: + - name: "2.2.12 | PATCH | Ensure rpcbind services are not in use | Remove package" + when: + - not rhel8cis_rpc_server + - not rhel8cis_rpc_mask + ansible.builtin.package: + name: rpcbind + state: absent -- name: "2.2.13 | PATCH | Ensure HTTP Proxy Server is not installed" - ansible.builtin.package: - name: squid - state: absent + - name: "2.2.12 | PATCH | Ensure rpcbind services are not in use | Mask service" + when: + - not rhel8cis_rpc_server + - rhel8cis_rpc_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - rpcbind.service + - rpcbind.socket + +- name: "2.2.13 | PATCH | Ensure rsync services are not in use" when: - - not rhel8cis_squid_server - - "'squid' in ansible_facts.packages" - - rhel8cis_rule_2_2_6 + - "'rsync-daemon' in ansible_facts.packages" + - rhel8cis_rule_2_2_13 tags: - level1-server - level1-workstation - - automation + - automated - patch - - squid + - rsync + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.13 + block: + - name: "2.2.13 | PATCH | Ensure rsync services are not in use | Remove package" + when: + - not rhel8cis_rsync_server + - not rhel8cis_rsync_mask + ansible.builtin.package: + name: rsync-daemon + state: absent -- name: "2.2.14 | PATCH | Ensure net-snmp is not installed" - ansible.builtin.package: - name: net-snmp - state: absent + - name: "2.2.13 | PATCH | Ensure rsync services are not in use | Mask service" + when: + - not rhel8cis_rsync_server + - rhel8cis_rsync_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'rsyncd.socket' + - 'rsyncd.service' + +- name: "2.2.14 | PATCH | Ensure snmp services are not in use" when: - - not rhel8cis_net_snmp_server - "'net-snmp' in ansible_facts.packages" - rhel8cis_rule_2_2_14 tags: @@ -238,162 +456,281 @@ - automation - patch - snmp + - NIST800-53R5_CM-7 - rule_2.2.14 + block: + - name: "2.2.14 | PATCH | Ensure snmp services are not in use | Remove package" + when: + - not rhel8cis_net_snmp_server + - not rhel8cis_net_snmp_mask + ansible.builtin.package: + name: net-snmp + state: absent -- name: "2.2.15 | PATCH | Ensure NIS Server is not installed" - ansible.builtin.package: - name: ypserv - state: absent + - name: "2.2.14 | PATCH | Ensure snmp services are not in use | Mask service" + when: + - not rhel8cis_net_snmp_server + - rhel8cis_net_snmp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: snmpd.service + enabled: false + state: stopped + masked: true + +- name: "2.2.15 | PATCH | Ensure telnet server services are not in use" when: - - not rhel8cis_nis_server - - "'ypserv' in ansible_facts.packages" + - "'telnet-server' in ansible_facts.packages" - rhel8cis_rule_2_2_15 tags: - level1-server - level1-workstation - automated - patch - - nis + - telnet + - NIST800-53R5_CM-7 + - NIST800-53R5_CM-11 - rule_2.2.15 + block: + - name: "2.2.15 | PATCH | Ensure telnet server services are not in use | Remove package" + when: + - not rhel8cis_telnet_server + - not rhel8cis_telnet_mask + ansible.builtin.package: + name: telnet-server + state: absent -- name: "2.2.16 | PATCH | Ensure telnet-server is not installed" - ansible.builtin.package: - name: telnet-server - state: absent + - name: "2.2.15 | PATCH | Ensure telnet server services are not in use | Mask service" + when: + - not rhel8cis_telnet_server + - rhel8cis_telnet_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: telnet.socket + enabled: false + state: stopped + masked: true + +- name: "2.2.16 | PATCH | Ensure tftp server services are not in use" when: - - not rhel8cis_telnet_server - - "'telnet-server' in ansible_facts.packages" + - "'tftp-server' in ansible_facts.packages" - rhel8cis_rule_2_2_16 tags: - level1-server - level1-workstation - automated - patch - - telnet + - tftp + - NIST800-53R5_CM-7 - rule_2.2.16 + block: + - name: "2.2.16 | PATCH | Ensure tftp server services are not in use | Remove package" + when: + - not rhel8cis_tftp_server + - not rhel8cis_tftp_mask + ansible.builtin.package: + name: tftp-server + state: absent -- name: "2.2.17 | PATCH | Ensure mail transfer agent is configured for local-only mode" - ansible.builtin.lineinfile: - path: /etc/postfix/main.cf - regexp: "^(#)?inet_interfaces" - line: "inet_interfaces = loopback-only" - notify: restart postfix + - name: "2.2.16 | PATCH | Ensure tftp server services are not in use | Mask service" + when: + - not rhel8cis_tftp_server + - rhel8cis_tftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'tftp.socket' + - 'tftp.service' + +- name: "2.2.17 | PATCH | Ensure web proxy server services are not in use" when: - - not rhel8cis_is_mail_server - - "'postfix' in ansible_facts.packages" - - rhel8cis_rule_2_2_17 + - "'squid' in ansible_facts.packages" + - rhel8cis_rule_2_217 tags: - level1-server - level1-workstation - - automated + - automation - patch - - postfix + - squid + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 - rule_2.2.17 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked" block: - - name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | Remove package" + - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use | Remove package" + when: + - not rhel8cis_squid_server + - not rhel8cis_squid_mask ansible.builtin.package: - name: nfs-utils + name: squid state: absent - when: - - not rhel8cis_nfs_server - - not rhel8cis_nfs_mask - - name: "2.2.18 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | Mask service" + - name: "2.2.17 | PATCH | Ensure web proxy server services are not in use | Mask service" + when: + - not rhel8cis_squid_server + - rhel8cis_squid_mask notify: Systemd_daemon_reload ansible.builtin.systemd: - name: nfs-server.service + name: squid.service enabled: false state: stopped masked: true - when: - - not rhel8cis_nfs_server - - rhel8cis_nfs_mask + +- name: "2.2.18 | PATCH | Ensure web server services are not in use" when: - - "'nfs-utils' in ansible_facts.packages" - rhel8cis_rule_2_2_18 tags: - level1-server - level1-workstation - automated - patch - - nfs - - services + - httpd + - nginx + - webserver + - NIST800-53R5_CM-7 - rule_2.2.18 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked" block: - - name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | Remove package" + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Remove httpd server" + when: + - not rhel8cis_httpd_server + - not rhel8cis_httpd_mask + - "'httpd' in ansible_facts.packages" ansible.builtin.package: - name: cups + name: httpd state: absent + + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Remove nginx server" when: - - not rhel8cis_rpc_server - - not rhel8cis_rpc_mask + - not rhel8cis_nginx_server + - not rhel8cis_nginx_mask + - "'nginx' in ansible_facts.packages" + ansible.builtin.package: + name: nginx + state: absent - - name: "2.2.19 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | Mask service" + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Mask httpd service" + when: + - not rhel8cis_httpd_server + - rhel8cis_httpd_mask + - "'httpd' in ansible_facts.packages" notify: Systemd_daemon_reload ansible.builtin.systemd: - name: "{{ item }}" + name: httpd.service enabled: false state: stopped masked: true - loop: - - rpcbind.service - - rpcbind.socket + + - name: "2.2.18 | PATCH | Ensure web server services are not in use | Mask nginx service" when: - - not rhel8cis_rpc_server - - rhel8cis_rpc_mask + - not rhel8cis_nginx_server + - rhel8cis_nginx_mask + - "'nginx' in ansible_facts.packages" + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: ngnix.service + enabled: false + state: stopped + masked: true + +- name: "2.2.19 | PATCH | Ensure xinetd services are not in use" when: - - not rhel8cis_rpc_server - - "'rpcbind' in ansible_facts.packages" + - "'xinetd' in ansible_facts.packages" - rhel8cis_rule_2_2_19 tags: - level1-server - level1-workstation - automated - patch - - rpc + - xinetd + - NIST800-53R5_CM-7 - rule_2.2.19 - -# The name title of the service says mask the service or remove packages -# Option available -- name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked" block: - - name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked | Remove package" + - name: "2.2.19 | PATCH | Ensure xinetd services are not in use | Remove package" + when: + - not rhel8cis_xinetd_server + - not rhel8cis_xinetd_mask ansible.builtin.package: - name: rsync-daemon + name: xinetd state: absent - when: - - not rhel8cis_rsync_server - - not rhel8cis_rsync_mask - - name: "2.2.20 | PATCH | Ensure rsync is not installed or the rsyncd service is masked | Mask service" + - name: "2.2.19 | PATCH | Ensure xinetd services are not in use | Mask service" + when: + - not rhel8cis_xinetd_server + - rhel8cis_xinetd_mask notify: Systemd_daemon_reload ansible.builtin.systemd: - name: "{{ item }}" + name: xinetd.service enabled: false state: stopped masked: true - loop: - - 'rsyncd.socket' - - 'rsyncd.service' - when: - - not rhel8cis_rsync_server - - rhel8cis_rsync_mask + +- name: "2.2.20 | PATCH | Ensure X window server services are not in use" when: - - not rhel8cis_rsync_server - - "'rsync-daemon' in ansible_facts.packages" + - not rhel8cis_xwindow_server + - "'xorg-x11-server-common' in ansible_facts.packages" - rhel8cis_rule_2_2_20 tags: - level1-server - level1-workstation - automated - patch - - rsync + - xwindow + - NIST800-53R5_CM-11 - rule_2.2.20 + ansible.builtin.package: + name: xorg-x11-server-common + state: absent + +- name: "2.2.21 | PATCH | Ensure mail transfer agents are configured for local-only mode" + when: + - not rhel8cis_is_mail_server + - "'postfix' in ansible_facts.packages" + - rhel8cis_rule_2_2_21 + tags: + - level1-server + - level1-workstation + - automated + - patch + - postfix + - NIST800-53R5_CM-7 + - rule_2.2.21 + notify: Restart_postfix + ansible.builtin.lineinfile: + path: /etc/postfix/main.cf + regexp: "^(#)?inet_interfaces" + line: "inet_interfaces = loopback-only" + +- name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface" + when: + - rhel8cis_rule_2_2_22 + tags: + - level1-server + - level1-workstation + - manual + - audit + - services + - NIST800-53R5_CM-7 + - rule_2.2.22 + vars: + warn_control_id: '2.2.22' + block: + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" + ansible.builtin.shell: systemctl list-units --type=service + changed_when: false + failed_when: discovered_running_services.rc not in [ 0, 1 ] + check_mode: false + register: discovered_running_services + + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Display list of services" + ansible.builtin.debug: + msg: + - "Warning!! Below are the list of services, both active and inactive" + - "Please review to make sure all are essential" + - "{{ discovered_running_services.stdout_lines }}" + + - name: "2.2.22 | AUDIT | Ensure only approved services are listening on a network interface | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_2/cis_2.3.x.yml b/tasks/section_2/cis_2.3.x.yml index 1c033a1b..9d3c16a4 100644 --- a/tasks/section_2/cis_2.3.x.yml +++ b/tasks/section_2/cis_2.3.x.yml @@ -1,57 +1,57 @@ --- -- name: "2.3.1 | PATCH | Ensure NIS Client is not installed" - ansible.builtin.package: - name: ypbind - state: absent +- name: "2.3.1 | PATCH | Ensure ftp client is not installed" when: - - not rhel8cis_ypbind_required - - "'ypbind' in ansible_facts.packages" + - not rhel8cis_ftp_client + - "'ftp' in ansible_facts.packages" - rhel8cis_rule_2_3_1 tags: - level1-server - level1-workstation - automated - patch - - nis + - ftp + - NIST800-53R5_CM-7 - rule_2.3.1 - -- name: "2.3.2 | PATCH | Ensure rsh client is not installed" ansible.builtin.package: - name: rsh + name: ftp state: absent + +- name: "2.3.2 | PATCH | Ensure ldap client is not installed" when: - - not rhel8cis_rsh_required - - "'rsh' in ansible_facts.packages" + - not rhel8cis_openldap_clients_required + - "'openldap-clients' in ansible_facts.packages" - rhel8cis_rule_2_3_2 tags: - - level1-server - level2-server + - level2-workstation - automated - patch - - rsh + - ldap + - NIST800-53R5_CM-7 - rule_2.3.2 - -- name: "2.3.3 | PATCH | Ensure talk client is not installed" ansible.builtin.package: - name: talk + name: openldap-clients state: absent + +- name: "2.3.3 | PATCH | Ensure nis client is not installed" when: - - not rhel8cis_talk_required - - "'talk' in ansible_facts.packages" + - not rhel8cis_ypbind_required + - "'ypbind' in ansible_facts.packages" - rhel8cis_rule_2_3_3 tags: - level1-server - level1-workstation - automated - patch - - talk + - nis + - NIST800-53R5_CM-7 - rule_2.3.3 - -- name: "2.3.4 | PATCH | Ensure telnet client is not installed" ansible.builtin.package: - name: telnet + name: ypbind state: absent + +- name: "2.3.4 | PATCH | Ensure telnet client is not installed" when: - not rhel8cis_telnet_required - "'telnet' in ansible_facts.packages" @@ -62,36 +62,25 @@ - automated - patch - telnet + - NIST800-53R5_CM-7 - rule_2.3.4 - -- name: "2.3.5 | PATCH | Ensure LDAP client is not installed" ansible.builtin.package: - name: openldap-clients + name: telnet state: absent + +- name: "2.3.5 | PATCH | Ensure TFTP client is not installed" when: - - not rhel8cis_openldap_clients_required - - "'openldap-clients' in ansible_facts.packages" + - not rhel8cis_tftp_client + - "'tftp' in ansible_facts.packages" - rhel8cis_rule_2_3_5 tags: - level1-server - level1-workstation - automated - patch - - ldap + - tftp + - NIST800-53R5_CM-7 - rule_2.3.5 - -- name: "2.3.6 | PATCH | Ensure TFTP client is not installed" ansible.builtin.package: name: tftp state: absent - when: - - not rhel8cis_tftp_client - - "'tftp' in ansible_facts.packages" - - rhel8cis_rule_2_3_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - tftp - - rule_2.3.6 diff --git a/tasks/section_2/cis_2.4.yml b/tasks/section_2/cis_2.4.yml deleted file mode 100644 index 1b60c8ad..00000000 --- a/tasks/section_2/cis_2.4.yml +++ /dev/null @@ -1,31 +0,0 @@ ---- - -- name: "2.4 | AUDIT | Ensure nonessential services are removed or masked" - block: - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Get list of services" - ansible.builtin.shell: systemctl list-units --type=service - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_2_4_services - - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Display list of services" - ansible.builtin.debug: - msg: - - "Warning!! Below are the list of services, both active and inactive" - - "Please review to make sure all are essential" - - "{{ rhel8cis_2_4_services.stdout_lines }}" - - - name: "2.4 | AUDIT | Ensure nonessential services are removed or masked | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '2.4' - when: - - rhel8cis_rule_2_4 - tags: - - level1-server - - level1-workstation - - manual - - audit - - services - - rule_2.4 diff --git a/tasks/section_2/main.yml b/tasks/section_2/main.yml index 39b912d5..8b9a094d 100644 --- a/tasks/section_2/main.yml +++ b/tasks/section_2/main.yml @@ -1,13 +1,13 @@ --- - name: "SECTION | 2.1 | Time Synchronization" - ansible.builtin.import_tasks: cis_2.1.x.yml + ansible.builtin.import_tasks: + file: cis_2.1.x.yml - name: "SECTION | 2.2 | Special Purpose Services" - ansible.builtin.import_tasks: cis_2.2.x.yml + ansible.builtin.import_tasks: + file: cis_2.2.x.yml - name: "SECTION | 2.3 | Service Clients" - ansible.builtin.import_tasks: cis_2.3.x.yml - -- name: "SECTION | 2.4 | Nonessential services removed" - ansible.builtin.import_tasks: cis_2.4.yml + ansible.builtin.import_tasks: + file: cis_2.3.x.yml diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index f704a17d..1b5d830b 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -4,6 +4,19 @@ # We are using the rhel8cis_ipv6_required to specify if you have IPv6 in use - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system" + when: + - not rhel8cis_ipv6_required + - rhel8cis_rule_3_1_1 + tags: + - level1-server + - level1-workstation + - manual + - patch + - ipv6 + - networking + - NIST800-53R5_CM-7 + - rule_3.1.1 + notify: Change_requires_reboot block: - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable all except localhost" ansible.posix.sysctl: @@ -11,122 +24,86 @@ value: '1' sysctl_set: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - with_items: + loop: - net.ipv6.conf.all.disable_ipv6 - net.ipv6.conf.default.disable_ipv6 - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable localhost sysctl" + when: + - rhel8cis_ipv6_disable_localhost ansible.posix.sysctl: name: net.ipv6.conf.lo.disable_ipv6 value: '1' sysctl_set: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: change_requires_reboot - when: - - rhel8cis_ipv6_disable_localhost - name: "3.1.1 | PATCH | Verify if IPv6 is enabled on the system | disable localhost /etc/hosts" + when: + - rhel8cis_ipv6_disable_localhost ansible.builtin.lineinfile: path: /etc/hosts regexp: '^(::1.*)' line: '#\1' backrefs: true - notify: change_requires_reboot - when: - - rhel8cis_ipv6_disable_localhost - - when: - - not rhel8cis_ipv6_required - - rhel8cis_rule_3_1_1 - tags: - - level1-server - - level1-workstation - - manual - - patch - - ipv6 - - networking - - rule_3.1.1 -- name: "3.1.2 | PATCH | Ensure SCTP is disabled" - block: - - name: "3.1.2 | PATCH | Ensure SCTP is disabled | CIS" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install sctp(\\s|$)" - line: "install sctp /bin/true" - create: true - mode: 0600 - - - name: "3.1.2 | PATCH | Ensure SCTP is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist sctp(\\s|$)" - line: "blacklist sctp" - create: true - mode: 0600 +- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: - rhel8cis_rule_3_1_2 tags: - - level2-server - - level2-workstation + - level1-server - automated - patch - - sctp + - wireless + - NIST800-53R5_CM-7 - rule_3.1.2 - -- name: "3.1.3 | PATCH | Ensure DCCP is disabled" block: - - name: "3.1.3 | PATCH | Ensure DCCP is disabled | CIS" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/CIS.conf - regexp: "^(#)?install dccp(\\s|$)" - line: "install dccp /bin/true" - create: true - mode: 0600 - - - name: "3.1.3 | PATCH | Ensure DCCP is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist dccp(\\s|$)" - line: "blacklist dccp" - create: true - mode: 0600 - when: - - rhel8cis_rule_3_1_3 - tags: - - level2-server - - level2-workstation - - automated - - dccp - - patch - - rule_3.1.3 - -- name: "3.1.4 | PATCH | Ensure wireless interfaces are disabled" - block: - - name: "3.1.4 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available" + - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available" ansible.builtin.shell: rpm -q NetworkManager changed_when: false failed_when: false check_mode: false - register: rhel_08_nmcli_available + register: discovered_nmcli_available - - name: "3.1.4 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" + - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" + when: discovered_nmcli_available.rc == 0 ansible.builtin.shell: nmcli radio wifi - register: rhel_08_wifi_enabled - changed_when: rhel_08_wifi_enabled.stdout != "disabled" + register: discovered_wifi_enabled + changed_when: discovered_wifi_enabled.stdout != "disabled" failed_when: false - when: rhel_08_nmcli_available.rc == 0 - - name: "3.1.4 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" + when: discovered_wifi_enabled is changed # noqa: no-handler ansible.builtin.shell: nmcli radio all off changed_when: false failed_when: false - when: rhel_08_wifi_enabled is changed # noqa: no-handler + +- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use" when: - - rhel8cis_rule_3_1_4 + - rhel8cis_rule_3_1_3 tags: - level1-server + - level2-workstation - automated - patch - - wireless - - rule_3.1.4 + - sctp + - NIST800-53R5_CM-7 + - rule_3.1.3 + block: + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | pkg" + when: + - not rhel8cis_bluetooth_service + - not rhel8cis_bluetooth_mask + ansible.builtin.package: + name: bluez + state: absent + + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | mask" + when: + - not rhel8cis_bluetooth_service + - rhel8cis_bluetooth_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: bluetooth.service + enabled: false + state: stopped + masked: true diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index 0e8707e5..97fa0aa4 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -1,54 +1,118 @@ --- -- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled" - block: - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" - ansible.posix.sysctl: - name: net.ipv4.ip_forward - value: '0' - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" - ansible.posix.sysctl: - name: net.ipv6.conf.all.forwarding - value: '0' - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - when: - - rhel8cis_ipv6_required or - rhel8cis_ipv6_sysctl_force +- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available" when: - - not rhel8cis_is_router - rhel8cis_rule_3_2_1 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - - sysctl + - dccp - patch + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 - rule_3.2.1 + block: + - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install dccp(\\s|$)" + line: "install dccp /bin/true" + create: true + mode: '0600' + + - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist dccp(\\s|$)" + line: "blacklist dccp" + create: true + mode: '0600' -- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.send_redirects, value: 0 } - - { name: net.ipv4.conf.default.send_redirects, value: 0 } +- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" when: - - not rhel8cis_is_router - rhel8cis_rule_3_2_2 tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - automated - patch - - sysctl + - tipc + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 - rule_3.2.2 + + block: + - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install tipc(\\s|$)" + line: "install tipc /bin/true" + create: true + mode: '0600' + + - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist tipc(\\s|$)" + line: "blacklist tipc" + create: true + mode: '0600' + +- name: "3.2.3 | PATCH | Ensure rds kernel module is not available" + when: + - rhel8cis_rule_3_2_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - rds + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + - rule_3.2.3 + block: + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install rpc(\\s|$)" + line: "install rds /bin/true" + create: true + mode: '0600' + + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist rpc(\\s|$)" + line: "blacklist rds" + create: true + mode: '0600' + +- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" + when: + - rhel8cis_rule_3_2_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - sctp + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + - rule_3.2.4 + block: + - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | CIS" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/CIS.conf + regexp: "^(#)?install sctp(\\s|$)" + line: "install sctp /bin/true" + create: true + mode: '0600' + + - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist sctp(\\s|$)" + line: "blacklist sctp" + create: true + mode: '0600' diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 2d775d62..f54eaa6f 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -1,68 +1,44 @@ --- -- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted" - block: - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv4" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.accept_source_route, value: 0 } - - { name: net.ipv4.conf.default.accept_source_route, value: 0 } - - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv6" - ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_source_route, value: 0} - - { name: net.ipv6.conf.default.accept_source_route, value: 0 } - when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force +- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled" when: + - not rhel8cis_is_router - rhel8cis_rule_3_3_1 tags: - level1-server - level1-workstation - automated - - patch - sysctl + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.1 - -- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" block: - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv4" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv4.ip_forward + value: '0' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.accept_redirects, value: 0 } - - { name: net.ipv4.conf.default.accept_redirects, value: 0 } + notify: Sysctl_flush_ipv4_routes - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv6" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" + when: + - rhel8cis_ipv6_required or + rhel8cis_ipv6_sysctl_force ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv6.conf.all.forwarding + value: '0' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_redirects, value: 0 } - - { name: net.ipv6.conf.default.accept_redirects, value: 0 } - when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + notify: Sysctl_flush_ipv6_routes + +- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled" when: + - not rhel8cis_is_router - rhel8cis_rule_3_3_2 tags: - level1-server @@ -70,19 +46,24 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.2 - -- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' + name: "{{ item.name }}" + value: "{{ item.value }}" sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.secure_redirects, value: 0 } - - { name: net.ipv4.conf.default.secure_redirects, value: 0 } + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.send_redirects, value: 0 } + - { name: net.ipv4.conf.default.send_redirects, value: 0 } + +- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored" when: - rhel8cis_rule_3_3_3 tags: @@ -91,19 +72,21 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.3 - -- name: "3.3.4 | PATCH | Ensure suspicious packets are logged" ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' - sysctl_set: true + name: net.ipv4.icmp_ignore_bogus_error_responses + value: '1' + state: present ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table - with_items: - - { name: net.ipv4.conf.all.log_martians, value: 1 } - - { name: net.ipv4.conf.default.log_martians, value: 1 } + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored" when: - rhel8cis_rule_3_3_4 tags: @@ -112,15 +95,21 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.3 - rule_3.3.4 - -- name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" ansible.posix.sysctl: name: net.ipv4.icmp_echo_ignore_broadcasts value: '1' ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted" when: - rhel8cis_rule_3_3_5 tags: @@ -129,16 +118,39 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.5 + block: + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv4" + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.accept_redirects, value: 0 } + - { name: net.ipv4.conf.default.accept_redirects, value: 0 } -- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" - ansible.posix.sysctl: - name: net.ipv4.icmp_ignore_bogus_error_responses - value: '1' - state: present - ignoreerrors: true - sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set ICMP redirects IPv6" + when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_redirects, value: 0 } + - { name: net.ipv6.conf.default.accept_redirects, value: 0 } + +- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted" when: - rhel8cis_rule_3_3_6 tags: @@ -147,9 +159,38 @@ - automated - patch - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_3.3.6 + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.secure_redirects, value: 0 } + - { name: net.ipv4.conf.default.secure_redirects, value: 0 } - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" + when: + - rhel8cis_rule_3_3_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.7 ansible.posix.sysctl: name: "{{ item }}" value: '1' @@ -159,53 +200,117 @@ loop: - net.ipv4.conf.all.rp_filter - net.ipv4.conf.default.rp_filter - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted" when: - - rhel8cis_rule_3_3_7 + - rhel8cis_rule_3_3_8 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.7 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.8 + block: + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv4" + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.accept_source_route, value: 0 } + - { name: net.ipv4.conf.default.accept_source_route, value: 0 } + + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | Set routed packets IPv6" + when: rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_source_route, value: 0} + - { name: net.ipv6.conf.default.accept_source_route, value: 0 } -- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" +- name: "3.3.9 | PATCH | Ensure suspicious packets are logged" + when: + - rhel8cis_rule_3_3_9 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sysctl + - NIST800-53R5_AU-3 + - rule_3.3.9 ansible.posix.sysctl: - name: net.ipv4.tcp_syncookies - value: '1' + name: "{{ item.name }}" + value: "{{ item.value }}" sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv4 route table + notify: Sysctl_flush_ipv4_routes + loop: + - { name: net.ipv4.conf.all.log_martians, value: 1 } + - { name: net.ipv4.conf.default.log_martians, value: 1 } + +- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled" when: - - rhel8cis_rule_3_3_8 + - rhel8cis_rule_3_3_10 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.8 - -- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.10 ansible.posix.sysctl: - name: '{{ item.name }}' - value: '{{ item.value }}' + name: net.ipv4.tcp_syncookies + value: '1' sysctl_set: true ignoreerrors: true sysctl_file: "{{ rhel8cis_sysctl_file }}" - notify: sysctl flush ipv6 route table - with_items: - - { name: net.ipv6.conf.all.accept_ra, value: 0 } - - { name: net.ipv6.conf.default.accept_ra, value: 0 } + notify: Sysctl_flush_ipv4_routes + +- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted" when: - rhel8cis_ipv6_required or rhel8cis_ipv6_sysctl_force - - rhel8cis_rule_3_3_9 + - rhel8cis_rule_3_3_11 tags: - level1-server - level1-workstation - automated - patch - sysctl - - rule_3.3.9 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_3.3.11 + ansible.posix.sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + sysctl_set: true + ignoreerrors: true + sysctl_file: "{{ rhel8cis_sysctl_file }}" + notify: Sysctl_flush_ipv6_routes + loop: + - { name: net.ipv6.conf.all.accept_ra, value: 0 } + - { name: net.ipv6.conf.default.accept_ra, value: 0 } diff --git a/tasks/section_3/cis_3.4.1.x.yml b/tasks/section_3/cis_3.4.1.x.yml index 8a20e276..1fe7c89f 100644 --- a/tasks/section_3/cis_3.4.1.x.yml +++ b/tasks/section_3/cis_3.4.1.x.yml @@ -1,152 +1,56 @@ --- -- name: "3.4.1.1 | PATCH | Ensure firewalld is installed" - ansible.builtin.package: - name: - - firewalld - - iptables - state: present +- name: "3.4.1.1 | PATCH | Ensure nftables is installed" when: - rhel8cis_rule_3_4_1_1 - - rhel8cis_firewall == "firewalld" + - "'nftables' not in ansible_facts.packages" tags: - level1-server - level1-workstation - - automated - patch - - firewalld + - nftables + - NIST800-53R5_CA-9 - rule_3.4.1.1 + ansible.builtin.package: + name: + - nftables + state: present -- name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld" - block: - - name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld | Stop running services" - ansible.builtin.systemd: - name: "{{ item }}" - masked: true - with_items: - - iptables - - ip6tables - when: item in ansible_facts.packages - - - name: "3.4.1.2 | PATCH | Ensure iptables-services not installed with firewalld | Remove IPTables" - ansible.builtin.package: - name: iptables-services - state: absent +- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use" when: - rhel8cis_rule_3_4_1_2 - - rhel8cis_firewall == "firewalld" tags: - level1-server - level1-workstation - - automated - patch - firewalld + - nftables - rule_3.4.1.2 - -- name: "3.4.1.3 | PATCH | Ensure nftables either not installed or masked with firewalld" - ansible.builtin.systemd: - name: nftables - state: stopped - masked: true - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3_4_1_3 - -- name: "3.4.1.4 | PATCH | Ensure firewalld service is enabled and running" - ansible.builtin.systemd: - name: firewalld - state: started - enabled: true - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3_4_1_4 - -- name: "3.4.1.5 | PATCH | Ensure firewalld default zone is set" block: - - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.shell: "firewall-cmd --get-default-zone | grep {{ rhel8cis_default_zone }}" - changed_when: false - failed_when: ( firewalld_zone_set.rc not in [ 0, 1 ] ) - register: firewalld_zone_set - - - name: "3.4.1.5 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.shell: firewall-cmd --set-default-zone="{{ rhel8cis_default_zone }}" + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables" when: - - firewalld_zone_set.rc != 0 - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - firewalld - - rule_3.4.1.5 - -- name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone" - block: - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and policies" - ansible.builtin.shell: "nmcli -t connection show | awk -F: '{ if($4){print $4} }' | while read INT; do firewall-cmd --get-active-zones | grep -B1 $INT; done" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_3_4_1_6_interfacepolicy - - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and policies | Show the interface to policy" - ansible.builtin.debug: - msg: - - "Warning!! The items below are the policies tied to the interfaces, please correct as needed" - - "{{ rhel8cis_3_4_1_6_interfacepolicy.stdout_lines }}" + - "'firewalld' in ansible_facts.packages" + - rhel8cis_firewall == "nftables" + ansible.builtin.systemd: + name: firewalld + masked: true - - name: "3.4.1.6 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '3.4.1.6' - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_6 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_3.4.1.6 + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld" + when: + - "'nftables' in ansible_facts.packages" + - rhel8cis_firewall == "firewalld" + ansible.builtin.systemd: + name: nftables + masked: true -- name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports" - block: - - name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports" - ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_3_4_1_7_servicesport + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel8cis_firewall }} package installed" + when: "rhel8cis_firewall not in ansible_facts.packages" + ansible.builtin.package: + name: "{{ rhel8cis_firewall }}" + state: present - - name: "3.4.1.7 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" - ansible.builtin.debug: - msg: - - "The items below are the services and ports that are accepted, please correct as needed" - - "{{ rhel8cis_3_4_1_7_servicesport.stdout_lines }}" - when: - - rhel8cis_firewall == "firewalld" - - rhel8cis_rule_3_4_1_7 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_3.4.1.7 + - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel8cis_firewall }} started and enabled" + ansible.builtin.systemd: + name: "{{ rhel8cis_firewall }}" + enabled: true + state: started diff --git a/tasks/section_3/cis_3.4.2.x.yml b/tasks/section_3/cis_3.4.2.x.yml index be9f79f4..5b0a3462 100644 --- a/tasks/section_3/cis_3.4.2.x.yml +++ b/tasks/section_3/cis_3.4.2.x.yml @@ -1,350 +1,248 @@ --- -- name: "3.4.2.1 | PATCH | Ensure nftables is installed" - ansible.builtin.package: - name: nftables - state: present +- name: "3.4.2.1 | PATCH | Ensure nftables base chains exist" when: - rhel8cis_firewall == "nftables" - rhel8cis_rule_3_4_2_1 tags: - level1-server - level1-workstation - - automated - patch - nftables + - NIST800-53R5_CA-9 - rule_3.4.2.1 - -# The control allows the service it be masked or not installed -# We have chosen not installed -- name: "3.4.2.2 | PATCH | Ensure firewalld is either not installed or masked with nftables" - ansible.builtin.package: - name: firewalld - state: absent - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.2 - -- name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables" - block: - - name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables | Stop services" - ansible.builtin.systemd: - name: "{{ item }}" - enabled: false - masked: true - ignore_errors: true # noqa ignore-errors - with_items: - - iptables - - ip6tables - - - name: "3.4.2.3 | PATCH | Ensure iptables-services not installed with nftables | Remove IPTables" - ansible.builtin.package: - name: iptables-service - state: absent - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.3 - -- name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables" - block: - - name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables | IPv4" - ansible.builtin.shell: iptables -F - - - name: "3.4.2.4 | PATCH | Ensure iptables are flushed with nftables | IPv6" - ansible.builtin.shell: ip6tables -F - when: rhel8cis_ipv6_required - when: - - rhel8cis_rule_3_4_2_4 - - rhel8cis_firewall != "firewalld" - tags: - - level1-server - - level1-workstation - - manual - - patch - - nftables - - rule_3.4.2.4 - -- name: "3.4.2.5 | AUDIT | Ensure an nftables table exists" block: - - name: "3.4.2.5 | AUDIT | Ensure a table exists | Check for tables" - ansible.builtin.shell: nft list tables - changed_when: false - failed_when: false - register: rhel8cis_3_4_2_5_nft_tables - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Show existing tables" - ansible.builtin.debug: - msg: - - "Below are the current nft tables, please review" - - "{{ rhel8cis_3_4_2_5_nft_tables.stdout_lines }}" - when: rhel8cis_3_4_2_5_nft_tables.stdout | length > 0 - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists | Alert on no tables" - ansible.builtin.debug: - msg: - - "Warning!! You currently have no nft tables, please review your setup" - - 'Use the command "nft create table inet " to create a new table' - when: - - rhel8cis_3_4_2_5_nft_tables.stdout | length == 0 - - not rhel8cis_nft_tables_autonewtable - - - name: "3.4.2.5 | AUDIT | Ensure an nftables table exists| Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '3.4.2.5' - when: - - rhel8cis_3_4_2_5_nft_tables.stdout | length == 0 - - not rhel8cis_nft_tables_autonewtable - - - name: "3.4.2.5 | PATCH | Ensure a table exists | Create table if needed" - ansible.builtin.shell: nft create table inet "{{ rhel8cis_nft_tables_tablename }}" - failed_when: false - when: rhel8cis_nft_tables_autonewtable - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.5 - -- name: "3.4.2.6 | PATCH | Ensure nftables base chains exist" - block: - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" ansible.builtin.shell: nft list ruleset | grep 'hook input' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_input_chains + register: discovered_input_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" ansible.builtin.shell: nft list ruleset | grep 'hook forward' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_forward_chains + register: discovered_forward_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" ansible.builtin.shell: nft list ruleset | grep 'hook output' changed_when: false failed_when: false - register: rhel8cis_3_4_2_6_output_chains + register: discovered_output_chains - - name: "3.4.2.6 | AUDIT | Ensure nftables base chains exist | Display chains for review" + - name: "3.4.2.1 | AUDIT | Ensure nftables base chains exist | Display chains for review" ansible.builtin.debug: msg: - "Below are the current INPUT chains" - - "{{ rhel8cis_3_4_2_6_input_chains.stdout_lines }}" + - "{{ discovered_input_chains.stdout_lines }}" - "Below are the current FORWARD chains" - - "{{ rhel8cis_3_4_2_6_forward_chains.stdout_lines }}" + - "{{ discovered_forward_chains.stdout_lines }}" - "Below are teh current OUTPUT chains" - - "{{ rhel8cis_3_4_2_6_output_chains.stdout_lines }}" + - "{{ discovered_output_chains.stdout_lines }}" when: not rhel8cis_nft_tables_autochaincreate - - name: "3.4.2.6 | PATCH | Ensure nftables base chains exist | Create chains if needed" + - name: "3.4.2.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" ansible.builtin.shell: "{{ item }}" failed_when: false - with_items: + loop: - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; } - nft create chain inet "{{ rhel8cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } when: rhel8cis_nft_tables_autochaincreate + +- name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured" when: - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_6 + - rhel8cis_rule_3_4_2_2 tags: - level1-server - level1-workstation - - automate - patch - nftables - - rule_3.4.2.6 - -- name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured" + - NIST800-53R5_CA-9 + - rule_3.4.2.2 block: - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather iif lo accept existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_iiflo + register: discovered_iiflo - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_ipsaddr + register: discovered_ipsaddr - - name: "3.4.2.7 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence" + - name: "3.4.2.2 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip6 saddr existence | nftables" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' changed_when: false failed_when: false - register: rhel8cis_3_4_2_7_ip6saddr + register: discovered_ip6saddr + + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set iif lo accept rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input iif lo accept + when: '"iif \"lo\" accept" not in discovered_iiflo.stdout' - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input iif lo accept - when: '"iif \"lo\" accept" not in rhel8cis_3_4_2_7_iiflo.stdout' + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip sddr rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop + when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_ipsaddr.stdout' - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop - when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_7_ipsaddr.stdout' + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip6 saddr rule | nftables" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop + when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_ip6saddr.stdout' - - name: "3.4.2.7 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop - when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel8cis_3_4_2_7_ip6saddr.stdout' +- name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | firewalld" when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_7 + - rhel8cis_firewall == "firewalld" + - rhel8cis_rule_3_4_2_2 tags: - level1-server - level1-workstation - - automated - patch - nftables - - rule_3.4.2.7 + - NIST800-53R5_CA-9 + - rule_3.4.2.2 + block: + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | add interface" + ansible.posix.firewalld: + zone: trusted + interface: lo + permanent: true + immediate: true + state: enabled + + - name: "3.4.2.2 | PATCH | Ensure host based firewall loopback traffic is configured | add loopback rule" + ansible.posix.firewalld: + rich_rule: "{{ item }}" + zone: trusted + permanent: true + immediate: true + state: enabled + loop: + - rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop + - rule family="ipv6" source address="::1" destination not address="::1" drop + +- name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports" + when: + - rhel8cis_firewall == "firewalld" + - rhel8cis_rule_3_4_2_3 + tags: + - level1-server + - level1-workstation + - manual + - audit + - NIST800-53R5_CA-9 + - rule_3.4.2.3 + block: + - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports" + ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done" + changed_when: false + failed_when: false + check_mode: false + register: discovered_servicesport -- name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured" + - name: "3.4.2.3 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports" + ansible.builtin.debug: + msg: + - "The items below are the services and ports that are accepted, please correct as needed" + - "{{ discovered_servicesport.stdout_lines }}" + +- name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured" + when: + - rhel8cis_firewall == "nftables" + - rhel8cis_rule_3_4_2_4 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_3.4.2.4 block: - - name: "3.4.2.8 | AUDIT | Ensure nftables outbound and established connections are configured | Gather incoming connection rules" + - name: "3.4.2.4 | AUDIT | Ensure nftables established connections are configured | Gather incoming connection rules" ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_8_inconnectionrule + register: discovered_inconnectionrule - - name: "3.4.2.8 | AUDIT | Ensure nftables outbound and established connections are configured | Gather outbound connection rules" + - name: "3.4.2.4| AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false - register: rhel8cis_3_4_2_8_outconnectionrule + register: discovered_outconnectionrule + + - name: "3.4.2.4| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + when: '"ip protocol tcp ct state established accept" not in discovered_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input tcp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - when: '"ip protocol tcp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol udp ct state established accept + when: '"ip protocol udp ct state established accept" not in discovered_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input udp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol udp ct state established accept - when: '"ip protocol udp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept + when: '"ip protocol icmp ct state established accept" not in discovered_inconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add input icmp established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept - when: '"ip protocol icmp ct state established accept" not in rhel8cis_3_4_2_8_inconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept + when: '"ip protocol tcp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output tcp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept - when: '"ip protocol tcp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept + when: '"ip protocol udp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output udp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept - when: '"ip protocol udp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' + - name: "3.4.2.4 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept + when: '"ip protocol icmp ct state established,related,new accept" not in discovered_outconnectionrule.stdout' - - name: "3.4.2.8 | PATCH | Ensure nftables outbound and established connections are configured | Add output icmp new, related, established accept policy" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept - when: '"ip protocol icmp ct state established,related,new accept" not in rhel8cis_3_4_2_8_outconnectionrule.stdout' +- name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy" when: - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_8 + - rhel8cis_rule_3_4_2_5 tags: - level1-server - level1-workstation - - automated - patch - nftables - - rule_3.4.3.8 - -- name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy" + - NIST800-53R5_CA-9 + - rule_3.4.2.5 block: - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_inputpolicy + register: discovered_inputpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_forwardpolicy + register: discovered_forwardpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_outputpolicy + register: discovered_outputpolicy - - name: "3.4.2.9 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" + - name: "3.4.2.5 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" ansible.builtin.shell: nft list table inet "{{ rhel8cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false - register: rhel8cis_3_4_2_9_sshallowcheck - - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" - ansible.builtin.shell: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input tcp dport ssh accept - when: '"tcp dport ssh accept" not in rhel8cis_3_4_2_9_sshallowcheck.stdout' - - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" input { policy drop \; } - when: '"type filter hook input priority 0; policy drop;" not in rhel8cis_3_4_2_9_inputpolicy.stdout' + register: discovered_sshallowcheck - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { policy drop \; } - when: '"type filter hook forward priority 0; policy drop;" not in rhel8cis_3_4_2_9_forwardpolicy.stdout' + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" + ansible.builtin.command: nft add rule inet "{{ rhel8cis_nft_tables_tablename }}" input tcp dport ssh accept + when: '"tcp dport ssh accept" not in discovered_sshallowcheck.stdout' - - name: "3.4.2.9 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" - ansible.builtin.shell: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" output { policy drop \; } - when: '"type filter hook output priority 0; policy drop;" not in rhel8cis_3_4_2_9_outputpolicy.stdout' - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.9 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" input { policy drop \; } + when: '"type filter hook input priority 0; policy drop;" not in discovered_inputpolicy.stdout' -- name: "3.4.2.10 | PATCH | Ensure nftables service is enabled" - ansible.builtin.service: - name: nftables - enabled: true - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_10 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.3.10 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" forward { policy drop \; } + when: '"type filter hook forward priority 0; policy drop;" not in discovered_forwardpolicy.stdout' -- name: "3.4.2.11 | PATCH | Ensure nftables rules are permanent" - ansible.builtin.lineinfile: - path: /etc/sysconfig/nftables.conf - state: present - insertafter: EOF - line: include "/etc/nftables/inet-{{ rhel8cis_nft_tables_tablename }}" - when: - - rhel8cis_firewall == "nftables" - - rhel8cis_rule_3_4_2_11 - tags: - - level1-server - - level1-workstation - - automated - - patch - - nftables - - rule_3.4.2.11 + - name: "3.4.2.5 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" + ansible.builtin.command: nft chain inet "{{ rhel8cis_nft_tables_tablename }}" output { policy drop \; } + when: '"type filter hook output priority 0; policy drop;" not in discovered_outputpolicy.stdout' diff --git a/tasks/section_3/cis_3.4.3.1.x.yml b/tasks/section_3/cis_3.4.3.1.x.yml deleted file mode 100644 index 37c21775..00000000 --- a/tasks/section_3/cis_3.4.3.1.x.yml +++ /dev/null @@ -1,50 +0,0 @@ ---- - -- name: "3.4.3.1.1 | PATCH | Ensure iptables packages are installed" - ansible.builtin.package: - name: - - iptables - - iptables-services - state: present - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.1 - -- name: "3.4.3.1.2 | PATCH | Ensure nftables is not installed with iptables" - ansible.builtin.package: - name: nftables - state: absent - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.2 - -# The control allows the service it be masked or not installed -# We have chosen not installed -- name: "3.4.3.1.3 | PATCH | Ensure firewalld is either not installed or masked with iptables" - ansible.builtin.package: - name: firewalld - state: absent - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.1.3 diff --git a/tasks/section_3/cis_3.4.3.2.x.yml b/tasks/section_3/cis_3.4.3.2.x.yml deleted file mode 100644 index 1d7bf337..00000000 --- a/tasks/section_3/cis_3.4.3.2.x.yml +++ /dev/null @@ -1,169 +0,0 @@ ---- - -- name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured" - block: - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | INPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: INPUT - in_interface: lo - jump: ACCEPT - - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | OUTPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: OUTPUT - out_interface: lo - jump: ACCEPT - - - name: "3.4.3.2.1 | PATCH | Ensure iptables loopback traffic is configured | INPUT Loopback 127.0.0.0/8" - ansible.builtin.iptables: - action: append - chain: INPUT - source: 127.0.0.0/8 - jump: DROP - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.1 - -- name: "3.4.3.2.2 | PATCH | Ensure iptables outbound and established connections are configured" - ansible.builtin.iptables: - action: append - chain: '{{ item.chain }}' - protocol: '{{ item.protocol }}' - match: state - ctstate: '{{ item.ctstate }}' - jump: ACCEPT - with_items: - - { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' } - - { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: udp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED } - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_2 - tags: - - level1-server - - level1-workstation - - manual - - patch - - iptables - - rule_3.4.3.2.2 - -- name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports" - block: - - name: "3.4.3.2.3 | AUDIT | Ensure iptables rules exist for all open ports | Get list of TCP open ports" - ansible.builtin.shell: netstat -ant |grep "tcp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_2_3_otcp - - - name: "3.4.3.2.3 | AUDIT | Ensure iptables rules exist for all open ports | Get the list of udp open ports" - ansible.builtin.shell: netstat -ant |grep "udp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_2_3_oudp - - - name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports | Adjust open tcp ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: tcp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - with_items: - - "{{ rhel8cis_3_4_3_2_3_otcp.stdout_lines }}" - when: rhel8cis_3_4_3_2_3_otcp.stdout is defined - - - name: "3.4.3.2.3 | PATCH | Ensure iptables rules exist for all open ports | Adjust open udp ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: udp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - with_items: - - "{{ rhel8cis_3_4_3_2_3_oudp.stdout_lines }}" - when: rhel8cis_3_4_3_2_3_otcp.stdout is defined - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.3 - -- name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy" - block: - - name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy | Configure ssh to be allowed" - ansible.builtin.iptables: - chain: INPUT - protocol: tcp - destination_port: "22" - jump: ACCEPT - - - name: "3.4.3.2.4 | PATCH | Ensure iptables default deny firewall policy | Set drop items" - ansible.builtin.iptables: - policy: DROP - chain: "{{ item }}" - with_items: - - INPUT - - FORWARD - - OUTPUT - when: - - rhel8cis_rule_3_4_3_2_4 - - rhel8cis_firewall == "iptables" - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.4 - -- name: "3.4.3.2.5 | PATCH | Ensure iptables rules are saved" - community.general.iptables_state: - state: saved - path: /etc/sysconfig/iptables - when: - - rhel8cis_rule_3_4_3_2_5 - - rhel8cis_firewall == "iptables" - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.5 - -- name: "3.4.3.2.6 | PATCH | Ensure iptables service is enabled and active" - ansible.builtin.service: - name: iptables - enabled: true - state: started - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_2_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - iptables - - rule_3.4.3.2.6 diff --git a/tasks/section_3/cis_3.4.3.3.x.yml b/tasks/section_3/cis_3.4.3.3.x.yml deleted file mode 100644 index 4bce1b99..00000000 --- a/tasks/section_3/cis_3.4.3.3.x.yml +++ /dev/null @@ -1,163 +0,0 @@ ---- - -- name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured" - block: - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: INPUT - in_interface: lo - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | OUTPUT Loopback ACCEPT" - ansible.builtin.iptables: - action: append - chain: OUTPUT - out_interface: lo - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback 127.0.0.0/8" - ansible.builtin.iptables: - action: append - chain: INPUT - source: ::1 - jump: DROP - ip_version: ipv6 - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_1 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.1 - -- name: "3.4.3.3.2 | PATCH | Ensure ip6tables outbound and established connections are configured" - ansible.builtin.iptables: - action: append - chain: '{{ item.chain }}' - protocol: '{{ item.protocol }}' - match: state - ctstate: '{{ item.ctstate }}' - jump: ACCEPT - ip_version: ipv6 - with_items: - - { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' } - - { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' } - - { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: udp, ctstate: ESTABLISHED } - - { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED } - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_2 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - manual - - patch - - ip6tables - - rule_3.4.3.3.2 - -- name: "3.4.3.3.3 | PATCH | Ensure ip6tables firewall rules exist for all open ports" - block: - - name: "3.4.3.3.3 | AUDIT | Ensure ip6tables firewall rules exist for all open ports | Get list of TCP6 open ports" - ansible.builtin.shell: netstat -ant |grep "tcp6.*LISTEN" | awk '{ print $4 }'| sed 's/.*://' - changed_when: false - failed_when: false - register: rhel8cis_3_4_3_3_3_otcp - - - name: "3.4.3.3.3 | PATCH |Ensure ip6tables firewall rules exist for all open ports| Adjust open tcp6 ports" - ansible.builtin.iptables: - action: append - chain: INPUT - protocol: tcp - destination_port: "{{ item }}" - match: state - ctstate: NEW - jump: ACCEPT - ip_version: ipv6 - with_items: - - "{{ rhel8cis_3_4_3_3_3_otcp.stdout_lines }}" - when: rhel8cis_3_4_3_3_3_otcp.stdout is defined - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_3 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.3 - -- name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy" - block: - - name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy | Configure ssh to be allowed" - ansible.builtin.iptables: - chain: INPUT - protocol: tcp - destination_port: "22" - jump: ACCEPT - ip_version: ipv6 - - - name: "3.4.3.3.4 | PATCH | Ensure ip6tables default deny firewall policy | Set drop items" - ansible.builtin.iptables: - policy: DROP - chain: "{{ item }}" - ip_version: ipv6 - with_items: - - INPUT - - FORWARD - - OUTPUT - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_4 - - rhel8cis_ipv6_required - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.4 - -- name: "3.4.3.3.5 | PATCH | Ensure ip6tables rules are saved" - community.general.iptables_state: - state: saved - path: /etc/sysconfig/ip6tables - ip_version: ipv6 - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_ipv6_required - - rhel8cis_rule_3_4_3_3_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.5 - -- name: "3.4.3.3.6 | PATCH | Ensure ip6tables service is enabled and active" - ansible.builtin.service: - name: ip6tables - enabled: true - state: started - when: - - rhel8cis_firewall == "iptables" - - rhel8cis_rule_3_4_3_3_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ip6tables - - rule_3.4.3.3.6 diff --git a/tasks/section_3/main.yml b/tasks/section_3/main.yml index a62f56ef..42726685 100644 --- a/tasks/section_3/main.yml +++ b/tasks/section_3/main.yml @@ -1,35 +1,21 @@ --- -- name: "SECTION | 3.1.x | Disable unused network protocols and devices" - ansible.builtin.import_tasks: cis_3.1.x.yml +- name: "SECTION | 3.1.x | Configure network devices" + ansible.builtin.import_tasks: + file: cis_3.1.x.yml -- name: "SECTION | 3.2.x | Network Parameters (Host Only)" - ansible.builtin.import_tasks: cis_3.2.x.yml +- name: "SECTION | 3.2.x | Network kernel modules" + ansible.builtin.import_tasks: + file: cis_3.2.x.yml -- name: "SECTION | 3.3.x | Network Parameters (Host and Router)" - ansible.builtin.import_tasks: cis_3.3.x.yml +- name: "SECTION | 3.3.x | Network kernel Parameters" + ansible.builtin.import_tasks: + file: cis_3.3.x.yml -- name: "SECTION | 3.4.1.x | Configure firewalld" - ansible.builtin.import_tasks: cis_3.4.1.x.yml - when: - - rhel8cis_firewall == "firewalld" +- name: "SECTION | 3.4.1.x | Configure firewall utility" + ansible.builtin.import_tasks: + file: cis_3.4.1.x.yml -- name: "SECTION | 3.4.2.x | Configure nftables" - ansible.builtin.import_tasks: cis_3.4.2.x.yml - when: - - rhel8cis_firewall == "nftables" - -- name: "SECTION | 3.4.3.1.x | Configure iptables software" - ansible.builtin.import_tasks: cis_3.4.3.1.x.yml - when: - - rhel8cis_firewall == "iptables" - -- name: "SECTION | 3.4.3.2.x | Configure IPv4 iptables" - ansible.builtin.import_tasks: cis_3.4.3.2.x.yml - when: - - rhel8cis_firewall == "iptables" - -- name: "SECTION | 3.4.3.3.x | Configure IPv6 iptables" - ansible.builtin.import_tasks: cis_3.4.3.3.x.yml - when: - - ( rhel8cis_firewall == "iptables" and rhel8cis_ipv6_required ) +- name: "SECTION | 3.4.2.x | Configure firewall rules" + ansible.builtin.import_tasks: + file: cis_3.4.2.x.yml diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml index 6f486d8d..b70ee61f 100644 --- a/tasks/section_4/cis_4.1.1.x.yml +++ b/tasks/section_4/cis_4.1.1.x.yml @@ -1,109 +1,164 @@ --- -- name: "4.1.1.1 | PATCH | Ensure auditd is installed" - block: - - name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd packages" - ansible.builtin.package: - name: audit - state: present - when: '"auditd" not in ansible_facts.packages' - - - name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages" - ansible.builtin.package: - name: audit-libs - state: present - when: '"auditd-lib" not in ansible_facts.packages' +- name: "4.1.1.1 | PATCH | Ensure cron daemon is enabled and active" when: - rhel8cis_rule_4_1_1_1 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_4.1.1.1 - -- name: "4.1.1.2 | PATCH | Ensure auditd service is enabled" - ansible.builtin.service: - name: auditd - state: started + ansible.builtin.systemd: + name: crond enabled: true + state: started + +- name: "4.1.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" when: - rhel8cis_rule_4_1_1_2 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.2 + ansible.builtin.file: + path: /etc/crontab + owner: root + group: root + mode: '0600' -- name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" - block: - - name: "4.1.1.3 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX" - ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_4_1_1_3_grub_cmdline_linux - - - name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" - ansible.builtin.replace: - path: /etc/default/grub - regexp: 'audit=.' - replace: 'audit=1' - notify: rhel8cis_grub2cfg - when: "'audit=' in rhel8cis_4_1_1_3_grub_cmdline_linux.stdout" - - - name: "4.1.1.3 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing" - ansible.builtin.lineinfile: - path: /etc/default/grub - regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_4_1_1_3_grub_cmdline_linux.stdout }} audit=1"' - notify: rhel8cis_grub2cfg - when: "'audit=' not in rhel8cis_4_1_1_3_grub_cmdline_linux.stdout" +- name: "4.1.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" when: - rhel8cis_rule_4_1_1_3 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd - - grub + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.3 + ansible.builtin.file: + path: /etc/cron.hourly + state: directory + owner: root + group: root + mode: '0700' -- name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient" - block: - - name: "4.1.1.4 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX" - ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_4_1_1_4_grub_cmdline_linux - - - name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" - ansible.builtin.replace: - path: /etc/default/grub - regexp: 'audit_backlog_limit=\d+' - replace: 'audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}' - notify: rhel8cis_grub2cfg - when: "'audit_backlog_limit=' in rhel8cis_4_1_1_4_grub_cmdline_linux.stdout" - - - name: "4.1.1.4 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing" - ansible.builtin.lineinfile: - path: /etc/default/grub - regexp: '^GRUB_CMDLINE_LINUX=' - line: '{{ rhel8cis_4_1_1_4_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' - notify: rhel8cis_grub2cfg - when: "'audit_backlog_limit=' not in rhel8cis_4_1_1_4_grub_cmdline_linux.stdout" +- name: "4.1.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" when: - rhel8cis_rule_4_1_1_4 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd - - grub + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.1.4 + ansible.builtin.file: + path: /etc/cron.daily + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" + when: + - rhel8cis_rule_4_1_1_5 + tags: + - level1-server + - level1-workstation + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.5 + ansible.builtin.file: + path: /etc/cron.weekly + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" + when: + - rhel8cis_rule_4_1_1_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.6 + ansible.builtin.file: + path: /etc/cron.monthly + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" + when: + - rhel8cis_rule_4_1_1_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.7 + ansible.builtin.file: + path: /etc/cron.d + state: directory + owner: root + group: root + mode: '0700' + +- name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users" + when: + - rhel8cis_rule_4_1_1_8 + tags: + - level1-server + - level1-workstation + - automated + - patch + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.1.1.8 + block: + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny" + ansible.builtin.file: + path: /etc/cron.deny + state: absent + + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists" + ansible.builtin.stat: + path: "/etc/cron.allow" + register: discovered_cron_allow_state + + - name: "4.1.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users" + ansible.builtin.file: + path: /etc/cron.allow + state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: g-wx,o-rwx diff --git a/tasks/section_4/cis_4.1.2.x.yml b/tasks/section_4/cis_4.1.2.x.yml index dfca1af6..b42dd300 100644 --- a/tasks/section_4/cis_4.1.2.x.yml +++ b/tasks/section_4/cis_4.1.2.x.yml @@ -1,53 +1,32 @@ --- -- name: "4.1.2.1 | PATCH | Ensure audit log storage size is configured" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^max_log_file( |=)" - line: "max_log_file = {{ rhel8cis_max_log_file_size }}" - notify: restart auditd +- name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users" when: - rhel8cis_rule_4_1_2_1 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - automated - patch - - auditd + - cron + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - rule_4.1.2.1 + block: + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Remove at.deny" + ansible.builtin.file: + path: /etc/at.deny + state: absent -- name: "4.1.2.2 | PATCH | Ensure audit logs are not automatically deleted" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^max_log_file_action" - line: "max_log_file_action = {{ rhel8cis_auditd['max_log_file_action'] }}" - notify: restart auditd - when: - - rhel8cis_rule_4_1_2_2 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.2.2 + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" + ansible.builtin.stat: + path: "/etc/at.allow" + register: discovered_at_allow_state -- name: "4.1.2.3 | PATCH | Ensure system is disabled when audit logs are full" - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - notify: restart auditd - with_items: - - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel8cis_auditd.admin_space_left_action }}' } - - { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel8cis_auditd.action_mail_acct }}' } - - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel8cis_auditd.space_left_action }}' } - when: - - rhel8cis_rule_4_1_2_3 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.2.3 + - name: "4.1.2.1 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users" + ansible.builtin.file: + path: /etc/at.allow + state: '{{ "file" if discovered_at_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: '0600' diff --git a/tasks/section_4/cis_4.2.3.yml b/tasks/section_4/cis_4.2.3.yml deleted file mode 100644 index 0aa9f25a..00000000 --- a/tasks/section_4/cis_4.2.3.yml +++ /dev/null @@ -1,35 +0,0 @@ ---- - -- name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured" - block: - - name: "4.2.3 | AUDIT | Ensure permissions on all logfiles are configured | find files" - ansible.builtin.shell: find /var/log/ -type f -perm /g+wx,o+rwx -exec ls {} \; - changed_when: false - failed_when: false - register: rhel8cis_4_2_3_logfiles - - - name: "4.2.3 | AUDIT | Ensure permissions on all logfiles are configured | set_fact" - ansible.builtin.set_fact: - rhel8cis_4_2_3_logfiles_flattened: "{{ rhel8cis_4_2_3_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: - - rhel8cis_4_2_3_logfiles.stdout_lines | length > 0 - - rhel8cis_4_2_3_logfiles is defined - - - name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured | change permissions" - ansible.builtin.file: - path: "{{ item }}" - mode: 0640 - loop: "{{ rhel8cis_4_2_3_logfiles_flattened }}" - when: - - rhel8cis_4_2_3_logfiles_flattened is defined - - item != "/var/log/btmp" - - item != "/var/log/utmp" - - item != "/var/log/wtmp" - when: - - rhel8cis_rule_4_2_3 - tags: - - level1-server - - level1-workstation - - patch - - logfiles - - rule_4.2.3 diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml new file mode 100644 index 00000000..e0c240ed --- /dev/null +++ b/tasks/section_4/cis_4.2.x.yml @@ -0,0 +1,488 @@ +--- + +- name: "4.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured" + when: + - rhel8cis_rule_4_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - permissions + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.1 + ansible.builtin.file: + path: /etc/ssh/sshd_config + owner: root + group: root + mode: '0600' + +- name: "4.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" + when: + - rhel8cis_rule_4_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - permissions + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.2 + block: + - name: "4.2.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys" + ansible.builtin.find: + paths: /etc/ssh + patterns: 'ssh_host_*_key' + recurse: true + file_type: any + register: discovered_ssh_private_host_key + + - name: "4.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + group: root + mode: '0600' + loop: "{{ discovered_ssh_private_host_key.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "4.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" + when: + - rhel8cis_rule_4_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.3 + block: + - name: "4.2.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys" + ansible.builtin.find: + paths: /etc/ssh + patterns: 'ssh_host_*_key.pub' + recurse: true + file_type: any + register: discovered_ssh_public_host_key + + - name: "4.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + group: root + mode: '0644' + loop: "{{ discovered_ssh_public_host_key.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "4.2.4 | PATCH | Ensure SSH access is configured" + when: + - rhel8cis_rule_4_2_4 + - rhel8cis_sshd_limited + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.2.4 + block: + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for allowusers" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^AllowUsers" + line: AllowUsers {{ rhel8cis_sshd['allowusers'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['allowusers']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for allowgroups" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^AllowGroups" + line: AllowGroups {{ rhel8cis_sshd['allowgroups'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['allowgroups']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for denyusers" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^DenyUsers" + line: DenyUsers {{ rhel8cis_sshd['denyusers'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['denyusers']|default('') | length > 0" + + - name: "4.2.4 | PATCH | Ensure SSH access is configured | Add line to sshd_config for denygroups" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^DenyGroups" + line: DenyGroups {{ rhel8cis_sshd['denygroups'] }} + notify: Restart_sshd + when: "rhel8cis_sshd['denygroups']|default('') | length > 0" + +- name: "4.2.5 | PATCH | Ensure SSH warning banner is configured" + when: + - rhel8cis_rule_4_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.5 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^Banner' + line: 'Banner /etc/issue.net' + +- name: "4.2.6 | PATCH | Ensure sshd Ciphers are configured" + when: + - rhel8cis_rule_4_2_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - ciphers + - NIST800-53R5_SC-8 + - rule_4.2.6 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#Ciphers|^Ciphers" + line: "Ciphers {{ rhel8cis_sshd['ciphers'] }}" + +- name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured" + when: + - rhel8cis_rule_4_2_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.7 + block: + - name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^ClientAliveInterval' + line: "ClientAliveInterval {{ rhel8cis_sshd['clientaliveinterval'] }}" + + - name: "4.2.7 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^ClientAliveCountMax' + line: "ClientAliveCountMax {{ rhel8cis_sshd['clientalivecountmax'] }}" + +- name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled" + when: + - rhel8cis_rule_4_2_8 + tags: + - level2-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-7 + - rule_4.2.8 + block: + - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled" + ansible.builtin.replace: + path: /etc/ssh/sshd_config + regexp: '^(#|)\s*DisableForwarding.*' + replace: 'DisableForwarding yes' + + - name: "4.2.8 | PATCH | Ensure sshd DisableForwarding is enabled | ensure x11 disabled" + ansible.builtin.replace: + path: /etc/ssh/sshd_config + regexp: ^X11Forwarding (yes|no) + replace: '#DisableForwarding yes' + +- name: "4.2.9 | PATCH | Ensure SSH HostbasedAuthentication is disabled" + when: + - rhel8cis_rule_4_2_9 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.9 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: ^#HostbasedAuthentication|^HostbasedAuthentication" + line: 'HostbasedAuthentication no' + +- name: "4.2.10 | PATCH | Ensure SSH IgnoreRhosts is enabled" + when: + - rhel8cis_rule_4_2_10 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.10 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#IgnoreRhosts|^IgnoreRhosts" + line: 'IgnoreRhosts yes' + +- name: "4.2.11 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel8cis_rule_4_2_11 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - kex + - NIST800-53R5_SC-8 + - rule_4.2.11 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#KexAlgorithms|^KexAlgorithms" + line: "KexAlgorithms {{ rhel8cis_sshd['kex'] }}" + +- name: "4.2.12 | PATCH | Ensure sshd LoginGraceTime is configured" + when: + - rhel8cis_rule_4_2_12 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-6 + - rule_4.2.12 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#LoginGraceTime|^LoginGraceTime" + line: "LoginGraceTime {{ rhel8cis_sshd['logingracetime'] }}" + +- name: "4.2.13 | PATCH | Ensure sshd LogLevel is configured" + when: + - rhel8cis_rule_4_2_13 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - rule_4.2.13 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#LogLevel|^LogLevel" + line: "LogLevel {{ rhel8cis_sshd['loglevel'] }}" + +- name: "4.2.14 | PATCH | Ensure sshd MACs are configured" + when: + - rhel8cis_rule_4_2_14 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - macs + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.14 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#MACs|^MACs" + line: "MACs {{ rhel8cis_sshd['macs'] }}" + +- name: "4.2.15 | PATCH | Ensure sshd MaxAuthTries is configured" + when: + - rhel8cis_rule_4_2_15 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AU-3 + - rule_4.2.15 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: '^(#)?MaxAuthTries \d' + line: "MaxAuthTries {{ rhel8cis_sshd['maxauthtries'] }}" + +- name: "4.2.16 | PATCH | Ensure sshd MaxSessions is configured" + when: + - rhel8cis_rule_4_2_16 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.16 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#MaxSessions|^MaxSessions" + line: "MaxSessions {{ rhel8cis_sshd['maxsessions'] }}" + +- name: "4.2.17 | PATCH | Ensure sshd MaxStartups is configured" + when: + - rhel8cis_rule_4_2_17 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.17 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: (?i)MaxStartups + line: "MaxStartups {{ rhel8cis_sshd['maxstartups'] }}" + +- name: "4.2.18 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" + when: + - rhel8cis_rule_4_2_18 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.18 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" + line: 'PermitEmptyPasswords no' + +- name: "4.2.19 | PATCH | Ensure sshd PermitRootLogin is disabled" + when: + - rhel8cis_rule_4_2_19 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_AC-6 + - rule_4.2.19 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitRootLogin|^PermitRootLogin" + line: 'PermitRootLogin no' + +- name: "4.2.20 | PATCH | Ensure sshd PermitUserEnvironment is disabled" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" + line: 'PermitUserEnvironment no' + when: + - rhel8cis_rule_4_2_20 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.20 + +- name: "4.2.21 | PATCH | Ensure sshd UsePAM is enabled" + when: + - rhel8cis_rule_4_2_21 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - rule_4.2.21 + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config + regexp: "^#UsePAM|^UsePAM" + line: 'UsePAM yes' + +- name: "4.2.22 | PATCH | Ensure sshd crypto_policy is not set" + when: + - rhel8cis_rule_4_2_22 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ssh + - NIST800-53R5_SC-8 + - NIST800-53R5_IA-5 + - NIST800-53R5_AC-17 + - rule_4.2.22 + block: + - name: "4.2.22 | AUDIT | Ensure system-wide crypto policy is not over-ridden" + ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd + failed_when: ( discovered_crypto_policy_override.rc not in [ 0, 1 ] ) + changed_when: false + register: discovered_crypto_policy_override + + - name: "4.2.22 | PATCH | Ensure system-wide crypto policy is not over-ridden" + ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd + notify: Restart_sshd + when: + - discovered_crypto_policy_override.stdout | length > 0 diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml new file mode 100644 index 00000000..4ad33145 --- /dev/null +++ b/tasks/section_4/cis_4.3.x.yml @@ -0,0 +1,143 @@ +--- + +- name: "4.3.1 | PATCH | Ensure sudo is installed" + when: + - rhel8cis_rule_4_3_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.1 + ansible.builtin.package: + name: sudo + state: present + +- name: "4.3.2 | PATCH | Ensure sudo commands use pty" + when: + - rhel8cis_rule_4_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.2 + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "Defaults use_pty" + validate: '/usr/sbin/visudo -cf %s' + +- name: "4.3.3 | PATCH | Ensure sudo log file exists" + when: + - rhel8cis_rule_4_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - sudo + - rule_4.3.3 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: '^Defaults\s+logfile=' + line: 'Defaults logfile={{ rhel8cis_sudolog_location }}' + +- name: "4.3.4 | PATCH | Ensure users must provide password for escalation" + when: + - rhel8cis_rule_4_3_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.4 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' + replace: '\1PASSWD\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ discovered_sudoers_files.stdout_lines }}" + +- name: "4.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" + when: + - rhel8cis_rule_4_3_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-6 + - sudo + - rule_4.3.5 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#].*)!authenticate(.*)' + replace: '\1authenticate\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ discovered_sudoers_files.stdout_lines }}" + +- name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" + when: + - rhel8cis_rule_4_3_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - sudo + - rule_4.3.6 + block: + - name: "4.3.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set" + ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort + changed_when: false + failed_when: false + register: discovered_timeout_files + + - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" + when: discovered_timeout_files.stdout | length == 0 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: 'Defaults timestamp_timeout=' + line: "Defaults timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + + - name: "4.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" + when: discovered_timeout_files.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'timestamp_timeout=(\d+)' + replace: "timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ discovered_timeout_files.stdout_lines }}" + +- name: "4.3.7 | PATCH | Ensure access to the su command is restricted" + when: + - rhel8cis_rule_4_3_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - sudo + - rule_4.3.7 + block: + - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" + ansible.builtin.group: + name: "{{ rhel8cis_sugroup }}" + state: present + + - name: "4.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" + ansible.builtin.lineinfile: + path: /etc/pam.d/su + regexp: '^(#)?auth\s+required\s+pam_wheel\.so' + line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' diff --git a/tasks/section_4/cis_4.3.yml b/tasks/section_4/cis_4.3.yml deleted file mode 100644 index 0797b80c..00000000 --- a/tasks/section_4/cis_4.3.yml +++ /dev/null @@ -1,28 +0,0 @@ ---- - -- name: "4.3 | PATCH | Ensure logrotate is configured" - block: - - name: "4.3 | AUDIT | Ensure logrotate is configured | Get logrotate settings" - ansible.builtin.find: - paths: /etc/logrotate.d/ - register: log_rotates - - - name: "4.3 | PATCH | Ensure logrotate is configured" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: '^(\s*)(daily|weekly|monthly|yearly)$' - replace: "\\1{{ rhel8cis_logrotate }}" - with_items: - - "{{ log_rotates.files }}" - - { path: "/etc/logrotate.conf" } - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_4_3 - tags: - - level1-server - - level1-workstation - - manual - - patch - - logrotate - - rule_4.3 diff --git a/tasks/section_4/cis_4.4.1.x.yml b/tasks/section_4/cis_4.4.1.x.yml new file mode 100644 index 00000000..e5db2ce4 --- /dev/null +++ b/tasks/section_4/cis_4.4.1.x.yml @@ -0,0 +1,37 @@ +--- + +- name: "4.4.1.1 | PATCH | Ensure latest version of pam is installed" + when: + - rhel8cis_rule_4_4_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.1.1 + ansible.builtin.package: + name: pam + state: latest + +- name: "4.4.1.2 | PATCH | Ensure latest version of authselect is installed" + when: + - rhel8cis_rule_4_4_1_2 + - rhel8cis_authselect_pkg_update + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.1.2 + ansible.builtin.package: + name: authselect + state: latest + +- name: "4.4.1.1 and 4.4.1.2 | Update package facts" + when: + - rhel8cis_rule_4_4_1_1 or + rhel8cis_rule_4_4_1_2 + ansible.builtin.package_facts: + manager: auto diff --git a/tasks/section_4/cis_4.4.2.x.yml b/tasks/section_4/cis_4.4.2.x.yml new file mode 100644 index 00000000..2d1850e8 --- /dev/null +++ b/tasks/section_4/cis_4.4.2.x.yml @@ -0,0 +1,168 @@ +--- + +- name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used" + when: + - rhel8cis_rule_4_4_2_1 + - authselect_version == "OK" + - pam_version == "OK" + - rhel8cis_disruption_high + tags: + - level1-server + - level1-workstation + - manual + - patch + - authselect + - rule_4.4.2.1 + block: + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" + when: + - rhel8cis_authselect_custom_profile_create + - discovered_authselect_running_config.stdout is not defined + - not discovered_authselect_profile.stat.exists + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }}" + args: + creates: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + + - name: "4.4.2.1 | PATCH | Ensure custom authselect profile is used | Select profiles" + when: + - rhel8cis_authselect_custom_profile_select + - (discovered_authselect_running_config.stdout is defined and "rhel8cis_authselect['custom_profile_name'] not in discovered_authselect_running_config.stdout") + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }}{% if rhel8cis_rule_4_4_2_2 %} with-faillock{% endif %}{% if rhel8cis_rule_4_4_2_4 %} with-pwhistory{% endif %}{% if rhel8cis_rule_4_4_3_4_1 %} without-nullok{% endif %} --force" + +- name: "4.4.2.2 | PATCH | Ensure pam_faillock module is enabled" + when: + - rhel8cis_rule_4_4_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.2 + notify: Update_authselect + block: + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep faillock + changed_when: false + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current + + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" + when: discovered_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-faillock" + +- name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled" + when: + - rhel8cis_rule_4_4_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.3 + notify: Update_authselect + block: + - name: "4.4.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Capture current state" + ansible.builtin.shell: | + grep -P -- '\bpam_pwquality\.so\b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: discovered_pwquality_enabled.rc not in [ 0, 1 ] + register: discovered_pwquality_enabled + + - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" + when: "'system-auth:password' not in discovered_pwquality_enabled.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + + - name: "4.4.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" + when: "'password-auth:password' not in discovered_pwquality_enabled.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(password\s+)(required|requisite|sufficient)(\s+pam_pwquality.so.*)(.*)', line: '\1requisite\3\4', before: '^password\s+[default=1 ignore=ignore success=ok]' } + +- name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled" + when: + - rhel8cis_rule_4_4_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.4 + notify: Update_authselect + block: + - name: "4.4.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep pwhistory + changed_when: false + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current + + - name: "4.4.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" + when: discovered_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-pwhistory" + +- name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled" + when: + - rhel8cis_rule_4_4_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_4.4.2.5 + block: + - name: "4.4.2.5 | AUDIT | Ensure pam_unix module is enabled" + ansible.builtin.shell: | + grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth + changed_when: false + failed_when: discovered_authselect_pam_unix.rc not in [ 0, 1 ] + register: discovered_authselect_pam_unix + + - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" + when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } + + - name: "4.4.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" + when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + line: "{{ item.line }}" + path: /etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/password-auth + regexp: "{{ item.regexp }}" + loop: + - { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\2', after: '^auth.*pam_faillock.*preauth' } + - { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' } diff --git a/tasks/section_4/cis_4.4.3.1.x.yml b/tasks/section_4/cis_4.4.3.1.x.yml new file mode 100644 index 00000000..062efcee --- /dev/null +++ b/tasks/section_4/cis_4.4.3.1.x.yml @@ -0,0 +1,131 @@ +--- + +- name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" + when: + - rhel8cis_rule_4_4_3_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.1 + block: + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: '^(#|)\s*deny\s*=\s*\d' + line: "deny = {{ rhel8cis_pam_faillock['deny'] }}" + + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.2.2 | AUDIT | Ensure pam_faillock module is enabled | get current state" + when: + - rhel8cis_allow_authselect_updates + ansible.builtin.shell: authselect current + changed_when: false + failed_when: discovered_authselect_current.rc not in [ 0, 1 ] + register: discovered_authselect_current + + - name: "4.4.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - discovered_authselect_current.rc != 0 + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured" + when: + - rhel8cis_rule_4_4_3_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.2 + block: + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: '^(#|)\s*unlock_time\s*=\s*\d' + line: "unlock_time = {{ rhel8cis_pam_faillock['unlock_time'] }}" + + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.1.2 | PATCH | Ensure password unlock time is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" + when: + - rhel8cis_rule_4_4_3_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.1.3 + block: + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + state: present + regexp: ^(#|)\s*"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*) + line: "{{ rhel8cis_pam_faillock['root_option'] }}" + + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\3\4 + loop: + - password + - system + + - name: "4.4.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s"{{ rhel8cis_pam_faillock['root_option'] }}"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\3\4 + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.2.x.yml b/tasks/section_4/cis_4.4.3.2.x.yml new file mode 100644 index 00000000..68c3fb07 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.2.x.yml @@ -0,0 +1,295 @@ +--- + +- name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured" + when: + - rhel8cis_rule_4_4_3_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.1 + block: + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*difok\s*=\s*\d' + line: "difok = {{ rhel8cis_pam_pwquality['difok'] }}" + + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+difok\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+difok\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.2 | PATCH | Ensure password length is configured" + when: + - rhel8cis_rule_4_4_3_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.2 + block: + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*minlen\s*=\s*\d' + line: "minlen = {{ rhel8cis_pam_pwquality['minlen'] }}" + + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minlen\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.2 | PATCH | Ensure password length is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minlen\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured" + when: + - rhel8cis_rule_4_4_3_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.3 + block: + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*minclass\s*=\s*\d' + line: "minclass = {{ rhel8cis_pam_pwquality['minclass'] }}" + + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minclass\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.3 | PATCH | Ensure password complexity is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+minclass\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured" + when: + - rhel8cis_rule_4_4_3_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.4 + block: + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*maxrepeat\s*=\s*\d' + line: "maxrepeat = {{ rhel8cis_pam_pwquality['maxrepeat'] }}" + + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxrepeat\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxrepeat\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured" + when: + - rhel8cis_rule_4_4_3_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.5 + block: + - name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | pwquality.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*maxsequence\s*=\s*\d' + line: "maxsequence = {{ rhel8cis_pam_pwquality['maxseq'] }}" + + - name: "4.4.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxsequence\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.5 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+maxsequence\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled" + when: + - rhel8cis_rule_4_4_3_2_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.6 + block: + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pwquality.conf" + ansible.builtin.lineinfile: + line: 'dictcheck = 1' + path: /etc/security/pwquality.conf + regexp: '^(#|)\s*dictcheck\s*=\s*\d' + state: present + + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+dictcheck\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.6 | PATCH | Ensure password dictionary check is enabled | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+dictcheck\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.2.7 | PATCH | Ensure password quality is enforced for the root user" + when: + - rhel8cis_rule_4_4_3_2_7 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.2.7 + block: + - name: "4.4.3.2.7 | PATCH | Ensure password quality is enforced for the root user | pwquality.conf" + ansible.builtin.lineinfile: + line: enforce_for_root + path: /etc/security/pwquality.conf + state: present + regexp: '^(#|)\s*enforce_for_root' + + - name: "4.4.3.2.7 | PATCH | Ensure password dictionary check is enabled | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.2.7 | PATCH | Ensure password dictionary check is enabled | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.3.x.yml b/tasks/section_4/cis_4.4.3.3.x.yml new file mode 100644 index 00000000..b321e3e1 --- /dev/null +++ b/tasks/section_4/cis_4.4.3.3.x.yml @@ -0,0 +1,118 @@ +--- + +- name: "4.4.3.3.1 | PATCH | Ensure password history remember is configured" + when: + - rhel8cis_rule_4_4_3_3_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.1 + block: + - name: "4.4.3.3.1 | PATCH | Ensure password history remember is configured | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*remember\s*=\s*\d' + line: "remember = {{ rhel8cis_pam_pwhistory['remember'] }}" + + - name: "4.4.3.3.1 | PATCH | Ensure password number of changed characters is configured | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+remember\s*=\s*\S+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user" + when: + - rhel8cis_rule_4_4_3_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.2 + block: + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*enforce_for_root' + line: "enforce_for_root" + + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | pam_files" + when: not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.3.2 | PATCH | Ensure password history is enforced for the root user | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\s+enforce_for_root(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" + when: + - rhel8cis_rule_4_4_3_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.3.3 + block: + - name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | pwhistory.conf" + ansible.builtin.lineinfile: + path: /etc/security/pwhistory.conf + state: present + regexp: '^(#|)\s*use_authtok' + line: "use_authtok" + + - name: "4.4.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Get current state" + ansible.builtin.shell: | + grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\ b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: discovered_pwhistory_authtok.rc not in [ 0, 1 ] + register: discovered_pwhistory_authtok + + - name: "4.4.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | authselect_files" + when: + - rhel8cis_allow_authselect_updates + - discovered_pwhistory_authtok.rc != 0 + notify: Update_authselect + community.general.pamd: + name: "{{ item }}-auth" + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" + type: password + control: requisite + module_path: pam_pwhistory.so + module_arguments: 'use_authtok' + state: updated + loop: + - password + - system diff --git a/tasks/section_4/cis_4.4.3.4.x.yml b/tasks/section_4/cis_4.4.3.4.x.yml new file mode 100644 index 00000000..87dbcc0e --- /dev/null +++ b/tasks/section_4/cis_4.4.3.4.x.yml @@ -0,0 +1,174 @@ +--- + +- name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok" + when: + - rhel8cis_rule_4_4_3_4_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_4.4.3.4.1 + block: + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" + ansible.builtin.shell: grep -P -- '^\h*(auth|account|password|session)\h+(requisite|required|sufficient)\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P -- '\bnullok\b' + changed_when: false + failed_when: discovered_pam_nullok.rc not in [ 0, 1 ] + register: discovered_pam_nullok + + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | pam_files" + when: + - discovered_pam_nullok.stdout | length > 0 + - not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: nullok + replace: '' + loop: + - password + - system + + - name: "4.4.3.4.1 | PATCH | Ensure pam_unix does not include nullok | update authselect" + when: + - discovered_pam_nullok is defined + - discovered_pam_nullok.stdout | length > 0 + - rhel8cis_allow_authselect_updates + notify: Update_authselect + ansible.builtin.shell: authselect enable-feature without-nullok + +- name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember" + when: + - rhel8cis_rule_4_4_3_4_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.2 + block: + - name: "4.4.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" + ansible.builtin.shell: grep -Pi '^\h*password\h+([^#\n\r]+\h+)?pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P '\bremember=\d\b' + changed_when: false + failed_when: discovered_pam_remember.rc not in [ 0, 1 ] + register: discovered_pam_remember + + - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | pam_files" + when: + - discovered_pam_remember is defined + - discovered_pam_remember | length > 0 + - not rhel8cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "4.4.3.4.2 | PATCH | Ensure pam_unix does not include remember | authconfig_files" + when: + - discovered_pam_remember is defined + - discovered_pam_remember | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)remember\s*=\s*\d+(.*$) + replace: \1\2\3 + loop: + - password + - system + +- name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm" + when: + - rhel8cis_rule_4_4_3_4_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.3 + block: + - name: "4.4.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" + ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?(sha512|yescrypt)\b' /etc/pam.d/{password,system}-auth | grep -v {{ rhel8cis_pam_pwhash }} + changed_when: false + failed_when: discovered_hash_state.rc not in [ 0, 1 ] + register: discovered_hash_state + + - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | pam_files" + when: + - discovered_hash_state is defined + - discovered_hash_state | length > 0 + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)(.*$) + replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + loop: + - password + - system + + - name: "4.4.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | authselect_files" + when: + - discovered_hash_state is defined + - discovered_hash_state | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)\s*=\s*\d+(.*$) + replace: \1\2\4 {{ rhel8cis_pam_pwhash }} + loop: + - password + - system + +- name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok" + when: + - rhel8cis_rule_4_4_3_4_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - pam + - rule_4.4.3.4.4 + block: + - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" + ansible.builtin.shell: grep -P -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth | grep -v use_authtok + changed_when: false + failed_when: discovered_pam_authtok.rc not in [ 0, 1 ] + register: discovered_pam_authtok + + - name: "4.4.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" + when: + - discovered_pam_authtok is defined + - discovered_pam_authtok | length > 0 + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\s+use_authtok(.*$) + replace: \1\3\4 use_authtok + loop: + - password + - system + + - name: "4.4.3.4.4 | PATCH | Ensure password same consecutive characters is configured | authselect_files" + when: + - discovered_pam_authtok is defined + - discovered_pam_authtok | length > 0 + - rhel8cis_allow_authselect_updates + - "'example' not in rhel8cis_authselect['custom_profile_name']" + notify: Update_authselect + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\s+use_authtok(.*$) + replace: \1\3\4 use_authtok + loop: + - password + - system diff --git a/tasks/section_4/cis_4.5.1.x.yml b/tasks/section_4/cis_4.5.1.x.yml new file mode 100644 index 00000000..619e69a1 --- /dev/null +++ b/tasks/section_4/cis_4.5.1.x.yml @@ -0,0 +1,196 @@ +--- + +- name: "4.5.1.1 | PATCH | Ensure strong password hashing algorithm is configured" + when: + - rhel8cis_rule_4_5_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.1 + ansible.builtin.lineinfile: + path: /etc/libuser.conf + regexp: ^(#|)\s*crypt_style\s*=\s* + line: "crypt_style = {{ rhel8cis_pam_pwhash }}" + +- name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less" + when: + - rhel8cis_rule_4_5_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.2 + block: + - name: "4.5.1.2 | AUDIT | Ensure password expiration is 365 days or less | Capture accounts more than 365" + ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$5>{{ rhel8cis_pass['max_days'] }} { print $1 }'" + changed_when: false + failed_when: discovered_pass_max_expire.rc not in [ 0, 1 ] + register: discovered_pass_max_expire + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | update login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MAX_DAYS' + line: "PASS_MAX_DAYS {{ rhel8cis_pass['max_days'] }}" + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Ensure all accounts set to 365" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ rhel8cis_pass['max_days'] }}" + loop: "{{ discovered_pass_max_expire.stdout_lines | default([]) }}" + when: + - rhel8cis_set_max_expiry + - item not in rhel8cis_user_skip_list + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Warning" + block: + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | Output list if not set to change" + ansible.builtin.debug: + msg: | + "Warning!! The following account are set beyond the expected expiration date: + {{ rhel8cis_pass_max_expire.stdout_lines | default([]) }}" + + - name: "4.5.1.2 | PATCH | Ensure password expiration is 365 days or less | set warning fact" + ansible.builtin.import_tasks: warning_facts.yml + vars: + warn_control_id: '4.5.1.2' + when: + - discovered_pass_max_expire is defined + - discovered_pass_max_expire.stdout | length > 0 + - not rhel8cis_set_max_expiry + +- name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more" + when: + - rhel8cis_rule_4_5_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - shadow_suite + - rule_4.5.1.3 + block: + - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: ^(#|)\s*PASS_WARN_AGE\s+\d+ + line: "PASS_WARN_AGE {{ rhel8cis_pass['warn_age'] }}" + + - name: "4.5.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | capture users not matching" + ansible.builtin.shell: | + awk -F: '/^[^:\n\r]+:[^!*xX\n\r]/ {print $1}' /etc/shadow + changed_when: false + failed_when: discovered_users_warn_days.rc not in [ 0, 1 ] + register: discovered_users_warn_days + + - name: "4.5.1.3 | PATCH | Ensure password expiration warning days is 7 or more | change users not matching req" + when: + - discovered_users_warn_days is defined + - discovered_users_warn_days.stdout | length > 0 + ansible.builtin.shell: chage --warndays {{ rhel8cis_pass['warn_age'] }} {{ item }} + loop: "{{ discovered_users_warn_days.stdout_lines }}" + +- name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less" + when: + - rhel8cis_rule_4_5_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.1.4 + block: + - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture default state" + ansible.builtin.shell: useradd -D | grep INACTIVE + changed_when: false + failed_when: discovered_users_inactive_def.rc not in [ 0, 1 ] + register: discovered_users_inactive_def + + - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change default" + when: + - discovered_users_inactive_def is defined + - "'30' not in discovered_users_inactive_def.stdout" + ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} + + - name: "4.5.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | capture users not matching" + ansible.builtin.shell: | + awk -F: '/^[^#:]+:[^!*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\s*$/ {print $1}' /etc/shadow + changed_when: false + failed_when: discovered_users_inactive.rc not in [ 0, 1 ] + register: discovered_users_inactive + + - name: "4.5.1.4 | PATCH | Ensure inactive password lock is 30 days or less | change users not matching req" + when: + - discovered_users_inactive is defined + - discovered_users_inactive.stdout | length > 0 + ansible.builtin.shell: chage --inactive {{ rhel8cis_pass['inactive'] }} {{ item }} + loop: "{{ discovered_users_inactive.stdout_lines }}" + +- name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past" + when: + - rhel8cis_rule_4_5_1_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.1.5 + vars: + warn_control_id: '4.5.1.5' + block: + - name: "4.5.1.5 | AUDIT | Ensure all users last password change date is in the past | capture default state" + ansible.builtin.shell: useradd -D | grep INACTIVE + changed_when: false + failed_when: discovered_users_inactive_default.rc not in [ 0, 1 ] + register: discovered_users_inactive_default + + - name: "4.5.1.5 | PATCH | Ensure all users last password change date is in the past | change default" + when: + - discovered_users_inactive_default is defined + - "'30' not in discovered_users_inactive_default.stdout" + ansible.builtin.shell: useradd -D -f {{ rhel8cis_pass['inactive'] }} + + - name: "4.5.1.5 | FACT | Ensure inactive password lock is 30 days or less | set fact days since_epoch" + ansible.builtin.set_fact: + days_since_epoch: "{{ (ansible_facts['date_time']['epoch']|int)/86400 }}" + + - name: "4.5.1.5 | AUDIT | Ensure inactive password lock is 30 days or less | capture users date in future" + ansible.builtin.shell: | + awk -F: '{ if ($3 > "{{ days_since_epoch }}") { print $1 } }' /etc/shadow + changed_when: false + failed_when: discovered_users_user_future.rc not in [ 0, 1 ] + register: discovered_users_user_future + + - name: "4.5.1.5 | WARNING | Ensure inactive password lock is 30 days or less | Warn Users in future" + when: + - discovered_users_user_future is defined + - discovered_users_user_future.stdout | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! - The following users have passwords set in the future please investigate" + - "{{ discovered_users_user_future.stdout_lines }}" + + - name: "4.5.1.5 | WARNING | Ensure inactive password lock is 30 days or less | Warn Users in future" + when: + - rhel8cis_users_user_future is defined + - rhel8cis_users_user_future.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_4/cis_4.5.2.x.yml b/tasks/section_4/cis_4.5.2.x.yml new file mode 100644 index 00000000..1a2eae1a --- /dev/null +++ b/tasks/section_4/cis_4.5.2.x.yml @@ -0,0 +1,87 @@ +--- + +- name: "4.5.2.1 | PATCH | Ensure default group for the root account is GID 0" + when: + - rhel8cis_rule_4_5_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - root + - rule_4.5.2.1 + ansible.builtin.user: + name: root + group: 0 + +- name: "4.5.2.2 | PATCH | Ensure root user umask is configured" + when: + - rhel8cis_rule_4_5_2_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - shadow_suite + - rule_4.5.2.2 + ansible.builtin.lineinfile: + path: /root/.bash_profile + regexp: \s*umask + line: "umask {{ rhel8cis_root_umask }}" + +- name: "4.5.2.3 | PATCH | Ensure system accounts are secured" + when: + - rhel8cis_rule_4_5_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-2 + - NIST800-53R5_AC-3 + - NIST800-53R5_AC-11 + - NIST800-53R5_MP-2 + - shadow_suite + - rule_4.5.2.3 + block: + - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Set nologin" + when: + - item.id not in discovered_interactive_usernames.stdout + - "'root' not in item.id" + ansible.builtin.user: + name: "{{ item.id }}" + shell: /usr/sbin/nologin + loop: "{{ rhel8cis_passwd }}" + loop_control: + label: "{{ item.id }}" + + - name: "4.5.2.3 | PATCH | | Ensure system accounts are secured | Lock accounts" + when: + - "item.id not in discovered_interactive_usernames.stdout" + - "'root' not in item.id" + ansible.builtin.user: + name: "{{ item.id }}" + password_lock: true + loop: "{{ rhel8cis_passwd }}" + loop_control: + label: "{{ item.id }}" + +- name: "4.5.2.4 | PATCH | Ensure root password is set" + when: + - rhel8cis_rule_4_5_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - shadow_suite + - rule_4.5.2.4 + ansible.builtin.debug: + msg: "This is set as an assert in tasks/main" diff --git a/tasks/section_4/cis_4.5.3.x.yml b/tasks/section_4/cis_4.5.3.x.yml new file mode 100644 index 00000000..ffcde18d --- /dev/null +++ b/tasks/section_4/cis_4.5.3.x.yml @@ -0,0 +1,68 @@ +--- + +- name: "4.5.3.1 | PATCH | Ensure nologin is not listed in /etc/shells" + when: + - rhel8cis_rule_4_5_3_1 + tags: + - level2-server + - level2-workstation + - automated + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - patch + - shells + - rule_4.5.3.1 + ansible.builtin.replace: + path: /etc/shells + regexp: nologin + replace: "" + +- name: "4.5.3.2 | PATCH | Ensure default user shell timeout is configured" + when: + - rhel8cis_rule_4_5_3_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - shell + - rule_4.5.3.2 + ansible.builtin.blockinfile: + path: "{{ item.path }}" + state: "{{ item.state }}" + marker: "# {mark} - CIS benchmark - Ansible-lockdown" + create: true + mode: '0644' + block: | + TMOUT={{ rhel8cis_shell_session_timeout.timeout }} + readonly TMOUT + export TMOUT + loop: + - { path: "{{ rhel8cis_shell_session_timeout.file }}", state: present } + - { path: /etc/profile, state: "{{ (rhel8cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" } + +- name: "4.5.3.3 | PATCH | Ensure default user umask is configured" + when: + - rhel8cis_rule_4_5_3_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - umask + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_4.5.3.3 + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: (?i)(umask\s+\d\d\d) + replace: '{{ item.line }} 027' + loop: + - { path: '/etc/bashrc', line: 'umask' } + - { path: '/etc/profile', line: 'umask' } + - { path: '/etc/login.defs', line: 'UMASK' } diff --git a/tasks/section_4/main.yml b/tasks/section_4/main.yml index 4b93685e..2ad47325 100644 --- a/tasks/section_4/main.yml +++ b/tasks/section_4/main.yml @@ -1,27 +1,64 @@ --- -# 4.1 Configure System Accounting (auditd) -- name: "SECTION | 4.1| Ensure auditing is enabled" - ansible.builtin.import_tasks: cis_4.1.1.x.yml +# Access, Authentication, and Authorization + +- name: "SECTION | 4.1.1 | Configure time-based job schedulers | cron" + ansible.builtin.import_tasks: + file: cis_4.1.1.x.yml + +- name: "SECTION | 4.1.2 | Configure job schedulers | at" + ansible.builtin.import_tasks: + file: cis_4.1.2.x.yml + +- name: "SECTION | 4.2 | Configure SSH Server" + ansible.builtin.import_tasks: + file: cis_4.2.x.yml + when: + - "'openssh-server' in ansible_facts.packages" + +- name: "SECTION | 4.3 | Configure privilege escalation" + ansible.builtin.import_tasks: + file: cis_4.3.x.yml + +- name: "SECTION | 4.4.1 | Configure PAM software packages" + ansible.builtin.import_tasks: + file: cis_4.4.1.x.yml + +- name: "SECTION | 4.4.2 | Authselect" when: - - not system_is_container + - rhel8cis_allow_authselect_updates + - rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.2.x.yml + +- name: "SECTION | 4.4.3.1.x | Configure module pam_faillock" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.1.x.yml -- name: "SECTION | 4.1.2.x| Configure Data Retention" - ansible.builtin.import_tasks: cis_4.1.2.x.yml +- name: "SECTION | 4.4.3.2.x | Configure module pam_pwquality" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.2.x.yml -- name: "SECTION | 4.1.3.x| Configure auditd rules" - ansible.builtin.import_tasks: cis_4.1.3.x.yml +- name: "SECTION | 4.4.3.3.x | Configure module pam_pwhistory" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.3.x.yml -# 4.2 Configure Logging -- name: "SECTION | 4.2.1.x| Configure rsyslog" - ansible.builtin.import_tasks: cis_4.2.1.x.yml - when: rhel8cis_syslog == 'rsyslog' +- name: "SECTION | 4.4.3.4.x | Configure module pam_unix" + when: rhel8cis_disruption_high + ansible.builtin.import_tasks: + file: cis_4.4.3.4.x.yml -- name: "SECTION | 4.2.2.x| Configure journald" - ansible.builtin.import_tasks: cis_4.2.2.x.yml +- name: "SECTION | 4.5.1.x | Shadow suite" + ansible.builtin.import_tasks: + file: cis_4.5.1.x.yml -- name: "SECTION | 4.2.3 | Configure logile perms" - ansible.builtin.import_tasks: cis_4.2.3.yml +- name: "SECTION | 4.5.2.x | Root and sys accounts" + ansible.builtin.import_tasks: + file: cis_4.5.2.x.yml -- name: "SECTION | 4.3 | Configure logrotate" - ansible.builtin.import_tasks: cis_4.3.yml +- name: "SECTION | 4.5.3.x | User enviroment" + ansible.builtin.import_tasks: + file: cis_4.5.3.x.yml diff --git a/tasks/section_4/cis_4.2.1.x.yml b/tasks/section_5/cis_5.1.1.x.yml similarity index 59% rename from tasks/section_4/cis_4.2.1.x.yml rename to tasks/section_5/cis_5.1.1.x.yml index a2dfba43..ae568735 100644 --- a/tasks/section_4/cis_4.2.1.x.yml +++ b/tasks/section_5/cis_5.1.1.x.yml @@ -1,84 +1,103 @@ --- -- name: "4.2.1.1 | PATCH | Ensure rsyslog installed" - ansible.builtin.package: - name: rsyslog - state: present +- name: "5.1.1.1 | PATCH | Ensure rsyslog installed" when: - "'rsyslog' not in ansible_facts.packages" - - rhel8cis_rule_4_2_1_1 + - rhel8cis_rule_5_1_1_1 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.1 - -- name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled" - ansible.builtin.service: + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - rule_5.1.1.1 + ansible.builtin.package: name: rsyslog - enabled: true + state: present + +- name: "5.1.1.2 | PATCH | Ensure rsyslog service is enabled" when: - - rhel8cis_rule_4_2_1_2 + - rhel8cis_rule_5_1_1_2 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - rule_5.1.1.2 + ansible.builtin.systemd: + name: rsyslog + enabled: true -# This is counter to control 4.2.1.5?? -- name: "4.2.1.3 | PATCH | Ensure journald is configured to send logs to rsyslog" +- name: "5.1.1.3 | PATCH | Ensure journald is configured to send logs to rsyslog" ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "^#ForwardToSyslog=|^ForwardToSyslog=" line: ForwardToSyslog=yes + notify: Restart_journald when: - - rhel8cis_rule_4_2_1_3 + - rhel8cis_rule_5_1_1_3 + - rhel8cis_syslog == "rsyslog" tags: - level1-server - level1-workstation - - manual - patch - - rule_4.2.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-4 + - NIST800-53R5_AU-12 + - NIST800-53R5_MP-2 + - NIST800-53R5_SI-5 + - rsyslog + - rule_5.1.1.3 -- name: "4.2.1.4 | PATCH | Ensure rsyslog default file permissions configured" +- name: "5.1.1.4 | PATCH | Ensure rsyslog default file permissions configured" + when: + - rhel8cis_rule_5_1_1_4 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_5.1.1.4 + notify: Restart_rsyslog ansible.builtin.lineinfile: path: /etc/rsyslog.conf regexp: '^\$FileCreateMode' line: '$FileCreateMode 0640' - notify: restart rsyslog + +- name: "5.1.1.5 | PATCH | Ensure logging is configured" when: - - rhel8cis_rule_4_2_1_4 + - rhel8cis_rule_5_1_1_5 tags: - level1-server - level1-workstation - - automated - patch - rsyslog - - rule_4.2.1.4 - -- name: "4.2.1.5 | PATCH | Ensure logging is configured" + - rule_5.1.1.5 + notify: Restart_rsyslog block: - - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" + - name: "5.1.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" ansible.builtin.shell: cat /etc/rsyslog.conf changed_when: false failed_when: false check_mode: false - register: rhel_08_4_2_1_5_audit + register: discovered_captured_rsyslog_conf - - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" + - name: "5.1.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" ansible.builtin.debug: msg: - "These are the current logging configurations for rsyslog, please review:" - - "{{ rhel_08_4_2_1_5_audit.stdout_lines }}" + - "{{ discovered_captured_rsyslog_conf.stdout_lines }}" - - name: "4.2.1.5 | PATCH | Ensure logging is configured | mail.* log setting" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | mail.* log setting" + when: rhel8cis_rsyslog_ansiblemanaged ansible.builtin.blockinfile: path: /etc/rsyslog.conf - marker: "# {mark} MAIL LOG SETTINGS (ANSIBLE MANAGED)" + marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # mail logging additions to meet CIS standards mail.* -/var/log/mail @@ -86,41 +105,25 @@ mail.warning -/var/log/mail.warning mail.err /var/log/mail.err insertafter: '# Log all the mail messages in one place.' - notify: restart rsyslog - when: rhel8cis_rsyslog_ansiblemanaged - - name: "4.2.1.5 | PATCH | Ensure logging is configured | news.crit log setting" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - marker: "# {mark} NEWS LOG SETTINGS (ANSIBLE MANAGED)" - block: | - # news logging additions to meet CIS standards - news.crit -/var/log/news/news.crit - news.notice -/var/log/news/news.crit - insertafter: '# Save news errors of level crit and higher in a special file.' - notify: restart rsyslog + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Misc. log setting" when: rhel8cis_rsyslog_ansiblemanaged - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Misc. log setting" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "# {mark} MISC. LOG SETTINGS (ANSIBLE MANAGED)" + marker: "# {mark} MISC. LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # misc. logging additions to meet CIS standards *.=warning;*.=err -/var/log/warn *.crit /var/log/warn *.*;mail.none;news.none /var/log/messages insertafter: '#### RULES ####' - notify: restart rsyslog - when: rhel8cis_rsyslog_ansiblemanaged - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Local log settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Local log settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} LOCAL LOG SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown" block: | # local log settings to meet CIS standards local0,local1.* -/var/log/localmessages @@ -129,96 +132,79 @@ local6,local7.* -/var/log/localmessages *.emerg :omusrmsg:* insertafter: '#### RULES ####' - notify: restart rsyslog - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Auth Settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Auth Settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} Auth SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown" block: | # Private settings to meet CIS standards - auth,authpriv.* -/var/log/secure + auth,authpriv.* /var/log/secure insertafter: '#### RULES ####' - notify: restart rsyslog - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Cron Settings" + - name: "5.1.1.5 | PATCH | Ensure logging is configured | Cron Settings" ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present - marker: "#{mark} Cron SETTINGS (ANSIBLE MANAGED)" + marker: "#{mark} Cron SETTINGS - CIS benchmark - Ansible-lockdown" block: | # Cron settings to meet CIS standards cron.* /var/log/cron insertafter: '#### RULES ####' - notify: restart rsyslog + +- name: "5.1.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host" when: - - rhel8cis_rule_4_2_1_5 + - rhel8cis_rule_5_1_1_6 + - rhel8cis_remote_log_server tags: - level1-server - level1-workstation - - manual - patch - rsyslog - - rule_4.2.1.5 - -- name: "4.2.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host" + - rule_5.1.1.6 + notify: Restart_rsyslog ansible.builtin.blockinfile: path: /etc/rsyslog.conf state: present block: | - # remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional - *.* @@{{ rhel8cis_remote_log_server }} + # target can be IP or FQDN + *.* action(type="omfwd" target="{{ rhel8cis_remote_log_host }}" port="{{ rhel8cis_remote_log_port }}" protocol="{{ rhel8cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel8cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel8cis_remote_log_queuesize }}") insertafter: EOF - register: result + register: set_remote_syslog failed_when: - - result is failed - - result.rc != 257 - notify: restart rsyslog + - set_remote_syslog is failed + - set_remote_syslog.rc != 257 + +- name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" when: - - rhel8cis_rule_4_2_1_6 - - rhel8cis_remote_log_server is defined + - rhel8cis_rule_5_1_1_7 tags: - level1-server - level1-workstation - - manual - patch - rsyslog - - rule_4.2.1.6 - -- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" + - rule_5.1.1.7 + notify: Restart_rsyslog block: - - name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + - name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + when: not rhel8cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf - regexp: '({{ item }})' + regexp: '{{ item }}' replace: '#\1' - notify: restart rsyslog - with_items: + loop: - '^(\$ModLoad imtcp)' - '^(\$InputTCPServerRun)' - '^(module\(load="imtcp"\))' - '^(input\(type="imtcp")' - when: not rhel8cis_system_is_log_server - - name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + - name: "5.1.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + when: rhel8cis_system_is_log_server ansible.builtin.replace: path: /etc/rsyslog.conf regexp: '^#(.*{{ item }}.*)' replace: '\1' - notify: restart rsyslog - with_items: + loop: - 'ModLoad imtcp' - 'InputTCPServerRun' - - 'module\(load="imtcp"\)' - - 'input\(type="imtcp"' - when: rhel8cis_system_is_log_server - when: - - rhel8cis_rule_4_2_1_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rsyslog - - rule_4.2.1.7 diff --git a/tasks/section_4/cis_4.2.2.x.yml b/tasks/section_5/cis_5.1.2.x.yml similarity index 52% rename from tasks/section_4/cis_4.2.2.x.yml rename to tasks/section_5/cis_5.1.2.x.yml index 269a7d01..6ee9aec5 100644 --- a/tasks/section_4/cis_4.2.2.x.yml +++ b/tasks/section_5/cis_5.1.2.x.yml @@ -1,131 +1,152 @@ --- -- name: "4.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" +- name: "5.1.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" + when: + - rhel8cis_rule_5_1_2_1_1 + - rhel8cis_syslog == 'journald' + tags: + - level1-server + - level1-workstation + - manual + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - journald + - rule_5.1.2.1.1 ansible.builtin.package: name: systemd-journal-remote state: present + +- name: "5.1.2.1.2 | PATCH | Ensure systemd-journal-remote is configured" when: - - rhel8cis_rule_4_2_2_1_1 + - rhel8cis_rule_5_1_2_1_2 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - manual - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 - journald - - rule_4.2.2.1.1 - -- name: "4.2.2.1.2 | PATCH | Ensure systemd-journal-remote is configured" + - rule_5.1.2.1.2 + notify: Restart_systemd_journal_upload ansible.builtin.lineinfile: path: /etc/systemd/journal-upload.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" - notify: restart systemd_journal_upload - with_items: + loop: - { regexp: 'URL=', line: 'URL={{ rhel8cis_journal_upload_url }}'} - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel8cis_journal_upload_serverkeyfile }}'} - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel8cis_journal_servercertificatefile }}'} - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel8cis_journal_trustedcertificatefile }}'} + +- name: "5.1.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled" when: - - rhel8cis_rule_4_2_2_1_2 + - rhel8cis_system_is_log_server + - rhel8cis_rule_5_1_2_1_3 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - - manual + - automated - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 - journald - - rule_4.2.2.1.2 - -- name: "4.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled" + - rule_5.1.2.1.3 ansible.builtin.systemd: name: systemd-journal-upload state: started enabled: true + +- name: "5.1.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client" when: - - rhel8cis_system_is_log_server - - rhel8cis_rule_4_2_2_1_3 + - not rhel8cis_system_is_log_server + - rhel8cis_rule_5_1_2_1_4 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - - manual + - automated - patch - journald - - rule_4.2.2.1.3 - -- name: "4.2.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client" + - rule_5.1.2.1.4 ansible.builtin.systemd: name: systemd-journal-remote.socket state: stopped enabled: false masked: true + +- name: "5.1.2.2 | PATCH | Ensure journald service is enabled" when: - - not rhel8cis_system_is_log_server - - rhel8cis_rule_4_2_2_1_4 + - rhel8cis_rule_5_1_2_2 - rhel8cis_syslog == 'journald' tags: - level1-server - level1-workstation - automated - - patch + - audit - journald - - rule_4.2.2.1.4 - -- name: "4.2.2.2 | PATCH | Ensure journald service is enabled" + - rule_5.1.2.2 block: - - name: "4.2.2.2 | PATCH | Ensure journald service is enabled | Enable service" + - name: "5.1.2.2 | PATCH | Ensure journald service is enabled | Enable service" ansible.builtin.systemd: name: systemd-journald state: started enabled: true - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Capture status" + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Capture status" ansible.builtin.shell: systemctl is-enabled systemd-journald.service changed_when: false failed_when: false - register: rhel8cis_4_2_2_2_status + register: discovered_journald_status - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status" ansible.builtin.debug: msg: - "Warning!! The status of systemd-journald should be static and it is not. Please investigate" - when: "'static' not in rhel8cis_4_2_2_2_status.stdout" + when: "'static' not in discovered_journald_status.stdout" - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml + - name: "5.1.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml vars: - warn_control_id: '4.2.2.2' - when: "'static' not in rhel8cis_4_2_2_2_status.stdout" + warn_control_id: '5.1.2.2' + when: "'static' not in discovered_journald_status.stdout" + +- name: "5.1.2.3 | PATCH | Ensure journald is configured to compress large log files" when: - - rhel8cis_rule_4_2_2_2 - - rhel8cis_syslog == 'journald' + - rhel8cis_rule_5_1_2_3 tags: - level1-server - level1-workstation - automated - - audit + - patch - journald - - rule_4.2.2.2 - -- name: "4.2.2.3 | PATCH | Ensure journald is configured to compress large log files" + - rule_5.1.2.3 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: 'Compress=' line: Compress=yes insertafter: ^#Compress validate: /usr/bin/bash -n %s + +- name: "5.1.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk" when: - - rhel8cis_rule_4_2_2_3 + - rhel8cis_rule_5_1_2_4 tags: - level1-server - level1-workstation - automated - patch - journald - - rule_4.2.2.3 - -- name: "4.2.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk" + - rule_5.1.2.4 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: 'Storage=' @@ -133,96 +154,44 @@ state: present insertafter: ^#Storage validate: /usr/bin/bash -n %s + +# This is counter to control 5.1.1.3?? +- name: "5.1.2.5 | PATCH | Ensure journald is not configured to send logs to rsyslog" when: - - rhel8cis_rule_4_2_2_4 + - rhel8cis_rule_5_1_2_5 + - rhel8cis_syslog == 'journald' tags: - level1-server - - level1-workstation - - automated + - level2-workstation + - manual - patch - journald - - rule_4.2.2.4 - -# This is counter to control 4.2.1.3?? -- name: "4.2.2.5 | PATCH | Ensure journald is not configured to send logs to rsyslog" + - rule_5.1.2.5 + notify: Restart_journald ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "^ForwardToSyslog=" line: "#ForwardToSyslog=yes" - notify: restart systemd_journal_upload + +- name: "5.1.2.6 | PATCH | Ensure journald log rotation is configured per site policy" when: - - rhel8cis_rule_4_2_2_5 + - rhel8cis_rule_5_1_2_6 - rhel8cis_syslog == 'journald' tags: - level1-server - - level2-workstation + - level1-workstation - manual - patch - journald - - rule_4.2.2.5 - -- name: "4.2.2.6 | PATCH | Ensure journald log rotation is configured per site policy" + - rule_5.1.2.6 ansible.builtin.lineinfile: path: /etc/systemd/journald.conf regexp: "{{ item.regexp }}" line: "{{ item.line }}" - notify: restart journald - with_items: + notify: Restart_journald + loop: - { regexp: '^#SystemMaxUse=|^SystemMaxUse=', line: 'SystemMaxUse={{ rhel8cis_journald_systemmaxuse }}'} - { regexp: '^#SystemKeepFree=|^SystemKeepFree=', line: 'SystemKeepFree={{ rhel8cis_journald_systemkeepfree }}' } - { regexp: '^#RuntimeMaxUse=|^RuntimeMaxUse=', line: 'RuntimeMaxUse={{ rhel8cis_journald_runtimemaxuse }}'} - { regexp: '^#RuntimeKeepFree=|^RuntimeKeepFree=', line: 'RuntimeKeepFree={{ rhel8cis_journald_runtimekeepfree }}'} - { regexp: '^#MaxFileSec=|^MaxFileSec=', line: 'MaxFileSec={{ rhel8cis_journald_maxfilesec }}'} - when: - - rhel8cis_rule_4_2_2_6 - - rhel8cis_syslog == 'journald' - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.6 - -- name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured" - block: - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Check for override file" - ansible.builtin.find: - paths: /etc/tmpfiles.d - patterns: systemd.conf - register: rhel8cis_4_2_2_7_override_status - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Get override file settings" - ansible.builtin.shell: cat /etc/tmpfiles.d/systemd.conf - changed_when: false - failed_when: false - register: rhel8cis_4_2_2_7_override_settings - when: rhel8cis_4_2_2_7_override_status.matched >= 1 - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Get non-override file settings" - ansible.builtin.shell: cat /usr/lib/tmpfiles.d/systemd.conf - changed_when: false - failed_when: false - register: rhel8cis_4_2_2_7_notoverride_settings - when: rhel8cis_4_2_2_7_override_status.matched == 0 - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Display file settings" - ansible.builtin.debug: - msg: - - "Warning!! Below are the current default settings for journald, please confirm they align with your site policies" - - "{{ (rhel8cis_4_2_2_7_override_status.matched >= 1) | ternary(rhel8cis_4_2_2_7_override_settings.stdout_lines, rhel8cis_4_2_2_7_notoverride_settings.stdout_lines) }}" - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '4.2.2.7' - when: - - rhel8cis_rule_4_2_2_7 - - rhel8cis_syslog == 'journald' - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.7 diff --git a/tasks/section_5/cis_5.1.3.yml b/tasks/section_5/cis_5.1.3.yml new file mode 100644 index 00000000..673dd0d7 --- /dev/null +++ b/tasks/section_5/cis_5.1.3.yml @@ -0,0 +1,30 @@ +--- + +- name: "5.1.3 | PATCH | Ensure logrotate is configured" + when: + - rhel8cis_rule_5_1_3 + tags: + - level1-server + - level1-workstation + - manual + - patch + - logrotate + - rule_5.1.3 + block: + - name: "5.1.3 | AUDIT | Ensure logrotate is configured | Get logrotate settings" + ansible.builtin.find: + paths: /etc/logrotate.d/ + register: discovered_log_rotate_conf + + - name: "5.1.3 | PATCH | Ensure logrotate is configured | conf files" + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: '^(\s*)(daily|weekly|monthly|yearly)$' + replace: "\\1{{ rhel8cis_logrotate }}" + loop: "{{ discovered_log_rotate_conf.files }}" + + - name: "5.1.3 | PATCH | Ensure logrotate is configured | logrotate.conf" + ansible.builtin.replace: + path: /etc/logrotate.conf + regexp: '^(\s*)(daily|weekly|monthly|yearly)$' + replace: "\\1{{ rhel8cis_logrotate }}" diff --git a/tasks/section_5/cis_5.1.4.yml b/tasks/section_5/cis_5.1.4.yml new file mode 100644 index 00000000..ef2ee18c --- /dev/null +++ b/tasks/section_5/cis_5.1.4.yml @@ -0,0 +1,40 @@ +--- + +- name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured" + when: + - rhel8cis_rule_5_1_4 + tags: + - level1-server + - level1-workstation + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - logfiles + - rule_5.1.4 + block: + - name: "5.1.4 | AUDIT | Ensure permissions on all logfiles are configured | find files" + ansible.builtin.shell: find /var/log/ -type f -exec ls {} \; + changed_when: false + failed_when: false + register: discovered_logfiles + + - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" + when: + - item != "/var/log/btmp" + - item != "/var/log/utmp" + - item != "/var/log/wtmp" + - item != "/var/log/lastlog" + ansible.builtin.file: + path: "{{ item }}" + mode: u-x,g-wx,o-rwx + loop: "{{ discovered_logfiles.stdout_lines }}" + + - name: "5.1.4 | PATCH | Ensure permissions on all logfiles are configured | change permissions" + ansible.builtin.file: + path: "{{ item.name }}" + mode: ('ug-x,o-wx') + with_fileglob: + - /var/log/*tmp.*" + - /var/log/lastlog" + - /var/log/ssd*" + - /var/log/SSD*" diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml deleted file mode 100644 index 80503035..00000000 --- a/tasks/section_5/cis_5.1.x.yml +++ /dev/null @@ -1,171 +0,0 @@ ---- - -- name: "5.1.1 | PATCH | Ensure cron daemon is enabled" - ansible.builtin.service: - name: crond - enabled: true - when: - - rhel8cis_rule_5_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.1 - -- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" - ansible.builtin.file: - path: /etc/crontab - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.2 - -- name: "5.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" - ansible.builtin.file: - path: /etc/cron.hourly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.3 - -- name: "5.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" - ansible.builtin.file: - path: /etc/cron.daily - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.4 - -- name: "5.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" - ansible.builtin.file: - path: /etc/cron.weekly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_5 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.1.5 - -- name: "5.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" - ansible.builtin.file: - path: /etc/cron.monthly - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - rule_5.1.6 - -- name: "5.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" - ansible.builtin.file: - path: /etc/cron.d - state: directory - owner: root - group: root - mode: 0700 - when: - - rhel8cis_rule_5_1_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.7 - -- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users" - block: - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny" - ansible.builtin.file: - path: /etc/cron.deny - state: absent - - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists" - ansible.builtin.stat: - path: "/etc/cron.allow" - register: rhel8cis_5_1_8_cron_allow_state - - - name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users" - ansible.builtin.file: - path: /etc/cron.allow - state: '{{ "file" if rhel8cis_5_1_8_cron_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.8 - -- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users" - block: - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Remove at.deny" - ansible.builtin.file: - path: /etc/at.deny - state: absent - - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" - ansible.builtin.stat: - path: "/etc/at.allow" - register: rhel8cis_5_1_9_at_allow_state - - - name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users" - ansible.builtin.file: - path: /etc/at.allow - state: '{{ "file" if rhel8cis_5_1_9_at_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_1_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - cron - - rule_5.1.9 diff --git a/tasks/section_5/cis_5.2.1.x.yml b/tasks/section_5/cis_5.2.1.x.yml new file mode 100644 index 00000000..550ee270 --- /dev/null +++ b/tasks/section_5/cis_5.2.1.x.yml @@ -0,0 +1,117 @@ +--- + +- name: "5.2.1.1 | PATCH | Ensure auditd is installed" + when: + - rhel8cis_rule_5_2_1_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.1.1 + block: + - name: "5.2.1.1 | PATCH | Ensure auditd is installed | Install auditd packages" + ansible.builtin.package: + name: audit + state: present + when: '"auditd" not in ansible_facts.packages' + + - name: "5.2.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages" + ansible.builtin.package: + name: audit-libs + state: present + when: '"auditd-lib" not in ansible_facts.packages' + +- name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" + when: + - rhel8cis_rule_5_2_1_2 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - grub + - rule_5.2.1.2 + notify: Rebuild_grub + block: + - name: "5.2.1.2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX" + ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' + changed_when: false + failed_when: false + check_mode: false + register: discovered_auditd_grub_cmdline_linux + + - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting" + when: "'audit=' in discovered_auditd_grub_cmdline_linux.stdout" + ansible.builtin.replace: + path: /etc/default/grub + regexp: 'audit=.' + replace: 'audit=1' + + - name: "5.2.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing" + when: "'audit=' not in discovered_auditd_grub_cmdline_linux.stdout" + ansible.builtin.lineinfile: + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX=' + line: '{{ discovered_auditd_grub_cmdline_linux.stdout }} audit=1"' + +- name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" + when: + - rhel8cis_rule_5_2_1_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - grub + - rule_5.2.1.3 + notify: Rebuild_grub + block: + - name: "5.2.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX" + ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//' + changed_when: false + failed_when: false + check_mode: false + register: discovered_backlog_grub_cmdline_linux + + - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting" + ansible.builtin.replace: + path: /etc/default/grub + regexp: 'audit_backlog_limit=\d+' + replace: 'audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}' + when: "'audit_backlog_limit=' in discovered_backlog_grub_cmdline_linux.stdout" + + - name: "5.2.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing" + ansible.builtin.lineinfile: + path: /etc/default/grub + regexp: '^GRUB_CMDLINE_LINUX=' + line: '{{ discovered_backlog_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel8cis_audit_back_log_limit }}"' + when: "'audit_backlog_limit=' not in discovered_backlog_grub_cmdline_linux.stdout" + +- name: "5.2.1.4 | PATCH | Ensure auditd service is enabled" + when: + - rhel8cis_rule_5_2_1_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.1.4 + ansible.builtin.service: + name: auditd + state: started + enabled: true diff --git a/tasks/section_5/cis_5.2.2.x.yml b/tasks/section_5/cis_5.2.2.x.yml new file mode 100644 index 00000000..f00ad44e --- /dev/null +++ b/tasks/section_5/cis_5.2.2.x.yml @@ -0,0 +1,81 @@ +--- + +- name: "5.2.2.1 | PATCH | Ensure audit log storage size is configured" + when: + - rhel8cis_rule_5_2_2_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-8 + - auditd + - rule_5.2.2.1 + notify: Restart_auditd + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: ^max_log_file(\s|=) + line: "max_log_file = {{ rhel8cis_max_log_file_size }}" + +- name: "5.2.2.2 | PATCH | Ensure audit logs are not automatically deleted" + when: + - rhel8cis_rule_5_2_2_2 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-8 + - auditd + - rule_5.2.2.2 + notify: Restart_auditd + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^max_log_file_action" + line: "max_log_file_action = {{ rhel8cis_auditd['max_log_file_action'] }}" + +- name: "5.2.2.3 | PATCH | Ensure system is disabled when audit logs are full" + when: + - rhel8cis_rule_5_2_2_3 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.2.3 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + notify: Restart_auditd + loop: + - { regexp: '^disk_full_action', line: 'disk_full_action = {{ rhel8cis_auditd.disk_full_action }}' } + - { regexp: '^disk_error_action', line: 'disk_error_action = {{ rhel8cis_auditd.disk_error_action }}' } + +- name: "5.2.2.4 | PATCH | Ensure system warns when audit logs are low on space" + when: + - rhel8cis_rule_5_2_2_4 + tags: + - level2-server + - level2-workstation + - automated + - patch + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + - auditd + - rule_5.2.2.4 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + notify: Restart_auditd + loop: + - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel8cis_auditd.admin_space_left_action }}' } + - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel8cis_auditd.space_left_action }}' } diff --git a/tasks/section_4/cis_4.1.3.x.yml b/tasks/section_5/cis_5.2.3.x.yml similarity index 62% rename from tasks/section_4/cis_4.1.3.x.yml rename to tasks/section_5/cis_5.2.3.x.yml index 184912c9..8e24f22a 100644 --- a/tasks/section_4/cis_4.1.3.x.yml +++ b/tasks/section_5/cis_5.2.3.x.yml @@ -1,291 +1,299 @@ --- -- name: "4.1.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" +- name: "5.2.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" + when: + - rhel8cis_rule_5_2_3_1 + tags: + - level2-server + - level2-workstation + - automated + - patch + - auditd + - rule_5.2.3.1 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.2 | PATCH | Ensure actions as another user are always logged" when: - - rhel8cis_rule_4_1_3_1 + - rhel8cis_rule_5_2_3_2 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.1 - -- name: "4.1.3.2 | PATCH | Ensure actions as another user are always logged" + - rule_5.2.3.2 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.3 | PATCH | Ensure events that modify the sudo log file are collected" when: - - rhel8cis_rule_4_1_3_2 + - rhel8cis_rule_5_2_3_3 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.2 - -- name: "4.1.3.3 | PATCH | Ensure events that modify the sudo log file are collected" + - rule_5.2.3.3 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.4 | PATCH | Ensure events that modify date and time information are collected" when: - - rhel8cis_rule_4_1_3_3 + - rhel8cis_rule_5_2_3_4 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.3 - -- name: "4.1.3.4 | PATCH | Ensure events that modify date and time information are collected" + - rule_5.2.3.4 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.5 | PATCH | Ensure events that modify the system's network environment are collected" when: - - rhel8cis_rule_4_1_3_4 + - rhel8cis_rule_5_2_3_5 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.4 - -- name: "4.1.3.5 | PATCH | Ensure events that modify the system's network environment are collected" + - rule_5.2.3.5 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" when: - - rhel8cis_rule_4_1_3_5 + - rhel8cis_rule_5_2_3_6 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.5 - -- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - rule_5.2.3.6 block: - - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm /6000 2>/dev/null; done changed_when: false failed_when: false check_mode: false - register: priv_procs + register: discovered_privilege_procs - - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" + - name: "5.2.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.set_fact: update_audit_template: true - notify: update auditd - when: - - rhel8cis_rule_4_1_3_6 - tags: - - level2-server - - level2-workstation - - automated - - patch - - auditd - - rule_4.1.3.6 + notify: Update_auditd_rules -- name: "4.1.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" +- name: "5.2.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" ansible.builtin.set_fact: update_audit_template: true when: - - rhel8cis_rule_4_1_3_7 + - rhel8cis_rule_5_2_3_7 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.7 + - rule_5.2.3_7 -- name: "4.1.3.8 | PATCH | Ensure events that modify user/group information are collected" - ansible.builtin.set_fact: - update_audit_template: true +- name: "5.2.3.8 | PATCH | Ensure events that modify user/group information are collected" when: - - rhel8cis_rule_4_1_3_8 + - rhel8cis_rule_5_2_3_8 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.8 - -- name: "4.1.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" + - rule_5.2.3.8 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" when: - - rhel8cis_rule_4_1_3_9 + - rhel8cis_rule_5_2_3_9 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.9 - -- name: "4.1.3.10 | PATCH | Ensure successful file system mounts are collected" + - rule_5.2.3.9 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.10 | PATCH | Ensure successful file system mounts are collected" when: - - rhel8cis_rule_4_1_3_10 + - rhel8cis_rule_5_2_3_10 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_CM-6 - auditd - - rule_4.1.3.10 - -- name: "4.1.3.11 | PATCH | Ensure session initiation information is collected" + - rule_5.2.3.10 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.11 | PATCH | Ensure session initiation information is collected" when: - - rhel8cis_rule_4_1_3_11 + - rhel8cis_rule_5_2_3_11 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.11 - -- name: "4.1.3.12 | PATCH | Ensure login and logout events are collected" + - rule_5.2.3.11 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.12 | PATCH | Ensure login and logout events are collected" when: - - rhel8cis_rule_4_1_3_12 + - rhel8cis_rule_5_2_3_12 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.12 - -- name: "4.1.3.13 | PATCH | Ensure file deletion events by users are collected" + - rule_5.2.3.12 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.13 | PATCH | Ensure file deletion events by users are collected" when: - - rhel8cis_rule_4_1_3_13 + - rhel8cis_rule_5_2_3_13 tags: - level2-server - level2-workstation - auditd - patch - - rule_4.1.3.13 - -- name: "4.1.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" + - rule_5.2.3.13 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" when: - - rhel8cis_rule_4_1_3_14 + - rhel8cis_rule_5_2_3_14 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AU-3 - auditd - - rule_4.1.3.14 - -- name: "4.1.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" + - rule_5.2.3.14 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" when: - - rhel8cis_rule_4_1_3_15 + - rhel8cis_rule_5_2_3_15 tags: - level2-server - level2- workstation - automated - patch - auditd - - rule_4.1.3.15 - -- name: "4.1.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" + - rule_5.2.3.15 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" when: - - rhel8cis_rule_4_1_3_16 + - rhel8cis_rule_5_2_3_16 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.16 - -- name: "4.1.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" + - rule_5.2.3.16 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" when: - - rhel8cis_rule_4_1_3_17 + - rhel8cis_rule_5_2_3_17 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.17 - -- name: "4.1.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" + - rule_5.2.3.17 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" when: - - rhel8cis_rule_4_1_3_18 + - rhel8cis_rule_5_2_3_18 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.18 - -- name: "4.1.3.19 | PATCH | Ensure kernel module loading and unloading is collected" + - rule_5.2.3.18 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.19 | PATCH | Ensure kernel module loading and unloading is collected" when: - - rhel8cis_rule_4_1_3_19 + - rhel8cis_rule_5_2_3_19 tags: - level2-server - level2-workstation - automated - patch - auditd - - rule_4.1.3.19 - -- name: "4.1.3.20 | PATCH | Ensure the audit configuration is immutable" + - rule_5.2.3.19 ansible.builtin.set_fact: update_audit_template: true + +- name: "5.2.3.20 | PATCH | Ensure the audit configuration is immutable" when: - - rhel8cis_rule_4_1_3_20 + - rhel8cis_rule_5_2_3_20 tags: - level2-server - level2-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-3 + - NIST800-53R5_MP-2 - auditd - rule_4.1.20 + ansible.builtin.set_fact: + update_audit_template: true -- name: "4.1.3.21 | AUDIT | Ensure the running and on disk configuration is the same" - ansible.builtin.debug: - msg: - - "Please run augenrules --load if you suspect there is a configuration that is not active" +- name: "5.2.3.21 | AUDIT | Ensure the running and on disk configuration is the same" when: - - rhel8cis_rule_4_1_3_21 + - rhel8cis_rule_5_2_3_21 tags: - level2-server - level2-workstation - manual - patch - auditd - - rule_4.1.3.21 + - rule_5.2.3.21 + ansible.builtin.debug: + msg: + - "Please run augenrules --load if you suspect there is a configuration that is not active" -- name: Auditd | 4.1.3 | Auditd controls updated +- name: Auditd | 5.2.3 | Auditd controls updated + when: + - update_audit_template ansible.builtin.debug: msg: "Auditd Controls handled in POST using template - updating /etc/auditd/rules.d/99_auditd.rules" changed_when: false - when: - - update_audit_template diff --git a/tasks/section_5/cis_5.2.4.x.yml b/tasks/section_5/cis_5.2.4.x.yml new file mode 100644 index 00000000..e78a7ff1 --- /dev/null +++ b/tasks/section_5/cis_5.2.4.x.yml @@ -0,0 +1,167 @@ +--- + +- name: "5.2.4.1 | PATCH | Ensure the audit log directory is 0750 or more restrictive" + when: + - rhel8cis_rule_5_2_4_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.1 + ansible.builtin.file: + path: "{{ discovered_audit_logfile.stdout | dirname }}" + state: directory + mode: g-w,o-rwx + +- name: | + "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" + "5.2.4.3 | PATCH | Ensure only authorized users own audit log files" + "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" + when: + - rhel8cis_rule_5_2_4_2 or + rhel8cis_rule_5_2_4_3 or + rhel8cis_rule_5_2_4_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.2 + - rule_5.2.4.3 + - rule_5.2.4.4 + block: + - name: "5.2.4.2 | AUDIT | Ensure audit log files are mode 0640 or less permissive | stat file" + ansible.builtin.stat: + path: "{{ discovered_audit_logfile.stdout }}" + changed_when: false + register: discovered_auditlog_info + + - name: | + "5.2.4.2 | PATCH | Ensure audit log files are mode 0640 or less permissive" + "5.2.4.3 | PATCH | Ensure only authorized users own audit log files" + "5.2.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" + ansible.builtin.file: + path: "{{ discovered_audit_logfile.stdout }}" + mode: "{% if discovered_auditlog_info.stat.mode != '0600' %}0640{% endif %}" + owner: root + group: root + +- name: "5.2.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" + when: + - rhel8cis_rule_5_2_4_5 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.5 + ansible.builtin.file: + path: "{{ item.path }}" + mode: g-wx,o-rwx + loop: "{{ discovered_auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.6 | PATCH | Ensure audit configuration files are owned by root" + when: + - rhel8cis_rule_5_2_4_6 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.6 + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + loop: "{{ discovered_auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.7 | PATCH | Ensure audit configuration files belong to group root" + when: + - rhel8cis_rule_5_2_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.7 + ansible.builtin.file: + path: "{{ item.path }}" + group: root + loop: "{{ discovered_auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "5.2.4.8 | PATCH | Ensure audit tools are 755 or more restrictive" + when: + - rhel8cis_rule_5_2_4_8 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.8 + block: + - name: "5.2.4.8 | AUDIT | Get audit binary file stat | get current mode" + ansible.builtin.stat: + path: "{{ item }}" + register: discovered_audit_bins_mode + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules + + - name: "5.2.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required" + ansible.builtin.file: + path: "{{ item.item }}" + mode: g-w,o-w + loop: "{{ discovered_audit_bins_mode.results }}" + loop_control: + label: "{{ item.item }}" + +- name: "5.2.4.9 | PATCH | Ensure audit tools are owned by root" + when: + - rhel8cis_rule_5_2_4_9 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.9 + ansible.builtin.file: + path: "{{ item }}" + owner: root + group: root + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules + +- name: "5.2.4.10 | PATCH | Ensure audit tools belong to group root" + when: + - rhel8cis_rule_5_2_4_10 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_5.2.4.10 + ansible.builtin.file: + path: "{{ item }}" + group: root + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml deleted file mode 100644 index 83469fd8..00000000 --- a/tasks/section_5/cis_5.2.x.yml +++ /dev/null @@ -1,378 +0,0 @@ ---- - -- name: "5.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured" - ansible.builtin.file: - path: /etc/ssh/sshd_config - owner: root - group: root - mode: 0600 - when: - - rhel8cis_rule_5_2_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - permissions - - rule_5.2.1 - -- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" - block: - - name: "5.2.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys" - ansible.builtin.find: - paths: /etc/ssh - patterns: 'ssh_host_*_key' - recurse: true - file_type: any - register: rhel8cis_5_2_2_ssh_private_host_key - - - name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" - ansible.builtin.file: - path: "{{ item.path }}" - owner: root - group: root - mode: 0600 - with_items: - - "{{ rhel8cis_5_2_2_ssh_private_host_key.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_5_2_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - permissions - - rule_5.2.2 - -- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" - block: - - name: "5.2.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys" - ansible.builtin.find: - paths: /etc/ssh - patterns: 'ssh_host_*_key.pub' - recurse: true - file_type: any - register: rhel8cis_5_2_3_ssh_public_host_key - - - name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" - ansible.builtin.file: - path: "{{ item.path }}" - owner: root - group: root - mode: 0644 - with_items: - - "{{ rhel8cis_5_2_3_ssh_public_host_key.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel8cis_rule_5_2_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.3 - -- name: "5.2.4 | PATCH | Ensure SSH access is limited" - block: - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^AllowUsers" - line: AllowUsers {{ rhel8cis_sshd['allowusers'] }} - notify: restart sshd - when: "rhel8cis_sshd['allowusers']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^AllowGroups" - line: AllowGroups {{ rhel8cis_sshd['allowgroups'] }} - notify: restart sshd - when: "rhel8cis_sshd['allowgroups']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^DenyUsers" - line: DenyUsers {{ rhel8cis_sshd['denyusers'] }} - notify: restart sshd - when: "rhel8cis_sshd['denyusers']|default('') | length > 0" - - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^DenyGroups" - line: DenyGroups {{ rhel8cis_sshd['denygroups'] }} - notify: restart sshd - when: "rhel8cis_sshd['denygroups']|default('') | length > 0" - when: - - rhel8cis_rule_5_2_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.4 - -- name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#LogLevel|^LogLevel" - line: 'LogLevel {{ rhel8cis_ssh_loglevel }}' - when: - - rhel8cis_rule_5_2_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sshs - - rule_5.2.5 - -- name: "5.2.6 | PATCH | Ensure SSH PAM is enabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#UsePAM|^UsePAM" - line: 'UsePAM yes' - when: - - rhel8cis_rule_5_2_6 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.6 - -- name: "5.2.7 | PATCH | Ensure SSH root login is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitRootLogin|^PermitRootLogin" - line: 'PermitRootLogin no' - when: - - rhel8cis_rule_5_2_7 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.7 - -- name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: ^#HostbasedAuthentication|^HostbasedAuthentication" - line: 'HostbasedAuthentication no' - when: - - rhel8cis_rule_5_2_8 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.8 - -- name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" - line: 'PermitEmptyPasswords no' - when: - - rhel8cis_rule_5_2_9 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.9 - -- name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" - line: 'PermitUserEnvironment no' - when: - - rhel8cis_rule_5_2_10 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.10 - -- name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#IgnoreRhosts|^IgnoreRhosts" - line: 'IgnoreRhosts yes' - when: - - rhel8cis_rule_5_2_11 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.11 - -- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - when: - - rhel8cis_rule_5_2_12 - tags: - - level2-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.12 - -- name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" - line: 'AllowTcpForwarding no' - when: - - rhel8cis_rule_5_2_13 - tags: - - level2-server - - level2-workstation - - automated - - patch - - ssh - - rule_5.2.13 - -- name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" - block: - - name: "5.2.14 | AUDIT | Ensure system-wide crypto policy is not over-ridden" - ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd - failed_when: ( crypto_policy_override.rc not in [ 0, 1 ] ) - changed_when: false - register: crypto_policy_override - - - name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden" - ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd - notify: restart sshd - when: - - crypto_policy_override.stdout | length > 0 - when: - - rhel8cis_rule_5_2_14 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.14 - -- name: "5.2.15 | PATCH | Ensure SSH warning banner is configured" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^Banner' - line: 'Banner /etc/issue.net' - when: - - rhel8cis_rule_5_2_15 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.15 - -- name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^(#)?MaxAuthTries \d' - line: 'MaxAuthTries 4' - when: - - rhel8cis_rule_5_2_16 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.16 - -- name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#MaxStartups|^MaxStartups" - line: 'MaxStartups 10:30:60' - when: - - rhel8cis_rule_5_2_17 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.17 - -- name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#MaxSessions|^MaxSessions" - line: 'MaxSessions {{ rhel8cis_ssh_maxsessions }}' - when: - - rhel8cis_rule_5_2_18 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.18 - -- name: "5.2.19 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: "^#LoginGraceTime|^LoginGraceTime" - line: "LoginGraceTime {{ rhel8cis_sshd['logingracetime'] }}" - when: - - rhel8cis_rule_5_2_19 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.19 - -- name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured" - block: - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^ClientAliveInterval' - line: "ClientAliveInterval {{ rhel8cis_sshd['clientaliveinterval'] }}" - - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config - regexp: '^ClientAliveCountMax' - line: "ClientAliveCountMax {{ rhel8cis_sshd['clientalivecountmax'] }}" - when: - - rhel8cis_rule_5_2_20 - tags: - - level1-server - - level1-workstation - - automated - - patch - - ssh - - rule_5.2.20 diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml index 72ad599d..bb955a9e 100644 --- a/tasks/section_5/cis_5.3.x.yml +++ b/tasks/section_5/cis_5.3.x.yml @@ -1,143 +1,94 @@ --- -- name: "5.3.1 | PATCH | Ensure sudo is installed" - ansible.builtin.package: - name: sudo - state: present +- name: "5.3.1 | PATCH | Ensure AIDE is installed" when: + - rhel8cis_config_aide - rhel8cis_rule_5_3_1 tags: - level1-server - level1-workstation - automated + - aide + - NIST800-53R5_AU-2 - patch - - sudo - rule_5.3.1 - -- name: "5.3.2 | PATCH | Ensure sudo commands use pty" - ansible.builtin.lineinfile: - path: /etc/sudoers - line: "Defaults use_pty" - when: - - rhel8cis_rule_5_3_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.2 - -- name: "5.3.3 | PATCH | Ensure sudo log file exists" - ansible.builtin.lineinfile: - path: /etc/sudoers - regexp: '^Defaults\s+logfile=' - line: 'Defaults logfile={{ rhel8cis_sudolog_location }}' - when: - - rhel8cis_rule_5_3_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.3 - -- name: "5.3.4 | PATCH | Ensure users must provide password for escalation" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)' - replace: '\1PASSWD\2' - with_items: - - "{{ rhel8cis_sudoers_files.stdout_lines }}" - when: - - rhel8cis_rule_5_3_4 - tags: - - level2-server - - level2-workstation - - automated - - patch - - sudo - - rule_5.3.4 - -- name: "5.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^([^#].*)!authenticate(.*)' - replace: '\1authenticate\2' - with_items: - - "{{ rhel8cis_sudoers_files.stdout_lines }}" - when: - - rhel8cis_rule_5_3_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - sudo - - rule_5.3.5 - -- name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly" block: - - name: "5.3.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set" - ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort + - name: "5.3.1 | PATCH | Ensure AIDE is installed | Install AIDE" + ansible.builtin.package: + name: aide + state: present + + - name: "5.3.1 | PATCH | Ensure AIDE is installed | Configure AIDE" + ansible.builtin.shell: /usr/sbin/aide --init changed_when: false failed_when: false - register: rhel8cis_5_3_6_timeout_files + async: 45 + poll: 0 + args: + creates: /var/lib/aide/aide.db.new.gz + when: not ansible_check_mode - - name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" - ansible.builtin.lineinfile: - path: /etc/sudoers - regexp: 'Defaults timestamp_timeout=' - line: "Defaults timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - when: rhel8cis_5_3_6_timeout_files.stdout | length == 0 + - name: "5.3.1 | PATCH | Ensure AIDE is installed | copy AIDE DB" + ansible.builtin.copy: + src: /var/lib/aide/aide.db.new.gz + dest: /var/lib/aide/aide.db.gz + remote_src: true - - name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" - ansible.builtin.replace: - path: "{{ item }}" - regexp: 'timestamp_timeout=(\d+)' - replace: "timestamp_timeout={{ rhel8cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - with_items: - - "{{ rhel8cis_5_3_6_timeout_files.stdout_lines }}" - when: rhel8cis_5_3_6_timeout_files.stdout | length > 0 +- name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked" when: - - rhel8cis_rule_5_3_6 + - rhel8cis_rule_5_3_2 + - rhel8cis_config_aide tags: - level1-server - level1-workstation - automated + - aide + - NIST800-53R5_AU-2 + - file_integrity - patch - - sudo - - rule_5.3.6 - -- name: "5.3.7 | PATCH | Ensure access to the su command is restricted" + - rule_5.3.2 block: - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" - ansible.builtin.group: - name: "{{ rhel8cis_sugroup }}" - state: present - register: rhel8cis_5_3_7_sugroup + - name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked | cron" + when: rhel8cis_aide_scan == "cron" + ansible.builtin.cron: + name: Run AIDE integrity check + cron_file: "{{ rhel8cis_aide_cron['cron_file'] }}" + user: "{{ rhel8cis_aide_cron['cron_user'] }}" + minute: "{{ rhel8cis_aide_cron['aide_minute'] | default('0') }}" + hour: "{{ rhel8cis_aide_cron['aide_hour'] | default('5') }}" + day: "{{ rhel8cis_aide_cron['aide_day'] | default('*') }}" + month: "{{ rhel8cis_aide_cron['aide_month'] | default('*') }}" + weekday: "{{ rhel8cis_aide_cron['aide_weekday'] | default('*') }}" + job: "{{ rhel8cis_aide_cron['aide_job'] }}" - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" - ansible.builtin.lineinfile: - path: /etc/group - regexp: '^{{ rhel8cis_sugroup }}(:.:.*:).*$' - line: '{{ rhel8cis_sugroup }}\g<1>' - backrefs: true + - name: "5.3.2 | PATCH | Ensure filesystem integrity is regularly checked | timer" + when: rhel8cis_aide_scan == "timer" + ansible.builtin.systemd: + name: "{{ item.name }}" + enabled: true + state: "{{ item.state | default(omit)}}" + loop: + - { name: 'aidecheck.service' } + - { name: 'aidecheck.timer', state: started } - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid" - ansible.builtin.lineinfile: - path: /etc/pam.d/su - regexp: '^(#)?auth\s+required\s+pam_wheel\.so' - line: 'auth required pam_wheel.so use_uid group={{ rhel8cis_sugroup }}' +- name: "5.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" when: - - rhel8cis_rule_5_3_7 + - rhel8cis_rule_5_3_3 tags: - level1-server - level1-workstation - - automated + - aide + - file_integrity - patch - - sudo - - rule_5.3.7 + - rule_5.3.3 + ansible.builtin.blockinfile: + path: /etc/aide.conf + marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown" + block: | + /usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512 + validate: aide -D --config %s diff --git a/tasks/section_5/cis_5.4.x.yml b/tasks/section_5/cis_5.4.x.yml deleted file mode 100644 index a300d9f5..00000000 --- a/tasks/section_5/cis_5.4.x.yml +++ /dev/null @@ -1,100 +0,0 @@ ---- - -- name: "5.4.1 | PATCH | Ensure custom authselect profile is used" - block: - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Gather profiles" - ansible.builtin.shell: authselect list | grep custom | awk '{print $2}' - failed_when: false - changed_when: false - check_mode: false - register: rhel8cis_5_4_1_profiles - - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Show profiles" - ansible.builtin.debug: - msg: - - "Below are the current custom profiles" - - "{{ rhel8cis_5_4_1_profiles.stdout_lines }}" - - - name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | see if profile already exists" - ansible.builtin.stat: - path: "/etc/authselect/custom/{{ rhel8cis_authselect['custom_profile_name'] }}" - register: rhel8cis_5_4_1_auth_select_profile - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" - ansible.builtin.shell: authselect create-profile {{ rhel8cis_authselect['custom_profile_name'] }} -b {{ rhel8cis_authselect['default_file_to_copy'] }} - when: - - not rhel8cis_5_4_1_auth_select_profile.stat.exists - - rhel8cis_authselect_custom_profile_create - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | select custom profiles" - ansible.builtin.shell: authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }} --force - when: - - rhel8cis_5_4_1_auth_select_profile.stat.exists - - rhel8cis_authselect_custom_profile_create - when: - - rhel8cis_rule_5_4_1 - tags: - - level1-server - - level1-workstation - - manual - - patch - - authselect - - rule_5.4.1 - -- name: "5.4.2 | PATCH | Ensure authselect includes with-faillock" - block: - - name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock | Gather profiles and enabled features" - ansible.builtin.shell: "authselect current | grep with-faillock" - failed_when: false - changed_when: false - check_mode: false - register: rhel8cis_5_4_2_profiles_faillock - - - name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock| Show profiles" - ansible.builtin.debug: - msg: - - "Below are the current custom profiles" - - "{{ rhel8cis_5_4_2_profiles_faillock.stdout_lines }}" - - - name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Create custom profiles" - ansible.builtin.shell: "authselect select custom/{{ rhel8cis_authselect['custom_profile_name'] }} with-faillock without-nullok --force" - when: rhel8cis_authselect_custom_profile_select - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not auth select profile" - ansible.builtin.lineinfile: - path: "/etc/pam.d/password-auth" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - insertbefore: "{{ item.before }}" - loop: - - { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so preauth', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'} - - { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail', 'before':'^auth\s+required\s+pam_deny.so'} - - { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'} - when: - - not rhel8cis_authselect_custom_profile_select - - rhel8cis_pamd_manual_risks == 'ACCEPT' - - ansible_distribution_version >= "8.2" - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not auth select profile" - ansible.builtin.lineinfile: - path: "/etc/pam.d/system-auth" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - insertbefore: "{{ item.before | default(omit)}}" - loop: - - { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line':'auth required pam_faillock.so preauth silent', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'} - - { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail', 'before':'^auth\s+required\s+pam_deny.so'} - - { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'} - when: - - not rhel8cis_authselect_custom_profile_select - - rhel8cis_pamd_manual_risks == 'ACCEPT' - - ansible_distribution_version >= "8.2" - when: - - rhel8cis_rule_5_4_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - authselect - - rule_5.4.2 diff --git a/tasks/section_5/cis_5.5.x.yml b/tasks/section_5/cis_5.5.x.yml deleted file mode 100644 index 56f86e9d..00000000 --- a/tasks/section_5/cis_5.5.x.yml +++ /dev/null @@ -1,121 +0,0 @@ ---- - -- name: "5.5.1 | PATCH | Ensure password creation requirements are configured" - block: - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set pwquality config settings" - ansible.builtin.lineinfile: - path: /etc/security/pwquality.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - with_items: - - { regexp: '^minlen', line: 'minlen = {{ rhel8cis_pam_password.minlen }}' } - - { regexp: '^minclass', line: 'minclass = {{ rhel8cis_pam_password.minclass }}' } - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth and password-auth retry settings" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^password\s*requisite\s*pam_pwquality.so' - line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3" - insertbefore: '^#?password ?' - with_items: - - /etc/pam.d/system-auth - - /etc/pam.d/password-auth - when: - - rhel8cis_rule_5_5_1 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.1 - -- name: "5.5.2 | PATCH | Ensure system accounts are secured | pre RHEL8.2" - block: - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | pre RHEL8.2 | Add deny count and unlock time for preauth" - ansible.builtin.lineinfile: - path: /etc/pam.d/{{ item }} - state: present - regexp: '^auth\s*required\s*pam_faillock.so preauth' - line: "auth required pam_faillock.so preauth silent deny={{ rhel8cis_pam_faillock.attempts }}{{ (rhel8cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel8cis_pam_faillock.unlock_time }}" - insertafter: '^#?auth ?' - with_items: - - "system-auth" - - "password-auth" - when: ansible_distribution_version <= "8.1" - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | pre RHEL8.2 | Add deny count and unlock times for authfail" - ansible.builtin.lineinfile: - dest: /etc/pam.d/{{ item }} - state: present - regexp: '^auth\s*required\s*pam_faillock.so authfail' - line: "auth required pam_faillock.so authfail deny={{ rhel8cis_pam_faillock.attempts }}{{ (rhel8cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel8cis_pam_faillock.unlock_time }}" - insertafter: '^#?auth ?' - with_items: - - "system-auth" - - "password-auth" - when: ansible_distribution_version <= "8.1" - - - name: "5.5.2 | PATCH | Ensure system accounts are secured | RHEL8.2+ " - ansible.builtin.lineinfile: - path: /etc/security/faillock.conf - state: present - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - with_items: - - { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = 5' } - - { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = 900' } - when: ansible_distribution_version >= "8.2" - when: - - rhel8cis_rule_5_5_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.2 - -# This is only setting the pam_pwhistory remember due to the man page for pam_unix.so saying you should not use the remember feature -# Man page entry below -# remember=n -# The last n passwords for each user are saved in /etc/security/opasswd in order to force password -# change history and keep the user from alternating between the same password too frequently. The MD5 -# password hash algorithm is used for storing the old passwords. Instead of this option the -# pam_pwhistory module should be used. -- name: "5.5.3 | PATCH | Ensure password reuse is limited" - ansible.builtin.lineinfile: - path: /etc/pam.d/system-auth - state: present - line: "password requisite pam_pwhistory.so try_first_pass local_users_only enforce_for_root retry=3 remember={{ rhel8cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - when: - - rhel8cis_rule_5_5_3 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.3 - -- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512" - block: - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: "{{ item.regexp }}" - replace: "{{ item.replace }}" - with_items: - - { path: /etc/libuser.conf, regexp: '^crypt_style\s*=\s*.*$', replace: 'crypt_style = sha512' } - - { path: /etc/login.defs, regexp: '^ENCRYPT_METHOD.*', replace: 'ENCRYPT_METHOD SHA512' } - - - name: "5.5.4 | PATCH | Ensure password reuse is limited | pwhistory" - ansible.builtin.replace: - path: "{{ item }}" - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel8cis_pam_faillock.remember }}' - with_items: - - /etc/pam.d/password-auth - - /etc/pam.d/system-auth - when: - - rhel8cis_rule_5_5_4 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.4 diff --git a/tasks/section_5/cis_5.6.1.x.yml b/tasks/section_5/cis_5.6.1.x.yml deleted file mode 100644 index 2cc5abd2..00000000 --- a/tasks/section_5/cis_5.6.1.x.yml +++ /dev/null @@ -1,230 +0,0 @@ ---- - -- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less" - block: - - name: "5.6.1.1 | AUDIT | Ensure password expiration is 365 days or less | Capture accounts more than 365" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$5>{{ rhel8cis_pass['max_days'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_1_pass_max_expire.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_1_pass_max_expire - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | update login.defs" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MAX_DAYS' - line: "PASS_MAX_DAYS {{ rhel8cis_pass['max_days'] }}" - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Ensure all accounts set to 365" - ansible.builtin.user: - name: "{{ item }}" - password_expire_max: "{{ rhel8cis_pass['max_days'] }}" - loop: "{{ rhel8cis_5_6_1_1_pass_max_expire.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_1_set_max_expiry - - item not in rhel8cis_5_6_1_1_user_skip_list - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Warning" - block: - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected expiration date: - {{ rhel8cis_5_6_1_1_pass_max_expire.stdout_lines | default([]) }}" - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.1' - when: - - rhel8cis_5_6_1_1_pass_max_expire is defined - - rhel8cis_5_6_1_1_pass_max_expire.stdout | length > 0 - - not rhel8cis_5_6_1_1_set_max_expiry - when: - - rhel8cis_rule_5_6_1_1 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.1 - -- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" - block: - - name: "5.6.1.2 | AUDIT | Ensure minimum days between password changes is 7 or more | Capture accounts 7 or more" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$4>{{ rhel8cis_pass['min_days'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_2_min_day_change.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_2_min_day_change - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MIN_DAYS' - line: "PASS_MIN_DAYS {{ rhel8cis_pass['min_days'] }}" - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Change users found" - ansible.builtin.user: - name: "{{ item }}" - password_expire_min: "{{ rhel8cis_pass['min_days'] }}" - loop: "{{ rhel8cis_5_6_1_2_min_day_change.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_2_set_min_days_change - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Warning" - block: - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected minimum days between passwords: - {{ rhel8cis_5_6_1_2_min_day_change.stdout_lines }}" - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.2' - when: - - rhel8cis_5_6_1_2_min_day_change is defined - - rhel8cis_5_6_1_2_min_day_change.stdout | length > 0 - - not rhel8cis_5_6_1_2_set_min_days_change - when: - - rhel8cis_rule_5_6_1_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.2 - -- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more" - block: - - name: "5.6.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | capture accounts" - ansible.builtin.shell: "grep -E '^[^:]+:[^!*]' /etc/shadow | awk -F':' '$4>{{ rhel8cis_pass['warn_age'] }} { print $1 }'" - changed_when: false - failed_when: rhel8cis_5_6_1_3_warn_age_change.rc not in [ 0, 1 ] - register: rhel8cis_5_6_1_3_warn_age_change - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set default" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_WARN_AGE' - line: "PASS_WARN_AGE {{ rhel8cis_pass['warn_age'] }}" - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Change users found" - ansible.builtin.shell: "change --warndays {{ rhel8cis_pass['warn_age'] }} {{ item }}" - loop: "{{ rhel8cis_5_6_1_3_warn_age_change.stdout_lines | default([]) }}" - when: - - rhel8cis_5_6_1_3_set_warn_age_change - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | warning" - block: - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Output list if not set to change" - ansible.builtin.debug: - msg: | - "Warning!! The following account are set beyond the expected warning date: - {{ rhel8cis_5_6_1_3_warn_age_change.stdout_lines }}" - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set warning fact" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.3' - when: - - rhel8cis_5_6_1_3_warn_age_change is defined - - rhel8cis_5_6_1_3_warn_age_change.stdout | length > 0 - - not rhel8cis_5_6_1_3_set_warn_age_change - - when: - - rhel8cis_rule_5_6_1_3 - - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.3 - -- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less" - block: - - name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list" - ansible.builtin.shell: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow" - changed_when: false - check_mode: false - register: rhel_8_5_6_1_4_user_list - - - name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Check current settings" - ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel8cis_inactivelock.lock_days }} | cut -f2 -d= - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_4_inactive_settings - - - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Set default inactive setting" - ansible.builtin.shell: useradd -D -f {{ rhel8cis_inactivelock.lock_days }} - when: rhel8cis_5_6_1_4_inactive_settings.stdout | length == 0 - - - name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - ansible.builtin.shell: "chage --inactive {{ rhel8cis_inactivelock.lock_days }} {{ item }}" - with_items: - - "{{ rhel_8_5_6_1_4_user_list.stdout_lines }}" - when: - - rhel8cis_rule_5_6_1_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - password - - rule_5.6.1.4 - -- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past" - block: - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time" - ansible.builtin.shell: echo $(($(date --utc --date "$1" +%s)/86400)) - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_5_currentut - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future" - ansible.builtin.shell: "cat /etc/shadow | awk -F: '{if($3>{{ rhel8cis_5_6_1_5_currentut.stdout }})print$1}'" - changed_when: false - failed_when: false - check_mode: false - register: rhel8cis_5_6_1_5_user_list - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert no pw change in the future exist" - ansible.builtin.debug: - msg: "Good News! All accounts have PW change dates that are in the past" - when: rhel8cis_5_6_1_5_user_list.stdout | length == 0 - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" - ansible.builtin.debug: - msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel8cis_5_6_1_5_user_list.stdout_lines }}" - when: - - rhel8cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel8cis_futurepwchgdate_autofix - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past| Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '5.6.1.5' - when: - - rhel8cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel8cis_futurepwchgdate_autofix - - - name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future" - ansible.builtin.shell: passwd --expire {{ item }} - when: - - rhel8cis_5_6_1_5_user_list | length > 0 - - rhel8cis_futurepwchgdate_autofix - with_items: - - "{{ rhel8cis_5_6_1_5_user_list.stdout_lines }}" - when: - - rhel8cis_rule_5_6_1_5 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.6.1.5 diff --git a/tasks/section_5/cis_5.6.x.yml b/tasks/section_5/cis_5.6.x.yml deleted file mode 100644 index 9f73d59a..00000000 --- a/tasks/section_5/cis_5.6.x.yml +++ /dev/null @@ -1,118 +0,0 @@ ---- - -- name: "5.6.2 | PATCH | Ensure system accounts are secured" - block: - - name: "5.6.2 | Ensure system accounts are secured | Set nologin" - ansible.builtin.user: - name: "{{ item.id }}" - shell: /usr/sbin/nologin - with_items: - - "{{ rhel8cis_passwd }}" - when: - - item.id != "root" - - item.id != "sync" - - item.id != "shutdown" - - item.id != "halt" - - item.uid < rhel8uid_interactive_uid_start | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - loop_control: - label: "{{ item.id }}" - - - name: "5.6.2 | PATCH | Ensure system accounts are secured | Lock accounts" - ansible.builtin.user: - name: "{{ item.id }}" - password_lock: true - with_items: - - "{{ rhel8cis_passwd }}" - when: - - item.id != "halt" - - item.id != "shutdown" - - item.id != "sync" - - item.id != "root" - - item.id != "nfsnobody" - - item.uid < rhel8uid_interactive_uid_start | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - loop_control: - label: "{{ item.id }}" - when: - - rhel8cis_rule_5_6_2 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.2 - -- name: "5.6.3 | PATCH | Ensure default user shell timeout is 900 seconds or less" - ansible.builtin.blockinfile: - path: "{{ item.path }}" - state: "{{ item.state }}" - create: true - mode: 0644 - marker: "# {mark} ANSIBLE MANAGED" - block: | - # Set session timeout - CIS ID RHEL-08-5.6.3 - TMOUT={{ rhel8cis_shell_session_timeout.timeout }} - export TMOUT - readonly TMOUT - with_items: - - { path: "{{ rhel8cis_shell_session_timeout.file }}", state: present } - - { path: /etc/profile, state: "{{ (rhel8cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" } - when: - - rhel8cis_rule_5_6_3 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.3 - -- name: "5.6.4 | PATCH | Ensure default group for the root account is GID 0" - ansible.builtin.shell: usermod -g 0 root - changed_when: false - failed_when: false - when: - - rhel8cis_rule_5_6_4 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.4 - -- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive" - block: - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/login.defs pam_umask settings" - ansible.builtin.replace: - path: /etc/login.defs - regexp: "{{ item.regexp }}" - replace: "{{ item.replace }}" - loop: - - { regexp: '(UMASK\s+)0[012][0-6]', replace: '\1 027' } - - { regexp: '(USERGROUPS_ENAB\s+)yes', replace: '\1 no' } - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc" - ansible.builtin.replace: - path: /etc/bashrc - regexp: '(^\s+umask) 0[012][0-6]' - replace: '\1 027' - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/profile" - ansible.builtin.replace: - path: /etc/profile - regexp: '(^\s+umask) 0[012][0-6]' - replace: '\1 027' - when: - - rhel8cis_rule_5_6_5 - tags: - - level1-server - - level1-workstation - - automated - - patch - - accounts - - rule_5.6.5 diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index 5aed1c18..bb681227 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -1,26 +1,44 @@ --- -# Access, Authentication, and Authorization - -- name: "SECTION | 5.1 | Configure time-based job schedulers" - ansible.builtin.import_tasks: cis_5.1.x.yml - -- name: "SECTION | 5.2 | Configure SSH Server" - ansible.builtin.import_tasks: cis_5.2.x.yml +# 5.1 Configure Logging +- name: "SECTION | 5.1.1.x | Configure rsyslog" + ansible.builtin.import_tasks: + file: cis_5.1.1.x.yml + when: rhel8cis_syslog == 'rsyslog' + +- name: "SECTION | 5.1.2.x | Configure journald" + ansible.builtin.import_tasks: + file: cis_5.1.2.x.yml + +- name: "SECTION | 5.1.3 | Configure logile perms" + ansible.builtin.import_tasks: + file: cis_5.1.3.yml + +- name: "SECTION | 5.1.4 | Configure logrotate" + ansible.builtin.import_tasks: + file: cis_5.1.4.yml + +# 5.2 Configure System Accounting (auditd) +- name: "SECTION | 5.2.1 | Ensure auditing is enabled" + ansible.builtin.import_tasks: + file: cis_5.2.1.x.yml when: - - "'openssh-server' in ansible_facts.packages" + - not system_is_container -- name: "SECTION | 5.3 | Configure privilege escalation" - ansible.builtin.import_tasks: cis_5.3.x.yml - -- name: "SECTION | 5.4 | Configure authselect" - ansible.builtin.import_tasks: cis_5.4.x.yml +- name: "SECTION | 5.2.2 | Configure Data Retention" + ansible.builtin.import_tasks: + file: cis_5.2.2.x.yml + when: + - not system_is_container -- name: "SECTION | 5.5 | Configure PAM " - ansible.builtin.import_tasks: cis_5.5.x.yml +- name: "SECTION | 5.2.3.x | Configure auditd rules" + ansible.builtin.import_tasks: + file: cis_5.2.3.x.yml -- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters" - ansible.builtin.import_tasks: cis_5.6.1.x.yml +- name: "SECTION | 5.2.4.x | Audit file permissions" + ansible.builtin.import_tasks: + file: cis_5.2.4.x.yml -- name: "SECTION | 5.6.x | Misc. User Account Settings" - ansible.builtin.import_tasks: cis_5.6.x.yml +- name: "SECTION | 5.3.x | Aide" + ansible.builtin.import_tasks: + file: cis_5.3.x.yml diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index e05701cc..0c16bd2f 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -1,68 +1,42 @@ --- -- name: "6.1.1 | AUDIT | Audit system file permissions" - block: - - name: "6.1.1 | AUDIT | Audit system file permissions | Audit the packages" - ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto - changed_when: false - failed_when: false - register: rhel8cis_6_1_1_packages_rpm - - - name: "6.1.1 | AUDIT | Audit system file permissions | Create list and warning" - block: - - name: "6.1.1 | AUDIT | Audit system file permissions | Add file discrepancy list to system" - ansible.builtin.copy: - dest: "{{ rhel8cis_rpm_audit_file }}" # noqa template-instead-of-copy - content: "{{ rhel8cis_6_1_1_packages_rpm.stdout }}" - owner: root - group: root - mode: 0644 - - - name: "6.1.1 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" - ansible.builtin.debug: - msg: | - "Warning!! You have some package descrepancies issues. - The file list can be found in {{ rhel8cis_rpm_audit_file }}" - when: rhel8cis_6_1_1_packages_rpm.stdout|length > 0 - - - name: "6.1.1 | AUDIT | Audit system file permissions | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.1' - when: rhel8cis_6_1_1_packages_rpm.stdout | length > 0 - +- name: "6.1.1 | PATCH | Ensure permissions on /etc/passwd are configured" when: - rhel8cis_rule_6_1_1 tags: - - level2-server - - level2-workstation - - manual - - audit + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.1 + ansible.builtin.file: + path: /etc/passwd + owner: root + group: root + mode: u-x,go-wx -- name: "6.1.2 | PATCH | Ensure sticky bit is set on all world-writable directories" - ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t - changed_when: false - failed_when: false +- name: "6.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured" when: - rhel8cis_rule_6_1_2 tags: - - skip_ansible_lint - level1-server - level1-workstation - automated - patch - - stickybits - - permissons + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.2 - -- name: "6.1.3 | PATCH | Ensure permissions on /etc/passwd are configured" ansible.builtin.file: - path: /etc/passwd + path: /etc/passwd- owner: root group: root - mode: 0644 + mode: u-x,go-wx + +- name: "6.1.3 | PATCH | Ensure permissions on /etc/security/opasswd are configured" when: - rhel8cis_rule_6_1_3 tags: @@ -70,15 +44,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.3 - -- name: "6.1.4 | PATCH | Ensure permissions on /etc/shadow are configured" ansible.builtin.file: - path: /etc/shadow + path: /etc/security/opasswd owner: root group: root - mode: 0000 + mode: '0600' + +- name: "6.1.4 | PATCH | Ensure permissions on /etc/group are configured" when: - rhel8cis_rule_6_1_4 tags: @@ -86,15 +62,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.4 - -- name: "6.1.5 | PATCH | Ensure permissions on /etc/group are configured" ansible.builtin.file: path: /etc/group owner: root group: root - mode: 0644 + mode: u-x,go-wx + +- name: "6.1.5 | PATCH | Ensure permissions on /etc/group- are configured" when: - rhel8cis_rule_6_1_5 tags: @@ -102,15 +80,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.5 - -- name: "6.1.6 | PATCH | Ensure permissions on /etc/gshadow are configured" ansible.builtin.file: - path: /etc/gshadow + path: /etc/group- owner: root group: root - mode: 0000 + mode: u-x,go-wx + +- name: "6.1.6 | PATCH | Ensure permissions on /etc/shadow are configured" when: - rhel8cis_rule_6_1_6 tags: @@ -118,15 +98,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.6 - -- name: "6.1.7 | PATCH | Ensure permissions on /etc/passwd- are configured" ansible.builtin.file: - path: /etc/passwd- + path: /etc/shadow owner: root group: root - mode: 0644 + mode: '0000' + +- name: "6.1.7 | PATCH | Ensure permissions on /etc/shadow- are configured" when: - rhel8cis_rule_6_1_7 tags: @@ -134,15 +116,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.7 - -- name: "6.1.8 | PATCH | Ensure permissions on /etc/shadow- are configured" ansible.builtin.file: path: /etc/shadow- owner: root group: root - mode: 0000 + mode: '0000' + +- name: "6.1.8 | PATCH | Ensure permissions on /etc/gshadow are configured" when: - rhel8cis_rule_6_1_8 tags: @@ -150,15 +134,17 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.8 - -- name: "6.1.9 | PATCH | Ensure permissions on /etc/group- are configured" ansible.builtin.file: - path: /etc/group- + path: /etc/gshadow owner: root group: root - mode: 0644 + mode: '0000' + +- name: "6.1.9 | PATCH | Ensure permissions on /etc/gshadow- are configured" when: - rhel8cis_rule_6_1_9 tags: @@ -166,15 +152,17 @@ - level1-workstation - automated - patch - - permissionss + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.9 - -- name: "6.1.10 | PATCH | Ensure permissions on /etc/gshadow- are configured" ansible.builtin.file: path: /etc/gshadow- owner: root group: root - mode: 0000 + mode: '0000' + +- name: "6.1.10 | PATCH | Ensure permissions on /etc/shells are configured" when: - rhel8cis_rule_6_1_10 tags: @@ -182,220 +170,260 @@ - level1-workstation - automated - patch + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 - permissions - rule_6.1.10 + ansible.builtin.file: + path: /etc/shells + owner: root + group: root + mode: u-x,go-wx -- name: "6.1.11 | PATCH | Ensure no world writable files exist" +- name: "6.1.11 | PATCH | Ensure world writable files and directories are secured" + when: + - rhel8cis_rule_6_1_11 + - rhel8cis_disruption_high + tags: + - level1-server + - level1-workstation + - automated + - patch + - files + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - permissions + - rule_6.1.11 + vars: + warn_control_id: '6.1.11' block: - - name: "6.1.11 | AUDIT | Ensure no world writable files exist | Get list of world-writable files" + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Get list of world-writable files" ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002 failed_when: false changed_when: false - register: rhel_08_6_1_11_perms_results + register: discovered_perms_results - - name: "6.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" + - name: "6.1.11 | PATCH | Adjust world-writable files if they exist (Configurable)" + when: + - discovered_perms_results.stdout_lines is defined + - rhel8cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' mode: o-w state: touch - with_items: "{{ rhel_08_6_1_11_perms_results.stdout_lines }}" + with_items: "{{ discovered_perms_results.stdout_lines }}" + + - name: "6.1.11 | PATCH | Ensure world writable files and directories are secured | sticky bit set on world-writable directories" + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t + changed_when: false + failed_when: false + + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warning" when: - - rhel_08_6_1_11_perms_results.stdout_lines is defined - - rhel8cis_no_world_write_adjust + - discovered_perms_results.stdout_lines is defined + - not rhel8cis_no_world_write_adjust + ansible.builtin.debug: + msg: "Warning!! - WorldWritable files have been found" - - name: "6.1.11 | AUDIT | Ensure no world writable files exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.11' + - name: "6.1.11 | AUDIT | Ensure world writable files and directories are secured | Warn Count" when: - - rhel_08_6_1_11_perms_results.stdout_lines is defined + - discovered_perms_results.stdout_lines is defined - not rhel8cis_no_world_write_adjust + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.1.12 | PATCH | Ensure no ungrouped files or directories exist" when: - - rhel8cis_rule_6_1_11 + - rhel8cis_rule_6_1_12 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - automated - patch - - files + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + - rule_6.1.12 - permissions - - rule_6.1.11 - -- name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist" + vars: + warn_control_id: '6.1.12' block: - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Get ungrouped files or directories" + ansible.builtin.shell: find {{ item.mount }} -xdev -nogroup -not -fstype nfs changed_when: false failed_when: false check_mode: false - register: rhel_08_6_1_12_audit - with_items: "{{ ansible_mounts }}" + register: discovered_ungrouped_items + with_items: + - "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" - when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | set fact" + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Flatten ungrouped_items results for easier use" ansible.builtin.set_fact: - rhel_08_6_1_12_unowned_files_found: true - loop: "{{ rhel_08_6_1_12_audit.results }}" - when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + discovered_ungrouped_items_flatten: "{{ discovered_ungrouped_items.results | map(attribute='stdout_lines') | flatten }}" - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Displaying any unowned files or directories" - ansible.builtin.debug: - msg: "Warning -- missing owner on items in {{ rhel_08_6_1_12_audit | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Alert on ungrouped files and directories" when: - - rhel_08_6_1_12_unowned_files_found - - - name: "6.1.12 | AUDIT | Ensure no unowned files or directories exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.12' - when: rhel_08_6_1_12_unowned_files_found - vars: - rhel_08_6_1_12_unowned_files_found: false - when: - - rhel8cis_rule_6_1_12 - tags: - - level1-server - - level1-workstation - - automated - - audit - - files - - permissions - - rule_6.1.12 + - not rhel8cis_ungrouped_adjust + - discovered_ungrouped_items_flatten | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! You have ungrouped files/directories and are configured to not auto-remediate for this task" + - "Please review the files/directories below and assign a group" + - "{{ discovered_ungrouped_items_flatten }}" -- name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist" - block: - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Finding all ungrouped files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nogroup - check_mode: false - failed_when: false - changed_when: false - register: rhel_08_6_1_13_audit - with_items: "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" + - name: "6.1.12 | PATCH | Ensure no ungrouped files or directories exist | Set ungrouped files/directories to configured group" when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] + - rhel8cis_ungrouped_adjust + - discovered_ungrouped_items_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + group: "{{ rhel8cis_ungrouped_group }}" + loop: + - "{{ discovered_ungrouped_items_flatten }}" - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | set fact" - ansible.builtin.set_fact: - rhel_08_6_1_13_ungrouped_files_found: true - loop: "{{ rhel_08_6_1_13_audit.results }}" + - name: "6.1.12 | AUDIT | Ensure no ungrouped files or directories exist | Warn Count" when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - rhel8cis_ungrouped_adjust + - discovered_ungrouped_items_flatten | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Displaying all ungrouped files or directories" - ansible.builtin.debug: - msg: "Warning!! -- Missing group on items in {{ rhel_08_6_1_13_audit | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel_08_6_1_13_ungrouped_files_found - - - name: "6.1.13 | AUDIT | Ensure no ungrouped files or directories exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.13' - when: rhel_08_6_1_13_ungrouped_files_found - vars: - rhel_08_6_1_13_ungrouped_files_found: false +- name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed" when: - rhel8cis_rule_6_1_13 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - - automated + - manual - audit - - files - - permissions - rule_6.1.13 - -- name: "6.1.14 | AUDIT | Audit SUID executables" + - permissions + vars: + warn_control_id: '6.1.13' block: - - name: "6.1.14 | AUDIT | Audit SUID executables | Find all SUID executables" - ansible.builtin.shell: df {{ item.mount }} -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000 + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find SUID executables" + ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -4000 -not -fstype nfs + changed_when: false failed_when: false + check_mode: false + register: discovered_suid_executables + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" + + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find all SGID executables" + ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm -2000 -not -fstype nfs changed_when: false - register: rhel_08_6_1_14_suid_perms - with_items: "{{ ansible_mounts }}" + failed_when: false + check_mode: false + register: discovered_sgid_executables + loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.mount }}" - - name: "6.1.14 | AUDIT | Audit SUID executables | set fact SUID executables" + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Flatten suid_executables results for easier use" ansible.builtin.set_fact: - rhel8cis_6_1_14_suid_found: true - loop: "{{ rhel_08_6_1_14_suid_perms.results }}" + discovered_suid_executables_flatten: "{{ discovered_suid_executables.results | map(attribute='stdout_lines') | flatten }}" + + - name: "6.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Set fact SGID executables" + ansible.builtin.set_fact: + discovered_sgid_executables_flatten: "{{ discovered_sgid_executables.results | map(attribute='stdout_lines') | flatten }}" + + - name: "6.1.13 | PATCH | Ensure SUID and SGID files are reviewed | Remove SUID bit" when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - rhel8cis_suid_adjust + - discovered_suid_executables_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-s' + loop: + - "{{ discovered_suid_executables_flatten }}" - - name: "6.1.14 | AUDIT | Audit SUID executables | Alert SUID executables exist" + - name: "6.1.13 | PATCH | Audit SGID executables | Remove SGID bit" + ansible.builtin.file: + path: "{{ item }}" + mode: 'g-s' + with_items: + - "{{ discovered_sgid_executables_flatten }}" + when: + - rhel8cis_sgid_adjust + - discovered_sgid_executables_flatten | length > 0 + + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Alert SUID executables exist" + when: + - discovered_suid_executables_flatten | length > 0 + - not rhel8cis_suid_adjust ansible.builtin.debug: - msg: "Warning!! -- SUID set on items in {{ rhel_08_6_1_14_suid_perms | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel8cis_6_1_14_suid_found - - - name: "6.1.14 | AUDIT | Audit SUID executables | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.14' - when: rhel8cis_6_1_14_suid_found - vars: - rhel8cis_6_1_14_suid_found: false + msg: + - "Warning!! You have SUID executables" + - "The files are listed below, please confirm the integrity of these binaries" + - "{{ discovered_suid_executables_flatten }}" + + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Alert SGID executables exist" + when: + - discovered_sgid_executables_flatten | length > 0 + - not rhel8cis_sgid_adjust + ansible.builtin.debug: + msg: + - "Warning!! You have SGID executables" + - "The files are listed below, please review the integrity of these binaries" + - "{{ discovered_sgid_executables_flatten }}" + + - name: "6.1.13 | WARNING | Ensure SUID and SGID files are reviewed | Warn Count" + when: + - (discovered_suid_executables_flatten | length > 0 and not rhel8cis_suid_adjust) or + (discovered_sgid_executables_flatten | length > 0 and not rhel8cis_sgid_adjust) + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.1.14 | AUDIT | Audit system file permissions" when: - rhel8cis_rule_6_1_14 + - rhel8cis_disruption_high tags: - - level1-server - - level1-workstation + - level2-server + - level2-workstation - manual - audit - - files + - NIST800-53R5_AC-3 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - NIST800-53R5_MP-2 + - permissions - rule_6.1.14 - -- name: "6.1.15 | AUDIT | Audit SGID executables" + vars: + warn_control_id: '6.1.14' block: - - name: "6.1.15 | AUDIT | Audit SGID executables | Find all SGID executables" - ansible.builtin.shell: df {{ item.mount }} -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 - failed_when: false + - name: "6.1.14 | AUDIT | Audit system file permissions | Audit the packages" + ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto changed_when: false - register: rhel_08_6_1_15_sgid_perms - loop: "{{ ansible_mounts }}" - loop_control: - label: "{{ item.mount }}" + failed_when: false + register: discovered_packages_rpm - - name: "6.1.15 | AUDIT | Audit SGID executables | Set fact SGID executables" - ansible.builtin.set_fact: - rhel8cis_6_1_15_sgid_found: true - loop: "{{ rhel_08_6_1_15_sgid_perms.results }}" - when: - - item | length > 0 - - item.stdout is defined # skipped items are part of results list, but don't have the registered module properties - - item.stdout | length > 0 + - name: "6.1.14 | AUDIT | Audit system file permissions | Create list and warning" + block: + - name: "6.1.14 | AUDIT | Audit system file permissions | Add file discrepancy list to system" + ansible.builtin.copy: + dest: "{{ rhel8cis_rpm_audit_file }}" # noqa template-instead-of-copy + content: "{{ discovered_packages_rpm.stdout }}" + owner: root + group: root + mode: '0644' - - name: "6.1.15 | AUDIT | Audit SGID executables | Alert SGID executables exist" - ansible.builtin.debug: - msg: "Warning!! -- SGID set on items in {{ rhel_08_6_1_15_sgid_perms | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] - when: rhel8cis_6_1_15_sgid_found - - - name: "6.1.15 | AUDIT | Audit SGID executables | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.1.15' - when: rhel8cis_6_1_15_sgid_found - vars: - rhel8cis_6_1_15_guid_found: false - when: - - rhel8cis_rule_6_1_15 - tags: - - level1-server - - level1-workstation - - manual - - audit - - files - - rule_6.1.15 + - name: "6.1.14 | AUDIT | Audit system file permissions | Message out alert for package descrepancies" + when: discovered_packages_rpm.stdout | length > 0 + ansible.builtin.debug: + msg: | + "Warning!! We have discovered package discrepancies. + The file list can be found in {{ rhel8cis_rpm_audit_file }}" + + - name: "6.1.14 | AUDIT | Audit system file permissions | Warn Count" + when: discovered_packages_rpm.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml index 94dbe775..24fe621b 100644 --- a/tasks/section_6/cis_6.2.x.yml +++ b/tasks/section_6/cis_6.2.x.yml @@ -1,69 +1,65 @@ --- -- name: "6.2.1 | PATCH | Ensure password fields are not empty" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - with_items: "{{ empty_password_accounts.stdout_lines }}" +- name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords" when: - - empty_password_accounts.stdout is defined - rhel8cis_rule_6_2_1 tags: - level1-server - level1-workstation - automated - - patch - - accounts + - audit + - NIST800-53R5_IA-5 - rule_6.2.1 - -- name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" + - user_accounts + vars: + warn_control_id: '6.2.1' block: - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Check /etc/passwd entries" - ansible.builtin.shell: pwck -r | grep 'no group' | awk '{ gsub("[:\47]",""); print $2}' + - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Get users not using shadowed passwords" + ansible.builtin.shell: awk -F':' '($2 != "x" ) { print $1}' /etc/passwd changed_when: false failed_when: false - check_mode: false - register: rhel8cis_6_2_2_passwd_gid_check + register: discovered_nonshadowed_users - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" + - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Warn on findings" + when: discovered_nonshadowed_users.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel8cis_6_2_2_passwd_gid_check.stdout_lines | join (', ') }}" - when: rhel8cis_6_2_2_passwd_gid_check.stdout | length > 0 - - - name: "6.2.2 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.2' - when: rhel8cis_6_2_2_passwd_gid_check.stdout | length > 0 + msg: + - "Warning!! You have users that are not using a shadowed password. Please convert the below accounts to use a shadowed password" + - "{{ discovered_nonshadowed_users.stdout_lines }}" + + - name: "6.2.1 | WARNING | Ensure accounts in /etc/passwd use shadowed passwords | warn_count" + when: discovered_nonshadowed_users.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.2 | PATCH | Ensure /etc/shadow password fields are not empty" when: - rhel8cis_rule_6_2_2 tags: - level1-server - level1-workstation - automated - - audit - - accounts - - groups + - patch - rule_6.2.2 - -- name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist" + - NIST800-53R5_IA-5 + - user + - permissions block: - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd" + - name: "6.2.2 | AUDIT | Ensure /etc/shadow password fields are not empty | Find users with no password" + ansible.builtin.shell: awk -F":" '($2 == "" ) { print $1 }' /etc/shadow changed_when: false - failed_when: false - register: rhel8cis_6_2_3_user_uid_check + check_mode: false + register: discovered_empty_password_acct - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" - ansible.builtin.debug: - msg: "Warning!! The following users have UIDs that are duplicates: {{ rhel8cis_6_2_3_user_uid_check.stdout_lines }}" - when: rhel8cis_6_2_3_user_uid_check.stdout | length > 0 - - - name: "6.2.3 | AUDIT | Ensure no duplicate UIDs exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.3' - when: rhel8cis_6_2_3_user_uid_check.stdout | length > 0 + - name: "6.2.2 | PATCH | Ensure /etc/shadow password fields are not empty | Lock users with empty password" + when: discovered_empty_password_acct.stdout | length > 0 + ansible.builtin.user: + name: "{{ item }}" + password_lock: true + loop: + - "{{ discovered_empty_password_acct.stdout_lines }}" + +- name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" when: - rhel8cis_rule_6_2_3 tags: @@ -71,29 +67,34 @@ - level1-workstation - automated - audit - - accounts - - users - rule_6.2.3 - -- name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - groups + vars: + warn_control_id: '6.2.3' block: - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Check for duplicate GIDs" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in users) print $1 ; else users[$3]}' /etc/group" + - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Check /etc/passwd entries" + ansible.builtin.shell: pwck -r | grep 'no group' | awk '{ gsub("[:\47]",""); print $2}' changed_when: false failed_when: false - register: rhel8cis_6_2_4_user_user_check + check_mode: false + register: discovered_passwd_gid_check - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" + - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group" + when: discovered_passwd_gid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following groups have duplicate GIDs: {{ rhel8cis_6_2_4_user_user_check.stdout_lines }}" - when: rhel8cis_6_2_4_user_user_check.stdout | length > 0 + msg: "Warning!! The following users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join (', ') }}" - - name: "6.2.4 | AUDIT | Ensure no duplicate GIDs exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.4' - when: rhel8cis_6_2_4_user_user_check.stdout | length > 0 + - name: "6.2.3 | WARNING | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" + when: discovered_passwd_gid_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml +- name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist" when: - rhel8cis_rule_6_2_4 tags: @@ -101,28 +102,34 @@ - level1-workstation - automated - audit - - accounts - - groups + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.4 - -- name: "6.2.5 | AUDIT | Ensure no duplicate user names exist" + - user + vars: + warn_control_id: '6.2.4' block: - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Check for duplicate User Names" - ansible.builtin.shell: "pwck -r | awk -F: '{if ($1 in users) print $1 ; else users[$1]}' /etc/passwd" + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd" changed_when: false failed_when: false - register: rhel8cis_6_2_5_user_username_check + check_mode: false + register: discovered_user_uid_check - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs" + when: discovered_user_uid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following user names are duplicates: {{ rhel8cis_6_2_5_user_username_check.stdout_lines }}" - when: rhel8cis_6_2_5_user_username_check.stdout | length > 0 - - - name: "6.2.5 | AUDIT | Ensure no duplicate user names exist | Warn Count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.5' - when: rhel8cis_6_2_5_user_username_check.stdout | length > 0 + msg: "Warning!! The following users have UIDs that are duplicates: {{ discovered_user_uid_check.stdout_lines }}" + + - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | Set warning count" + when: discovered_user_uid_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist" when: - rhel8cis_rule_6_2_5 tags: @@ -130,29 +137,36 @@ - level1-workstation - automated - audit - - accounts - - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.5 - -- name: "6.2.6 | AUDIT | Ensure no duplicate group names exist" + - groups + vars: + warn_control_id: '6.2.5' block: - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Check for duplicate group names" - ansible.builtin.shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d' + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Check for duplicate GIDs" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($3 in users) print $1 ; else users[$3]}' /etc/group" changed_when: false failed_when: false check_mode: false - register: rhel8cis_6_2_6_group_group_check + register: discovered_user_gid_check - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" + when: discovered_user_gid_check.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ rhel8cis_6_2_6_group_group_check.stdout_lines }}" - when: rhel8cis_6_2_6_group_group_check.stdout | length > 0 - - - name: "6.2.6 | AUDIT | Ensure no duplicate group names exist | Warn count" - ansible.builtin.import_tasks: warning_facts.yml - vars: - warn_control_id: '6.2.6' - when: rhel8cis_6_2_6_group_group_check.stdout | length > 0 + msg: "Warning!! The following groups have duplicate GIDs: {{ discovered_user_gid_check.stdout_lines }}" + + - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Set warning count" + when: discovered_user_gid_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.6 | AUDIT | Ensure no duplicate user names exist" + vars: + warn_control_id: '6.2.6' when: - rhel8cis_rule_6_2_6 tags: @@ -160,321 +174,248 @@ - level1-workstation - automated - audit - - accounts - - groups - rule_6.2.6 - -- name: "6.2.7 | PATCH | Ensure root PATH Integrity" + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - user block: - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine empty value" - ansible.builtin.shell: 'echo $PATH | grep ::' - changed_when: false - failed_when: rhel8cis_6_2_7_path_colon.rc == 0 - check_mode: false - register: rhel8cis_6_2_7_path_colon - - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determin colon end" - ansible.builtin.shell: 'echo $PATH | grep :$' - changed_when: false - failed_when: rhel8cis_6_2_7_path_colon_end.rc == 0 - check_mode: false - register: rhel8cis_6_2_7_path_colon_end - - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Determine dot in path" - ansible.builtin.shell: "/bin/bash --login -c 'env | grep ^PATH=' | sed -e 's/PATH=//' -e 's/::/:/' -e 's/:$//' -e 's/:/\\n/g'" + - name: "6.2.6 | AUDIT | Ensure no duplicate user names exist | Check for duplicate User Names" + ansible.builtin.shell: "pwck -r | awk -F: '{if ($1 in users) print $1 ; else users[$1]}' /etc/passwd" changed_when: false - failed_when: '"." in rhel8cis_6_2_7_dot_in_path.stdout_lines' + failed_when: false check_mode: false - register: rhel8cis_6_2_7_dot_in_path + register: discovered_username_check - - name: "6.2.7 | AUDIT | Ensure root PATH Integrity | Alert on empty value, colon end, and dot in path" + - name: "6.2.6 | WARNING | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" + when: discovered_username_check.stdout | length > 0 ansible.builtin.debug: - msg: - - "The following paths have an empty value: {{ rhel8cis_6_2_7_path_colon.stdout_lines }}" - - "The following paths have colon end: {{ rhel8cis_6_2_7_path_colon_end.stdout_lines }}" - - "The following paths have a dot in the path: {{ rhel8cis_6_2_7_dot_in_path.stdout_lines }}" + msg: "Warning!! The following user names are duplicates: {{ discovered_user_username_check.stdout_lines }}" - - name: "6.2.7 | PATCH | Ensure root PATH Integrity | Determine rights and owner" - ansible.builtin.file: - path: '{{ item }}' - follow: true - state: directory - owner: root - mode: 'o-w,g-w' - with_items: "{{ rhel8cis_6_2_7_dot_in_path.stdout_lines }}" + - name: "6.2.6 | WARNING | Ensure no duplicate user names exist | Set warning count" + when: discovered_username_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.7 | AUDIT | Ensure no duplicate group names exist" when: - rhel8cis_rule_6_2_7 tags: - level1-server - level1-workstation - automated - - patch - - paths + - audit + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.7 + - groups + vars: + warn_control_id: '6.2.7' + block: + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Check for duplicate group names" + ansible.builtin.shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d' + changed_when: false + failed_when: false + check_mode: false + register: discovered_group_check -- name: "6.2.8 | PATCH | Ensure root is the only UID 0 account" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - with_items: "{{ rhel8cis_uid_zero_accounts_except_root.stdout_lines }}" + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" + when: discovered_group_check.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! The following group names are duplicates: {{ discovered_group_group_check.stdout_lines }}" + + - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" + when: discovered_group_check.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "6.2.8 | PATCH | Ensure root PATH Integrity" when: - - rhel8cis_uid_zero_accounts_except_root.stdout is defined - rhel8cis_rule_6_2_8 tags: - level1-server - level1-workstation - - automated - patch - - accounts - - users + - paths + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.8 - -- name: "6.2.9 | PATCH | Ensure all users' home directories exist" block: - - name: "6.2.9 | AUDIT | Ensure all users' home directories exist" - ansible.builtin.stat: - path: "{{ item }}" - register: rhel_08_6_2_9_audit - with_items: "{{ rhel8cis_passwd | selectattr('shell', '!=', '/bin/false') | selectattr('shell', '!=', '/usr/bin/nologin') | selectattr('uid', '>=', rhel8uid_interactive_uid_start | int ) | selectattr('uid', '<=', rhel8uid_interactive_uid_stop | int ) | map(attribute='dir') | list }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" + ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 + changed_when: false + register: discovered_root_paths - - name: "6.2.9 | AUDIT | Ensure all users' home directories exist" - ansible.builtin.shell: find -H {{ item.0 | quote }} -type d -not -type l -perm /027 - check_mode: false - changed_when: rhel_08_6_2_9_patch_audit.stdout | length > 0 - register: rhel_08_6_2_9_patch_audit - when: - - ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_9_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_9_audit.results | map(attribute='stat') | list }}" - loop_control: - label: "{{ item.0 }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Get root paths" + ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 | tr ":" "\n" + changed_when: false + register: discovered_root_paths_split - - name: "6.2.9 | PATCH | Ensure all users' home directories exist" - ansible.builtin.file: - path: "{{ item.0 }}" - recurse: false - mode: a-st,g-w,o-rwx - register: rhel_08_6_2_9_patch - when: - - not ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_9_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_9_audit.results | map(attribute='stat') | list }}" - loop_control: - label: "{{ item.0 }}" + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set fact" + ansible.builtin.set_fact: + root_paths: "{{ discovered_root_paths.stdout }}" - # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.9 | PATCH | Ensure all users' home directories exist" - ansible.posix.acl: - path: "{{ item.0 }}" - default: true - state: present - recursive: true - follow: "{{ rhel_08_6_2_9_follow_home_symlinks }}" - etype: "{{ item.1.etype }}" - permissions: "{{ item.1.mode }}" - when: - - not system_is_container - with_nested: - - "{{ (ansible_check_mode | ternary(rhel_08_6_2_9_patch_audit, rhel_08_6_2_9_patch)).results | - rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" - - - - etype: group - mode: rx - - etype: other - mode: '0' + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" + ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"' + changed_when: false + failed_when: discovered_root_path_empty_dir.rc not in [ 0, 1 ] + register: discovered_root_path_empty_dir + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for trailing ':'" + ansible.builtin.shell: '{{ root_paths }} | cut -d= -f2 | grep -q ":$" && echo "roots path contains a trailing (:)"' + changed_when: false + failed_when: discovered_root_path_trailing_colon.rc not in [ 0, 1 ] + register: discovered_root_path_trailing_colon + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" + block: + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" + ansible.builtin.stat: + path: "{{ item }}" + register: discovered_root_path_perms + loop: "{{ discovered_root_paths_split.stdout_lines }}" + + - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set permissions" + when: + - item.stat.exists + - item.stat.isdir + - item.stat.pw_name != 'root' or item.stat.gr_name != 'root' or item.stat.woth or item.stat.wgrp + - (item != 'root') and (not rhel8cis_uses_root) + ansible.builtin.file: + path: "{{ item.stat.path }}" + state: directory + owner: root + group: root + mode: '0755' + follow: false + loop: "{{ discovered_root_path_perms.results }}" + loop_control: + label: "{{ item }}" + +- name: "6.2.9 | PATCH | Ensure root is the only UID 0 account" when: + - discovered_uid_zero_accounts_except_root.rc - rhel8cis_rule_6_2_9 tags: - level1-server - level1-workstation - - automated - patch + - accounts - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.9 + ansible.builtin.shell: passwd -l {{ item }} + changed_when: false + failed_when: false + loop: "{{ discovered_uid_zero_accounts_except_root.stdout_lines }}" -- name: "6.2.10 | PATCH | Ensure users own their home directories" - ansible.builtin.file: - path: "{{ item.dir }}" - owner: "{{ item.id }}" - state: directory - with_items: "{{ rhel8cis_passwd }}" - loop_control: - label: "{{ rhel8cis_passwd_label }}" +- name: "6.2.10 | PATCH | Ensure local interactive user home directories exist" when: - - item.uid >= rhel8uid_interactive_uid_start|int - - item.id != 'nobody' - - item.dir != '/dev/null' - rhel8cis_rule_6_2_10 tags: - - skip_ansible_lint # settings found on 6_2_7 - level1-server - level1-workstation - - automated - patch - users + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.10 - -- name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" block: - - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" - ansible.builtin.stat: - path: "{{ item }}" - with_items: "{{ rhel8cis_passwd | selectattr('shell', '!=', '/bin/false') | selectattr('shell', '!=', '/usr/bin/nologin') | selectattr('uid', '>=', rhel8uid_interactive_uid_start | int) | selectattr('uid', '<=', rhel8uid_interactive_uid_stop | int) | map(attribute='dir') | list }}" - register: rhel_08_6_2_11_audit - - - name: "6.2.11 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive" - ansible.builtin.shell: find -H {{ item.0 | quote }} type -d -not -type l -perm /027 - check_mode: false - changed_when: rhel_08_6_2_11_patch_audit.stdout | length > 0 - register: rhel_08_6_2_11_patch_audit - when: - - ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_11_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_11_audit.results | map(attribute='stat') | list }}" - loop_control: - label: "{{ item.0 }}" - - - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Create dir if absent" ansible.builtin.file: - path: "{{ item.0 }}" - recurse: true - mode: a-st,g-w,o-rwx - follow: false - register: rhel_08_6_2_11_patch - when: - - not ansible_check_mode - - item.1.exists - with_together: - - "{{ rhel_08_6_2_11_audit.results | map(attribute='item') | list }}" - - "{{ rhel_08_6_2_11_audit.results | map(attribute='stat') | list }}" + path: "{{ item.dir }}" + state: directory + owner: "{{ item.id }}" + group: "{{ item.gid }}" + loop: "{{ rhel8cis_passwd | selectattr('uid', '>=', rhel8uid_uid_start | int ) | selectattr('uid', '<=', rhel8uid_uid_stop | int ) | list }}" loop_control: - label: "{{ item.0 }}" + label: "{{ item.id }}" # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.11 | PATCH | Ensure users' home directories permissions are 750 or more restrictive" + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set group ACL" ansible.posix.acl: - path: "{{ item.0 }}" + path: "{{ item }}" default: true + etype: group + permissions: rx state: present - recursive: true - etype: "{{ item.1.etype }}" - permissions: "{{ item.1.mode }}" - when: - - not system_is_container - with_nested: - - "{{ (ansible_check_mode | ternary(rhel_08_6_2_11_patch_audit, rhel_08_6_2_11_patch)).results | - rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}" - - - - etype: group - mode: rx - - etype: other - mode: '0' + loop: "{{ discovered_interactive_users_home.stdout_lines }}" + when: not system_is_container + + - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set other ACL" + ansible.posix.acl: + path: "{{ item }}" + default: true + etype: other + permissions: 0 + state: present + loop: "{{ discovered_interactive_users_home.stdout_lines }}" + when: not system_is_container + +- name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured" when: - rhel8cis_rule_6_2_11 + - rhel8cis_disruption_high tags: - level1-server - level1-workstation - automated - patch - - users - - permissions + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 - rule_6.2.11 - -- name: "6.2.12 | PATCH | Ensure users' dot files are not group or world-writable" + - user + vars: + warn_control_id: '6.2.11' block: - - name: "6.2.12 | AUDIT | Ensure users' dot files are not group or world-writable | Check for files" - ansible.builtin.shell: find /home/ -maxdepth 2 -name "\.*" -perm /g+w,o+w + - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" + ansible.builtin.shell: find /home/ -name "\.*" -perm /g+w,o+w changed_when: false - failed_when: false - register: rhel8cis_6_2_12_audit + failed_when: discovered_dot_files.rc not in [ 0, 1 ] + check_mode: false + register: discovered_dot_files - - name: "6.2.12 | PATCH | Ensure users' dot files are not group or world-writable | Changes files if configured" - ansible.builtin.file: - path: '{{ item }}' - mode: go-w - with_items: "{{ rhel8cis_6_2_12_audit.stdout_lines }}" + - name: "6.2.11 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - - rhel8cis_6_2_12_audit.stdout is defined + - discovered_dot_files.stdout | length > 0 - rhel8cis_dotperm_ansiblemanaged - when: - - rhel8cis_rule_6_2_12 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - permissions - - rule_6.2.12 -- name: "6.2.13 | PATCH | Ensure users' .netrc Files are not group or world accessible" - ansible.builtin.shell: /bin/true - changed_when: false - failed_when: false - when: - - rhel8cis_rule_6_2_13 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - permissions - - notimplemented - - rule_6.2.13 - -- name: "6.2.14 | PATCH | Ensure no users have .forward files" - ansible.builtin.file: - path: "~{{ item }}/.forward" - state: absent - with_items: - - "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_14 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.14 - -- name: "6.2.15 | PATCH | Ensure no users have .netrc files" - ansible.builtin.file: - path: "~{{ item }}/.netrc" - state: absent - with_items: - - "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_15 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.15 - -- name: "6.2.16 | PATCH | Ensure no users have .rhosts files" - ansible.builtin.file: - path: "~{{ item }}/.rhosts" - state: absent - with_items: "{{ users.stdout_lines }}" - when: - - rhel8cis_rule_6_2_16 - tags: - - level1-server - - level1-workstation - - automated - - patch - - users - - files - - rule_6.2.16 + ansible.builtin.debug: + msg: + - "Warning!! We have discovered group or world-writable dot files on your system and this host is configured for manual intervention. Please investigate these files further." + + - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" + when: + - discovered_dot_files.stdout | length > 0 + - rhel8cis_dotperm_ansiblemanaged + + ansible.builtin.import_tasks: + file: warning_facts.yml + + - name: "6.2.11 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" + when: + - discovered_dot_files.stdout | length > 0 + - rhel8cis_dotperm_ansiblemanaged + + ansible.builtin.file: + path: '{{ item }}' + mode: go-w + with_items: "{{ discovered_dot_files.stdout_lines }}" diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index 35328e5f..b194fdc8 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -1,7 +1,9 @@ --- - name: "SECTION | 6.1 | System File Permissions" - ansible.builtin.import_tasks: cis_6.1.x.yml + ansible.builtin.import_tasks: + file: cis_6.1.x.yml - name: "SECTION | 6.2 | User and Group Settings" - ansible.builtin.import_tasks: cis_6.2.x.yml + ansible.builtin.import_tasks: + file: cis_6.2.x.yml diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 6e804873..3032b7cb 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -14,7 +14,7 @@ # # warn_count the main variable for the number of warnings and each time a warn_control_id is added # the count increases by a value of 1 -- name: "{{ warn_control_id }} | AUDIT | Set fact for manual task warning." +- name: "{{ warn_control_id }} | WARNING | Set fact for manual task warning." ansible.builtin.set_fact: warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" warn_count: "{{ warn_count | int + 1 }}" diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index d86b83d3..04a487bc 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -1,8 +1,5 @@ ## metadata for Audit benchmark -benchmark_version: '2.0.0' - -# Set if pre version 8.2 -is_pre82_release: {% if ansible_distribution_version >= "8.2" %}false{% else %}true{% endif %} +benchmark_version: '3.0.0' # Set if genuine RHEL (subscription manager check) not for derivatives e.g. CentOS host_os_distribution: {{ ansible_distribution }} @@ -10,9 +7,6 @@ host_os_distribution: {{ ansible_distribution }} # timeout for each command to run where set - default = 10seconds/10000ms timeout_ms: {{ audit_cmd_timeout }} -# Allow the audit to run heavy tests which may utilise resources and impact performance -run_heavy_tests: {{ audit_run_heavy_tests }} - # Taken from LE rhel8-cis rhel8cis_section1: {{ rhel8cis_section1 }} rhel8cis_section2: {{ rhel8cis_section2 }} @@ -27,7 +21,8 @@ rhel8cis_level_2: {{ rhel8cis_level_2 }} rhel8cis_selinux_disable: {{ rhel8cis_selinux_disable }} # to enable rules that may have IO impact on a system e.g. full filesystem scans or CPU heavy -run_heavy_tests: true +run_heavy_tests: {{ audit_run_heavy_tests }} + {% if rhel8cis_legacy_boot is defined %} rhel8cis_legacy_boot: {{ rhel8cis_legacy_boot }} {% endif %} @@ -40,62 +35,85 @@ rhel8cis_legacy_boot: {{ rhel8cis_legacy_boot }} rhel8cis_rule_1_1_1_1: {{ rhel8cis_rule_1_1_1_1 }} rhel8cis_rule_1_1_1_2: {{ rhel8cis_rule_1_1_1_2 }} rhel8cis_rule_1_1_1_3: {{ rhel8cis_rule_1_1_1_3 }} -rhel8cis_rule_1_1_2_1: {{ rhel8cis_rule_1_1_2_1 }} -rhel8cis_rule_1_1_2_2: {{ rhel8cis_rule_1_1_2_2 }} -rhel8cis_rule_1_1_2_3: {{ rhel8cis_rule_1_1_2_3 }} -rhel8cis_rule_1_1_2_4: {{ rhel8cis_rule_1_1_2_4 }} -rhel8cis_rule_1_1_3_1: {{ rhel8cis_rule_1_1_3_1 }} -rhel8cis_rule_1_1_3_2: {{ rhel8cis_rule_1_1_3_2 }} -rhel8cis_rule_1_1_3_3: {{ rhel8cis_rule_1_1_3_3 }} -rhel8cis_rule_1_1_3_4: {{ rhel8cis_rule_1_1_3_4 }} -rhel8cis_rule_1_1_4_1: {{ rhel8cis_rule_1_1_4_1 }} -rhel8cis_rule_1_1_4_2: {{ rhel8cis_rule_1_1_4_2 }} -rhel8cis_rule_1_1_4_3: {{ rhel8cis_rule_1_1_4_3 }} -rhel8cis_rule_1_1_4_4: {{ rhel8cis_rule_1_1_4_4 }} -rhel8cis_rule_1_1_5_1: {{ rhel8cis_rule_1_1_5_1 }} -rhel8cis_rule_1_1_5_2: {{ rhel8cis_rule_1_1_5_2 }} -rhel8cis_rule_1_1_5_3: {{ rhel8cis_rule_1_1_5_3 }} -rhel8cis_rule_1_1_5_4: {{ rhel8cis_rule_1_1_5_4 }} -rhel8cis_rule_1_1_6_1: {{ rhel8cis_rule_1_1_6_1 }} -rhel8cis_rule_1_1_6_2: {{ rhel8cis_rule_1_1_6_2 }} -rhel8cis_rule_1_1_6_3: {{ rhel8cis_rule_1_1_6_3 }} -rhel8cis_rule_1_1_6_4: {{ rhel8cis_rule_1_1_6_4 }} -rhel8cis_rule_1_1_7_1: {{ rhel8cis_rule_1_1_7_1 }} -rhel8cis_rule_1_1_7_2: {{ rhel8cis_rule_1_1_7_2 }} -rhel8cis_rule_1_1_7_3: {{ rhel8cis_rule_1_1_7_3 }} -rhel8cis_rule_1_1_7_4: {{ rhel8cis_rule_1_1_7_4 }} -rhel8cis_rule_1_1_7_5: {{ rhel8cis_rule_1_1_7_5 }} -rhel8cis_rule_1_1_8_1: {{ rhel8cis_rule_1_1_8_1 }} -rhel8cis_rule_1_1_8_2: {{ rhel8cis_rule_1_1_8_2 }} -rhel8cis_rule_1_1_8_3: {{ rhel8cis_rule_1_1_8_3 }} -rhel8cis_rule_1_1_9: {{ rhel8cis_rule_1_1_9 }} -rhel8cis_rule_1_1_10: {{ rhel8cis_rule_1_1_10 }} - -rhel8cis_rule_1_2_1: {% if ansible_distribution == "RedHat" and rhel8cis_rule_1_2_1 %}True{% else %}False{% endif %} # Only run if Redhat and Subscribed +rhel8cis_rule_1_1_1_4: {{ rhel8cis_rule_1_1_1_4 }} +rhel8cis_rule_1_1_1_5: {{ rhel8cis_rule_1_1_1_5 }} +rhel8cis_rule_1_1_1_6: {{ rhel8cis_rule_1_1_1_6 }} +rhel8cis_rule_1_1_1_7: {{ rhel8cis_rule_1_1_1_7 }} +rhel8cis_rule_1_1_1_8: {{ rhel8cis_rule_1_1_1_8 }} +# /tmp +rhel8cis_rule_1_1_2_1_1: {{ rhel8cis_rule_1_1_2_1_1 }} +rhel8cis_rule_1_1_2_1_2: {{ rhel8cis_rule_1_1_2_1_2 }} +rhel8cis_rule_1_1_2_1_3: {{ rhel8cis_rule_1_1_2_1_3 }} +rhel8cis_rule_1_1_2_1_4: {{ rhel8cis_rule_1_1_2_1_4 }} + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: {{ rhel8cis_rule_1_1_2_2_1 }} +rhel8cis_rule_1_1_2_2_2: {{ rhel8cis_rule_1_1_2_2_2 }} +rhel8cis_rule_1_1_2_2_3: {{ rhel8cis_rule_1_1_2_2_3 }} +rhel8cis_rule_1_1_2_2_4: {{ rhel8cis_rule_1_1_2_2_4 }} + +# /home +rhel8cis_rule_1_1_2_3_1: {{ rhel8cis_rule_1_1_2_3_1 }} +rhel8cis_rule_1_1_2_3_2: {{ rhel8cis_rule_1_1_2_3_2 }} +rhel8cis_rule_1_1_2_3_3: {{ rhel8cis_rule_1_1_2_3_3 }} + +# /var +rhel8cis_rule_1_1_2_4_1: {{ rhel8cis_rule_1_1_2_4_1 }} +rhel8cis_rule_1_1_2_4_2: {{ rhel8cis_rule_1_1_2_4_2 }} +rhel8cis_rule_1_1_2_4_3: {{ rhel8cis_rule_1_1_2_4_3 }} + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: {{ rhel8cis_rule_1_1_2_5_1 }} +rhel8cis_rule_1_1_2_5_2: {{ rhel8cis_rule_1_1_2_5_2 }} +rhel8cis_rule_1_1_2_5_3: {{ rhel8cis_rule_1_1_2_5_3 }} +rhel8cis_rule_1_1_2_5_4: {{ rhel8cis_rule_1_1_2_5_4 }} + +# /var/log +rhel8cis_rule_1_1_2_6_1: {{ rhel8cis_rule_1_1_2_6_1 }} +rhel8cis_rule_1_1_2_6_2: {{ rhel8cis_rule_1_1_2_6_2 }} +rhel8cis_rule_1_1_2_6_3: {{ rhel8cis_rule_1_1_2_6_3 }} +rhel8cis_rule_1_1_2_6_4: {{ rhel8cis_rule_1_1_2_6_4 }} + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: {{ rhel8cis_rule_1_1_2_7_1 }} +rhel8cis_rule_1_1_2_7_2: {{ rhel8cis_rule_1_1_2_7_2 }} +rhel8cis_rule_1_1_2_7_3: {{ rhel8cis_rule_1_1_2_7_3 }} +rhel8cis_rule_1_1_2_7_4: {{ rhel8cis_rule_1_1_2_7_4 }} + +# DNF - Patching +rhel8cis_rule_1_2_1: {{ rhel8cis_rule_1_2_1 }} rhel8cis_rule_1_2_2: {{ rhel8cis_rule_1_2_2 }} rhel8cis_rule_1_2_3: {{ rhel8cis_rule_1_2_3 }} rhel8cis_rule_1_2_4: {{ rhel8cis_rule_1_2_4 }} +rhel8cis_rule_1_2_5: {{ rhel8cis_rule_1_2_5 }} +# bootloader grub rhel8cis_rule_1_3_1: {{ rhel8cis_rule_1_3_1 }} rhel8cis_rule_1_3_2: {{ rhel8cis_rule_1_3_2 }} +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: {{ rhel8cis_rule_1_4_1 }} rhel8cis_rule_1_4_2: {{ rhel8cis_rule_1_4_2 }} rhel8cis_rule_1_4_3: {{ rhel8cis_rule_1_4_3 }} - -rhel8cis_rule_1_5_1: {{ rhel8cis_rule_1_5_1 }} -rhel8cis_rule_1_5_2: {{ rhel8cis_rule_1_5_2 }} -rhel8cis_rule_1_5_3: {{ rhel8cis_rule_1_5_3 }} - -rhel8cis_rule_1_6_1_1: {{ rhel8cis_rule_1_6_1_1 }} -rhel8cis_rule_1_6_1_2: {{ rhel8cis_rule_1_6_1_2 }} -rhel8cis_rule_1_6_1_3: {{ rhel8cis_rule_1_6_1_3 }} -rhel8cis_rule_1_6_1_4: {{ rhel8cis_rule_1_6_1_4 }} -rhel8cis_rule_1_6_1_5: {{ rhel8cis_rule_1_6_1_5 }} -rhel8cis_rule_1_6_1_6: {{ rhel8cis_rule_1_6_1_6 }} -rhel8cis_rule_1_6_1_7: {{ rhel8cis_rule_1_6_1_7 }} -rhel8cis_rule_1_6_1_8: {{ rhel8cis_rule_1_6_1_8 }} - +rhel8cis_rule_1_4_4: {{ rhel8cis_rule_1_4_4 }} + +# SElinux +rhel8cis_rule_1_5_1_1: {{ rhel8cis_rule_1_5_1_1 }} +rhel8cis_rule_1_5_1_2: {{ rhel8cis_rule_1_5_1_2 }} +rhel8cis_rule_1_5_1_3: {{ rhel8cis_rule_1_5_1_3 }} +rhel8cis_rule_1_5_1_4: {{ rhel8cis_rule_1_5_1_4 }} +rhel8cis_rule_1_5_1_5: {{ rhel8cis_rule_1_5_1_5 }} +rhel8cis_rule_1_5_1_6: {{ rhel8cis_rule_1_5_1_6 }} +rhel8cis_rule_1_5_1_7: {{ rhel8cis_rule_1_5_1_7 }} +rhel8cis_rule_1_5_1_8: {{ rhel8cis_rule_1_5_1_8 }} + +# Crypto Policies +rhel8cis_rule_1_6_1: {{ rhel8cis_rule_1_6_1 }} +rhel8cis_rule_1_6_2: {{ rhel8cis_rule_1_6_2 }} +rhel8cis_rule_1_6_3: {{ rhel8cis_rule_1_6_3 }} +rhel8cis_rule_1_6_4: {{ rhel8cis_rule_1_6_4 }} + +# MOTD and messages rhel8cis_rule_1_7_1: {{ rhel8cis_rule_1_7_1 }} rhel8cis_rule_1_7_2: {{ rhel8cis_rule_1_7_2 }} rhel8cis_rule_1_7_3: {{ rhel8cis_rule_1_7_3 }} @@ -103,19 +121,25 @@ rhel8cis_rule_1_7_4: {{ rhel8cis_rule_1_7_4 }} rhel8cis_rule_1_7_5: {{ rhel8cis_rule_1_7_5 }} rhel8cis_rule_1_7_6: {{ rhel8cis_rule_1_7_6 }} +# Gnome desktop rhel8cis_rule_1_8_1: {{ rhel8cis_rule_1_8_1 }} rhel8cis_rule_1_8_2: {{ rhel8cis_rule_1_8_2 }} rhel8cis_rule_1_8_3: {{ rhel8cis_rule_1_8_3 }} rhel8cis_rule_1_8_4: {{ rhel8cis_rule_1_8_4 }} rhel8cis_rule_1_8_5: {{ rhel8cis_rule_1_8_5 }} - -rhel8cis_rule_1_9: {{ rhel8cis_rule_1_9 }} -rhel8cis_rule_1_10: {{ rhel8cis_rule_1_10 }} - -# section 2 rules +rhel8cis_rule_1_8_6: {{ rhel8cis_rule_1_8_6 }} +rhel8cis_rule_1_8_7: {{ rhel8cis_rule_1_8_7 }} +rhel8cis_rule_1_8_8: {{ rhel8cis_rule_1_8_8 }} +rhel8cis_rule_1_8_9: {{ rhel8cis_rule_1_8_9 }} +rhel8cis_rule_1_8_10: {{ rhel8cis_rule_1_8_10 }} + +# Section 2 rules +# time sync rhel8cis_rule_2_1_1: {{ rhel8cis_rule_2_1_1 }} rhel8cis_rule_2_1_2: {{ rhel8cis_rule_2_1_2 }} +rhel8cis_rule_2_1_3: {{ rhel8cis_rule_2_1_3 }} +# Server services rhel8cis_rule_2_2_1: {{ rhel8cis_rule_2_2_1 }} rhel8cis_rule_2_2_2: {{ rhel8cis_rule_2_2_2 }} rhel8cis_rule_2_2_3: {{ rhel8cis_rule_2_2_3 }} @@ -136,25 +160,29 @@ rhel8cis_rule_2_2_17: {{ rhel8cis_rule_2_2_17 }} rhel8cis_rule_2_2_18: {{ rhel8cis_rule_2_2_18 }} rhel8cis_rule_2_2_19: {{ rhel8cis_rule_2_2_19 }} rhel8cis_rule_2_2_20: {{ rhel8cis_rule_2_2_20 }} +rhel8cis_rule_2_2_21: {{ rhel8cis_rule_2_2_21 }} +rhel8cis_rule_2_2_22: {{ rhel8cis_rule_2_2_22 }} +# Client services rhel8cis_rule_2_3_1: {{ rhel8cis_rule_2_3_1 }} rhel8cis_rule_2_3_2: {{ rhel8cis_rule_2_3_2 }} rhel8cis_rule_2_3_3: {{ rhel8cis_rule_2_3_3 }} rhel8cis_rule_2_3_4: {{ rhel8cis_rule_2_3_4 }} rhel8cis_rule_2_3_5: {{ rhel8cis_rule_2_3_5 }} -rhel8cis_rule_2_3_6: {{ rhel8cis_rule_2_3_6 }} - -rhel8cis_rule_2_4: {{ rhel8cis_rule_2_4 }} # Section 3 rules +# network connectivity wifi/bluetooth/ipv6 rhel8cis_rule_3_1_1: {{ rhel8cis_rule_3_1_1 }} rhel8cis_rule_3_1_2: {{ rhel8cis_rule_3_1_2 }} rhel8cis_rule_3_1_3: {{ rhel8cis_rule_3_1_3 }} -rhel8cis_rule_3_1_4: {{ rhel8cis_rule_3_1_4 }} +# Network Kernel module rhel8cis_rule_3_2_1: {{ rhel8cis_rule_3_2_1 }} rhel8cis_rule_3_2_2: {{ rhel8cis_rule_3_2_2 }} +rhel8cis_rule_3_2_3: {{ rhel8cis_rule_3_2_3 }} +rhel8cis_rule_3_2_4: {{ rhel8cis_rule_3_2_4 }} +# Network Kernel Params rhel8cis_rule_3_3_1: {{ rhel8cis_rule_3_3_1 }} rhel8cis_rule_3_3_2: {{ rhel8cis_rule_3_3_2 }} rhel8cis_rule_3_3_3: {{ rhel8cis_rule_3_3_3 }} @@ -164,161 +192,206 @@ rhel8cis_rule_3_3_6: {{ rhel8cis_rule_3_3_6 }} rhel8cis_rule_3_3_7: {{ rhel8cis_rule_3_3_7 }} rhel8cis_rule_3_3_8: {{ rhel8cis_rule_3_3_8 }} rhel8cis_rule_3_3_9: {{ rhel8cis_rule_3_3_9 }} +rhel8cis_rule_3_3_10: {{ rhel8cis_rule_3_3_10 }} +rhel8cis_rule_3_3_11: {{ rhel8cis_rule_3_3_11 }} +# Firewall rhel8cis_rule_3_4_1_1: {{ rhel8cis_rule_3_4_1_1 }} rhel8cis_rule_3_4_1_2: {{ rhel8cis_rule_3_4_1_2 }} -rhel8cis_rule_3_4_1_3: {{ rhel8cis_rule_3_4_1_3 }} -rhel8cis_rule_3_4_1_4: {{ rhel8cis_rule_3_4_1_4 }} -rhel8cis_rule_3_4_1_5: {{ rhel8cis_rule_3_4_1_5 }} -rhel8cis_rule_3_4_1_6: {{ rhel8cis_rule_3_4_1_6 }} -rhel8cis_rule_3_4_1_7: {{ rhel8cis_rule_3_4_1_7 }} +# Firewall rules rhel8cis_rule_3_4_2_1: {{ rhel8cis_rule_3_4_2_1 }} rhel8cis_rule_3_4_2_2: {{ rhel8cis_rule_3_4_2_2 }} rhel8cis_rule_3_4_2_3: {{ rhel8cis_rule_3_4_2_3 }} rhel8cis_rule_3_4_2_4: {{ rhel8cis_rule_3_4_2_4 }} rhel8cis_rule_3_4_2_5: {{ rhel8cis_rule_3_4_2_5 }} -rhel8cis_rule_3_4_2_6: {{ rhel8cis_rule_3_4_2_6 }} -rhel8cis_rule_3_4_2_7: {{ rhel8cis_rule_3_4_2_7 }} -rhel8cis_rule_3_4_2_8: {{ rhel8cis_rule_3_4_2_8 }} -rhel8cis_rule_3_4_2_9: {{ rhel8cis_rule_3_4_2_9 }} -rhel8cis_rule_3_4_2_10: {{ rhel8cis_rule_3_4_2_10 }} -rhel8cis_rule_3_4_2_11: {{ rhel8cis_rule_3_4_2_11 }} - -rhel8cis_rule_3_4_3_1_1: {{ rhel8cis_rule_3_4_3_1_1 }} -rhel8cis_rule_3_4_3_1_2: {{ rhel8cis_rule_3_4_3_1_2 }} -rhel8cis_rule_3_4_3_1_3: {{ rhel8cis_rule_3_4_3_1_3 }} - -rhel8cis_rule_3_4_3_2_1: {{ rhel8cis_rule_3_4_3_2_1 }} -rhel8cis_rule_3_4_3_2_2: {{ rhel8cis_rule_3_4_3_2_2 }} -rhel8cis_rule_3_4_3_2_3: {{ rhel8cis_rule_3_4_3_2_3 }} -rhel8cis_rule_3_4_3_2_4: {{ rhel8cis_rule_3_4_3_2_4 }} -rhel8cis_rule_3_4_3_2_5: {{ rhel8cis_rule_3_4_3_2_5 }} -rhel8cis_rule_3_4_3_2_6: {{ rhel8cis_rule_3_4_3_2_6 }} - -rhel8cis_rule_3_4_3_3_1: {{ rhel8cis_rule_3_4_3_3_1 }} -rhel8cis_rule_3_4_3_3_2: {{ rhel8cis_rule_3_4_3_3_2 }} -rhel8cis_rule_3_4_3_3_3: {{ rhel8cis_rule_3_4_3_3_3 }} -rhel8cis_rule_3_4_3_3_4: {{ rhel8cis_rule_3_4_3_3_4 }} -rhel8cis_rule_3_4_3_3_5: {{ rhel8cis_rule_3_4_3_3_5 }} -rhel8cis_rule_3_4_3_3_6: {{ rhel8cis_rule_3_4_3_3_6 }} - -# Section 4 rules + +## +## Section 4 rules +## +# cron rhel8cis_rule_4_1_1_1: {{ rhel8cis_rule_4_1_1_1 }} rhel8cis_rule_4_1_1_2: {{ rhel8cis_rule_4_1_1_2 }} rhel8cis_rule_4_1_1_3: {{ rhel8cis_rule_4_1_1_3 }} rhel8cis_rule_4_1_1_4: {{ rhel8cis_rule_4_1_1_4 }} +rhel8cis_rule_4_1_1_5: {{ rhel8cis_rule_4_1_1_5 }} +rhel8cis_rule_4_1_1_6: {{ rhel8cis_rule_4_1_1_6 }} +rhel8cis_rule_4_1_1_7: {{ rhel8cis_rule_4_1_1_7 }} +rhel8cis_rule_4_1_1_8: {{ rhel8cis_rule_4_1_1_8 }} +# at rhel8cis_rule_4_1_2_1: {{ rhel8cis_rule_4_1_2_1 }} -rhel8cis_rule_4_1_2_2: {{ rhel8cis_rule_4_1_2_2 }} -rhel8cis_rule_4_1_2_3: {{ rhel8cis_rule_4_1_2_3 }} - -rhel8cis_rule_4_1_3_1: {{ rhel8cis_rule_4_1_3_1 }} -rhel8cis_rule_4_1_3_2: {{ rhel8cis_rule_4_1_3_2 }} -rhel8cis_rule_4_1_3_3: {{ rhel8cis_rule_4_1_3_3 }} -rhel8cis_rule_4_1_3_4: {{ rhel8cis_rule_4_1_3_4 }} -rhel8cis_rule_4_1_3_5: {{ rhel8cis_rule_4_1_3_5 }} -rhel8cis_rule_4_1_3_6: {{ rhel8cis_rule_4_1_3_6 }} -rhel8cis_rule_4_1_3_7: {{ rhel8cis_rule_4_1_3_7 }} -rhel8cis_rule_4_1_3_8: {{ rhel8cis_rule_4_1_3_8 }} -rhel8cis_rule_4_1_3_9: {{ rhel8cis_rule_4_1_3_9 }} -rhel8cis_rule_4_1_3_10: {{ rhel8cis_rule_4_1_3_10 }} -rhel8cis_rule_4_1_3_11: {{ rhel8cis_rule_4_1_3_11 }} -rhel8cis_rule_4_1_3_12: {{ rhel8cis_rule_4_1_3_12 }} -rhel8cis_rule_4_1_3_13: {{ rhel8cis_rule_4_1_3_13 }} -rhel8cis_rule_4_1_3_14: {{ rhel8cis_rule_4_1_3_14 }} -rhel8cis_rule_4_1_3_15: {{ rhel8cis_rule_4_1_3_15 }} -rhel8cis_rule_4_1_3_16: {{ rhel8cis_rule_4_1_3_16 }} -rhel8cis_rule_4_1_3_17: {{ rhel8cis_rule_4_1_3_17 }} -rhel8cis_rule_4_1_3_18: {{ rhel8cis_rule_4_1_3_18 }} -rhel8cis_rule_4_1_3_19: {{ rhel8cis_rule_4_1_3_19 }} -rhel8cis_rule_4_1_3_20: {{ rhel8cis_rule_4_1_3_20 }} -rhel8cis_rule_4_1_3_21: {{ rhel8cis_rule_4_1_3_21 }} - -rhel8cis_rule_4_2_1_1: {{ rhel8cis_rule_4_2_1_1 }} -rhel8cis_rule_4_2_1_2: {{ rhel8cis_rule_4_2_1_2 }} -rhel8cis_rule_4_2_1_3: {{ rhel8cis_rule_4_2_1_3 }} -rhel8cis_rule_4_2_1_4: {{ rhel8cis_rule_4_2_1_4 }} -rhel8cis_rule_4_2_1_5: {{ rhel8cis_rule_4_2_1_5 }} -rhel8cis_rule_4_2_1_6: {{ rhel8cis_rule_4_2_1_6 }} -rhel8cis_rule_4_2_1_7: {{ rhel8cis_rule_4_2_1_7 }} - -rhel8cis_rule_4_2_2_1_1: {{ rhel8cis_rule_4_2_2_1_1 }} -rhel8cis_rule_4_2_2_1_2: {{ rhel8cis_rule_4_2_2_1_2 }} -rhel8cis_rule_4_2_2_1_3: {{ rhel8cis_rule_4_2_2_1_3 }} -rhel8cis_rule_4_2_2_1_4: {{ rhel8cis_rule_4_2_2_1_4 }} - -rhel8cis_rule_4_2_2_2: {{ rhel8cis_rule_4_2_2_2 }} -rhel8cis_rule_4_2_2_3: {{ rhel8cis_rule_4_2_2_3 }} -rhel8cis_rule_4_2_2_4: {{ rhel8cis_rule_4_2_2_4 }} -rhel8cis_rule_4_2_2_5: {{ rhel8cis_rule_4_2_2_5 }} -rhel8cis_rule_4_2_2_6: {{ rhel8cis_rule_4_2_2_6 }} -rhel8cis_rule_4_2_2_7: {{ rhel8cis_rule_4_2_2_7 }} +# sshd +rhel8cis_rule_4_2_1: {{ rhel8cis_rule_4_2_1 }} +rhel8cis_rule_4_2_2: {{ rhel8cis_rule_4_2_2 }} rhel8cis_rule_4_2_3: {{ rhel8cis_rule_4_2_3 }} - -rhel8cis_rule_4_3: {{ rhel8cis_rule_4_3 }} - -# Section 5 -rhel8cis_rule_5_1_1: {{ rhel8cis_rule_5_1_1 }} -rhel8cis_rule_5_1_2: {{ rhel8cis_rule_5_1_2 }} +rhel8cis_rule_4_2_4: {{ rhel8cis_rule_4_2_4 }} +rhel8cis_rule_4_2_5: {{ rhel8cis_rule_4_2_5 }} +rhel8cis_rule_4_2_6: {{ rhel8cis_rule_4_2_6 }} +rhel8cis_rule_4_2_7: {{ rhel8cis_rule_4_2_7 }} +rhel8cis_rule_4_2_8: {{ rhel8cis_rule_4_2_8 }} +rhel8cis_rule_4_2_9: {{ rhel8cis_rule_4_2_9 }} +rhel8cis_rule_4_2_10: {{ rhel8cis_rule_4_2_10 }} +rhel8cis_rule_4_2_12: {{ rhel8cis_rule_4_2_12 }} +rhel8cis_rule_4_2_11: {{ rhel8cis_rule_4_2_11 }} +rhel8cis_rule_4_2_13: {{ rhel8cis_rule_4_2_13 }} +rhel8cis_rule_4_2_14: {{ rhel8cis_rule_4_2_14 }} +rhel8cis_rule_4_2_15: {{ rhel8cis_rule_4_2_15 }} +rhel8cis_rule_4_2_16: {{ rhel8cis_rule_4_2_16 }} +rhel8cis_rule_4_2_17: {{ rhel8cis_rule_4_2_17 }} +rhel8cis_rule_4_2_18: {{ rhel8cis_rule_4_2_18 }} +rhel8cis_rule_4_2_19: {{ rhel8cis_rule_4_2_19 }} +rhel8cis_rule_4_2_20: {{ rhel8cis_rule_4_2_20 }} +rhel8cis_rule_4_2_21: {{ rhel8cis_rule_4_2_21 }} +rhel8cis_rule_4_2_22: {{ rhel8cis_rule_4_2_22 }} + +# sudo +rhel8cis_rule_4_3_1: {{ rhel8cis_rule_4_3_1 }} +rhel8cis_rule_4_3_2: {{ rhel8cis_rule_4_3_2 }} +rhel8cis_rule_4_3_3: {{ rhel8cis_rule_4_3_3 }} +rhel8cis_rule_4_3_4: {{ rhel8cis_rule_4_3_4 }} +rhel8cis_rule_4_3_5: {{ rhel8cis_rule_4_3_5 }} +rhel8cis_rule_4_3_6: {{ rhel8cis_rule_4_3_6 }} +rhel8cis_rule_4_3_7: {{ rhel8cis_rule_4_3_7 }} + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: {{ rhel8cis_rule_4_4_1_1 }} +rhel8cis_rule_4_4_1_2: {{ rhel8cis_rule_4_4_1_2 }} + +# authselect +rhel8cis_rule_4_4_2_1: {{ rhel8cis_rule_4_4_2_1 }} +rhel8cis_rule_4_4_2_2: {{ rhel8cis_rule_4_4_2_2 }} +rhel8cis_rule_4_4_2_3: {{ rhel8cis_rule_4_4_2_3 }} +rhel8cis_rule_4_4_2_4: {{ rhel8cis_rule_4_4_2_4 }} +rhel8cis_rule_4_4_2_5: {{ rhel8cis_rule_4_4_2_5 }} + +# pam faillock +rhel8cis_rule_4_4_3_1_1: {{ rhel8cis_rule_4_4_3_1_1 }} +rhel8cis_rule_4_4_3_1_2: {{ rhel8cis_rule_4_4_3_1_2 }} +rhel8cis_rule_4_4_3_1_3: {{ rhel8cis_rule_4_4_3_1_3 }} + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: {{ rhel8cis_rule_4_4_3_2_1 }} +rhel8cis_rule_4_4_3_2_2: {{ rhel8cis_rule_4_4_3_2_2 }} +rhel8cis_rule_4_4_3_2_3: {{ rhel8cis_rule_4_4_3_2_3 }} +rhel8cis_rule_4_4_3_2_4: {{ rhel8cis_rule_4_4_3_2_4 }} +rhel8cis_rule_4_4_3_2_5: {{ rhel8cis_rule_4_4_3_2_5 }} +rhel8cis_rule_4_4_3_2_6: {{ rhel8cis_rule_4_4_3_2_6 }} +rhel8cis_rule_4_4_3_2_7: {{ rhel8cis_rule_4_4_3_2_7 }} + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: {{ rhel8cis_rule_4_4_3_3_1 }} +rhel8cis_rule_4_4_3_3_2: {{ rhel8cis_rule_4_4_3_3_2 }} +rhel8cis_rule_4_4_3_3_3: {{ rhel8cis_rule_4_4_3_3_3 }} + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: {{ rhel8cis_rule_4_4_3_4_1 }} +rhel8cis_rule_4_4_3_4_2: {{ rhel8cis_rule_4_4_3_4_2 }} +rhel8cis_rule_4_4_3_4_3: {{ rhel8cis_rule_4_4_3_4_3 }} +rhel8cis_rule_4_4_3_4_4: {{ rhel8cis_rule_4_4_3_4_4 }} + +# Shadow user settings +rhel8cis_rule_4_5_1_1: {{ rhel8cis_rule_4_5_1_1 }} +rhel8cis_rule_4_5_1_2: {{ rhel8cis_rule_4_5_1_2 }} +rhel8cis_rule_4_5_1_3: {{ rhel8cis_rule_4_5_1_3 }} +rhel8cis_rule_4_5_1_4: {{ rhel8cis_rule_4_5_1_4 }} +rhel8cis_rule_4_5_1_5: {{ rhel8cis_rule_4_5_1_5 }} + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: {{ rhel8cis_rule_4_5_2_1 }} +rhel8cis_rule_4_5_2_2: {{ rhel8cis_rule_4_5_2_2 }} +rhel8cis_rule_4_5_2_3: {{ rhel8cis_rule_4_5_2_3 }} +rhel8cis_rule_4_5_2_4: {{ rhel8cis_rule_4_5_2_4 }} +rhel8cis_rule_4_5_2_5: {{ rhel8cis_rule_4_5_2_5 }} + +# User enviroment +rhel8cis_rule_4_5_3_1: {{ rhel8cis_rule_4_5_3_1 }} +rhel8cis_rule_4_5_3_2: {{ rhel8cis_rule_4_5_3_2 }} +rhel8cis_rule_4_5_3_3: {{ rhel8cis_rule_4_5_3_3 }} + +## +## Section 5 rules +## + +# Rsyslog +rhel8cis_rule_5_1_1_1: {{ rhel8cis_rule_5_1_1_1 }} +rhel8cis_rule_5_1_1_2: {{ rhel8cis_rule_5_1_1_2 }} +rhel8cis_rule_5_1_1_3: {{ rhel8cis_rule_5_1_1_3 }} +rhel8cis_rule_5_1_1_4: {{ rhel8cis_rule_5_1_1_4 }} +rhel8cis_rule_5_1_1_5: {{ rhel8cis_rule_5_1_1_5 }} +rhel8cis_rule_5_1_1_6: {{ rhel8cis_rule_5_1_1_6 }} +rhel8cis_rule_5_1_1_7: {{ rhel8cis_rule_5_1_1_7 }} + +# Journald +rhel8cis_rule_5_1_2_1_1: {{ rhel8cis_rule_5_1_2_1_1 }} +rhel8cis_rule_5_1_2_1_2: {{ rhel8cis_rule_5_1_2_1_2 }} +rhel8cis_rule_5_1_2_1_3: {{ rhel8cis_rule_5_1_2_1_3 }} +rhel8cis_rule_5_1_2_1_4: {{ rhel8cis_rule_5_1_2_1_4 }} +rhel8cis_rule_5_1_2_2: {{ rhel8cis_rule_5_1_2_2 }} +rhel8cis_rule_5_1_2_3: {{ rhel8cis_rule_5_1_2_3 }} +rhel8cis_rule_5_1_2_4: {{ rhel8cis_rule_5_1_2_4 }} +rhel8cis_rule_5_1_2_5: {{ rhel8cis_rule_5_1_2_5 }} +rhel8cis_rule_5_1_2_6: {{ rhel8cis_rule_5_1_2_6 }} rhel8cis_rule_5_1_3: {{ rhel8cis_rule_5_1_3 }} rhel8cis_rule_5_1_4: {{ rhel8cis_rule_5_1_4 }} -rhel8cis_rule_5_1_5: {{ rhel8cis_rule_5_1_5 }} -rhel8cis_rule_5_1_6: {{ rhel8cis_rule_5_1_6 }} -rhel8cis_rule_5_1_7: {{ rhel8cis_rule_5_1_7 }} -rhel8cis_rule_5_1_8: {{ rhel8cis_rule_5_1_8 }} -rhel8cis_rule_5_1_9: {{ rhel8cis_rule_5_1_9 }} - -rhel8cis_rule_5_2_1: {{ rhel8cis_rule_5_2_1 }} -rhel8cis_rule_5_2_2: {{ rhel8cis_rule_5_2_2 }} -rhel8cis_rule_5_2_3: {{ rhel8cis_rule_5_2_3 }} -rhel8cis_rule_5_2_4: {{ rhel8cis_rule_5_2_4 }} -rhel8cis_rule_5_2_5: {{ rhel8cis_rule_5_2_5 }} -rhel8cis_rule_5_2_6: {{ rhel8cis_rule_5_2_6 }} -rhel8cis_rule_5_2_7: {{ rhel8cis_rule_5_2_7 }} -rhel8cis_rule_5_2_8: {{ rhel8cis_rule_5_2_8 }} -rhel8cis_rule_5_2_9: {{ rhel8cis_rule_5_2_9 }} -rhel8cis_rule_5_2_10: {{ rhel8cis_rule_5_2_10 }} -rhel8cis_rule_5_2_11: {{ rhel8cis_rule_5_2_11 }} -rhel8cis_rule_5_2_12: {{ rhel8cis_rule_5_2_12 }} -rhel8cis_rule_5_2_13: {{ rhel8cis_rule_5_2_13 }} -rhel8cis_rule_5_2_14: {{ rhel8cis_rule_5_2_14 }} -rhel8cis_rule_5_2_15: {{ rhel8cis_rule_5_2_15 }} -rhel8cis_rule_5_2_16: {{ rhel8cis_rule_5_2_16 }} -rhel8cis_rule_5_2_17: {{ rhel8cis_rule_5_2_17 }} -rhel8cis_rule_5_2_18: {{ rhel8cis_rule_5_2_18 }} -rhel8cis_rule_5_2_19: {{ rhel8cis_rule_5_2_19 }} -rhel8cis_rule_5_2_20: {{ rhel8cis_rule_5_2_20 }} + +# Auditd +rhel8cis_rule_5_2_1_1: {{ rhel8cis_rule_5_2_1_1 }} +rhel8cis_rule_5_2_1_2: {{ rhel8cis_rule_5_2_1_2 }} +rhel8cis_rule_5_2_1_3: {{ rhel8cis_rule_5_2_1_3 }} +rhel8cis_rule_5_2_1_4: {{ rhel8cis_rule_5_2_1_4 }} +rhel8cis_rule_5_2_2_1: {{ rhel8cis_rule_5_2_2_1 }} +rhel8cis_rule_5_2_2_2: {{ rhel8cis_rule_5_2_2_2 }} +rhel8cis_rule_5_2_2_3: {{ rhel8cis_rule_5_2_2_3 }} +rhel8cis_rule_5_2_2_4: {{ rhel8cis_rule_5_2_2_4 }} + +# auditd rules +rhel8cis_rule_5_2_3_1: {{ rhel8cis_rule_5_2_3_1 }} +rhel8cis_rule_5_2_3_2: {{ rhel8cis_rule_5_2_3_2 }} +rhel8cis_rule_5_2_3_3: {{ rhel8cis_rule_5_2_3_3 }} +rhel8cis_rule_5_2_3_4: {{ rhel8cis_rule_5_2_3_4 }} +rhel8cis_rule_5_2_3_5: {{ rhel8cis_rule_5_2_3_5 }} +rhel8cis_rule_5_2_3_6: {{ rhel8cis_rule_5_2_3_6 }} +rhel8cis_rule_5_2_3_7: {{ rhel8cis_rule_5_2_3_7 }} +rhel8cis_rule_5_2_3_8: {{ rhel8cis_rule_5_2_3_8 }} +rhel8cis_rule_5_2_3_9: {{ rhel8cis_rule_5_2_3_9 }} +rhel8cis_rule_5_2_3_10: {{ rhel8cis_rule_5_2_3_10 }} +rhel8cis_rule_5_2_3_11: {{ rhel8cis_rule_5_2_3_11 }} +rhel8cis_rule_5_2_3_12: {{ rhel8cis_rule_5_2_3_12 }} +rhel8cis_rule_5_2_3_13: {{ rhel8cis_rule_5_2_3_13 }} +rhel8cis_rule_5_2_3_14: {{ rhel8cis_rule_5_2_3_14 }} +rhel8cis_rule_5_2_3_15: {{ rhel8cis_rule_5_2_3_15 }} +rhel8cis_rule_5_2_3_16: {{ rhel8cis_rule_5_2_3_16 }} +rhel8cis_rule_5_2_3_17: {{ rhel8cis_rule_5_2_3_17 }} +rhel8cis_rule_5_2_3_18: {{ rhel8cis_rule_5_2_3_18 }} +rhel8cis_rule_5_2_3_19: {{ rhel8cis_rule_5_2_3_19 }} +rhel8cis_rule_5_2_3_20: {{ rhel8cis_rule_5_2_3_20 }} +rhel8cis_rule_5_2_3_21: {{ rhel8cis_rule_5_2_3_21 }} + +# auditd log perms +rhel8cis_rule_5_2_4_1: {{ rhel8cis_rule_5_2_4_1 }} +rhel8cis_rule_5_2_4_2: {{ rhel8cis_rule_5_2_4_2 }} +rhel8cis_rule_5_2_4_3: {{ rhel8cis_rule_5_2_4_3 }} +rhel8cis_rule_5_2_4_4: {{ rhel8cis_rule_5_2_4_4 }} +rhel8cis_rule_5_2_4_5: {{ rhel8cis_rule_5_2_4_5 }} +rhel8cis_rule_5_2_4_6: {{ rhel8cis_rule_5_2_4_6 }} +rhel8cis_rule_5_2_4_7: {{ rhel8cis_rule_5_2_4_7 }} +rhel8cis_rule_5_2_4_8: {{ rhel8cis_rule_5_2_4_8 }} +rhel8cis_rule_5_2_4_9: {{ rhel8cis_rule_5_2_4_9 }} +rhel8cis_rule_5_2_4_10: {{ rhel8cis_rule_5_2_4_10 }} + +# AIDE rhel8cis_rule_5_3_1: {{ rhel8cis_rule_5_3_1 }} rhel8cis_rule_5_3_2: {{ rhel8cis_rule_5_3_2 }} rhel8cis_rule_5_3_3: {{ rhel8cis_rule_5_3_3 }} -rhel8cis_rule_5_3_4: {{ rhel8cis_rule_5_3_4 }} -rhel8cis_rule_5_3_5: {{ rhel8cis_rule_5_3_5 }} -rhel8cis_rule_5_3_6: {{ rhel8cis_rule_5_3_6 }} -rhel8cis_rule_5_3_7: {{ rhel8cis_rule_5_3_7 }} - -rhel8cis_rule_5_4_1: {{ rhel8cis_rule_5_4_1 }} -rhel8cis_rule_5_4_2: {{ rhel8cis_rule_5_4_2 }} - -rhel8cis_rule_5_5_1: {{ rhel8cis_rule_5_5_1 }} -rhel8cis_rule_5_5_2: {{ rhel8cis_rule_5_5_2 }} -rhel8cis_rule_5_5_3: {{ rhel8cis_rule_5_5_3 }} -rhel8cis_rule_5_5_4: {{ rhel8cis_rule_5_5_4 }} - -rhel8cis_rule_5_6_1_1: {{ rhel8cis_rule_5_6_1_1 }} -rhel8cis_rule_5_6_1_2: {{ rhel8cis_rule_5_6_1_2 }} -rhel8cis_rule_5_6_1_3: {{ rhel8cis_rule_5_6_1_3 }} -rhel8cis_rule_5_6_1_4: {{ rhel8cis_rule_5_6_1_4 }} -rhel8cis_rule_5_6_1_5: {{ rhel8cis_rule_5_6_1_5 }} - -rhel8cis_rule_5_6_2: {{ rhel8cis_rule_5_6_2 }} -rhel8cis_rule_5_6_3: {{ rhel8cis_rule_5_6_3 }} -rhel8cis_rule_5_6_4: {{ rhel8cis_rule_5_6_4 }} -rhel8cis_rule_5_6_5: {{ rhel8cis_rule_5_6_5 }} - -# Section 6 + +## +## Section 6 rules +## + +# System file perms rhel8cis_rule_6_1_1: {{ rhel8cis_rule_6_1_1 }} rhel8cis_rule_6_1_2: {{ rhel8cis_rule_6_1_2 }} rhel8cis_rule_6_1_3: {{ rhel8cis_rule_6_1_3 }} @@ -333,8 +406,8 @@ rhel8cis_rule_6_1_11: {{ rhel8cis_rule_6_1_11 }} rhel8cis_rule_6_1_12: {{ rhel8cis_rule_6_1_12 }} rhel8cis_rule_6_1_13: {{ rhel8cis_rule_6_1_13 }} rhel8cis_rule_6_1_14: {{ rhel8cis_rule_6_1_14 }} -rhel8cis_rule_6_1_15: {{ rhel8cis_rule_6_1_15 }} +# local and usergroup rhel8cis_rule_6_2_1: {{ rhel8cis_rule_6_2_1 }} rhel8cis_rule_6_2_2: {{ rhel8cis_rule_6_2_2 }} rhel8cis_rule_6_2_3: {{ rhel8cis_rule_6_2_3 }} @@ -346,159 +419,329 @@ rhel8cis_rule_6_2_8: {{ rhel8cis_rule_6_2_8 }} rhel8cis_rule_6_2_9: {{ rhel8cis_rule_6_2_9 }} rhel8cis_rule_6_2_10: {{ rhel8cis_rule_6_2_10 }} rhel8cis_rule_6_2_11: {{ rhel8cis_rule_6_2_11 }} -rhel8cis_rule_6_2_12: {{ rhel8cis_rule_6_2_12 }} -rhel8cis_rule_6_2_13: {{ rhel8cis_rule_6_2_13 }} -rhel8cis_rule_6_2_14: {{ rhel8cis_rule_6_2_14 }} -rhel8cis_rule_6_2_15: {{ rhel8cis_rule_6_2_15 }} -rhel8cis_rule_6_2_16: {{ rhel8cis_rule_6_2_16 }} -# Service configuration booleans set true to keep service +## +## Section 1 vars +## +# 1.1.2.2 +# 1.1.2.3 +# 1.1.2.4 +# These settings go into the /etc/fstab file for the /tmp mount settings +# The value must contain nosuid,nodev,noexec to conform to CIS standards +# rhel8cis_tmp_tmpfs_settings: "defaults,rw,nosuid,nodev,noexec,relatime 0 0" +# If set true uses the tmp.mount service else using fstab configuration +rhel8cis_tmp_svc: {{ rhel8cis_tmp_svc }} + +# 1.2 patch system +rhel8cis_apply_installed_kernel_limit: {{ rhel8cis_apply_installed_kernel_limit }} +rhel8cis_installed_kernel_limit: {{ rhel8cis_installed_kernel_limit }} + +# 1.3 Bootloader password +rhel8cis_bootloader_password_hash: {{ rhel8cis_bootloader_password_hash }} +rhel8cis_bootloader_password: {{ rhel8cis_bootloader_password }} +rhel8cis_set_boot_pass: {{ rhel8cis_set_boot_pass }} +rhel8cis_boot_path: {{ rhel8cis_boot_path }} + +# 1.5 SELinux policy +rhel8cis_selinux_pol: {{ rhel8cis_selinux_policy }} + +# 1.6 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS) +rhel8cis_crypto_policy: {{ rhel8cis_crypto_policy }} +# Added module to be allowed as default setting (Allowed options in vars/main.yml) +rhel8cis_crypto_policy_module: {{ rhel8cis_crypto_policy_module }} + +# 1.7 +# Warning Banner Content (issue, issue.net, motd) +rhel8cis_warning_banner: {{ rhel8cis_warning_banner }} +# End Banner + +# 1.8 Gnome Desktop +# Whether or not to run tasks related to auditing/patching the desktop environment +rhel8cis_gui: {{ rhel8cis_gui }} +rhel8cis_dconf_db_name: {{ rhel8cis_dconf_db_name }} +rhel8cis_screensaver_idle_delay: {{ rhel8cis_screensaver_idle_delay }} # Set max value for idle-delay in seconds (between 1 and 900) +rhel8cis_screensaver_lock_delay: {{ rhel8cis_screensaver_lock_delay }} # Set max value for lock-delay in seconds (between 0 and 5) +## +## Section 2 vars +## +# 2.1.1 Time Synchronization - Either chrony or ntp +rhel8cis_time_synchronization: {{ rhel8cis_time_synchronization }} + +# Time Synchronization servers - used in template file chrony.conf.j2 +rhel8cis_time_synchronization_servers: +{% for server in rhel8cis_time_synchronization_servers %} + - {{ server }} +{% endfor %} + +rhel8cis_chrony_server_options: "{{ rhel8cis_chrony_server_options }}" +rhel8cis_ntp_server_options: "{{ rhel8cis_ntp_server_options }}" + +# Service configuration +# Options are +# true to leave installed if exists not changes take place +# false - this removes the package +# mask - if a dependancy for product so cannot be removed +# Server Services +rhel8cis_autofs_services: {{ rhel8cis_autofs_services }} +rhel8cis_autofs_mask: {{ rhel8cis_autofs_mask }} rhel8cis_avahi_server: {{ rhel8cis_avahi_server }} -rhel8cis_cups_server: {{ rhel8cis_cups_server }} +rhel8cis_avahi_mask: {{ rhel8cis_avahi_mask }} rhel8cis_dhcp_server: {{ rhel8cis_dhcp_server }} +rhel8cis_dhcp_mask: {{ rhel8cis_dhcp_mask }} rhel8cis_dns_server: {{ rhel8cis_dns_server }} -rhel8cis_dovecot_cyrus_server: {{ rhel8cis_dovecot_cyrus_server }} +rhel8cis_dns_mask: {{ rhel8cis_dns_mask }} +rhel8cis_dnsmasq_server: {{ rhel8cis_dnsmasq_server }} +rhel8cis_dnsmasq_mask: {{ rhel8cis_dnsmasq_mask }} +rhel8cis_samba_server: {{ rhel8cis_samba_server }} +rhel8cis_samba_mask: {{ rhel8cis_samba_mask }} rhel8cis_ftp_server: {{ rhel8cis_ftp_server }} -rhel8cis_httpd_server: {{ rhel8cis_httpd_server }} -rhel8cis_is_mail_server: {{ rhel8cis_is_mail_server }} -rhel8cis_net_snmp_server: {{ rhel8cis_net_snmp_server }} +rhel8cis_ftp_mask: {{ rhel8cis_ftp_mask }} +rhel8cis_message_server: {{ rhel8cis_message_server }} # This is for messaging dovecot and cyrus-imap +rhel8cis_message_mask: {{ rhel8cis_message_mask }} rhel8cis_nfs_server: {{ rhel8cis_nfs_server }} -rhel8cis_nginx_server: {{ rhel8cis_nginx_server }} -rhel8cis_nis_server: {{ rhel8cis_nis_server }} +rhel8cis_nfs_mask: {{ rhel8cis_nfs_mask }} +rhel8cis_nis_server: {{ rhel8cis_nis_server }} # set to mask if nis client required +rhel8cis_nis_mask: {{ rhel8cis_nis_mask }} +rhel8cis_print_server: {{ rhel8cis_print_server }} # replaces cups +rhel8cis_print_mask: {{ rhel8cis_print_mask }} rhel8cis_rpc_server: {{ rhel8cis_rpc_server }} +rhel8cis_rpc_mask: {{ rhel8cis_rpc_mask }} rhel8cis_rsync_server: {{ rhel8cis_rsync_server }} -rhel8cis_samba_server: {{ rhel8cis_samba_server }} -rhel8cis_squid_server: {{ rhel8cis_squid_server }} +rhel8cis_rsync_mask: {{ rhel8cis_rsync_mask }} +rhel8cis_net_snmp_server: {{ rhel8cis_net_snmp_server }} +rhel8cis_net_snmp_mask: {{ rhel8cis_net_snmp_mask }} rhel8cis_telnet_server: {{ rhel8cis_telnet_server }} +rhel8cis_telnet_mask: {{ rhel8cis_telnet_mask }} rhel8cis_tftp_server: {{ rhel8cis_tftp_server }} -rhel8cis_vsftpd_server: {{ rhel8cis_vsftpd_server }} - -rhel8cis_allow_autofs: {{ rhel8cis_allow_autofs }} +rhel8cis_tftp_mask: {{ rhel8cis_tftp_mask }} +rhel8cis_squid_server: {{ rhel8cis_squid_server }} +rhel8cis_squid_mask: {{ rhel8cis_squid_mask }} +rhel8cis_httpd_server: {{ rhel8cis_httpd_server }} +rhel8cis_httpd_mask: {{ rhel8cis_httpd_mask }} +rhel8cis_nginx_server: {{ rhel8cis_nginx_server }} +rhel8cis_nginx_mask: {{ rhel8cis_nginx_mask }} +rhel8cis_xinetd_server: {{ rhel8cis_xinetd_server }} +rhel8cis_xinetd_mask: {{ rhel8cis_xinetd_mask }} +rhel8cis_xwindow_server: {{ rhel8cis_xwindow_server }} # will remove mask not an option +rhel8cis_is_mail_server: {{ rhel8cis_is_mail_server }} -# client services +# Client Services +rhel8cis_ftp_client: {{ rhel8cis_ftp_client }} rhel8cis_openldap_clients_required: {{ rhel8cis_openldap_clients_required }} +rhel8cis_ypbind_required: {{ rhel8cis_ypbind_required }} # Same package as NIS server rhel8cis_telnet_required: {{ rhel8cis_telnet_required }} -rhel8cis_talk_required: {{ rhel8cis_talk_required }} -rhel8cis_rsh_required: {{ rhel8cis_rsh_required }} -rhel8cis_ypbind_required: {{ rhel8cis_ypbind_required }} -rhel8cis_tftp_required: {{ rhel8cis_tftp_client }} +rhel8cis_tftp_client: {{ rhel8cis_tftp_client }} -# AIDE -rhel8cis_config_aide: {{ rhel8cis_config_aide }} +## +## Section 3 vars +## -# aide setup via - cron, timer -rhel8_aide_scan: cron +rhel8cis_bluetooth_service: {{ rhel8cis_bluetooth_service }} +rhel8cis_bluetooth_mask: {{ rhel8cis_bluetooth_mask }} -# AIDE cron settings -rhel8cis_aide_cron: - cron_user: {{ rhel8cis_aide_cron.cron_user }} - cron_file: '{{ rhel8cis_aide_cron.cron_file }}' - aide_job: ' {{ rhel8cis_aide_cron.aide_job }}' - aide_minute: '{{ rhel8cis_aide_cron.aide_minute }}' - aide_hour: '{{ rhel8cis_aide_cron.aide_hour }}' - aide_day: '{{ rhel8cis_aide_cron.aide_day }}' - aide_month: '{{ rhel8cis_aide_cron.aide_month }}' - aide_weekday: '{{ rhel8cis_aide_cron.aide_weekday }}' - -# 1.5.1 Bootloader password -rhel8cis_bootloader_password: {{ rhel8cis_bootloader_password_hash }} -rhel8cis_set_boot_pass: {{ rhel8cis_set_boot_pass }} +# System network parameters (host only OR host and router) +rhel8cis_is_router: {{ rhel8cis_is_router }} -# 1.10 crypto -rhel8cis_crypto_policy: {{ rhel8cis_crypto_policy }} +# IPv6 required +rhel8cis_ipv6_required: {{ rhel8cis_ipv6_required }} -# Warning Banner Content (issue, issue.net, motd) -rhel8cis_warning_banner: {{ rhel8cis_warning_banner }} -# End Banner +rhel8cis_ipv6_sysctl_force: {{ rhel8cis_ipv6_sysctl_force }} + +## Optional - Understand the impact of making the following two control to true +# By default, we do not disable IPv6 on localhost, as it's important for multiple +# components. If you want to disable it anyway, change the following +# value to true refer https://access.redhat.com/solutions/8709 +# this changes sysctl and /etc/hosts +# requires reboot +rhel8cis_ipv6_disable_localhost: {{ rhel8cis_ipv6_disable_localhost }} +# disable ipv6 for sshd +rhel8cis_ipv6_sshd_disable: {{ rhel8cis_ipv6_sshd_disable }} +# disable chrony on ipv6 +rhel8cis_ipv6_chrony_disable: {{ rhel8cis_ipv6_chrony_disable }} # Set to 'true' if X Windows is needed in your environment rhel8cis_xwindows_required: {{ rhel8cis_xwindows_required }} -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel8cis_gui: {{ rhel8cis_gui }} +## Section3 vars -# xinetd required -rhel8cis_xinetd_required: {{ rhel8cis_xinetd_required }} +# default location for the sysctl overrides. +rhel8cis_sysctl_file: {{ rhel8cis_sysctl_file }} -# IPv6 required -rhel8cis_ipv6_required: {{ rhel8cis_ipv6_required }} +# Firewall Service - either firewalld or nftables +rhel8cis_firewall: {{ rhel8cis_firewall }} -# System network parameters (host only OR host and router) -rhel8cis_is_router: {{ rhel8cis_is_router }} +rhel8cis_default_zone: {{ rhel8cis_default_zone }} + +rhel8cis_nft_tables_autonewtable: {{ rhel8cis_nft_tables_autonewtable }} +rhel8cis_nft_tables_tablename: {{ rhel8cis_nft_tables_tablename }} + +# 3.4.2.6 Set nftables new chain create +rhel8cis_nft_tables_autochaincreate: {{ rhel8cis_nft_tables_autochaincreate }} + +####### +## Section4 vars +###### +## If using the allow/deny user groups options +rhel8cis_sshd_limited: {{ rhel8cis_sshd_limited }} +rhel8cis_sshd: + clientalivecountmax: {{ rhel8cis_sshd.clientalivecountmax }} + clientaliveinterval: {{ rhel8cis_sshd.clientaliveinterval }} + logingracetime: {{ rhel8cis_sshd.logingracetime }} + loglevel: {{ rhel8cis_sshd.loglevel }} + macs: '{{ rhel8cis_sshd.macs }}' + maxauthtries: {{ rhel8cis_sshd.maxauthtries }} + maxsessions: {{ rhel8cis_sshd.maxsessions }} + maxstartups: '{{ rhel8cis_sshd.maxstartups }}' + ciphers: '{{ rhel8cis_sshd.ciphers }}' + kex: '{{ rhel8cis_sshd.kex }}' +{% if rhel8cis_sshd_limited %} + # WARNING: make sure you understand the precedence when working with these values!! + {% if rhel8cis_sshd.allowusers is defined %} + # allowusers: '{{ rhel8cis_sshd.allowusers }}' + {% endif %} + {% if rhel8cis_sshd.allowgroups is defined %} + # allowgroups: '{{ rhel8cis_sshd.allowgroups }}' + {% endif %} + {% if rhel8cis_sshd.denyusers is defined %} + # denyusers: '{{ rhel8cis_sshd.denyusers }}' + {% endif %} + {% if rhel8cis_sshd.denygroups is defined %} + # denygroups: '{{ rhel8cis_sshd.denygroups }}' + {% endif %} +{% endif %} -# Time Synchronization -rhel8cis_time_synchronization: {{ rhel8cis_time_synchronization }} +# 4.3. sudo +rhel8cis_sudolog_location: "{{ rhel8cis_sudolog_location }}" +rhel8cis_sudo_timestamp_timeout: {{ rhel8cis_sudo_timestamp_timeout }} -rhel8cis_sudolog_location: {{ rhel8cis_sudolog_location }} +## PAM +# 4.4.2.x +rhel8cis_authselect_pkg_update: {{ rhel8cis_authselect_pkg_update }} # NOTE the risks if system is using SSSD or using ipa-client-install +rhel8cis_allow_authselect_updates: {{ rhel8cis_allow_authselect_updates }} +rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} +rhel8cis_authselect_custom_profile_select: {{ rhel8cis_authselect_custom_profile_select }} +rhel8cis_authselect: + custom_profile_name: '{{ rhel8cis_authselect.custom_profile_name }}' + default_file_to_copy: "{{ rhel8cis_authselect.default_file_to_copy }}" + options: {{ rhel8cis_authselect }} + +rhel8cis_pam_faillock: + attempts: {{ rhel8cis_pam_faillock.attempts }} + deny: {{ rhel8cis_pam_faillock.deny }} + interval: {{ rhel8cis_pam_faillock.interval }} + unlock_time: {{ rhel8cis_pam_faillock.unlock_time }} + root_unlock_time: {{ rhel8cis_pam_faillock.root_unlock_time }} + # Choose options below for root options + root_option: {{ rhel8cis_pam_faillock.root_option }} + +rhel8cis_pam_pwquality: + difok: {{ rhel8cis_pam_pwquality.difok }} + maxrepeat: {{ rhel8cis_pam_pwquality.maxrepeat }} + maxseq: {{ rhel8cis_pam_pwquality.maxseq }} + minlen: {{ rhel8cis_pam_pwquality.minlen }} + minclass: {{ rhel8cis_pam_pwquality.minclass }} + +rhel8cis_pam_pwhistory: + remember: {{ rhel8cis_pam_pwhistory }} + +rhel8cis_pam_pwhash: {{ rhel8cis_pam_pwhash }} -rhel8cis_firewall: {{ rhel8cis_firewall }} -#rhel8cis_firewall: iptables -rhel8cis_default_firewall_zone: {{ rhel8cis_default_zone }} -rhel8cis_firewall_interface: -- enp0s3 -- enp0s8 +rhel8cis_pass: + inactive: {{ rhel8cis_pass.inactive }} + max_days: {{ rhel8cis_pass.max_days }} + min_days: {{ rhel8cis_pass.min_days }} + warn_age: {{ rhel8cis_pass.warn_age }} -rhel8cis_firewall_services: {% for svc in rhel8cis_firewall_services %}{{ svc }} {% endfor %} +rhel8cis_root_umask: {{ rhel8cis_root_umask }} # 0027 or more restrictive -### Section 4 -## auditd settings -rhel8cis_auditd: - space_left_action: {{ rhel8cis_auditd.space_left_action}} - action_mail_acct: {{ rhel8cis_auditd.action_mail_acct }} - admin_space_left_action: {{ rhel8cis_auditd.admin_space_left_action }} - max_log_file_action: {{ rhel8cis_auditd.max_log_file_action }} - auditd_backlog_limit: {{ rhel8cis_audit_back_log_limit }} +rhel8cis_shell_session_timeout: + file: {{ rhel8cis_shell_session_timeout.file }} + timeout: {{ rhel8cis_shell_session_timeout.timeout }} -## syslog -rhel8cis_syslog: {{ rhel8cis_syslog }} +# 5.3.7 +rhel8cis_sugroup: {{ rhel8cis_sugroup }} -### Section 5 -rhel8cis_sshd_limited: false -#Note the following to understand precedence and layout -rhel8cis_sshd_access: - AllowUser: - AllowGroup: - DenyUser: - DenyGroup: +# wheel users list +rhel8cis_sugroup_users: "{{ rhel8cis_sugroup_users }}" -rhel8cis_ssh_aliveinterval: "300" -rhel8cis_ssh_countmax: "3" +rhel8cis_inactivelock: + lock_days: {{ rhel8cis_inactivelock.lock_days }} -## PAM -rhel8cis_pam_password: - minlen: {{ rhel8cis_pam_password.minlen }} - minclass: {{ rhel8cis_pam_password.minclass }} -rhel8cis_pam_passwd_retry: "3" -# faillock or tally2 -rhel8cis_accountlock: faillock - -## note this is to skip tests -skip_rhel8cis_pam_passwd_auth: true -skip_rhel8cis_pam_system_auth: true - -# choose one of below -rhel8cis_pwhistory_so: "14" -rhel8cis_unix_so: false -rhel8cis_passwd_remember: "5" - -# logins.def password settings -rhel8cis_pass: - max_days: {{ rhel8cis_pass.max_days }} - min_days: {{ rhel8cis_pass.min_days }} - warn_age: {{ rhel8cis_pass.warn_age }} +# 5.6.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords +rhel8cis_futurepwchgdate_autofix: {{ rhel8cis_futurepwchgdate_autofix }} -# 5.3.1/5.3.2 Custon authselect profile settings. Settings in place now will fail, they are place holders from the control example -rhel8cis_authselect: - custom_profile_name: {{ rhel8cis_authselect['custom_profile_name'] }} - default_file_to_copy: {{ rhel8cis_authselect.default_file_to_copy }} - options: {{ rhel8cis_authselect.options }} +rhel8uid_uid_start: {{ rhel8uid_uid_start }} +rhel8uid_uid_stop: {{ rhel8uid_uid_stop }} -# 5.3.1 Enable automation to creat custom profile settings, using the setings above -rhel8cis_authselect_custom_profile_create: {{ rhel8cis_authselect_custom_profile_create }} +## Section5 vars -# 5.3.2 Enable automation to select custom profile options, using the settings above -rhel8cis_authselect_custom_profile_select: {{ rhel8cis_authselect_custom_profile_select }} +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +rhel8cis_syslog: {{ rhel8cis_syslog }} +rhel8cis_rsyslog_ansiblemanaged: {{ rhel8cis_rsyslog_ansiblemanaged }} +# Set if system is the log server +rhel8cis_system_is_log_server: {{ rhel8cis_system_is_log_server }} + +#### remote and destination log server name +rhel8cis_remote_log_server: {{ rhel8cis_remote_log_server }} +rhel8cis_remote_log_host: {{ rhel8cis_remote_log_host }} +rhel8cis_remote_log_port: {{ rhel8cis_remote_log_port }} +rhel8cis_remote_log_protocol: {{ rhel8cis_remote_log_protocol }} +rhel8cis_remote_log_retrycount: {{ rhel8cis_remote_log_retrycount }} +rhel8cis_remote_log_queuesize: {{ rhel8cis_remote_log_queuesize }} -# 5.7 -rhel8cis_sugroup: {{ rhel8cis_sugroup| default('wheel') }} -rhel8cis_sugroup_users: {{ rhel8cis_sugroup_users }} +update_audit_template: {{ update_audit_template }} + +rhel8cis_auditd: + disk_error_action: {{ rhel8cis_auditd.disk_error_action }} + disk_full_action: {{ rhel8cis_auditd.disk_full_action }} + action_mail_acct: {{ rhel8cis_auditd.action_mail_acct }} + space_left_action: {{ rhel8cis_auditd.space_left_action }} + admin_space_left_action: {{ rhel8cis_auditd.admin_space_left_action }} + max_log_file_action: {{ rhel8cis_auditd.max_log_file_action }} + +rhel8cis_logrotate: {{ rhel8cis_logrotate }} + +## Journald +# rhel8cis_journal_upload_url is the ip address to upload the journal entries to +rhel8cis_journal_upload_url: {{ rhel8cis_journal_upload_url }} +# The paths below have the default paths/files, but allow user to create custom paths/filenames +rhel8cis_journal_upload_serverkeyfile: {{ rhel8cis_journal_upload_serverkeyfile }} +rhel8cis_journal_servercertificatefile: {{ rhel8cis_journal_servercertificatefile }} +rhel8cis_journal_trustedcertificatefile: {{ rhel8cis_journal_trustedcertificatefile }} + +# The variables below related to journald, please set these to your site specific values +# rhel8cis_journald_systemmaxuse is the max amount of disk space the logs will use +rhel8cis_journald_systemmaxuse: {{ rhel8cis_journald_systemmaxuse }} +# rhel8cis_journald_systemkeepfree is the amount of disk space to keep free +rhel8cis_journald_systemkeepfree: {{ rhel8cis_journald_systemkeepfree }} +rhel8cis_journald_runtimemaxuse: {{ rhel8cis_journald_runtimemaxuse }} +rhel8cis_journald_runtimekeepfree: {{ rhel8cis_journald_runtimekeepfree }} +# rhel8cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +rhel8cis_journald_maxfilesec: {{ rhel8cis_journald_maxfilesec }} + +# logrotate configuration +# change to true if you wish to change logrotate.d conf files +allow_logrotate_conf_umask_updates: {{ allow_logrotate_conf_umask_updates }} + +# The audit_back_log_limit value should never be below 8192 +rhel8cis_audit_back_log_limit: {{ rhel8cis_audit_back_log_limit }} + +# The max_log_file parameter should be based on your sites policy +rhel8cis_max_log_file_size: {{ rhel8cis_max_log_file_size }} + +## AIDE +rhel8cis_aide_scan: {{ rhel8cis_aide_scan }} +rhel8cis_config_aide: {{ rhel8cis_config_aide }} +# AIDE cron settings +rhel8cis_aide_cron: + cron_user: '{{ rhel8cis_aide_cron.cron_user }}' + cron_file: '{{ rhel8cis_aide_cron.cron_file }}' + aide_job: '{{ rhel8cis_aide_cron.aide_job }}' + aide_minute: '{{ rhel8cis_aide_cron.aide_minute }}' + aide_hour: '{{ rhel8cis_aide_cron.aide_hour }}' + aide_day: '{{ rhel8cis_aide_cron.aide_day }}' + aide_month: '{{ rhel8cis_aide_cron.aide_month }}' + aide_weekday: '{{ rhel8cis_aide_cron.aide_weekday }}' + +## Section6 vars diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 32f61f05..9dd63740 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,95 +1,95 @@ ## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # This template will set all of the auditd configurations via a handler in the role in one task instead of individually -{% if rhel8cis_rule_4_1_3_1 %} +{% if rhel8cis_rule_5_2_3_1 %} -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d/ -p wa -k scope {% endif %} -{% if rhel8cis_rule_4_1_3_2 %} +{% if rhel8cis_rule_5_2_3_2 %} -a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S execve -k user_emulation -a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S execve -k user_emulation {% endif %} -{% if rhel8cis_rule_4_1_3_3 %} +{% if rhel8cis_rule_5_2_3_3 %} -w {{ rhel8cis_sudolog_location }} -p wa -k sudo_log_file {% endif %} -{% if rhel8cis_rule_4_1_3_4 %} +{% if rhel8cis_rule_5_2_3_4 %} -a always,exit -F arch=b64 -S adjtimex,settimeofday,clock_settime -k time-change -a always,exit -F arch=b32 -S adjtimex,settimeofday,clock_settime -k time-change -w /etc/localtime -p wa -k time-change {% endif %} -{% if rhel8cis_rule_4_1_3_5 %} +{% if rhel8cis_rule_5_2_3_5 %} -a always,exit -F arch=b64 -S sethostname,setdomainname -F key=system-locale -a always,exit -F arch=b32 -S sethostname,setdomainname -F key=system-locale -w /etc/issue -p wa -k system-locale -w /etc/issue.net -p wa -k system-locale -w /etc/hosts -p wa -k system-locale -w /etc/sysconfig/network -p wa -k system-locale --w /etc/sysconfig/network-scripts -p wa -k system-locale +-w /etc/sysconfig/network-scripts/ -p wa -k system-locale {% endif %} -{% if rhel8cis_rule_4_1_3_6 %} -{% for proc in priv_procs.stdout_lines -%} --a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k privileged +{% if rhel8cis_rule_5_2_3_6 %} +{% for proc in discovered_privilege_procs.stdout_lines -%} +-a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k privileged {% endfor %} {% endif %} -{% if rhel8cis_rule_4_1_3_7 %} --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=access +{% if rhel8cis_rule_5_2_3_7 %} +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=access {% endif %} -{% if rhel8cis_rule_4_1_3_8 %} +{% if rhel8cis_rule_5_2_3_8 %} -w /etc/group -p wa -k identity -w /etc/passwd -p wa -k identity -w /etc/gshadow -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/security/opasswd -p wa -k identity {% endif %} -{% if rhel8cis_rule_4_1_3_9 %} --a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=perm_mod +{% if rhel8cis_rule_5_2_3_9 %} +-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=perm_mod {% endif %} -{% if rhel8cis_rule_4_1_3_10 %} --a always,exit -F arch=b32 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts --a always,exit -F arch=b64 -S mount -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k mounts +{% if rhel8cis_rule_5_2_3_10 %} +-a always,exit -F arch=b32 -S mount -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k mounts +-a always,exit -F arch=b64 -S mount -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k mounts {% endif %} -{% if rhel8cis_rule_4_1_3_11 %} +{% if rhel8cis_rule_5_2_3_11 %} -w /var/run/utmp -p wa -k session -w /var/log/wtmp -p wa -k session -w /var/log/btmp -p wa -k session {% endif %} -{% if rhel8cis_rule_4_1_3_12 %} +{% if rhel8cis_rule_5_2_3_12 %} -w /var/log/lastlog -p wa -k logins -w /var/run/faillock -p wa -k logins {% endif %} -{% if rhel8cis_rule_4_1_3_13 %} --a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete --a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -F key=delete +{% if rhel8cis_rule_5_2_3_13 %} +-a always,exit -F arch=b64 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=delete +-a always,exit -F arch=b32 -S unlink,unlinkat,rename,renameat -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -F key=delete {% endif %} -{% if rhel8cis_rule_4_1_3_14 %} +{% if rhel8cis_rule_5_2_3_14 %} -w /etc/selinux/ -p wa -k MAC-policy -w /usr/share/selinux/ -p wa -k MAC-policy {% endif %} -{% if rhel8cis_rule_4_1_3_15 %} --a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng +{% if rhel8cis_rule_5_2_3_15 %} +-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_16 %} --a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k perm_chng +{% if rhel8cis_rule_5_2_3_16 %} +-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k priv_cmd +{% if rhel8cis_rule_5_2_3_17 %} +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel8cis_rule_4_1_3_18 %} --a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k usermod +{% if rhel8cis_rule_5_2_3_18 %} +-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k usermod {% endif %} -{% if rhel8cis_rule_4_1_3_19 %} --a always,exit -F arch=b32 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules --a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules --a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ rhel8uid_interactive_uid_start }} -F auid!=unset -k kernel_modules +{% if rhel8cis_rule_5_2_3_19 %} +-a always,exit -F arch=b32 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules +-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules +-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ rhel8uid_uid_start }} -F auid!=unset -k kernel_modules {% endif %} -{% if rhel8cis_rule_4_1_3_20 %} +{% if rhel8cis_rule_5_2_3_20 %} -e 2 {% endif %} diff --git a/templates/crypto_policy_RSA.j2 b/templates/crypto_policy_RSA.j2 deleted file mode 100644 index a88f452e..00000000 --- a/templates/crypto_policy_RSA.j2 +++ /dev/null @@ -1,4 +0,0 @@ -# Enable additional options to crypto policies -# Set via ansible-lockdown project - sponsored by MindPoint Group -key_exchange = {{ rhel8cis_optional_key_exchange }} -min_rsa_size = {{ rhel8cis_optional_rsa_size }} diff --git a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 new file mode 100644 index 00000000..03d40e81 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -0,0 +1,6 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +hash = -SHA1 +sign = -*-SHA1 +sha1_in_certs = 0 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 new file mode 100644 index 00000000..418abe8e --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -0,0 +1,6 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +# This is a subpolicy to disable all CBC mode ciphers +# for the SSH protocol (libssh and OpenSSH) +cipher@SSH = -*-CBC diff --git a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 new file mode 100644 index 00000000..24e4c2c8 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -0,0 +1,5 @@ +# Added as part of RHEL8-CIS by ansible-lockdown +# Sponsored by MindPointGroup + +# This is a subpolicy to disable weak macs +mac = -*-64 diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 new file mode 100644 index 00000000..2831c6b4 --- /dev/null +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -0,0 +1,5 @@ +[org/gnome/desktop/media-handling] +automount-open=false + +[org/gnome/desktop/media-handling] +automount=false diff --git a/templates/etc/dconf/db/00-media-autorun.j2 b/templates/etc/dconf/db/00-media-autorun.j2 new file mode 100644 index 00000000..85f8bf5a --- /dev/null +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -0,0 +1,2 @@ +[org/gnome/desktop/media-handling] +autorun-never=true diff --git a/templates/etc/dconf/db/00-screensaver.j2 b/templates/etc/dconf/db/00-screensaver.j2 new file mode 100644 index 00000000..e28f12a8 --- /dev/null +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -0,0 +1,9 @@ +[org/gnome/desktop/session] +# Number of seconds of inactivity before the screen goes blank +# Set to 0 seconds if you want to deactivate the screensaver. +idle-delay=uint32 {{ rhel8cis_screensaver_idle_delay }} + +# Specify the dconf path +[org/gnome/desktop/screensaver] +# Number of seconds after the screen is blank before locking the screen +lock-delay=uint32 {{ rhel8cis_screensaver_lock_delay }} diff --git a/templates/etc/dconf/db/locks/00-automount_lock.j2 b/templates/etc/dconf/db/locks/00-automount_lock.j2 new file mode 100644 index 00000000..0e8e193c --- /dev/null +++ b/templates/etc/dconf/db/locks/00-automount_lock.j2 @@ -0,0 +1,6 @@ +# Lock automount settings + +# Lock desktop media-handling automount setting +/org/gnome/desktop/media-handling/automount +# Lock desktop media-handling automount-open setting +/org/gnome/desktop/media-handling/automount-open diff --git a/templates/etc/dconf/db/locks/00-autorun_lock.j2 b/templates/etc/dconf/db/locks/00-autorun_lock.j2 new file mode 100644 index 00000000..1be853de --- /dev/null +++ b/templates/etc/dconf/db/locks/00-autorun_lock.j2 @@ -0,0 +1,3 @@ +# Lock desktop media-handling settings +# Lock desktop media-handling autorun-never setting +/org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/locks/00-screensaver_lock.j2 b/templates/etc/dconf/db/locks/00-screensaver_lock.j2 new file mode 100644 index 00000000..c1e0cbe1 --- /dev/null +++ b/templates/etc/dconf/db/locks/00-screensaver_lock.j2 @@ -0,0 +1,4 @@ +# Lock desktop screensaver idle-delay setting +/org/gnome/desktop/session/idle-delay +# Lock desktop screensaver lock-delay setting +/org/gnome/desktop/screensaver/lock-delay diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 6bfcd6a9..3cf0bf8b 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -1,4 +1,4 @@ -{{ ansible_managed | comment }} +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! # SPDX-License-Identifier: LGPL-2.1+ # @@ -23,7 +23,7 @@ After=swap.target What=tmpfs Where=/tmp Type=tmpfs -Options=mode=1777,strictatime,{% if rhel8cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_4 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_3 %}noexec{% endif %} +Options=mode=1777,strictatime,{% if rhel8cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel8cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel8cis_rule_1_1_2_1_4 %}noexec{% endif %} # Make 'systemctl enable tmp.mount' work: [Install] diff --git a/templates/ntp.conf.j2 b/templates/ntp.conf.j2 index 34fe555f..1fc240a3 100644 --- a/templates/ntp.conf.j2 +++ b/templates/ntp.conf.j2 @@ -1,4 +1,4 @@ -{{ ansible_managed | comment }} +## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! # For more information about this file, see the man pages # ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5). diff --git a/vars/AlmaLinux.yml b/vars/AlmaLinux.yml index 7c7ea872..7e7ca9be 100644 --- a/vars/AlmaLinux.yml +++ b/vars/AlmaLinux.yml @@ -4,4 +4,4 @@ rpm_gpg_key: /etc/pki/rpm-gpg/RPM-GPG-KEY-AlmaLinux rpm_packager: "AlmaLinux Packaging Team" # found on https://wiki.almalinux.org/cloud/Generic-cloud.html#download-and-verification note lower cas -rpm_key: "51d6647ec21ad6ea" # pragma: allowlist secret +rpm_key: "2ae81e8aced7258b" # pragma: allowlist secret https://almalinux.org/blog/2023-12-20-almalinux-8-key-update/ diff --git a/vars/audit.yml b/vars/audit.yml index c7471f35..9dc666a6 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -2,9 +2,7 @@ #### Audit Configuration Settings #### -# This variable specifies the timeout (in ms) for audit commands that -# take a very long time: if a command takes too long to complete, -# it will be forcefully terminated after the specified duration. +# Timeout for those cmds that take longer to run where timeout set audit_cmd_timeout: 120000 # if get_audit_binary_method == download change accordingly @@ -14,30 +12,29 @@ audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_ ## managed by the control audit_content # git audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_git_version: "benchmark_{{ benchmark_version }}_rh8" +audit_git_version: "benchmark_{{ benchmark_version }}" ## Goss configuration information -# Where the goss configs and outputs are stored -audit_out_dir: '/opt' -# Where the goss audit configuration will be stored -audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit" +# Where the goss audit configuration will be stored - NOTE benchmark-audit is expected +audit_conf_dir: "{{ audit_conf_dest | default('/opt') }}/{{ benchmark }}-Audit" # If changed these can affect other products -pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" -post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +pre_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" +post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}" ## The following should not need changing ### Audit binary settings ### audit_bin_version: - release: v0.3.23 - AMD64_checksum: 'sha256:9e9f24e25f86d6adf2e669a9ffbe8c3d7b9b439f5f877500dea02ba837e10e4d' + release: v0.4.4 + AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The pre remediation results are: {{ pre_audit_summary }}. - The post remediation results are: {{ post_audit_summary }}. - Full breakdown can be found in {{ audit_out_dir }} + The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results}} + {% if not audit_only %}The post remediation audit results are: {{ post_audit_results }}{% endif %} + + Full breakdown can be found in {{ audit_log_dir }} diff --git a/vars/is_container.yml b/vars/is_container.yml index 67039fd3..83f929b9 100644 --- a/vars/is_container.yml +++ b/vars/is_container.yml @@ -1,5 +1,9 @@ --- +## Example file that maybe used for containers +## This is still dependant in the container usage +## Please confirm before running that it is suitable for your environment + rhel8cis_section1: true rhel8cis_section2: true rhel8cis_section3: true @@ -7,8 +11,6 @@ rhel8cis_section4: true rhel8cis_section5: true rhel8cis_section6: true -rhel8cis_firewall: none - # These variables correspond with the CIS rule IDs or paragraph numbers defined in # the CIS benchmark documents. # PLEASE NOTE: These work in coordination with the section # group variables and tags. @@ -17,70 +19,88 @@ rhel8cis_firewall: none rhel8cis_rule_1_1_1_1: true rhel8cis_rule_1_1_1_2: true rhel8cis_rule_1_1_1_3: true -rhel8cis_rule_1_1_2_1: false -rhel8cis_rule_1_1_2_2: false -rhel8cis_rule_1_1_2_3: false -rhel8cis_rule_1_1_2_4: false -rhel8cis_rule_1_1_3_1: false -rhel8cis_rule_1_1_3_2: false -rhel8cis_rule_1_1_3_3: false -rhel8cis_rule_1_1_3_4: false -rhel8cis_rule_1_1_4_1: false -rhel8cis_rule_1_1_4_2: false -rhel8cis_rule_1_1_4_3: false -rhel8cis_rule_1_1_4_4: false -rhel8cis_rule_1_1_5_1: false -rhel8cis_rule_1_1_5_2: false -rhel8cis_rule_1_1_5_3: false -rhel8cis_rule_1_1_5_4: false -rhel8cis_rule_1_1_6_1: false -rhel8cis_rule_1_1_6_2: false -rhel8cis_rule_1_1_6_3: false -rhel8cis_rule_1_1_6_4: false -rhel8cis_rule_1_1_7_1: false -rhel8cis_rule_1_1_7_2: false -rhel8cis_rule_1_1_7_3: false -rhel8cis_rule_1_1_7_4: false -rhel8cis_rule_1_1_7_5: false -rhel8cis_rule_1_1_8_1: false -rhel8cis_rule_1_1_8_2: false -rhel8cis_rule_1_1_8_3: false -rhel8cis_rule_1_1_9: false -rhel8cis_rule_1_1_10: false -rhel8cis_rule_1_2_1: false +rhel8cis_rule_1_1_1_4: true +rhel8cis_rule_1_1_1_5: true +rhel8cis_rule_1_1_1_6: true +rhel8cis_rule_1_1_1_7: true +rhel8cis_rule_1_1_1_8: true + +# /tmp +rhel8cis_rule_1_1_2_1_1: false +rhel8cis_rule_1_1_2_1_2: false +rhel8cis_rule_1_1_2_1_3: false +rhel8cis_rule_1_1_2_1_4: false + +# /dev/shm +rhel8cis_rule_1_1_2_2_1: false +rhel8cis_rule_1_1_2_2_2: false +rhel8cis_rule_1_1_2_2_3: false +rhel8cis_rule_1_1_2_2_4: false + +# /home +rhel8cis_rule_1_1_2_3_1: false +rhel8cis_rule_1_1_2_3_2: false +rhel8cis_rule_1_1_2_3_3: false + +# /var +rhel8cis_rule_1_1_2_4_1: false +rhel8cis_rule_1_1_2_4_2: false +rhel8cis_rule_1_1_2_4_3: false + +# /var/tmp +rhel8cis_rule_1_1_2_5_1: false +rhel8cis_rule_1_1_2_5_2: false +rhel8cis_rule_1_1_2_5_3: false +rhel8cis_rule_1_1_2_5_4: false + +# /var/log +rhel8cis_rule_1_1_2_6_1: false +rhel8cis_rule_1_1_2_6_2: false +rhel8cis_rule_1_1_2_6_3: false +rhel8cis_rule_1_1_2_6_4: false + +# /var/log/audit +rhel8cis_rule_1_1_2_7_1: false +rhel8cis_rule_1_1_2_7_2: false +rhel8cis_rule_1_1_2_7_3: false +rhel8cis_rule_1_1_2_7_4: false + +# DNF - Patching +rhel8cis_rule_1_2_1: true rhel8cis_rule_1_2_2: true rhel8cis_rule_1_2_3: true rhel8cis_rule_1_2_4: true +rhel8cis_rule_1_2_5: true + +# bootloader grub rhel8cis_rule_1_3_1: false rhel8cis_rule_1_3_2: false + +# kernel sysctl and coredumps rhel8cis_rule_1_4_1: false rhel8cis_rule_1_4_2: false rhel8cis_rule_1_4_3: false -rhel8cis_rule_1_5_1: false -rhel8cis_rule_1_5_2: false -rhel8cis_rule_1_5_3: false +rhel8cis_rule_1_4_4: false + +# SElinux +rhel8cis_selinux_disable: true + +# Crypto Policies rhel8cis_rule_1_6_1: true -rhel8cis_rule_1_6_2: false -rhel8cis_rule_1_6_1_1: true -rhel8cis_rule_1_6_1_2: false -rhel8cis_rule_1_6_1_3: false -rhel8cis_rule_1_6_1_4: false -rhel8cis_rule_1_6_1_5: false -rhel8cis_rule_1_6_1_6: false -rhel8cis_rule_1_6_1_7: false -rhel8cis_rule_1_6_1_8: false +rhel8cis_rule_1_6_2: true +rhel8cis_rule_1_6_3: true +rhel8cis_rule_1_6_4: true + +# MOTD and messages rhel8cis_rule_1_7_1: true rhel8cis_rule_1_7_2: true rhel8cis_rule_1_7_3: true rhel8cis_rule_1_7_4: true rhel8cis_rule_1_7_5: true rhel8cis_rule_1_7_6: true -rhel8cis_rule_1_8_1: false -rhel8cis_rule_1_8_2: false -rhel8cis_rule_1_8_3: false -rhel8cis_rule_1_8_4: false -rhel8cis_rule_1_8_5: false -rhel8cis_rule_1_9: true + +# Gnome desktop +rhel8cis_gui: false # Section 2 rules rhel8cis_rule_2_1_1: true @@ -114,12 +134,18 @@ rhel8cis_rule_2_3_6: true rhel8cis_rule_2_4: true # Section 3 rules -rhel8cis_rule_3_1_1: true -rhel8cis_rule_3_1_2: true -rhel8cis_rule_3_1_3: true -rhel8cis_rule_3_1_4: true +# network connectivity wifi/bluetooth/ipv6 +rhel8cis_rule_3_1_1: false +rhel8cis_rule_3_1_2: false +rhel8cis_rule_3_1_3: false + +# Network Kernel module rhel8cis_rule_3_2_1: false rhel8cis_rule_3_2_2: false +rhel8cis_rule_3_2_3: false +rhel8cis_rule_3_2_4: false + +# Network Kernel Params rhel8cis_rule_3_3_1: false rhel8cis_rule_3_3_2: false rhel8cis_rule_3_3_3: false @@ -129,144 +155,172 @@ rhel8cis_rule_3_3_6: false rhel8cis_rule_3_3_7: false rhel8cis_rule_3_3_8: false rhel8cis_rule_3_3_9: false -rhel8cis_rule_3_4_1_1: true -rhel8cis_rule_3_4_1_2: true -rhel8cis_rule_3_4_1_3: true -rhel8cis_rule_3_4_1_4: true -rhel8cis_rule_3_4_1_5: true -rhel8cis_rule_3_4_1_6: true -rhel8cis_rule_3_4_1_7: true -rhel8cis_rule_3_4_2_1: true -rhel8cis_rule_3_4_2_2: true -rhel8cis_rule_3_4_2_3: true -rhel8cis_rule_3_4_2_4: true -rhel8cis_rule_3_4_2_5: true -rhel8cis_rule_3_4_2_6: true -rhel8cis_rule_3_4_2_7: true -rhel8cis_rule_3_4_2_8: true -rhel8cis_rule_3_4_2_9: true -rhel8cis_rule_3_4_2_10: true -rhel8cis_rule_3_4_2_11: true -rhel8cis_rule_3_4_3_1_1: true -rhel8cis_rule_3_4_3_1_2: true -rhel8cis_rule_3_4_3_1_3: true -rhel8cis_rule_3_4_3_2_1: true -rhel8cis_rule_3_4_3_2_2: true -rhel8cis_rule_3_4_3_2_3: true -rhel8cis_rule_3_4_3_2_4: true -rhel8cis_rule_3_4_3_2_5: true -rhel8cis_rule_3_4_3_2_6: true -rhel8cis_rule_3_4_3_3_1: true -rhel8cis_rule_3_4_3_3_2: true -rhel8cis_rule_3_4_3_3_3: true -rhel8cis_rule_3_4_3_3_4: true -rhel8cis_rule_3_4_3_3_5: true -rhel8cis_rule_3_4_3_3_6: true +rhel8cis_rule_3_3_10: false +rhel8cis_rule_3_3_11: false + +# Firewall +rhel8cis_firewall: none # Section 4 rules -rhel8cis_rule_4_1_1_1: false -rhel8cis_rule_4_1_1_2: false -rhel8cis_rule_4_1_1_3: false -rhel8cis_rule_4_1_1_4: false -rhel8cis_rule_4_1_2_1: false -rhel8cis_rule_4_1_2_2: false -rhel8cis_rule_4_1_2_3: false -rhel8cis_rule_4_1_3_1: false -rhel8cis_rule_4_1_3_2: false -rhel8cis_rule_4_1_3_3: false -rhel8cis_rule_4_1_3_4: false -rhel8cis_rule_4_1_3_5: false -rhel8cis_rule_4_1_3_6: false -rhel8cis_rule_4_1_3_7: false -rhel8cis_rule_4_1_3_8: false -rhel8cis_rule_4_1_3_9: false -rhel8cis_rule_4_1_3_10: false -rhel8cis_rule_4_1_3_11: false -rhel8cis_rule_4_1_3_12: false -rhel8cis_rule_4_1_3_13: false -rhel8cis_rule_4_1_3_14: false -rhel8cis_rule_4_1_3_15: false -rhel8cis_rule_4_1_3_16: false -rhel8cis_rule_4_1_3_17: false -rhel8cis_rule_4_1_3_18: false -rhel8cis_rule_4_1_3_19: false -rhel8cis_rule_4_1_3_20: false -rhel8cis_rule_4_1_3_21: false -rhel8cis_rule_4_2_1_1: true -rhel8cis_rule_4_2_1_2: true -rhel8cis_rule_4_2_1_3: true -rhel8cis_rule_4_2_1_4: true -rhel8cis_rule_4_2_1_5: true -rhel8cis_rule_4_2_1_6: true -rhel8cis_rule_4_2_1_7: true -rhel8cis_rule_4_2_2_1_1: true -rhel8cis_rule_4_2_2_1_2: true -rhel8cis_rule_4_2_2_1_3: true -rhel8cis_rule_4_2_2_1_4: true -rhel8cis_rule_4_2_2_2: true -rhel8cis_rule_4_2_2_3: true -rhel8cis_rule_4_2_2_4: true -rhel8cis_rule_4_2_2_5: true -rhel8cis_rule_4_2_2_6: true -rhel8cis_rule_4_2_2_7: true -rhel8cis_rule_4_2_3: false -rhel8cis_rule_4_3: true +# cron +rhel8cis_rule_4_1_1_1: true +rhel8cis_rule_4_1_1_2: true +rhel8cis_rule_4_1_1_3: true +rhel8cis_rule_4_1_1_4: true +rhel8cis_rule_4_1_1_5: true +rhel8cis_rule_4_1_1_6: true +rhel8cis_rule_4_1_1_7: true +rhel8cis_rule_4_1_1_8: true + +# at +rhel8cis_rule_4_1_2_1: true + +# sshd +# Only if installed + +# sudo +rhel8cis_rule_4_3_1: false +rhel8cis_rule_4_3_2: false +rhel8cis_rule_4_3_3: false +rhel8cis_rule_4_3_4: false +rhel8cis_rule_4_3_5: false +rhel8cis_rule_4_3_6: false +rhel8cis_rule_4_3_7: false + +# Pam software pkgs +rhel8cis_rule_4_4_1_1: false +rhel8cis_rule_4_4_1_2: false + +# authselect +rhel8cis_rule_4_4_2_1: false +rhel8cis_rule_4_4_2_2: false +rhel8cis_rule_4_4_2_3: false +rhel8cis_rule_4_4_2_4: false +rhel8cis_rule_4_4_2_5: false + +# pam faillock +rhel8cis_rule_4_4_3_1_1: false +rhel8cis_rule_4_4_3_1_2: false +rhel8cis_rule_4_4_3_1_3: false + +# pam pwquality +rhel8cis_rule_4_4_3_2_1: false +rhel8cis_rule_4_4_3_2_2: false +rhel8cis_rule_4_4_3_2_3: false +rhel8cis_rule_4_4_3_2_4: false +rhel8cis_rule_4_4_3_2_5: false +rhel8cis_rule_4_4_3_2_6: false +rhel8cis_rule_4_4_3_2_7: false + +# pam pwhistory +rhel8cis_rule_4_4_3_3_1: false +rhel8cis_rule_4_4_3_3_2: false +rhel8cis_rule_4_4_3_3_3: false + +# pam pam_unix +rhel8cis_rule_4_4_3_4_1: false +rhel8cis_rule_4_4_3_4_2: false +rhel8cis_rule_4_4_3_4_3: false +rhel8cis_rule_4_4_3_4_4: false + +# Shadow user settings +rhel8cis_rule_4_5_1_1: true +rhel8cis_rule_4_5_1_2: true +rhel8cis_rule_4_5_1_3: true +rhel8cis_rule_4_5_1_4: true +rhel8cis_rule_4_5_1_5: true + +# root and sys accts and env +rhel8cis_rule_4_5_2_1: true +rhel8cis_rule_4_5_2_2: true +rhel8cis_rule_4_5_2_3: true +rhel8cis_rule_4_5_2_4: true +rhel8cis_rule_4_5_2_5: true + +# User enviroment +rhel8cis_rule_4_5_3_1: true +rhel8cis_rule_4_5_3_2: true +rhel8cis_rule_4_5_3_3: true # Section 5 rules -rhel8cis_rule_5_1_1: false -rhel8cis_rule_5_1_2: false -rhel8cis_rule_5_1_3: false -rhel8cis_rule_5_1_4: false -rhel8cis_rule_5_1_5: false -rhel8cis_rule_5_1_6: false -rhel8cis_rule_5_1_7: false -rhel8cis_rule_5_1_8: false -rhel8cis_rule_5_1_9: false -rhel8cis_rule_5_2_1: false -rhel8cis_rule_5_2_2: true -rhel8cis_rule_5_2_3: true -rhel8cis_rule_5_2_4: true -rhel8cis_rule_5_2_5: true -rhel8cis_rule_5_2_6: true -rhel8cis_rule_5_2_7: true -rhel8cis_rule_5_2_8: true -rhel8cis_rule_5_2_9: true -rhel8cis_rule_5_2_10: true -rhel8cis_rule_5_2_12: true -rhel8cis_rule_5_2_11: true -rhel8cis_rule_5_2_13: true -rhel8cis_rule_5_2_14: true -rhel8cis_rule_5_2_15: true -rhel8cis_rule_5_2_16: true -rhel8cis_rule_5_2_17: true -rhel8cis_rule_5_2_18: true -rhel8cis_rule_5_2_19: true -rhel8cis_rule_5_2_20: true + +rhel8cis_syslog: none + +# Rsyslog +rhel8cis_rule_5_1_1_1: true +rhel8cis_rule_5_1_1_2: true +rhel8cis_rule_5_1_1_3: true +rhel8cis_rule_5_1_1_4: true +rhel8cis_rule_5_1_1_5: true +rhel8cis_rule_5_1_1_6: true +rhel8cis_rule_5_1_1_7: true + +# Journald +rhel8cis_rule_5_1_2_1_1: true +rhel8cis_rule_5_1_2_1_2: true +rhel8cis_rule_5_1_2_1_3: true +rhel8cis_rule_5_1_2_1_4: true +rhel8cis_rule_5_1_2_2: true +rhel8cis_rule_5_1_2_3: true +rhel8cis_rule_5_1_2_4: true +rhel8cis_rule_5_1_2_5: true +rhel8cis_rule_5_1_2_6: true +rhel8cis_rule_5_1_3: true +rhel8cis_rule_5_1_4: true + +# Auditd +rhel8cis_rule_5_2_1_1: true +rhel8cis_rule_5_2_1_2: true +rhel8cis_rule_5_2_1_3: true +rhel8cis_rule_5_2_1_4: true +rhel8cis_rule_5_2_2_1: true +rhel8cis_rule_5_2_2_2: true +rhel8cis_rule_5_2_2_3: true +rhel8cis_rule_5_2_2_4: true + +# auditd rules +rhel8cis_rule_5_2_3_1: true +rhel8cis_rule_5_2_3_2: true +rhel8cis_rule_5_2_3_3: true +rhel8cis_rule_5_2_3_4: true +rhel8cis_rule_5_2_3_5: true +rhel8cis_rule_5_2_3_6: true +rhel8cis_rule_5_2_3_7: true +rhel8cis_rule_5_2_3_8: true +rhel8cis_rule_5_2_3_9: true +rhel8cis_rule_5_2_3_10: true +rhel8cis_rule_5_2_3_11: true +rhel8cis_rule_5_2_3_12: true +rhel8cis_rule_5_2_3_13: true +rhel8cis_rule_5_2_3_14: true +rhel8cis_rule_5_2_3_15: true +rhel8cis_rule_5_2_3_16: true +rhel8cis_rule_5_2_3_17: true +rhel8cis_rule_5_2_3_18: true +rhel8cis_rule_5_2_3_19: true +rhel8cis_rule_5_2_3_20: true +rhel8cis_rule_5_2_3_21: true + +# auditd log perms +rhel8cis_rule_5_2_4_1: true +rhel8cis_rule_5_2_4_2: true +rhel8cis_rule_5_2_4_3: true +rhel8cis_rule_5_2_4_4: true +rhel8cis_rule_5_2_4_5: true +rhel8cis_rule_5_2_4_6: true +rhel8cis_rule_5_2_4_7: true +rhel8cis_rule_5_2_4_8: true +rhel8cis_rule_5_2_4_9: true +rhel8cis_rule_5_2_4_10: true + +# AIDE + rhel8cis_rule_5_3_1: true rhel8cis_rule_5_3_2: true rhel8cis_rule_5_3_3: true -rhel8cis_rule_5_3_4: false -rhel8cis_rule_5_3_5: false -rhel8cis_rule_5_3_6: true -rhel8cis_rule_5_3_7: true -rhel8cis_rule_5_4_1: false -rhel8cis_rule_5_4_2: false -rhel8cis_rule_5_5_1: true -rhel8cis_rule_5_5_2: true -rhel8cis_rule_5_5_3: true -rhel8cis_rule_5_5_4: false -rhel8cis_rule_5_5_5: true -rhel8cis_rule_5_6_1_1: true -rhel8cis_rule_5_6_1_2: true -rhel8cis_rule_5_6_1_3: true -rhel8cis_rule_5_6_1_4: true -rhel8cis_rule_5_6_1_5: true -rhel8cis_rule_5_6_2: true -rhel8cis_rule_5_6_3: true -rhel8cis_rule_5_6_4: true -rhel8cis_rule_5_6_5: true # Section 6 rules +# System file perms rhel8cis_rule_6_1_1: true rhel8cis_rule_6_1_2: true rhel8cis_rule_6_1_3: true @@ -281,7 +335,8 @@ rhel8cis_rule_6_1_11: true rhel8cis_rule_6_1_12: true rhel8cis_rule_6_1_13: true rhel8cis_rule_6_1_14: true -rhel8cis_rule_6_1_15: true + +# local and usergroup rhel8cis_rule_6_2_1: true rhel8cis_rule_6_2_2: true rhel8cis_rule_6_2_3: true @@ -289,12 +344,7 @@ rhel8cis_rule_6_2_4: true rhel8cis_rule_6_2_5: true rhel8cis_rule_6_2_6: true rhel8cis_rule_6_2_7: true -rhel8cis_rule_6_2_8: false +rhel8cis_rule_6_2_8: true rhel8cis_rule_6_2_9: true -rhel8cis_rule_6_2_10: true +rhel8cis_rule_6_2_10: false rhel8cis_rule_6_2_11: true -rhel8cis_rule_6_2_12: true -rhel8cis_rule_6_2_13: true -rhel8cis_rule_6_2_14: true -rhel8cis_rule_6_2_15: true -rhel8cis_rule_6_2_16: true diff --git a/vars/main.yml b/vars/main.yml index 9868ccb1..9a92b432 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -6,15 +6,12 @@ rhel8cis_allowed_crypto_policies: - 'DEFAULT' - 'FUTURE' - 'FIPS' -rhel8cis_crypto_override: false - -rhel8cis_allowed_crypto_policies_modules: - - 'OSPP' - - 'AD-SUPPORT' # default setting, this should not be changed # and is overridden if a task that changed sets the value if required. -change_requires_reboot: false +reboot_required: false + +rhel8cis_legacy_boot: false # Used to control warning summary warn_control_list: ""