From 8c1b1890fe8bb388cece9b16fe16b47ebddf199e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 17 Jun 2024 17:46:23 +0000 Subject: [PATCH 001/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.18.3 → v8.18.4](https://github.com/gitleaks/gitleaks/compare/v8.18.3...v8.18.4) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e5a1186..04229d3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.3 + rev: v8.18.4 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From d40f2d032a19def99b8c3ae57a1145357f20d168 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Jun 2024 17:47:06 +0000 Subject: [PATCH 002/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.6.0 → v24.6.1](https://github.com/ansible-community/ansible-lint/compare/v24.6.0...v24.6.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 04229d3..309edb5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.6.0 + rev: v24.6.1 hooks: - id: ansible-lint name: Ansible-lint From 611b9ce0b99696709eeb3faec03e911fcc84194e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 11 Jul 2024 16:05:40 +0100 Subject: [PATCH 003/327] issue #217 addressed thanks to tedunder237 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 84df13e..d6c31ef 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -258,7 +258,7 @@ - name: "6.1.13 | AUDIT | Audit SUID executables" block: - name: "6.1.13 | 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 + ansible.builtin.shell: df {{ item.mount }} --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000 failed_when: false changed_when: false register: rhel_09_6_1_13_suid_perms @@ -301,7 +301,7 @@ - name: "6.1.14 | AUDIT | Audit SGID executables" block: - name: "6.1.14 | 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 + ansible.builtin.shell: df {{ item.mount }} --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 failed_when: false changed_when: false register: rhel_09_6_1_14_sgid_perms From a946ec65341f76f7b80d178a2c8c365986c78107 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 11 Jul 2024 16:06:26 +0100 Subject: [PATCH 004/327] issue #216 addressed thanks to tedunder237 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.8.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index b7f4791..ce35a48 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -89,8 +89,8 @@ group: root mode: '0644' loop: - - { regexp: '^user-db', line: 'user-db: user' } - - { regexp: '^system-db', line: 'system-db: local' } + - { regexp: '^user-db', line: 'user-db:user' } + - { regexp: '^system-db', line: 'system-db:local' } - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory" ansible.builtin.file: From 7dcb2cae1c6bae57dbf29bb550a482b3149d07cf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 11 Jul 2024 16:57:45 +0100 Subject: [PATCH 005/327] removed jmespath dependancy Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 52 ++++++++++++----------------------- 1 file changed, 18 insertions(+), 34 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index d6c31ef..ef3d3b3 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -173,7 +173,7 @@ - name: "6.1.10 | 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_09_6_1_10_audit | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid] + msg: "Warning!! Missing owner on items in {{ rhel_09_6_1_10_audit.stdout_lines }}" when: rhel_09_6_1_10_unowned_files_found - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | warning" @@ -220,7 +220,7 @@ - name: "6.1.11 | 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_09_6_1_11_audit | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid] + msg: "Warning!! Missing group on items in {{ rhel_09_6_1_11_audit.stdout_lines }}" when: rhel_09_6_1_11_ungrouped_files_found - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | warning" @@ -258,34 +258,26 @@ - name: "6.1.13 | AUDIT | Audit SUID executables" block: - name: "6.1.13 | AUDIT | Audit SUID executables | Find all SUID executables" - ansible.builtin.shell: df {{ item.mount }} --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000 + ansible.builtin.shell: "df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000" failed_when: false changed_when: false register: rhel_09_6_1_13_suid_perms - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.mount }}" - - - name: "6.1.13 | AUDIT | Audit SUID executables | set fact SUID executables" - ansible.builtin.set_fact: - rhel9_6_1_13_suid_found: true - loop: "{{ rhel_09_6_1_13_suid_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.13 | AUDIT | Audit SUID executables | Alert SUID executables exist" ansible.builtin.debug: - msg: "Warning!! SUID set on items in {{ rhel_09_6_1_13_suid_perms | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid] - when: rhel9_6_1_13_suid_found + msg: "Warning!! SUID set on items in {{ rhel_09_6_1_13_suid_perms.stdout_lines }}" + when: + - rhel_09_6_1_13_suid_perms.stdout is defined + - rhel_09_6_1_13_suid_perms.stdout | length > 0 - name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist | warning" ansible.builtin.import_tasks: file: warning_facts.yml vars: warn_control_id: '6.1.13' - when: rhel9_6_1_13_suid_found + when: + - rhel_09_6_1_13_suid_perms.stdout is defined + - rhel_09_6_1_13_suid_perms.stdout | length > 0 vars: rhel9_6_1_13_suid_found: false when: @@ -301,34 +293,26 @@ - name: "6.1.14 | AUDIT | Audit SGID executables" block: - name: "6.1.14 | AUDIT | Audit SGID executables | Find all SGID executables" - ansible.builtin.shell: df {{ item.mount }} --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 failed_when: false changed_when: false register: rhel_09_6_1_14_sgid_perms - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.mount }}" - - - name: "6.1.14 | AUDIT | Audit SGID executables | Set fact SGID executables" - ansible.builtin.set_fact: - rhel9_6_1_14_sgid_found: true - loop: "{{ rhel_09_6_1_14_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 SGID executables | Alert SGID executables exist" ansible.builtin.debug: - msg: "Warning!! SGID set on items in {{ rhel_09_6_1_14_sgid_perms | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid] - when: rhel9_6_1_14_sgid_found + msg: "Warning!! SGID set on items in {{ rhel_09_6_1_14_sgid_perms.stdout_lines }}" + when: + - rhel_09_6_1_14_sgid_perms.stdout is defined + - rhel_09_6_1_14_sgid_perms.stdout | length > 0 - name: "6.1.14 | AUDIT | Audit SGID executables| warning" ansible.builtin.import_tasks: file: warning_facts.yml vars: warn_control_id: '6.1.14' - when: rhel9_6_1_14_sgid_found + when: + - rhel_09_6_1_14_sgid_perms.stdout is defined + - rhel_09_6_1_14_sgid_perms.stdout | length > 0 vars: rhel9_6_1_14_sgid_found: false when: From 54e4ee15889f219edccb54129bcd921e9f4e723a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 11 Jul 2024 17:02:38 +0100 Subject: [PATCH 006/327] update audit output and remove jmespath Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 22 ++++++++++------------ tasks/pre_remediation_audit.yml | 25 ++++++++++++------------- vars/audit.yml | 4 ++-- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index b3111c8..d58e921 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -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 9777bd1..5a99844 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -90,31 +90,30 @@ when: - audit_format == "json" block: - - name: Pre Audit | 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/vars/audit.yml b/vars/audit.yml index bb50f6d..9dc666a 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -34,7 +34,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The audit results are: {{ pre_audit_summary }} - {% if not audit_only %}The post remediation audit results are: {{ post_audit_summary }}{% endif %} + 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 }} From 065ab6aec6cd30fbe9c01cf1a6ef24953da8ff46 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 12 Jul 2024 08:08:34 +0100 Subject: [PATCH 007/327] updated to latest workflow Signed-off-by: Mark Bolwell --- .../workflows/devel_pipeline_validation.yml | 259 ++++++++++-------- .../workflows/main_pipeline_validation.yml | 246 +++++++++-------- .github/workflows/update_galaxy.yml | 30 +- 3 files changed, 291 insertions(+), 244 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 64feef4..912b3db 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -1,139 +1,158 @@ --- - name: Devel pipeline + name: Devel pipeline - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + 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: - # 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 + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read - 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. + # 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 - # 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 + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} + 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. - # 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 + # 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 - - 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 + steps: - - 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: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - - 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: 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 - - 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 }} + # 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 }} - - 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 + # 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 }} - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml + - 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 }} - # Aws deployments taking a while to come up insert sleep or playbook fails + - 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: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - 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 }} - # Run the Ansibleplaybook - - 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" - ANSIBLE_INJECT_FACT_VARS: "false" + - 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 - # Remove test system - User secrets to keep if necessary +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml - - 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 + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to 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 cfa5801..4a5adc9 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -1,128 +1,156 @@ --- - name: Main pipeline + name: Main pipeline - on: # yamllint disable-line rule:truthy - pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + 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: + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read - # 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 + # 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: - - name: Clone ${{ github.event.repository.name }} - uses: actions/checkout@v4 + steps: + - uses: actions/first-interaction@main with: - ref: ${{ github.event.pull_request.head.sha }} + 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. - # 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 + # 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 - - 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 + steps: - - 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: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - - 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: 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 - - 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 }} + # 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 }} - - 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 + # 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 }} - ## Debug Section - - name: DEBUG - Show Ansible hostfile - if: env.ENABLE_DEBUG == 'true' - run: cat hosts.yml + - 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 }} - # Aws deployments taking a while to come up insert sleep or playbook fails + - 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: Sleep for 60 seconds - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - 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 }} - # Run the Ansibleplaybook - - 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" - ANSIBLE_INJECT_FACT_VARS: "false" + - 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 - # Remove test system - User secrets to keep if necessary +## Debug Section + - name: DEBUG - Show Ansible hostfile + if: env.ENABLE_DEBUG == 'true' + run: cat hosts.yml - - 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 + # Aws deployments taking a while to come up insert sleep or playbook fails + + - name: Sleep to 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/update_galaxy.yml b/.github/workflows/update_galaxy.yml index f935280..b6ee6a1 100644 --- a/.github/workflows/update_galaxy.yml +++ b/.github/workflows/update_galaxy.yml @@ -1,19 +1,19 @@ --- -name: update galaxy + name: update galaxy -on: - push: - branches: - - main -jobs: - update_role: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 + on: + push: + branches: + - main + jobs: + update_role: + runs-on: ubuntu-latest + steps: + - name: Checkout repo + uses: actions/checkout@v4 - - name: Action Ansible Galaxy Release ${{ github.ref_name }} - uses: ansible-actions/ansible-galaxy-action@main - with: - galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} + - name: Action Ansible Galaxy Release ${{ github.ref_name }} + uses: ansible-actions/ansible-galaxy-action@main + with: + galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} From 62baec6d16e4674e81d16b5a7838ef1f105cdd24 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 12 Jul 2024 12:37:45 +0100 Subject: [PATCH 008/327] changed to default bootloader hash Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index f1a2dea..117933e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -421,7 +421,7 @@ rhel9cis_rule_enable_repogpg: true # This variable will store the hashed GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value # must be changed to a value that may be generated with this command 'grub2-mkpasswd-pbkdf2' and must comply with # this format: 'grub.pbkdf2.sha512...' -rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.10000.9306A36764A7BEA3BF492D1784396B27F52A71812E9955A58709F94EE70697F9BD5366F36E07DEC41B52279A056E2862A93E42069D7BBB08F5DFC2679CD43812.6C32ADA5449303AD5E67A4C150558592A05381331DE6B33463469A236871FA8E70738C6F9066091D877EF88A213C86825E093117F30E9E1BF158D0DB75E7581B' # pragma: allowlist secret +rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret ## Control 1.4.1 # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. From 56dd646f08e27384c75e50aa0f03fcb4da320174 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Jul 2024 17:49:49 +0000 Subject: [PATCH 009/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.6.1 → v24.7.0](https://github.com/ansible-community/ansible-lint/compare/v24.6.1...v24.7.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 309edb5..260cffe 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.6.1 + rev: v24.7.0 hooks: - id: ansible-lint name: Ansible-lint From 8b58d71e4b0ee159bbfb0d41a357ba796cb88324 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 19 Jul 2024 17:01:23 +0100 Subject: [PATCH 010/327] section1 v2 initial Signed-off-by: Mark Bolwell --- defaults/main.yml | 133 ++++-- handlers/main.yml | 58 ++- tasks/LE_audit_setup.yml | 42 +- tasks/main.yml | 285 +++++------ tasks/parse_etc_password.yml | 56 +-- tasks/post.yml | 72 ++- tasks/post_remediation_audit.yml | 50 +- tasks/pre_remediation_audit.yml | 128 ++--- tasks/prelim.yml | 263 +++++------ tasks/section_1/cis_1.1.1.x.yml | 351 +++++++++++--- tasks/section_1/cis_1.1.2.1.x.yml | 83 ++++ tasks/section_1/cis_1.1.2.2.x.yml | 54 +++ tasks/section_1/cis_1.1.2.3.x.yml | 49 ++ tasks/section_1/cis_1.1.2.4.x.yml | 49 ++ tasks/section_1/cis_1.1.2.5.x.yml | 53 +++ tasks/section_1/cis_1.1.2.6.x.yml | 51 ++ tasks/section_1/cis_1.1.2.7.x.yml | 51 ++ tasks/section_1/cis_1.1.2.x.yml | 82 ---- tasks/section_1/cis_1.1.3.x.yml | 50 -- tasks/section_1/cis_1.1.4.x.yml | 54 --- tasks/section_1/cis_1.1.5.x.yml | 54 --- tasks/section_1/cis_1.1.6.x.yml | 53 --- tasks/section_1/cis_1.1.7.x.yml | 51 -- tasks/section_1/cis_1.1.8.x.yml | 56 --- tasks/section_1/cis_1.1.x.yml | 36 -- tasks/section_1/cis_1.10.yml | 25 - tasks/section_1/cis_1.2.1.x.yml | 121 +++++ .../{cis_1.9.yml => cis_1.2.2.x.yml} | 6 +- tasks/section_1/cis_1.2.x.yml | 122 ----- tasks/section_1/cis_1.3.1.x.yml | 136 ++++++ .../{cis_1.3.x.yml => cis_1.3.x.yml_AIDE} | 0 tasks/section_1/cis_1.4.x.yml | 69 ++- tasks/section_1/cis_1.5.x.yml | 98 ++-- tasks/section_1/cis_1.6.1.x.yml | 130 ----- tasks/section_1/cis_1.6.x.yml | 163 +++++++ tasks/section_1/cis_1.7.x.yml | 136 +++--- tasks/section_1/cis_1.8.x.yml | 445 +++++++++--------- tasks/section_1/main.yml | 72 ++- tasks/warning_facts.yml | 4 +- .../policies/modules/NO-SHA1.pmod.j2 | 6 + .../policies/modules/NO-SSHCBC.pmod.j2 | 5 + .../policies/modules/NO-SSHCHACHA20.pmod.j2 | 5 + .../policies/modules/NO-SSHETM.pmod.j2 | 5 + .../policies/modules/NO-WEAKMAC.pmod.j2 | 4 + .../etc/sysctl.d/60-kernel_sysctl.conf.j2 | 11 +- templates/fs_with_cves.sh | 60 +++ vars/main.yml | 1 + 47 files changed, 2181 insertions(+), 1707 deletions(-) create mode 100644 tasks/section_1/cis_1.1.2.1.x.yml create mode 100644 tasks/section_1/cis_1.1.2.2.x.yml create mode 100644 tasks/section_1/cis_1.1.2.3.x.yml create mode 100644 tasks/section_1/cis_1.1.2.4.x.yml create mode 100644 tasks/section_1/cis_1.1.2.5.x.yml create mode 100644 tasks/section_1/cis_1.1.2.6.x.yml create mode 100644 tasks/section_1/cis_1.1.2.7.x.yml delete mode 100644 tasks/section_1/cis_1.1.2.x.yml delete mode 100644 tasks/section_1/cis_1.1.3.x.yml delete mode 100644 tasks/section_1/cis_1.1.4.x.yml delete mode 100644 tasks/section_1/cis_1.1.5.x.yml delete mode 100644 tasks/section_1/cis_1.1.6.x.yml delete mode 100644 tasks/section_1/cis_1.1.7.x.yml delete mode 100644 tasks/section_1/cis_1.1.8.x.yml delete mode 100644 tasks/section_1/cis_1.1.x.yml delete mode 100644 tasks/section_1/cis_1.10.yml create mode 100644 tasks/section_1/cis_1.2.1.x.yml rename tasks/section_1/{cis_1.9.yml => cis_1.2.2.x.yml} (60%) delete mode 100644 tasks/section_1/cis_1.2.x.yml create mode 100644 tasks/section_1/cis_1.3.1.x.yml rename tasks/section_1/{cis_1.3.x.yml => cis_1.3.x.yml_AIDE} (100%) delete mode 100644 tasks/section_1/cis_1.6.1.x.yml create mode 100644 tasks/section_1/cis_1.6.x.yml create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 create mode 100644 templates/fs_with_cves.sh diff --git a/defaults/main.yml b/defaults/main.yml index 117933e..3ce2c46 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -28,11 +28,11 @@ os_check: true # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. # If you do not want the tasks from that section to get executed you simply set the variable to "false". rhel9cis_section1: true -rhel9cis_section2: true -rhel9cis_section3: true -rhel9cis_section4: true -rhel9cis_section5: true -rhel9cis_section6: true +rhel9cis_section2: false +rhel9cis_section3: false +rhel9cis_section4: false +rhel9cis_section5: false +rhel9cis_section6: false # This is used for audit purposes to run only specifc level use the tags # e.g. @@ -125,61 +125,98 @@ audit_log_dir: '/opt' # Section 1 is Initial setup (FileSystem Configuration, Configure Software Updates, Filesystem Integrity Checking, Secure Boot Settings, # Additional Process Hardening, Mandatory Access Control, Command Line Warning Banners, and GNOME Display Manager) +# Filesystem kernel modules rhel9cis_rule_1_1_1_1: true rhel9cis_rule_1_1_1_2: true -rhel9cis_rule_1_1_2_1: true -rhel9cis_rule_1_1_2_2: true -rhel9cis_rule_1_1_2_3: true -rhel9cis_rule_1_1_2_4: true -rhel9cis_rule_1_1_3_1: true -rhel9cis_rule_1_1_3_2: true -rhel9cis_rule_1_1_3_3: true -rhel9cis_rule_1_1_4_1: true -rhel9cis_rule_1_1_4_2: true -rhel9cis_rule_1_1_4_3: true -rhel9cis_rule_1_1_4_4: true -rhel9cis_rule_1_1_5_1: true -rhel9cis_rule_1_1_5_2: true -rhel9cis_rule_1_1_5_3: true -rhel9cis_rule_1_1_5_4: true -rhel9cis_rule_1_1_6_1: true -rhel9cis_rule_1_1_6_2: true -rhel9cis_rule_1_1_6_3: true -rhel9cis_rule_1_1_6_4: true -rhel9cis_rule_1_1_7_1: true -rhel9cis_rule_1_1_7_2: true -rhel9cis_rule_1_1_7_3: true -rhel9cis_rule_1_1_8_1: true -rhel9cis_rule_1_1_8_2: true -rhel9cis_rule_1_1_8_3: true -rhel9cis_rule_1_1_8_4: true -rhel9cis_rule_1_1_9: true -rhel9cis_rule_1_2_1: true -rhel9cis_rule_1_2_2: true -rhel9cis_rule_1_2_3: true -rhel9cis_rule_1_2_4: true -rhel9cis_rule_1_3_1: true -rhel9cis_rule_1_3_2: true -rhel9cis_rule_1_3_3: true +rhel9cis_rule_1_1_1_3: true +rhel9cis_rule_1_1_1_4: true +rhel9cis_rule_1_1_1_5: true +rhel9cis_rule_1_1_1_6: true +rhel9cis_rule_1_1_1_7: true +rhel9cis_rule_1_1_1_8: true +rhel9cis_rule_1_1_1_9: true +# Filesystems +# /tmp +rhel9cis_rule_1_1_2_1_1: true +rhel9cis_rule_1_1_2_1_2: true +rhel9cis_rule_1_1_2_1_3: true +rhel9cis_rule_1_1_2_1_4: true +# /dev/shm +rhel9cis_rule_1_1_2_2_1: true +rhel9cis_rule_1_1_2_2_2: true +rhel9cis_rule_1_1_2_2_3: true +rhel9cis_rule_1_1_2_2_4: true +# /home +rhel9cis_rule_1_1_2_3_1: true +rhel9cis_rule_1_1_2_3_2: true +rhel9cis_rule_1_1_2_3_3: true +# /var +rhel9cis_rule_1_1_2_4_1: true +rhel9cis_rule_1_1_2_4_2: true +rhel9cis_rule_1_1_2_4_3: true +# /var/tmp +rhel9cis_rule_1_1_2_5_1: true +rhel9cis_rule_1_1_2_5_2: true +rhel9cis_rule_1_1_2_5_3: true +rhel9cis_rule_1_1_2_5_4: true +# /var/log +rhel9cis_rule_1_1_2_6_1: true +rhel9cis_rule_1_1_2_6_2: true +rhel9cis_rule_1_1_2_6_3: true +rhel9cis_rule_1_1_2_6_4: true +# /var/log/audit +rhel9cis_rule_1_1_2_7_1: true +rhel9cis_rule_1_1_2_7_2: true +rhel9cis_rule_1_1_2_7_3: true +rhel9cis_rule_1_1_2_7_4: true + +# Package Mgmt +# Config Pkg Repos +rhel9cis_rule_1_2_1_1: true +rhel9cis_rule_1_2_1_2: true +rhel9cis_rule_1_2_1_3: true +rhel9cis_rule_1_2_1_4: true +# Package updates +rhel9cis_rule_1_2_2_1: true + +# Selinux +rhel9cis_rule_1_3_1_1: true +rhel9cis_rule_1_3_1_2: true +rhel9cis_rule_1_3_1_3: true +rhel9cis_rule_1_3_1_4: true +rhel9cis_rule_1_3_1_5: true +rhel9cis_rule_1_3_1_6: true +rhel9cis_rule_1_3_1_7: true +rhel9cis_rule_1_3_1_8: true + +# Bootloader rhel9cis_rule_1_4_1: true rhel9cis_rule_1_4_2: true + +# Additional Process Hardening rhel9cis_rule_1_5_1: true rhel9cis_rule_1_5_2: true rhel9cis_rule_1_5_3: true -rhel9cis_rule_1_6_1_1: true -rhel9cis_rule_1_6_1_2: true -rhel9cis_rule_1_6_1_3: true -rhel9cis_rule_1_6_1_4: true -rhel9cis_rule_1_6_1_5: true -rhel9cis_rule_1_6_1_6: true -rhel9cis_rule_1_6_1_7: true -rhel9cis_rule_1_6_1_8: true +rhel9cis_rule_1_5_4: true + +# Config system wide Crypto +rhel9cis_rule_1_6_1: true +rhel9cis_rule_1_6_2: true +rhel9cis_rule_1_6_3: true +rhel9cis_rule_1_6_4: true +rhel9cis_rule_1_6_5: true +rhel9cis_rule_1_6_6: true +rhel9cis_rule_1_6_7: true + +# Coomand line warning banners rhel9cis_rule_1_7_1: true rhel9cis_rule_1_7_2: true rhel9cis_rule_1_7_3: true rhel9cis_rule_1_7_4: true rhel9cis_rule_1_7_5: true rhel9cis_rule_1_7_6: true + +# Gnome Display Manager rhel9cis_rule_1_8_1: true rhel9cis_rule_1_8_2: true rhel9cis_rule_1_8_3: true @@ -190,8 +227,6 @@ rhel9cis_rule_1_8_7: true rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -rhel9cis_rule_1_9: true -rhel9cis_rule_1_10: true # Section 2 rules are controling Services (Special Purpose Services, and service clients) rhel9cis_rule_2_1_1: true diff --git a/handlers/main.yml b/handlers/main.yml index dd97fec..69743d6 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -36,20 +36,34 @@ path: /tmp state: remounted +- name: Update Crypto Policy + ansible.builtin.set_fact: + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}:{{ rhel9cis_crypto_policy_module }}{% endif %}" + notify: Set Crypto Policy + +- name: Set Crypto Policy + when: rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy + ansible.builtin.shell: | + update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + update-crypto-policies + notify: + - Change_requires_reboot + - Restart sshd + - name: Restart firewalld ansible.builtin.systemd: - name: firewalld - state: restarted + name: firewalld + state: restarted - name: Restart sshd ansible.builtin.systemd: - name: sshd - state: restarted + name: sshd + state: restarted - name: Restart postfix ansible.builtin.systemd: - name: postfix - state: restarted + name: postfix + state: restarted - name: Reload dconf ansible.builtin.shell: dconf update @@ -57,35 +71,33 @@ - name: Grub2cfg ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" ignore_errors: true # noqa ignore-errors - tags: - - skip_ansible_lint - name: Restart rsyslog ansible.builtin.systemd: - name: rsyslog - state: restarted + name: rsyslog + state: restarted - name: Restart journald ansible.builtin.systemd: - name: systemd-journald - state: restarted + name: systemd-journald + state: restarted - name: Restart systemd_journal_upload ansible.builtin.systemd: - name: systemd-journal-upload - state: restarted + name: systemd-journal-upload + state: restarted - name: Systemd daemon reload ansible.builtin.systemd: - daemon-reload: true + daemon-reload: true - name: Apply_authselect - ansible.builtin.shell: authselect apply-changes when: not rhel9cis_rule_5_4_2 + ansible.builtin.shell: authselect apply-changes - name: Apply_authselect - ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}" when: rhel9cis_rule_5_4_2 + ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}" ## Auditd tasks note order for handlers to run - name: Auditd immutable check @@ -94,17 +106,15 @@ register: auditd_immutable_check - name: Audit immutable fact - ansible.builtin.debug: - msg: "Reboot required for auditd to apply new rules as immutable set" - notify: Change_requires_reboot when: - - auditd_immutable_check.stdout == '1' + - auditd_immutable_check.stdout == '1' + ansible.builtin.debug: + msg: "Reboot required for auditd to apply new rules as immutable set" + notify: Change_requires_reboot - name: Restart auditd ansible.builtin.shell: service auditd restart - tags: - - skip_ansible_lint - name: Change_requires_reboot ansible.builtin.set_fact: - change_requires_reboot: true + change_requires_reboot: true diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7ef94b4..b3964ce 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -2,33 +2,33 @@ - name: Pre Audit Setup | Set audit package name block: - - name: Pre Audit Setup | Set audit package name | 64bit - ansible.builtin.set_fact: - audit_pkg_arch_name: AMD64 - when: ansible_facts.machine == "x86_64" + - name: Pre Audit Setup | Set audit package name | 64bit + ansible.builtin.set_fact: + audit_pkg_arch_name: AMD64 + when: ansible_facts.machine == "x86_64" - - name: Pre Audit Setup | Set audit package name | ARM64 - ansible.builtin.set_fact: - audit_pkg_arch_name: ARM64 - when: ansible_facts.machine == "arm64" + - name: Pre Audit Setup | Set audit package name | ARM64 + ansible.builtin.set_fact: + audit_pkg_arch_name: ARM64 + when: ansible_facts.machine == "arm64" - name: Pre Audit Setup | Download audit binary ansible.builtin.get_url: - url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" - dest: "{{ audit_bin }}" - owner: root - group: root - checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: '0555' + url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}" + dest: "{{ audit_bin }}" + owner: root + group: root + checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" + mode: '0555' when: - - get_audit_binary_method == 'download' + - get_audit_binary_method == 'download' - name: Pre Audit Setup | Copy audit binary ansible.builtin.copy: - src: "{{ audit_bin_copy_location }}" - dest: "{{ audit_bin }}" - mode: '0555' - owner: root - group: root + src: "{{ audit_bin_copy_location }}" + dest: "{{ audit_bin }}" + mode: '0555' + owner: root + group: root when: - - get_audit_binary_method == 'copy' + - get_audit_binary_method == 'copy' diff --git a/tasks/main.yml b/tasks/main.yml index 509ae27..b2c2695 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -3,224 +3,231 @@ - name: Check OS version and family ansible.builtin.assert: - that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') - 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_facts.distribution_major_version }}" + that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') + 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_facts.distribution_major_version }}" when: - - os_check + - os_check tags: - - always + - always - name: Check ansible version 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 }}" + 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 + - always - name: "Check password set for {{ ansible_env.SUDO_USER }}" - block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" - ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_ansible_user_password_set - - - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" - ansible.builtin.debug: - msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." - when: - - rhel9cis_ansible_user_password_set.stdout == "not found" - - - name: "Check local account" - block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" - ansible.builtin.assert: - that: - - rhel9cis_ansible_user_password_set.stdout | length != 0 - - rhel9cis_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" - - - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" - ansible.builtin.assert: - that: - - not rhel9cis_ansible_user_password_set.stdout.startswith("!") - fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" - success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" - when: - - rhel9cis_ansible_user_password_set.stdout != "not found" when: - - rhel9cis_rule_5_3_4 - - ansible_env.SUDO_USER is defined - - not system_is_ec2 + - rhel9cis_rule_5_3_4 + - ansible_env.SUDO_USER is defined + - not system_is_ec2 tags: - - user_passwd - - rule_5.3.4 + - user_passwd + - rule_5.3.4 vars: sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret + block: + - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" + ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_ansible_user_password_set + + - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" + when: rhel9cis_ansible_user_password_set.stdout == "not found" + ansible.builtin.debug: + msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." + + - name: "Check local account" + when: + - rhel9cis_ansible_user_password_set.stdout != "not found" + block: + - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" + ansible.builtin.assert: + that: + - rhel9cis_ansible_user_password_set.stdout | length != 0 + - rhel9cis_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" + + - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" + ansible.builtin.assert: + that: + - not rhel9cis_ansible_user_password_set.stdout.startswith("!") + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" + success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" - name: Ensure root password is set - block: - - name: Ensure root password is set - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" - changed_when: false - register: root_passwd_set - - - name: Ensure root password is set - ansible.builtin.assert: - that: root_passwd_set.rc == 0 - fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" - success_msg: "You have a root password set" when: - - rhel9cis_rule_5_6_6 + - rhel9cis_rule_5_6_6 tags: - - level1-server - - level1-workstation - - patch - - accounts - - root - - rule_5.6.6 + - level1-server + - level1-workstation + - patch + - accounts + - root + - rule_5.6.6 + block: + - name: Ensure root password is set + ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + changed_when: false + register: root_passwd_set + + - name: Ensure root password is set + ansible.builtin.assert: + that: root_passwd_set.rc == 0 + fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" + success_msg: "You have a root password set" - name: Setup rules if container - block: - - name: Discover and set container variable if required - ansible.builtin.set_fact: - system_is_container: true - - - name: Load variable for container - ansible.builtin.include_vars: - 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_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + - ansible_connection == 'docker' or + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] tags: - - container_discovery - - always + - container_discovery + - always + block: + - name: Discover and set container variable if required + ansible.builtin.set_fact: + system_is_container: true + + - name: Load variable for container + ansible.builtin.include_vars: + file: "{{ container_vars_file }}" + + - name: Output if discovered is a container + when: + - system_is_container + ansible.builtin.debug: + msg: system has been discovered as a container - name: Check crypto-policy input ansible.builtin.assert: - that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies - fail_msg: "Crypto policy is not a permitted version" - success_msg: "Crypto policy is a permitted version" + that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies + fail_msg: "Crypto policy is not a permitted version" + success_msg: "Crypto policy is a permitted version" - name: Check crypto-policy module input - ansible.builtin.assert: - that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules - fail_msg: "Crypto policy module is not a permitted version" - success_msg: "Crypto policy module is a permitted version" when: - - rhel9cis_rule_1_10 - - rhel9cis_crypto_policy_module | length > 0 + - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_module | length > 0 tags: - - rule_1.10 + - rule_1.6.1 + ansible.builtin.assert: + that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules + fail_msg: "Crypto policy module is not a permitted version" + success_msg: "Crypto policy module is a permitted version" - name: Check rhel9cis_bootloader_password_hash variable has been changed - ansible.builtin.assert: - that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" when: - - rhel9cis_set_boot_pass - - rhel9cis_rule_1_4_1 + - rhel9cis_set_boot_pass + - rhel9cis_rule_1_4_1 tags: - - always + - always + ansible.builtin.assert: + that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret + msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" - name: Gather the package facts - ansible.builtin.package_facts: - manager: auto tags: - - always + - always + ansible.builtin.package_facts: + manager: auto - name: Include OS specific variables - ansible.builtin.include_vars: "{{ ansible_facts.distribution }}.yml" tags: - - always + - always + ansible.builtin.include_vars: + file: "{{ ansible_facts.distribution }}.yml" - name: Include preliminary steps - ansible.builtin.import_tasks: - file: prelim.yml tags: - - prelim_tasks - - always + - prelim_tasks + - always + ansible.builtin.import_tasks: + file: prelim.yml - name: Run Section 1 tasks - ansible.builtin.import_tasks: - file: section_1/main.yml when: rhel9cis_section1 tags: - - rhel9cis_section1 + - rhel9cis_section1 + ansible.builtin.import_tasks: + file: section_1/main.yml - name: Run Section 2 tasks - ansible.builtin.import_tasks: - file: section_2/main.yml when: rhel9cis_section2 tags: - - rhel9cis_section2 + - rhel9cis_section2 + ansible.builtin.import_tasks: + file: section_2/main.yml - name: Run Section 3 tasks - ansible.builtin.import_tasks: - file: section_3/main.yml when: rhel9cis_section3 tags: - - rhel9cis_section3 + - rhel9cis_section3 + ansible.builtin.import_tasks: + file: section_3/main.yml - name: Run Section 4 tasks - ansible.builtin.import_tasks: - file: section_4/main.yml when: rhel9cis_section4 tags: - - rhel9cis_section4 + - rhel9cis_section4 + ansible.builtin.import_tasks: + file: section_4/main.yml - name: Run Section 5 tasks - ansible.builtin.import_tasks: - file: section_5/main.yml when: rhel9cis_section5 tags: - - rhel9cis_section5 + - rhel9cis_section5 + ansible.builtin.import_tasks: + file: section_5/main.yml - name: Run Section 6 tasks - ansible.builtin.import_tasks: - file: section_6/main.yml when: rhel9cis_section6 tags: - - rhel9cis_section6 + - rhel9cis_section6 + ansible.builtin.import_tasks: + file: section_6/main.yml + +# - name: Run Section 7 tasks +# when: rhel9cis_section7 +# tags: +# - rhel9cis_section7 +# ansible.builtin.import_tasks: +# file: section_7/main.yml - name: Run auditd logic - ansible.builtin.import_tasks: - file: auditd.yml when: update_audit_template tags: - - always + - always + ansible.builtin.import_tasks: + file: auditd.yml - name: Run post remediation tasks - ansible.builtin.import_tasks: - file: post.yml tags: - - post_tasks - - always + - post_tasks + - always + ansible.builtin.import_tasks: + file: post.yml - name: Run post_remediation audit - ansible.builtin.import_tasks: - file: post_remediation_audit.yml when: - - run_audit + - 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 + ansible.builtin.debug: + msg: "{{ audit_results.split('\n') }}" - name: If Warnings found Output 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 }}" when: warn_count != 0 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 8ff13fd..e16f8b9 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -1,32 +1,32 @@ --- - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - block: - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.shell: cat /etc/passwd - changed_when: false - check_mode: false - register: rhel9cis_passwd_file_audit - - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" - ansible.builtin.set_fact: - rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" - vars: - ld_passwd_regex: >- - ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) - ld_passwd_yaml: | - id: >-4 - \g - password: >-4 - \g - uid: \g - gid: \g - gecos: >-4 - \g - dir: >-4 - \g - shell: >-4 - \g tags: - - always + - always + block: + - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" + ansible.builtin.shell: cat /etc/passwd + changed_when: false + check_mode: false + register: rhel9cis_passwd_file_audit + + - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" + ansible.builtin.set_fact: + rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" + vars: + ld_passwd_regex: >- + ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) + ld_passwd_yaml: | + id: >-4 + \g + password: >-4 + \g + uid: \g + gid: \g + gecos: >-4 + \g + dir: >-4 + \g + shell: >-4 + \g diff --git a/tasks/post.yml b/tasks/post.yml index 3f1f706..59766f5 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -2,12 +2,16 @@ # Post tasks - name: POST | Gather the package facts after remediation - ansible.builtin.package_facts: - manager: auto tags: - - always + - always + ansible.builtin.package_facts: + manager: auto - name: POST | Update sysctl + when: + - rhel9cis_sysctl_update + - not system_is_container + - "'procps-ng' in ansible_facts.packages" ansible.builtin.template: src: "etc/sysctl.d/{{ item }}.j2" dest: "/etc/sysctl.d/{{ item }}" @@ -21,47 +25,33 @@ - 60-disable_ipv6.conf - 60-netipv4_sysctl.conf - 60-netipv6_sysctl.conf - when: - - rhel9cis_sysctl_update - - not system_is_container - - "'procps-ng' in ansible_facts.packages" - name: Flush handlers ansible.builtin.meta: flush_handlers - 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 - - not skip_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 - - skip_reboot - - - name: "POST | Warning a reboot required but skip option set | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: - - change_requires_reboot - - skip_reboot - vars: - warn_control_id: Reboot_required tags: - - grub - - level1-server - - level1-workstation - - level2-server - - level2-workstation - - rhel9cis_section1 - - rhel9cis_section2 - - rhel9cis_section3 - - rhel9cis_section4 - - rhel9cis_section5 - - rhel9cis_section6 + - always + block: + - name: POST | Reboot system if changes require it and not skipped + ansible.builtin.reboot: + when: + - change_requires_reboot + - not skip_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 + - skip_reboot + + - name: "POST | Warning a reboot required but skip option set | warning count" + ansible.builtin.import_tasks: + file: warning_facts.yml + when: + - change_requires_reboot + - skip_reboot + vars: + warn_control_id: Reboot_required diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index d58e921..a6f9461 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -4,41 +4,41 @@ 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_conf_dest | default('/opt') }}" - AUDIT_FILE: goss.yml + AUDIT_BIN: "{{ audit_bin }}" + 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' - state: file + path: "{{ item }}" + mode: '0644' + state: file loop: - - "{{ post_audit_outfile }}" - - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + - "{{ pre_audit_outfile }}" - name: Post Audit | Capture audit data if json format when: - - audit_format == "json" + - audit_format == "json" block: - - 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: 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: Post Audit | Set Fact for audit summary - ansible.builtin.set_fact: - post_audit_results: "{{ post_audit_summary.stdout }}" + - name: Post Audit | Set Fact for audit summary + ansible.builtin.set_fact: + post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format when: - - audit_format == "documentation" + - audit_format == "documentation" block: - - 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 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 | Set Fact for audit summary - ansible.builtin.set_fact: - post_audit_results: "{{ post_audit_summary.stdout }}" + - name: Post Audit | Set Fact for audit summary + ansible.builtin.set_fact: + post_audit_results: "{{ post_audit_summary.stdout }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 5a99844..266603e 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -2,118 +2,118 @@ - name: Pre Audit Setup | Setup the LE audit when: - - setup_audit + - setup_audit tags: - - setup_audit + - setup_audit ansible.builtin.include_tasks: - file: LE_audit_setup.yml + file: LE_audit_setup.yml - name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists ansible.builtin.file: - path: "{{ audit_conf_dir }}" - state: directory - mode: '0755' + path: "{{ audit_conf_dir }}" + state: directory + mode: '0755' - name: Pre Audit Setup | If using git for content set up when: - - audit_content == 'git' + - audit_content == 'git' block: - - name: Pre Audit Setup | Install git - ansible.builtin.package: - name: git - state: present + - name: Pre Audit Setup | Install git + ansible.builtin.package: + name: git + state: present - - name: Pre Audit Setup | Retrieve audit content files from git - ansible.builtin.git: - repo: "{{ audit_file_git }}" - dest: "{{ audit_conf_dir }}" - version: "{{ audit_git_version }}" + - name: Pre Audit Setup | Retrieve audit content files from git + ansible.builtin.git: + repo: "{{ audit_file_git }}" + dest: "{{ audit_conf_dir }}" + version: "{{ audit_git_version }}" - name: Pre Audit Setup | Copy to audit content files to server when: - - audit_content == 'copy' + - audit_content == 'copy' ansible.builtin.copy: - src: "{{ audit_conf_source }}" - dest: "{{ audit_conf_dest }}" - mode: preserve + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" + mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server when: - - audit_content == 'archive' + - audit_content == 'archive' ansible.builtin.unarchive: - src: "{{ audit_conf_source }}" - dest: "{{ audit_conf_dest }}" + src: "{{ audit_conf_source }}" + dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url when: - - audit_content == 'get_url' + - audit_content == 'get_url' 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', [] ) }}" + 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: - - run_audit + - run_audit block: - - name: Pre Audit Setup | Check for goss file - ansible.builtin.stat: - path: "{{ audit_bin }}" - register: goss_available + - name: Pre Audit Setup | Check for goss file + ansible.builtin.stat: + path: "{{ audit_bin }}" + register: goss_available - - name: Pre Audit Setup | If audit ensure goss is available - ansible.builtin.assert: - that: goss_available.stat.exists - msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" + - name: Pre Audit Setup | If audit ensure goss is available + ansible.builtin.assert: + that: goss_available.stat.exists + 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 tags: - - goss_template - - run_audit + - goss_template + - run_audit when: - - run_audit + - run_audit ansible.builtin.template: - src: ansible_vars_goss.yml.j2 - dest: "{{ audit_vars_path }}" - mode: '0600' + 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 }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" changed_when: true environment: - AUDIT_BIN: "{{ audit_bin }}" - AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" - AUDIT_FILE: goss.yml + AUDIT_BIN: "{{ audit_bin }}" + 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" + - audit_format == "json" block: - - 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 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 | Set Fact for audit summary - ansible.builtin.set_fact: - pre_audit_results: "{{ pre_audit_summary.stdout }}" + - name: Pre Audit | Set Fact for audit summary + ansible.builtin.set_fact: + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format when: - - audit_format == "documentation" + - audit_format == "documentation" block: - - 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 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 | Set Fact for audit summary - ansible.builtin.set_fact: - pre_audit_results: "{{ pre_audit_summary.stdout }}" + - name: Pre Audit | Set Fact for audit summary + ansible.builtin.set_fact: + pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only when: - - audit_only + - audit_only ansible.builtin.import_tasks: - file: audit_only.yml + file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0db27d3..c6ecbda 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -5,50 +5,51 @@ - name: PRELIM | Include audit specific variables when: - - run_audit or audit_only - - setup_audit + - run_audit or audit_only + - setup_audit tags: - - setup_audit - - run_audit - ansible.builtin.include_vars: audit.yml + - setup_audit + - run_audit + ansible.builtin.include_vars: + file: audit.yml - name: PRELIM | Include pre-remediation audit tasks when: - - run_audit or audit_only - - setup_audit + - run_audit or audit_only + - setup_audit tags: - run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml - name: "PRELIM | AUDIT | Interactive Users" tags: - - always + - 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 }' + 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 + register: prelim_interactive_usernames - name: "PRELIM | AUDIT | Interactive User accounts home directories" tags: - - always + - 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 }' + 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 + register: prelim_interactive_users_home - name: "PRELIM | AUDIT | Interactive UIDs" tags: - - always + - 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 }' + 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 + register: prelim_interactive_uids - name: "PRELIM | capture /etc/password variables" ansible.builtin.include_tasks: - file: parse_etc_password.yml + file: parse_etc_password.yml tags: - - always + - always - name: "PRELIM | List users accounts" ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" @@ -56,9 +57,9 @@ check_mode: false register: users tags: - - level1-server - - level1-workstation - - users + - level1-server + - level1-workstation + - users - name: "PRELIM | Gather accounts with empty password fields" ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" @@ -66,63 +67,16 @@ check_mode: false register: empty_password_accounts tags: - - level1-server - - level1-workstation - - passwords + - level1-server + - level1-workstation + - passwords -- 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}'" - changed_when: false - check_mode: false - register: rhel9cis_uid_zero_accounts_except_root - tags: - - rule_6.2.9 - - level1-server - - level1-workstation - - users - -- name: "PRELIM | Setup crypto-policy" - block: - - name: "PRELIM | Install crypto-policies | pkgs present" - ansible.builtin.package: - name: - - crypto-policies - - crypto-policies-scripts - state: present - - - name: "PRELIM | Gather system-wide crypto-policy" - ansible.builtin.shell: 'update-crypto-policies --show' - changed_when: false - check_mode: false - register: rhel9cis_system_wide_crypto_policy - - - name: "PRELIM | Gather system-wide crypto-policy | set fact system policy" - ansible.builtin.set_fact: - current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" - - - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" - ansible.builtin.set_fact: - current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" - when: "':' in rhel9cis_system_wide_crypto_policy.stdout" +- name: "PRELIM | Ensure python3-libselinux is installed" + ansible.builtin.package: + name: python3-libselinux + state: present when: - - rhel9cis_rule_1_10 - tags: - - level1-server - - level1-workstation - - rule_1.10 - - crypto - -- name: "PRELIM | if systemd coredump" - ansible.builtin.stat: - path: /etc/systemd/coredump.conf - register: systemd_coredump - when: - - rhel9cis_rule_1_5_1 - tags: - - level1-server - - level1-workstation - - rule_1.5.1 - - systemd + - '"python3-libselinux" not in ansible_facts.packages' - name: "PRELIM | Section 1.1 | Create list of mount points" ansible.builtin.set_fact: @@ -131,79 +85,115 @@ - level1-server - level1-workstation -- name: "PRELIM | Ensure python3-libselinux is installed" - ansible.builtin.package: - name: python3-libselinux - state: present - when: - - '"python3-libselinux" not in ansible_facts.packages' - -- name: "PRELIM | Set facts based on boot type" - block: - - name: "PRELIM | Check whether machine is UEFI-based" - ansible.builtin.stat: - path: /sys/firmware/efi - register: rhel_09_efi_boot - - - name: "PRELIM | set legacy boot and grub path | Bios" - ansible.builtin.set_fact: - rhel9cis_legacy_boot: true - grub2_path: /etc/grub2.cfg - when: not rhel_09_efi_boot.stat.exists - - - name: "PRELIM | set grub fact | UEFI" - ansible.builtin.set_fact: - grub2_path: /etc/grub2-efi.cfg - when: rhel_09_efi_boot.stat.exists - - name: "PRELIM | Update to latest gpg keys" ansible.builtin.package: name: "{{ gpg_key_package }}" state: latest when: - - rhel9cis_rule_1_2_4 + - rhel9cis_rule_1_2_1_1 - ansible_facts.distribution != 'RedHat' - ansible_facts.distribution != 'OracleLinux' -- name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not | RedHat Only" +- name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not | RedHat Only" block: - - name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not" - ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' - changed_when: false - failed_when: false - register: check_gpg_imported + - name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not" + ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' + changed_when: false + failed_when: false + register: check_gpg_imported - - name: "PRELIM | Check key package matches RedHat" - ansible.builtin.shell: rpm -qi redhat-release | grep Signature - changed_when: false - failed_when: false - register: os_gpg_package_valid - when: "'not installed' in check_gpg_imported.stdout" + - name: "PRELIM | Check key package matches RedHat" + ansible.builtin.shell: rpm -qi redhat-release | grep Signature + changed_when: false + failed_when: false + register: os_gpg_package_valid + when: "'not installed' in check_gpg_imported.stdout" - - name: "PRELIM | Force keys to be imported" - ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release - when: - - "'not installed' in check_gpg_imported.stdout" - - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" + - name: "PRELIM | Force keys to be imported" + ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + when: + - "'not installed' in check_gpg_imported.stdout" + - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" when: - - rhel9cis_rule_1_2_1 - - rhel9cis_force_gpg_key_import - - ansible_facts.distribution == 'RedHat' + - rhel9cis_rule_1_2_1_1 + - rhel9cis_force_gpg_key_import + - ansible_facts.distribution == 'RedHat' + +- name: "PRELIM | if systemd coredump" + ansible.builtin.stat: + path: /etc/systemd/coredump.conf + register: systemd_coredump + when: + - rhel9cis_rule_1_5_4 + tags: + - level1-server + - level1-workstation + - rule_1.5.4 + - systemd + +- name: "PRELIM | Setup crypto-policy" + block: + - name: "PRELIM | Install crypto-policies | pkgs present" + ansible.builtin.package: + name: + - crypto-policies + - crypto-policies-scripts + state: present + + - name: "PRELIM | Gather system-wide crypto-policy" + ansible.builtin.shell: 'update-crypto-policies --show' + changed_when: false + check_mode: false + register: rhel9cis_system_wide_crypto_policy + + - name: "PRELIM | Gather system-wide crypto-policy | set fact system policy" + ansible.builtin.set_fact: + current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" + + - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" + ansible.builtin.set_fact: + current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" + when: "':' in rhel9cis_system_wide_crypto_policy.stdout" + when: + - rhel9cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - rule_1.6.1 + - crypto + +- name: "PRELIM | Set facts based on boot type" + block: + - name: "PRELIM | Check whether machine is UEFI-based" + ansible.builtin.stat: + path: /sys/firmware/efi + register: rhel_09_efi_boot + + - name: "PRELIM | set legacy boot and grub path | Bios" + ansible.builtin.set_fact: + rhel9cis_legacy_boot: true + grub2_path: /etc/grub2.cfg + when: not rhel_09_efi_boot.stat.exists + + - name: "PRELIM | set grub fact | UEFI" + ansible.builtin.set_fact: + grub2_path: /etc/grub2-efi.cfg + when: rhel_09_efi_boot.stat.exists - name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: - name: audit - state: present + name: audit + state: present become: true when: - - '"auditd" not in ansible_facts.packages' - - rhel9cis_rule_4_1_1_1 + - '"auditd" not in ansible_facts.packages' + - rhel9cis_rule_4_1_1_1 tags: - - level2-server - - level2-workstation - - patch - - rule_4.1.1.1 - - auditd + - level2-server + - level2-workstation + - patch + - rule_4.1.1.1 + - auditd - name: "PRELIM | 4.1.4.5 | Audit conf and rules files | list files" ansible.builtin.find: @@ -268,6 +258,17 @@ - rule_5.3.4 - rule_5.3.5 +- 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}'" + changed_when: false + check_mode: false + register: rhel9cis_uid_zero_accounts_except_root + tags: + - rule_6.2.9 + - level1-server + - level1-workstation + - users + - name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" block: - name: "PRELIM | Capture UID_MIN information from logins.def" diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 263fc50..8ea6909 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -1,66 +1,303 @@ --- -- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled" - block: - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | 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' - - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist squashfs(\\s|$)" - line: "blacklist squashfs" - create: true - mode: '0600' - - - name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs" - community.general.modprobe: - name: squashfs - state: absent - when: not system_is_container - +- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available" when: - - rhel9cis_rule_1_1_1_1 + - rhel9cis_rule_1_1_1_1 tags: - - level2-server - - level2-workstation - - patch - - rule_1.1.1.1 - - squashfs - -- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled" + - level1-server + - level1-workstation + - patch + - rule_1.1.1.1 + - cramfs block: - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | 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' + - 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' - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist udf(\\s|$)" - line: "blacklist udf" - create: true - mode: '0600' + - 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' - - name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf" - community.general.modprobe: - name: udf - state: absent - when: not system_is_container + - 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: - - rhel9cis_rule_1_1_1_2 + - rhel9cis_rule_1_1_1_2 tags: - - level2-server - - level2-workstation - - patch - - rule_1.1.1.2 - - udf + - level1-server + - level1-workstation + - patch + - rule_1.1.1.2 + - 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" + when: + - not system_is_container + community.general.modprobe: + name: freevxfs + state: absent + +- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available" + when: + - rhel9cis_rule_1_1_1_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.3 + - 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: + - rhel9cis_rule_1_1_1_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.4 + - 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.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: + - rhel9cis_rule_1_1_1_5 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.5 + - jffs2 + block: + - 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: + - rhel9cis_rule_1_1_1_6 + tags: + - level2-server + - level2-workstation + - patch + - rule_1.1.1.6 + - 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' + + - 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' + + - 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 + +- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available" + when: + - rhel9cis_rule_1_1_1_7 + tags: + - level2-server + - level2-workstation + - patch + - rule_1.1.1.7 + - udf + block: + - 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' + + - 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' + + - 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 + +- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available" + when: + - rhel9cis_rule_1_1_1_8 + tags: + - level1-server + - level2-workstation + - patch + - rule_1.1.1.8 + - 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 + +- name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available" + when: + - rhel9cis_rule_1_1_1_9 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.1.1.9 + - usb + vars: + warn_control_id: '1.1.1.9' + block: + - name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available | Add discovery script" + ansible.builtin.template: + src: fs_with_cves.sh + dest: /var/fs_with_cves.sh + owner: root + group: root + mode: '0744' + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Run discovery script" + ansible.builtin.shell: /var/fs_with_cves.sh + changed_when: false + failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ] + register: discovered_fs_modules_loaded + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning" + when: discovered_fs_modules_loaded.stdout | length > 0 + ansible.builtin.debug: + msg: | + "Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task + {{ discovered_fs_modules_loaded.stdout_lines}}" + + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" + when: discovered_fs_modules_loaded.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml 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 0000000..cd27f5e --- /dev/null +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -0,0 +1,83 @@ +--- + +- name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_1_1 + tags: + - level1-server + - level1-workstation + - audit + - mounts + - 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 }} doesn't exist. This is a manual task" + + - 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" + ansible.posix.mount: + name: /tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_1_4 %}noexec{% endif %} + notify: Remount tmp + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + when: + - item.mount == "/tmp" + - not rhel9cis_tmp_svc + - rhel9cis_rule_1_1_2_1_2 or + rhel9cis_rule_1_1_2_1_3 or + rhel9cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + +# 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 noexec option set on /tmp partition" + "1.1.2.1.4 | PATCH | Ensure nosuid option set on /tmp partition" + when: + - rhel9cis_tmp_svc + - rhel9cis_rule_1_1_2_1_1 or + rhel9cis_rule_1_1_2_1_2 or + rhel9cis_rule_1_1_2_1_3 or + rhel9cis_rule_1_1_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.1 + - rule_1.1.2.1.2 + - rule_1.1.2.1.3 + - rule_1.1.2.1.4 + 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 + 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 0000000..0831626 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -0,0 +1,54 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" + when: + - rhel9cis_rule_1_1_2_2_1 + tags: + - level1-server + - level1-workstation + - audit + - mounts + - rule_1.1.2.2.1 + vars: + warn_control_id: '1.1.2.2.1' + block: + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" + ansible.builtin.shell: mount -l | grep -w /dev/shm + changed_when: false + register: rhel9cis_1_8_1_1_mount_check + + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" + when: rhel9cis_1_8_1_1_mount_check.rc == 1 + block: + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.2.1 | AUDIT | Ensure separate partition exists for /home | Present" + 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: + - rhel9cis_rule_1_1_2_2_2 or + rhel9cis_rule_1_1_2_2_3 or + rhel9cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.2.2 + - rule_1.1.2.2.3 + - rule_1.1.2.2.4 + ansible.posix.mount: + name: /dev/shm + src: tmpfs + fstype: tmpfs + state: mounted + opts: defaults,{% if rhel9cis_rule_1_1_2_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_2_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_2_4 %}noexec{% endif %} + notify: Change_requires_reboot 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 0000000..1468135 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -0,0 +1,49 @@ +--- + +- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_3_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.3.1 + - 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 | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- 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: + - item.mount == "/home" + - rhel9cis_rule_1_1_2_3_2 or + rhel9cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.3.2 + - rule_1_1_2.3.3 + ansible.builtin.mount: + name: /home + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot 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 0000000..afa754b --- /dev/null +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -0,0 +1,49 @@ +--- + +- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_4_1 + tags: + - level2-server + - level2-workstation + - patch + - mounts + - rule_1_1_2.4.1 + vars: + warn_control_id: '1.1.2.4.1' + required_mount: '/var' + block: + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +# 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: + - item.mount == "/var" + - rhel9cis_rule_1_1_2_4_2 or + rhel9cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.4.2 + - rule_1_1_2.4.3 + ansible.builtin.mount: + name: /var + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_4_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_4_3 %}nosuid{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot 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 0000000..93fa27c --- /dev/null +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -0,0 +1,53 @@ +--- + +# Skips if mount is absent +- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_5_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - 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 | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - 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: + - item.mount == "/var/tmp" + - rhel9cis_rule_1_1_2_5_2 or + rhel9cis_rule_1_1_2_5_3 or + rhel9cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.5.2 + - rule_1_1_2.5.3 + - rule_1_1_2.5.4 + ansible.builtin.mount: + name: /var/tmp + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_5_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_5_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot 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 0000000..6b497ec --- /dev/null +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -0,0 +1,51 @@ +--- + +- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_6_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.6.1 + 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 | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- 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: + - item.mount == "/var/log" + - rhel9cis_rule_1_1_2_6_2 or + rhel9cis_rule_1_1_2_6_3 or + rhel9cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.6.2 + - rule_1_1_2.6.3 + - rule_1_1_2.6.4 + ansible.builtin.mount: + name: /var/log + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_6_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_6_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_6_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot 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 0000000..6b5d760 --- /dev/null +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -0,0 +1,51 @@ +--- + +- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" + when: + - required_mount not in mount_names + - rhel9cis_rule_1_1_2_7_1 + tags: + - level2-server + - level2-workstation + - audit + - mounts + - rule_1_1_2.7.1 + 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 | Absent" + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + + - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- 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" + ansible.builtin.mount: + name: /var/log/audit + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_7_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot + when: + - item.mount == "/var/log/audit" + - rhel9cis_rule_1_1_2_7_2 or + rhel9cis_rule_1_1_2_7_3 or + rhel9cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1_1_2.7.2 + - rule_1_1_2.7.3 + - rule_1_1_2.7.4 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 10d6d2d..0000000 --- a/tasks/section_1/cis_1.1.2.x.yml +++ /dev/null @@ -1,82 +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 }} doesn't exist. This is a manual task" - - - name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.2.1' - required_mount: '/tmp' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_2_1 - tags: - - level1-server - - level1-workstation - - 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 rhel9cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_2_4 %}nosuid{% endif %} - notify: Remount tmp - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - when: - - item.mount == "/tmp" - - not rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_2 or - rhel9cis_rule_1_1_2_3 or - rhel9cis_rule_1_1_2_4 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_1 or - rhel9cis_rule_1_1_2_2 or - rhel9cis_rule_1_1_2_3 or - rhel9cis_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 3a64a06..0000000 --- a/tasks/section_1/cis_1.1.3.x.yml +++ /dev/null @@ -1,50 +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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.3.1' - required_mount: '/var' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_3_1 - tags: - - level2-server - - level2-workstation - - 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 nosuid option set on /var partition" - ansible.builtin.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_3_3 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var" - - rhel9cis_rule_1_1_3_2 or - rhel9cis_rule_1_1_3_3 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - skip_ansible_lint - - rule_1.1.3.2 - - rule_1.1.3.3 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 713dba6..0000000 --- a/tasks/section_1/cis_1.1.4.x.yml +++ /dev/null @@ -1,54 +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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.1.4.1' - required_mount: '/var/tmp' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_4_1 - tags: - - level2-server - - level2-workstation - - 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.builtin.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_4_4 %}nodev{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/tmp" - - rhel9cis_rule_1_1_4_2 or - rhel9cis_rule_1_1_4_3 or - rhel9cis_rule_1_1_4_4 - tags: - - level1-server - - level1-workstation - - 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 ac8b827..0000000 --- a/tasks/section_1/cis_1.1.5.x.yml +++ /dev/null @@ -1,54 +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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.5.1' - required_mount: '/var/log' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_5_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.5.1 - - skip_ansible_lint - -- 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.builtin.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_5_4 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/log" - - rhel9cis_rule_1_1_5_2 or - rhel9cis_rule_1_1_5_3 or - rhel9cis_rule_1_1_5_4 - tags: - - level1-server - - level1-workstation - - 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 5a7c8f4..0000000 --- a/tasks/section_1/cis_1.1.6.x.yml +++ /dev/null @@ -1,53 +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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.6.1' - required_mount: '/var/log/audit' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_6_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.6.1 - -- 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.builtin.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_6_4 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/var/log/audit" - - rhel9cis_rule_1_1_6_2 or - rhel9cis_rule_1_1_6_3 or - rhel9cis_rule_1_1_6_4 - tags: - - level1-server - - level1-workstation - - 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 d113361..0000000 --- a/tasks/section_1/cis_1.1.7.x.yml +++ /dev/null @@ -1,51 +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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - - vars: - warn_control_id: '1.1.7.1' - required_mount: '/home' - when: - - required_mount not in mount_names - - rhel9cis_rule_1_1_7_1 - tags: - - level2-server - - level2-workstation - - audit - - mounts - - rule_1.1.7.1 - - skip_ansible_lint - -- 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" - ansible.builtin.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_7_3 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot - when: - - item.mount == "/home" - - rhel9cis_rule_1_1_7_2 or - rhel9cis_rule_1_1_7_3 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.7.2 - - rule_1.1.7.3 - - 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 6a50de8..0000000 --- a/tasks/section_1/cis_1.1.8.x.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- - -# Skips if mount is absent -- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition" - block: - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" - ansible.builtin.shell: mount -l | grep -w /dev/shm - changed_when: false - register: rhel9cis_1_8_1_1_mount_check - - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition" - block: - - name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" - - - name: "1.1.8.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: rhel9cis_1_8_1_1_mount_check.rc == 1 - - vars: - warn_control_id: '1.1.8.1' - when: - - rhel9cis_rule_1_1_8_1 - tags: - - level1-server - - level1-workstation - - audit - - mounts - - rule_1.1.8.1 - - skip_ansible_lint - -- name: | - "1.1.8.2 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option - 1.1.8.3 | PATCH | Ensure noexec option set on /dev/shm partition | Set nosuid option - 1.1.8.4 | 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 rhel9cis_rule_1_1_8_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_4 %}nosuid{% endif %} - notify: Change_requires_reboot - when: - - rhel9cis_rule_1_1_8_2 or - rhel9cis_rule_1_1_8_3 or - rhel9cis_rule_1_1_8_4 - tags: - - level1-server - - level1-workstation - - patch - - mounts - - rule_1.1.8.2 - - rule_1.1.8.3 - - rule_1.1.8.4 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 c6cde83..0000000 --- a/tasks/section_1/cis_1.1.x.yml +++ /dev/null @@ -1,36 +0,0 @@ ---- - -- name: "1.1.9 | PATCH | Disable USB Storage" - block: - - name: "1.1.9 | 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.9 | PATCH | Disable USB Storage | Edit modprobe config" - community.general.modprobe: - name: usb-storage - state: absent - when: not system_is_container - - - name: "1.1.9 | 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' - when: - - rhel9cis_rule_1_1_9 - tags: - - level1-server - - level2-workstation - - patch - - mounts - - removable_storage - - rule_1.1.9 diff --git a/tasks/section_1/cis_1.10.yml b/tasks/section_1/cis_1.10.yml deleted file mode 100644 index adb25c1..0000000 --- a/tasks/section_1/cis_1.10.yml +++ /dev/null @@ -1,25 +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: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}:{{ rhel9cis_crypto_policy_module }}{% endif %}" - - - name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy" - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" - update-crypto-policies - notify: Change_requires_reboot - when: - - rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy - when: - - rhel9cis_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.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml new file mode 100644 index 0000000..8e805ab --- /dev/null +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -0,0 +1,121 @@ +--- + +- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured" + when: + - rhel9cis_rule_1_2_1_1 + - ansible_facts.distribution == "RedHat" or + ansible_facts.distribution == "Rocky" or + ansible_facts.distribution == "AlmaLinux" + tags: + - level1-server + - level1-workstation + - manual + - patch + - rule_1.2.1.1 + block: + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" + ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + changed_when: false + failed_when: false + register: os_installed_pub_keys + + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" + ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' + changed_when: false + failed_when: false + register: os_gpg_key_check + when: os_installed_pub_keys.rc == 0 + + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" + when: + - os_installed_pub_keys.rc == 1 or + os_gpg_key_check.rc == 1 + ansible.builtin.fail: + msg: Installed GPG Keys do not meet expected values or expected keys are not installed + +- name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated" + when: + - rhel9cis_rule_1_2_1_2 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.2.1.2 + block: + - name: "1.2.1.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: yum_repos + + - name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" + ansible.builtin.replace: + name: "{{ item.path }}" + regexp: "^gpgcheck=0" + replace: "gpgcheck=1" + loop: "{{ yum_repos.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "1.2.1.3 | AUDIT | Ensure repo_gpgcheck is globally activated" + when: + - rhel9cis_rule_1_2_1_3 + - rhel9cis_rule_enable_repogpg + - not rhel9cis_rhel_default_repo + tags: + - level1-server + - level1-workstation + - manual + - audit + - rule_1.2.1.3 + block: + - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf" + ansible.builtin.lineinfile: + path: /etc/dnf/dnf.conf + regexp: '^repo_gpgcheck' + line: repo_gpgcheck=1 + + - name: "1.2.1.3 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files" + ansible.builtin.find: + paths: /etc/yum.repos.d + patterns: "*.repo" + register: repo_files + + - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: '^repo_gpgcheck( |)=( |)0' + replace: repo_gpgcheck=1 + loop: "{{ repo_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured" + when: + - rhel9cis_rule_1_2_1_4 + tags: + - level1-server + - level1-workstation + - manual + - audit + - rule_1.2.1.4 + - skip_ansible_lint + vars: + warn_control_id: '1.2.1.4' + block: + - name: "1.2.1.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 + check_mode: false + + - name: "1.2.1.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 }}" + + - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_1/cis_1.9.yml b/tasks/section_1/cis_1.2.2.x.yml similarity index 60% rename from tasks/section_1/cis_1.9.yml rename to tasks/section_1/cis_1.2.2.x.yml index e226948..7c6dff7 100644 --- a/tasks/section_1/cis_1.9.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -1,16 +1,16 @@ --- -- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed" +- name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installed" ansible.builtin.package: name: "*" state: latest notify: Change_requires_reboot when: - - rhel9cis_rule_1_9 + - rhel9cis_rule_1_2_2_1 - not system_is_ec2 tags: - level1-server - level1-workstation - patch - - rule_1.9 + - rule_1.2.2.1 - skip_ansible_lint diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml deleted file mode 100644 index fc0bf27..0000000 --- a/tasks/section_1/cis_1.2.x.yml +++ /dev/null @@ -1,122 +0,0 @@ ---- - -- name: "1.2.1 | AUDIT | Ensure GPG keys are configured" - block: - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" - ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" - changed_when: false - failed_when: false - register: os_installed_pub_keys - - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | Query found keys" - ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' - changed_when: false - failed_when: false - register: os_gpg_key_check - when: os_installed_pub_keys.rc == 0 - - - name: "1.2.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" - ansible.builtin.fail: - msg: Installed GPG Keys do not meet expected values or expected keys are not installed - when: - - os_installed_pub_keys.rc == 1 or - os_gpg_key_check.rc == 1 - when: - - rhel9cis_rule_1_2_1 - - ansible_facts.distribution == "RedHat" or - ansible_facts.distribution == "Rocky" or - ansible_facts.distribution == "AlmaLinux" - tags: - - level1-server - - level1-workstation - - manual - - patch - - rule_1.2.1 - -- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated" - block: - - 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 - - - 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" - loop: "{{ yum_repos.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel9cis_rule_1_2_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_1.2.2 - -- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured" - block: - - name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Get repo list" - ansible.builtin.shell: dnf repolist - changed_when: false - failed_when: false - register: dnf_configured - check_mode: false - - - name: "1.2.3 | 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 }}" - - - name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Warn Count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '1.2.3' - when: - - rhel9cis_rule_1_2_3 - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_1.2.3 - - skip_ansible_lint - -- name: "1.2.4 | AUDIT | Ensure repo_gpgcheck is globally activated" - block: - - name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf" - ansible.builtin.lineinfile: - path: /etc/dnf/dnf.conf - regexp: '^repo_gpgcheck' - line: repo_gpgcheck=1 - - - name: "1.2.4 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files" - ansible.builtin.find: - paths: /etc/yum.repos.d - patterns: "*.repo" - register: repo_files - - - name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" - ansible.builtin.replace: - path: "{{ item.path }}" - regexp: '^repo_gpgcheck( |)=( |)0' - replace: repo_gpgcheck=1 - loop: "{{ repo_files.files }}" - loop_control: - label: "{{ item.path }}" - - when: - - rhel9cis_rule_1_2_4 - - rhel9cis_rule_enable_repogpg - - not rhel9cis_rhel_default_repo - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_1.2.4 diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml new file mode 100644 index 0000000..2e0f0ce --- /dev/null +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -0,0 +1,136 @@ +--- + +- name: "1.3.1.1 | PATCH | Ensure SELinux is installed" + when: + - rhel9cis_rule_1_3_1_1 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - patch + - rule_1.3.1.1 + ansible.builtin.package: + name: libselinux + state: present + +- name: "1.3.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration" + when: + - rhel9cis_rule_1_3_1_2 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - scored + - patch + - rule_1.3.1.2 + ansible.builtin.replace: + path: /etc/default/grub + regexp: '{{ item }}' + replace: '' + loop: + - selinux=0 + - enforcing=0 + register: selinux_grub_patch + ignore_errors: true # noqa ignore-errors + notify: Grub2cfg + +# State set to enforcing because control 1.3.1.5 requires enforcing to be set +- name: "1.3.1.3 | PATCH | Ensure SELinux policy is configured" + when: + - rhel9cis_rule_1_3_1_3 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - selinux + - patch + - rule_1.3.1.3 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: "{{ rhel9cis_selinux_enforce }}" + +- name: "1.3.1.4 | PATCH | Ensure the SELinux state is not disabled" + when: + - rhel9cis_rule_1_3_1_4 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - selinux + - patch + - rule_1.3.1.4 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: "{{ rhel9cis_selinux_enforce }}" + +- name: "1.3.1.5 | PATCH | Ensure the SELinux state is enforcing" + when: + - rhel9cis_selinux_enforce == 'enforcing' + - rhel9cis_rule_1_3_1_5 + - not rhel9cis_selinux_disable + tags: + - level2-server + - level2-workstation + - selinux + - patch + - rule_1.3.1.5 + ansible.posix.selinux: + conf: /etc/selinux/config + policy: "{{ rhel9cis_selinux_pol }}" + state: enforcing + +- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist" + when: + - rhel9cis_rule_1_3_1_6 + - not rhel9cis_selinux_disable + tags: + - level1-server + - level1-workstation + - audit + - services + - rule_1.3.1.6 + vars: + warn_control_id: '1.3.1.6' + block: + - name: "1.3.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_3_1_6_unconf_services + failed_when: false + changed_when: false + + - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" + when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! You have unconfined services: {{ rhelcis_1_3_1_6_unconf_services.stdout_lines }}" + + - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | warning count" + when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "1.3.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" + when: + - rhel9cis_rule_1_3_1_7 + tags: + - level1-server + - level1-workstation + - patch + - rule_1.3.1.7 + ansible.builtin.package: + name: mcstrans + state: absent + +- name: "1.3.1.8 | PATCH | Ensure SETroubleshoot is not installed" + ansible.builtin.package: + name: setroubleshoot + state: absent + when: + - rhel9cis_rule_1_3_1_8 + - "'setroubleshoot' in ansible_facts.packages" + tags: + - level1-server + - selinux + - patch + - rule_1.3.1.8 diff --git a/tasks/section_1/cis_1.3.x.yml b/tasks/section_1/cis_1.3.x.yml_AIDE similarity index 100% rename from tasks/section_1/cis_1.3.x.yml rename to tasks/section_1/cis_1.3.x.yml_AIDE diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index dd8d83f..384ab24 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -1,44 +1,43 @@ --- - name: "1.4.1 | PATCH | Ensure bootloader password is set" - ansible.builtin.copy: - dest: /boot/grub2/user.cfg - content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy - owner: root - group: root - mode: '0600' - notify: Grub2cfg when: - - rhel9cis_set_boot_pass - - rhel9cis_rule_1_4_1 + - rhel9cis_set_boot_pass + - rhel9cis_rule_1_4_1 tags: - - level1-server - - level1-workstation - - grub - - patch - - rule_1.4.1 + - level1-server + - level1-workstation + - grub + - patch + - rule_1.4.1 + ansible.builtin.copy: + dest: /boot/grub2/user.cfg + content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy + owner: root + group: root + mode: '0600' + notify: Grub2cfg - 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: "/boot/grub2/{{ item.path }}" - owner: root - group: root - mode: "{{ item.mode }}" - state: touch - modification_time: preserve - access_time: preserve - loop: - - { path: 'grub.cfg', mode: '0700' } - - { path: 'grubenv', mode: '0600' } - - { path: 'user.cfg', mode: '0600' } - when: - - rhel9cis_rule_1_4_2 + - rhel9cis_rule_1_4_2 tags: - - level1-server - - level1-workstation - - grub - - patch - - rule_1.4.2 + - level1-server + - level1-workstation + - grub + - patch + - rule_1.4.2 + block: + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" + ansible.builtin.file: + path: "/boot/grub2/{{ item.path }}" + owner: root + group: root + mode: "{{ item.mode }}" + state: touch + modification_time: preserve + access_time: preserve + loop: + - { path: 'grub.cfg', mode: '0700' } + - { path: 'grubenv', mode: '0600' } + - { path: 'user.cfg', mode: '0600' } diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 3f80647..b8ea0dd 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -1,48 +1,66 @@ --- -- name: "1.5.1 | PATCH | Ensure core dump storage is disabled" - ansible.builtin.lineinfile: - path: /etc/systemd/coredump.conf - regexp: '^Storage\s*=\s*(?!none).*' - line: 'Storage=none' - notify: Systemd daemon reload +- name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" when: - - rhel9cis_rule_1_5_1 - - systemd_coredump.stat.exists + - rhel9cis_rule_1_5_1 tags: - - level1-server - - level1-workstation - - 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\s*=\s*.*[1-9]$' - line: 'ProcessSizeMax=0' - when: - - rhel9cis_rule_1_5_2 - tags: - - level1-server - - level1-workstation - - patch - - sysctl - - rule_1.5.2 - -- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.1 block: - - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true + - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true - - name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + +- name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" when: - - rhel9cis_rule_1_5_3 + - rhel9cis_rule_1_5_2 tags: - - level1-server - - level1-workstation - - patch - - sysctl - - rule_1.5.3 + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.2 + block: + - name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + + - name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" + +- name: "1.5.3 | PATCH | Ensure core dump backtraces are disabled" + when: + - rhel9cis_rule_1_5_3 + tags: + - level1-server + - level1-workstation + - patch + - sysctl + - rule_1.5.3 + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' + line: 'ProcessSizeMax=0' + +- name: "1.5.4 | PATCH | Ensure core dump storage is disabled" + when: + - rhel9cis_rule_1_5_4 + - systemd_coredump.stat.exists + tags: + - level1-server + - level1-workstation + - patch + - rule_1.5.4 + ansible.builtin.lineinfile: + path: /etc/systemd/coredump.conf + regexp: '^Storage\s*=\s*(?!none).*' + line: 'Storage=none' + notify: Systemd daemon reload 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 7ca0fd1..0000000 --- a/tasks/section_1/cis_1.6.1.x.yml +++ /dev/null @@ -1,130 +0,0 @@ ---- - -- name: "1.6.1.1 | PATCH | Ensure SELinux is installed" - ansible.builtin.package: - name: libselinux - state: present - when: - - rhel9cis_rule_1_6_1_1 - tags: - - level1-server - - level1-workstation - - 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: '{{ item }}' - replace: '' - loop: - - selinux=0 - - enforcing=0 - register: selinux_grub_patch - ignore_errors: true # noqa ignore-errors - notify: Grub2cfg - when: - - rhel9cis_rule_1_6_1_2 - tags: - - level1-server - - level1-workstation - - scored - - 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: "{{ rhel9cis_selinux_pol }}" - state: "{{ rhel9cis_selinux_enforce }}" - when: - - rhel9cis_rule_1_6_1_3 - tags: - - level1-server - - level1-workstation - - selinux - - patch - - rule_1.6.1.3 - -- name: "1.6.1.4 | PATCH | Ensure the SELinux state is not disabled" - ansible.posix.selinux: - conf: /etc/selinux/config - policy: "{{ rhel9cis_selinux_pol }}" - state: "{{ rhel9cis_selinux_enforce }}" - when: - - rhel9cis_rule_1_6_1_4 - tags: - - level1-server - - level1-workstation - - 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: "{{ rhel9cis_selinux_pol }}" - state: enforcing - when: - - rhel9cis_selinux_enforce == 'enforcing' - - rhel9cis_rule_1_6_1_5 - tags: - - level2-server - - level2-workstation - - 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: - file: warning_facts.yml - when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0 - vars: - warn_control_id: '1.6.1.6' - when: - - rhel9cis_rule_1_6_1_6 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_rule_1_6_1_7 - - "'setroubleshoot' in ansible_facts.packages" - tags: - - level1-server - - 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: - - rhel9cis_rule_1_6_1_8 - tags: - - level1-server - - level1-workstation - - 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 0000000..bc15fbb --- /dev/null +++ b/tasks/section_1/cis_1.6.x.yml @@ -0,0 +1,163 @@ +--- + +- name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" + when: + - rhel9cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.1 + ansible.builtin.debug: + msg: "Captured in prelim to ensure not LEGACY. Runs handler to update" + changed_when: true + notify: + - Update Crypto Policy + - Set Crypto Policy + +- name: "1.6.2 | PATCH | Ensure system wide crypto policy is not set in sshd configuration" + when: + - rhel9cis_rule_1_6_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.2 + ansible.builtin.lineinfile: + path: /etc/sysconfig/sshd + regexp: ^CRYPTO_POLICY\s*= + state: absent + notify: Restart sshd + +- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" + when: + - rhel9cis_rule_1_6_3 + - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.3 + block: + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" + when: + - rhel9cis_rule_1_6_4 + - "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.4 + block: + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-WEAKMAC' }}" + + +- name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh" + when: + - rhel9cis_rule_1_6_5 + - "'NO-SSHCBC' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.5 + block: + - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCBC' }}" + +- name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh" + when: + - rhel9cis_rule_1_6_6 + - "'NO-SSHCHACHA20' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.6 + block: + - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCHACHA20' }}" + +- name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh" + when: + - rhel9cis_rule_1_6_7 + - "'NO-SSHETM' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - rule_1.6.7 + block: + - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHETM.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHETM' }}" diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index 883b35b..e5ab0b4 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -1,93 +1,93 @@ --- - 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: - - rhel9cis_rule_1_7_1 + - rhel9cis_rule_1_7_1 tags: - - level1-server - - level1-workstation - - banner - - patch - - rule_1.7.1 + - level1-server + - level1-workstation + - banner + - patch + - rule_1.7.1 + ansible.builtin.template: + src: etc/motd.j2 + dest: /etc/motd + owner: root + group: root + mode: u-x,go-wx - name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" - ansible.builtin.template: - src: etc/issue.j2 - dest: /etc/issue - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_2 + - rhel9cis_rule_1_7_2 tags: - - level1-server - - level1-workstation - - patch - - rule_1.7.2 + - level1-server + - level1-workstation + - patch + - rule_1.7.2 + ansible.builtin.template: + src: etc/issue.j2 + dest: /etc/issue + owner: root + group: root + mode: '0644' - 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 - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_3 + - rhel9cis_rule_1_7_3 tags: - - level1-server - - level1-workstation - - banner - - patch - - rule_1.7.3 + - level1-server + - level1-workstation + - banner + - patch + - rule_1.7.3 + ansible.builtin.template: + src: etc/issue.net.j2 + dest: /etc/issue.net + owner: root + group: root + mode: '0644' - name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured" - ansible.builtin.file: - path: /etc/motd - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_4 + - rhel9cis_rule_1_7_4 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.4 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.4 + ansible.builtin.file: + path: /etc/motd + owner: root + group: root + mode: '0644' - name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured" - ansible.builtin.file: - path: /etc/issue - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_5 + - rhel9cis_rule_1_7_5 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.5 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.5 + ansible.builtin.file: + path: /etc/issue + owner: root + group: root + mode: '0644' - name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured" - ansible.builtin.file: - path: /etc/issue.net - owner: root - group: root - mode: '0644' when: - - rhel9cis_rule_1_7_6 + - rhel9cis_rule_1_7_6 tags: - - level1-server - - level1-workstation - - perms - - patch - - rule_1.7.6 + - level1-server + - level1-workstation + - perms + - patch + - rule_1.7.6 + ansible.builtin.file: + path: /etc/issue.net + owner: root + group: root + mode: '0644' diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index ce35a48..b29aa15 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -1,264 +1,265 @@ --- - name: "1.8.1 | PATCH | Ensure GNOME Display Manager is removed" - ansible.builtin.package: - name: gdm - state: absent when: - - rhel9cis_rule_1_8_1 - - "'gdm' in ansible_facts.packages" - - not rhel9cis_gui + - rhel9cis_rule_1_8_1 + - "'gdm' in ansible_facts.packages" + - not rhel9cis_gui tags: - - level2-server - - patch - - gui - - gdm - - rule_1.8.1 + - level2-server + - patch + - gui + - gdm + - rule_1.8.1 + ansible.builtin.package: + name: gdm + state: absent - name: "1.8.2 | PATCH | Ensure GDM login banner is configured" - block: - - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" - ansible.builtin.lineinfile: - path: /etc/dconf/profile/gdm - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - create: true - owner: root - group: root - mode: '0644' - notify: Reload dconf - loop: - - { regexp: 'user-db', line: 'user-db:user' } - - { regexp: 'system-db', line: 'system-db:gdm' } - - { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } - - - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" - ansible.builtin.template: - src: etc/dconf/db/gdm.d/01-banner-message.j2 - dest: /etc/dconf/db/gdm.d/01-banner-message - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_2 - - rhel9cis_gui + - rhel9cis_rule_1_8_2 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - gdm - - rule_1.8.2 + - level1-server + - level1-workstation + - patch + - gui + - gdm + - rule_1.8.2 + block: + - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" + ansible.builtin.lineinfile: + path: /etc/dconf/profile/gdm + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + create: true + owner: root + group: root + mode: '0644' + notify: Reload dconf + loop: + - { regexp: 'user-db', line: 'user-db:user' } + - { regexp: 'system-db', line: 'system-db:gdm' } + - { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' } + + - name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile" + ansible.builtin.template: + src: etc/dconf/db/gdm.d/01-banner-message.j2 + dest: /etc/dconf/db/gdm.d/01-banner-message + owner: root + group: root + mode: '0644' + notify: Reload dconf + - name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" + when: + - rhel9cis_rule_1_8_3 + - rhel9cis_gui + tags: + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.3 ansible.builtin.lineinfile: - path: "{{ item.file }}" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - create: true - owner: root - group: root - mode: '0644' + 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' } - when: - - rhel9cis_rule_1_8_3 - - rhel9cis_gui - tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.3 + - { 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" - 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 GDM screen locks when the user is idle | Make db directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_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/{{ rhel9cis_dconf_db_name }}.d/00-screensaver" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_4 - - rhel9cis_gui + - rhel9cis_rule_1_8_4 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.4 + - level1-server + - level1-workstation + - patch + - gui + - rule_1.8.4 + 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 GDM screen locks when the user is idle | Make db directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_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/{{ rhel9cis_dconf_db_name }}.d/00-screensaver" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden" - block: - - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" - owner: root - group: root - mode: '0755' - state: directory - - - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" - ansible.builtin.template: - src: etc/dconf/db/00-screensaver_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_5 - - rhel9cis_gui + - rhel9cis_rule_1_8_5 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.5 + - level1-server + - level1-workstation + - patch + - gui + - 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/{{ rhel9cis_dconf_db_name }}.d/locks" + owner: root + group: root + mode: '0755' + state: directory + + - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" + ansible.builtin.template: + src: etc/dconf/db/00-screensaver_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled" - ansible.builtin.template: - src: etc/dconf/db/00-media-automount.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_6 - - rhel9cis_gui + - rhel9cis_rule_1_8_6 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.6 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.6 + ansible.builtin.template: + src: etc/dconf/db/00-media-automount.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden" - 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/{{ rhel9cis_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/00-automount_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_7 - - rhel9cis_gui + - rhel9cis_rule_1_8_7 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.7 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.7 + 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/{{ rhel9cis_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/00-automount_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled" - block: - - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_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/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_8 - - rhel9cis_gui + - rhel9cis_rule_1_8_8 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.8 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.8 + block: + - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_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/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden" - block: - - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" - ansible.builtin.file: - path: "/etc/dconf/db/{{ rhel9cis_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/00-autorun_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock" - owner: root - group: root - mode: '0644' - notify: Reload dconf when: - - rhel9cis_rule_1_8_9 - - rhel9cis_gui + - rhel9cis_rule_1_8_9 + - rhel9cis_gui tags: - - level1-server - - level2-workstation - - patch - - gui - - rule_1.8.9 + - level1-server + - level2-workstation + - patch + - gui + - rule_1.8.9 + block: + - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory" + ansible.builtin.file: + path: "/etc/dconf/db/{{ rhel9cis_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/00-autorun_lock.j2 + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock" + owner: root + group: root + mode: '0644' + notify: Reload dconf - name: "1.8.10 | PATCH | Ensure XDMCP is not enabled" - ansible.builtin.lineinfile: - path: /etc/gdm/custom.conf - regexp: 'Enable=true' - state: absent when: - - rhel9cis_rule_1_8_10 - - rhel9cis_gui + - rhel9cis_rule_1_8_10 + - rhel9cis_gui tags: - - level1-server - - level1-workstation - - patch - - gui - - rule_1.8.10 + - 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/main.yml b/tasks/section_1/main.yml index ccc1e04..5d99f48 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -2,76 +2,64 @@ - name: "SECTION | 1.1.1.x | Disable unused filesystems" ansible.builtin.import_tasks: - file: cis_1.1.1.x.yml + file: cis_1.1.1.x.yml -- name: "SECTION | 1.1.2.x | Configure /tmp" +- name: "SECTION | 1.1.2.1.x | Configure /tmp" ansible.builtin.import_tasks: - file: cis_1.1.2.x.yml + file: cis_1.1.2.1.x.yml -- name: "SECTION | 1.1.3.x | Configure /var" +- name: "SECTION | 1.1.2.2.x | Configure /dev/shm" ansible.builtin.import_tasks: - file: cis_1.1.3.x.yml + file: cis_1.1.2.2.x.yml -- name: "SECTION | 1.1.4.x | Configure /var/tmp" +- name: "SECTION | 1.1.2.3.x | Configure /home" ansible.builtin.import_tasks: - file: cis_1.1.4.x.yml + file: cis_1.1.2.3.x.yml -- name: "SECTION | 1.1.5.x | Configure /var/log" +- name: "SECTION | 1.1.2.4.x | Configure /var" ansible.builtin.import_tasks: - file: cis_1.1.5.x.yml + file: cis_1.1.2.4.x.yml -- name: "SECTION | 1.1.6.x | Configure /var/log/audit" +- name: "SECTION | 1.1.2.5.x | Configure /var/tmp" ansible.builtin.import_tasks: - file: cis_1.1.6.x.yml + file: cis_1.1.2.5.x.yml -- name: "SECTION | 1.1.7.x | Configure /home" +- name: "SECTION | 1.1.2.6.x | Configure /var/log" ansible.builtin.import_tasks: - file: cis_1.1.7.x.yml + file: cis_1.1.2.6.x.yml -- name: "SECTION | 1.1.8.x | Configure /dev/shm" +- name: "SECTION | 1.1.2.7.x | Configure /var/log/audit" ansible.builtin.import_tasks: - file: cis_1.1.8.x.yml + file: cis_1.1.2.7.x.yml -- name: "SECTION | 1.1.x | Disable various mounting" +- name: "SECTION | 1.2.1.x | Configure Package Repositories" ansible.builtin.import_tasks: - file: cis_1.1.x.yml + file: cis_1.2.1.x.yml -- name: "SECTION | 1.2 | Configure Software Updates" +- name: "SECTION | 1.2.2.x | Configure Package Updates" ansible.builtin.import_tasks: - file: cis_1.2.x.yml + file: cis_1.2.2.x.yml -- name: "SECTION | 1.3 | Filesystem Integrity Checking" - ansible.builtin.import_tasks: - file: cis_1.3.x.yml - when: rhel9cis_config_aide +- name: "SECTION | 1.3.1 | Configure SELinux" + ansible.builtin.include_tasks: + file: cis_1.3.1.x.yml -- name: "SECTION | 1.4 | Secure Boot Settings" +- name: "SECTION | 1.4 | Configure Bootloader" ansible.builtin.import_tasks: - file: cis_1.4.x.yml + file: cis_1.4.x.yml - name: "SECTION | 1.5 | Additional Process Hardening" ansible.builtin.import_tasks: - file: cis_1.5.x.yml + file: cis_1.5.x.yml -- name: "SECTION | 1.6 | Mandatory Access Control" - ansible.builtin.include_tasks: - file: cis_1.6.1.x.yml - when: not rhel9cis_selinux_disable +- name: "SECTION | 1.6 | Configure system wide crypto policy" + ansible.builtin.import_tasks: + file: cis_1.6.x.yml - name: "SECTION | 1.7 | Command Line Warning Banners" ansible.builtin.import_tasks: - file: cis_1.7.x.yml + file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" ansible.builtin.import_tasks: - file: cis_1.8.x.yml - -- name: "SECTION | 1.9 | Updates and Patches" - ansible.builtin.import_tasks: - file: cis_1.9.yml - -- name: "SECTION | 1.10 | Crypto policies" - ansible.builtin.include_tasks: - file: cis_1.10.yml - when: - - not system_is_ec2 + file: cis_1.8.x.yml diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 6e80487..98cd4b6 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -16,5 +16,5 @@ # the count increases by a value of 1 - name: "{{ warn_control_id }} | AUDIT | 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 }}" + warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" + warn_count: "{{ warn_count | int + 1 }}" 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 0000000..2a593d7 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -0,0 +1,6 @@ +# This is a subpolicy dropping the SHA1 hash and signature support +# Carried out as part of CIS Benchmark + +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 0000000..8eb8ae8 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable all CBC mode ciphers +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +cipher@SSH = -*-CBC diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 new file mode 100644 index 0000000..03fe414 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable the chacha20-poly1305 ciphers +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +cipher@SSH = -CHACHA20-POLY1305 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 new file mode 100644 index 0000000..fe5fb7f --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -0,0 +1,5 @@ +# This is a subpolicy to disable Encrypt then MAC +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark + +etm@SSH = DISABLE_ETM 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 0000000..ace7fa0 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -0,0 +1,4 @@ +# This is a subpolicy to disable weak macs +# Carried out as part of CIS Benchmark + +mac = -*-64 diff --git a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 index 11b3e2a..11a93f2 100644 --- a/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-kernel_sysctl.conf.j2 @@ -1,7 +1,12 @@ ## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! -{% if rhel9cis_rule_1_5_3 %} -# Kernel sysctl -# CIS 1.5.3 +{% if rhel9cis_rule_1_5_1 %} +# Adress space randomise +# CIS 1.5.1 kernel.randomize_va_space = 2 {% endif %} +{% if rhel9cis_rule_1_5_2 %} +# Ptrace scope +# CIS 1.5.2 +kernel.yama.ptrace_scope = 1 +{% endif %} diff --git a/templates/fs_with_cves.sh b/templates/fs_with_cves.sh new file mode 100644 index 0000000..89ba49b --- /dev/null +++ b/templates/fs_with_cves.sh @@ -0,0 +1,60 @@ +{% raw %} +#! /usr/bin/env bash + +# Based on original Script provided by CIS +# CVEs correct at time of creation - April2024 + +#! /usr/bin/env bash + +{ + a_output=(); a_output2=(); a_modprope_config=(); a_excluded=(); a_available_modules=() + a_ignore=("xfs" "vfat" "ext2" "ext3" "ext4") + a_cve_exists=("afs" "ceph" "cifs" "exfat" "ext" "fat" "fscache" "fuse" "gfs2" "nfs_common" "nfsd" "smbfs_common") + f_module_chk() + { + l_out2=""; grep -Pq -- "\b$l_mod_name\b" <<< "${a_cve_exists[*]}" && l_out2=" <- CVE exists!" + if ! grep -Pq -- '\bblacklist\h+'"$l_mod_name"'\b' <<< "${a_modprope_config[*]}"; then + a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2") + elif ! grep -Pq -- '\binstall\h+'"$l_mod_name"'\h+\/bin\/(false|true)\b' <<< "${a_modprope_config[*]}"; then + a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2") + fi + if lsmod | grep "$l_mod_name" &> /dev/null; then # Check if the module is currently loaded + l_output2+=(" - Kernel module: \"$l_mod_name\" is loaded" "") + fi + } + while IFS= read -r -d $'\0' l_module_dir; do + a_available_modules+=("$(basename "$l_module_dir")") + done < <(find "$(readlink -f /lib/modules/"$(uname -r)"/kernel/fs)" -mindepth 1 -maxdepth 1 -type d ! -empty -print0) + while IFS= read -r l_exclude; do + if grep -Pq -- "\b$l_exclude\b" <<< "${a_cve_exists[*]}"; then + a_output2+=(" - ** WARNING: kernel module: \"$l_exclude\" has a CVE and is currently mounted! **") + elif + grep -Pq -- "\b$l_exclude\b" <<< "${a_available_modules[*]}"; then + a_output+=(" - Kernel module: \"$l_exclude\" is currently mounted - do NOT unload or disable") + fi + ! grep -Pq -- "\b$l_exclude\b" <<< "${a_ignore[*]}" && a_ignore+=("$l_exclude") + done < <(findmnt -knD | awk '{print $2}' | sort -u) + while IFS= read -r l_config; do + a_modprope_config+=("$l_config") + done < <(modprobe --showconfig | grep -P '^\h*(blacklist|install)') + for l_mod_name in "${a_available_modules[@]}"; do # Iterate over all filesystem modules + [[ "$l_mod_name" =~ overlay ]] && l_mod_name="${l_mod_name::-2}" + if grep -Pq -- "\b$l_mod_name\b" <<< "${a_ignore[*]}"; then + a_excluded+=(" - Kernel module: \"$l_mod_name\"") + else + f_module_chk + fi + done +# Output findings + + echo "### Script can be found at ${BASH_SOURCE} ##" + if [ "${#a_output2[@]}" -le 0 ]; then + printf '%s\n' "" " - No unused filesystem kernel modules are enabled" "${a_output[@]}" "" + else + printf '%s\n' "" "-- Audit Result: --" " ** REVIEW the following **" "${a_output2[@]}" + # Changed return value to capture error + exit 99 + #[ "${#a_output[@]}" -gt 0 ] && printf '%s\n' "" "-- Correctly set: --" "${a_output[@]}" "" + fi +} +{% endraw %} diff --git a/vars/main.yml b/vars/main.yml index 6f73a63..68fe21d 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -11,6 +11,7 @@ rhel9cis_allowed_crypto_policies_modules: - 'OSPP' - 'AD-SUPPORT' - 'AD-SUPPORT-LEGACY' + - 'NO-SHA1' # Used to control warning summary warn_control_list: "" From 2bf67cde0d77c40fed616a91708c21bc2fe94e51 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 22 Jul 2024 12:42:39 +0100 Subject: [PATCH 011/327] Added Nist values Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 8 +------- tasks/section_1/cis_1.1.1.x.yml | 9 ++++++++- tasks/section_1/cis_1.1.2.1.x.yml | 6 ++++++ tasks/section_1/cis_1.1.2.2.x.yml | 3 +++ tasks/section_1/cis_1.1.2.3.x.yml | 5 ++++- tasks/section_1/cis_1.1.2.4.x.yml | 3 +++ tasks/section_1/cis_1.1.2.5.x.yml | 3 +++ tasks/section_1/cis_1.1.2.6.x.yml | 3 +++ tasks/section_1/cis_1.1.2.7.x.yml | 3 +++ tasks/section_1/cis_1.2.1.x.yml | 5 ++++- tasks/section_1/cis_1.2.2.x.yml | 22 +++++++++++----------- tasks/section_1/cis_1.3.1.x.yml | 16 ++++++++++++++++ tasks/section_1/cis_1.4.x.yml | 2 ++ tasks/section_1/cis_1.5.x.yml | 3 +++ tasks/section_1/cis_1.6.x.yml | 15 +++++++++++++++ tasks/section_1/cis_1.7.x.yml | 15 +++++++++++++++ 16 files changed, 100 insertions(+), 21 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index c6ecbda..aa85840 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -270,6 +270,7 @@ - users - name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" + when: rhel9cis_discover_int_uid block: - name: "PRELIM | Capture UID_MIN information from logins.def" ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' @@ -292,13 +293,6 @@ max_int_uid: "{{ uid_max_id.stdout }}" min_int_gid: "{{ gid_min_id.stdout }}" -- name: "PRELIM | Output of uid findings" - ansible.builtin.debug: - msg: "{{ min_int_uid }} {{ max_int_uid }}" - - when: - - not discover_int_uid - - name: "PRELIM | Gather the package facts after prelim" ansible.builtin.package_facts: manager: auto diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 8ea6909..4381911 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -9,6 +9,7 @@ - patch - rule_1.1.1.1 - cramfs + - NIST800-53R5_CM-7 block: - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -42,6 +43,7 @@ - patch - rule_1.1.1.2 - freevxfs + - NIST800-53R5_CM-7 block: - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -75,6 +77,7 @@ - patch - rule_1.1.1.3 - hfs + - NIST800-53R5_CM-7 block: - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -108,6 +111,7 @@ - patch - rule_1.1.1.4 - hfsplus + - NIST800-53R5_CM-7 block: - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -141,6 +145,7 @@ - patch - rule_1.1.1.5 - jffs2 + - NIST800-53R5_CM-7 block: - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -174,6 +179,7 @@ - patch - rule_1.1.1.6 - squashfs + - NIST800-53R5_CM-7 block: - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -207,6 +213,7 @@ - patch - rule_1.1.1.7 - udf + - NIST800-53R5_CM-7 block: - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -240,6 +247,7 @@ - patch - rule_1.1.1.8 - usb + - NIST800-53R5_SI-3 block: - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Edit modprobe config" ansible.builtin.lineinfile: @@ -272,7 +280,6 @@ - level1-workstation - patch - rule_1.1.1.9 - - usb vars: warn_control_id: '1.1.1.9' block: diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index cd27f5e..770753e 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -10,6 +10,7 @@ - audit - mounts - rule_1.1.2.1.1 + - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.1.1' required_mount: '/tmp' @@ -51,6 +52,9 @@ - rule_1.1.2.1.2 - rule_1.1.2.1.3 - rule_1.1.2.1.4 + - NIST800-53R5_CM-7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 # via systemd - name: | @@ -73,6 +77,8 @@ - rule_1.1.2.1.2 - rule_1.1.2.1.3 - rule_1.1.2.1.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.template: src: etc/systemd/system/tmp.mount.j2 dest: /etc/systemd/system/tmp.mount diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index 0831626..f93a1d4 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -10,6 +10,7 @@ - audit - mounts - rule_1.1.2.2.1 + - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.2.1' block: @@ -45,6 +46,8 @@ - rule_1.1.2.2.2 - rule_1.1.2.2.3 - rule_1.1.2.2.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.posix.mount: name: /dev/shm src: tmpfs diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 1468135..6fd1303 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -10,7 +10,7 @@ - audit - mounts - rule_1_1_2.3.1 - - skip_ansible_lint + - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.3.1' required_mount: '/home' @@ -37,6 +37,9 @@ - mounts - rule_1_1_2.3.2 - rule_1_1_2.3.3 + - NIST800-53R5_CM-7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.mount: name: /home src: "{{ 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 index afa754b..85df1b2 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -10,6 +10,7 @@ - patch - mounts - rule_1_1_2.4.1 + - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.4.1' required_mount: '/var' @@ -37,6 +38,8 @@ - mounts - rule_1_1_2.4.2 - rule_1_1_2.4.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.mount: name: /var src: "{{ 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 index 93fa27c..dba75f5 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -11,6 +11,7 @@ - audit - mounts - rule_1_1_2.5.1 + - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.5.1' required_mount: '/var/tmp' @@ -41,6 +42,8 @@ - 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 ansible.builtin.mount: name: /var/tmp src: "{{ 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 index 6b497ec..00e0711 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -10,6 +10,7 @@ - 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' @@ -39,6 +40,8 @@ - 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 ansible.builtin.mount: name: /var/log src: "{{ 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 index 6b5d760..8e59fe6 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -10,6 +10,7 @@ - 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' @@ -49,3 +50,5 @@ - 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 diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index 8e805ab..c6ee203 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -12,6 +12,7 @@ - manual - patch - rule_1.2.1.1 + - NIST800-53R5_SI-2 block: - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" @@ -41,6 +42,7 @@ - level1-workstation - patch - rule_1.2.1.2 + - NIST800-53R5_SI-2 block: - name: "1.2.1.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos" ansible.builtin.find: @@ -68,6 +70,7 @@ - manual - audit - rule_1.2.1.3 + - NIST800-53R5_SI-2 block: - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf" ansible.builtin.lineinfile: @@ -99,7 +102,7 @@ - manual - audit - rule_1.2.1.4 - - skip_ansible_lint + - NIST800-53R5_SI-2 vars: warn_control_id: '1.2.1.4' block: diff --git a/tasks/section_1/cis_1.2.2.x.yml b/tasks/section_1/cis_1.2.2.x.yml index 7c6dff7..2ccb59f 100644 --- a/tasks/section_1/cis_1.2.2.x.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -1,16 +1,16 @@ --- - name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installed" - ansible.builtin.package: - name: "*" - state: latest - notify: Change_requires_reboot when: - - rhel9cis_rule_1_2_2_1 - - not system_is_ec2 + - rhel9cis_rule_1_2_2_1 + - not system_is_ec2 tags: - - level1-server - - level1-workstation - - patch - - rule_1.2.2.1 - - skip_ansible_lint + - level1-server + - level1-workstation + - patch + - rule_1.2.2.1 + - NIST800-53R5_SI-2 + ansible.builtin.package: + name: "*" + state: latest + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 2e0f0ce..197e474 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -9,6 +9,8 @@ - level1-workstation - patch - rule_1.3.1.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.package: name: libselinux state: present @@ -23,6 +25,8 @@ - scored - patch - rule_1.3.1.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.replace: path: /etc/default/grub regexp: '{{ item }}' @@ -45,6 +49,8 @@ - selinux - patch - rule_1.3.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.posix.selinux: conf: /etc/selinux/config policy: "{{ rhel9cis_selinux_pol }}" @@ -60,6 +66,8 @@ - selinux - patch - rule_1.3.1.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.posix.selinux: conf: /etc/selinux/config policy: "{{ rhel9cis_selinux_pol }}" @@ -76,6 +84,8 @@ - selinux - patch - rule_1.3.1.5 + - NIST800-53R4_AC-3 + - NIST800-53R4_SI-6 ansible.posix.selinux: conf: /etc/selinux/config policy: "{{ rhel9cis_selinux_pol }}" @@ -91,6 +101,8 @@ - audit - services - rule_1.3.1.6 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 vars: warn_control_id: '1.3.1.6' block: @@ -118,6 +130,8 @@ - level1-workstation - patch - rule_1.3.1.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.package: name: mcstrans state: absent @@ -134,3 +148,5 @@ - selinux - patch - rule_1.3.1.8 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 384ab24..747faa8 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -10,6 +10,7 @@ - grub - patch - rule_1.4.1 + - NIST800-53R5_AC-3 ansible.builtin.copy: dest: /boot/grub2/user.cfg content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy @@ -27,6 +28,7 @@ - grub - patch - rule_1.4.2 + - NIST800-53R5_AC-3 block: - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" ansible.builtin.file: diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index b8ea0dd..05d4b6e 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -9,6 +9,8 @@ - patch - sysctl - rule_1.5.1 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-6.1 block: - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" ansible.builtin.set_fact: @@ -45,6 +47,7 @@ - patch - sysctl - rule_1.5.3 + - NIST800-53R5_CM-6b ansible.builtin.lineinfile: path: /etc/systemd/coredump.conf regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index bc15fbb..7c015a2 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -8,7 +8,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.1 + - NIST800-53R5_SC-6 ansible.builtin.debug: msg: "Captured in prelim to ensure not LEGACY. Runs handler to update" changed_when: true @@ -25,6 +27,9 @@ - automated - patch - rule_1.6.2 + - NIST800-53R5_SC-8 + - NIST800-53R5_IA-5 + - NIST800-53R5_AC-17- NIST800-53R5_SC-6 ansible.builtin.lineinfile: path: /etc/sysconfig/sshd regexp: ^CRYPTO_POLICY\s*= @@ -40,7 +45,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.3 + - NIST800-53R5_SC-6 block: - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | Add submodule exclusion" ansible.builtin.template: @@ -66,7 +73,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.4 + - NIST800-53R5_SC-6 block: - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" ansible.builtin.template: @@ -93,7 +102,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.5 + - NIST800-53R5_SC-6 block: - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion" ansible.builtin.template: @@ -119,7 +130,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.6 + - NIST800-53R5_SC-6 block: - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" ansible.builtin.template: @@ -145,7 +158,9 @@ - level1-workstation - automated - patch + - crypto - rule_1.6.7 + - NIST800-53R5_SC-6 block: - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion" ansible.builtin.template: diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index e5ab0b4..c7484cd 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -9,6 +9,9 @@ - banner - patch - rule_1.7.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 ansible.builtin.template: src: etc/motd.j2 dest: /etc/motd @@ -24,6 +27,9 @@ - level1-workstation - patch - rule_1.7.2 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 ansible.builtin.template: src: etc/issue.j2 dest: /etc/issue @@ -40,6 +46,9 @@ - banner - patch - rule_1.7.3 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-3 + - NIST800-53R5_CM-6 ansible.builtin.template: src: etc/issue.net.j2 dest: /etc/issue.net @@ -56,6 +65,8 @@ - perms - patch - rule_1.7.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.file: path: /etc/motd owner: root @@ -71,6 +82,8 @@ - perms - patch - rule_1.7.5 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.file: path: /etc/issue owner: root @@ -86,6 +99,8 @@ - perms - patch - rule_1.7.6 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.file: path: /etc/issue.net owner: root From bad08c0228b4da6d7f4d7fccb8793f05b4dc267d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 22 Jul 2024 12:43:08 +0100 Subject: [PATCH 012/327] section2 v2.0.0 updates Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 754 ++++++++++++++++++++++++++++++++-- tasks/section_2/cis_2.2.x.yml | 412 ++++--------------- tasks/section_2/cis_2.3.x.yml | 92 ++--- tasks/section_2/cis_2.4.yml | 40 -- tasks/section_2/main.yml | 10 +- 5 files changed, 846 insertions(+), 462 deletions(-) delete mode 100644 tasks/section_2/cis_2.4.yml diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 3312843..34e57f2 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -1,40 +1,736 @@ --- -- name: "2.1.1 | PATCH | Ensure time synchronization is in use" - ansible.builtin.package: - name: chrony - state: present +- name: "2.1.1 | PATCH | Ensure autofs services are not in use" when: - - rhel9cis_rule_2_1_1 - - not system_is_container + - rhel9cis_rule_2_1_1 + - "'autofs' in ansible_facts.packages" tags: - - level1-server - - level1-workstation - - patch - - rule_2.1.1 - -- name: "2.1.2 | PATCH | Ensure chrony is configured" + - level1-server + - level2-workstation + - automated + - patch + - NIST800-53R5_SI-3 + - NIST800-53R5_MP-7 + - rule_2.1.1 block: - - name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration" - ansible.builtin.template: - src: etc/chrony.conf.j2 - dest: /etc/chrony.conf - owner: root - group: root - mode: '0644' + - name: "2.1.1 | PATCH | Ensure autofs services are not in use | Remove Package" + when: + - not rhel9cis_autofs_services + - not rhel9cis_autofs_mask + ansible.builtin.package: + name: autofs + state: absent - - name: "2.1.2 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd | 1" - ansible.builtin.lineinfile: - path: /etc/sysconfig/chronyd - regexp: "^(#)?OPTIONS" - line: "OPTIONS=\"-u chrony\"" - create: true - mode: '0644' + - name: "2.1.1 | PATCH | Ensure autofs services are not in use | Mask service" + when: + - not rhel9cis_autofs_services + - rhel9cis_autofs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: autofs + enabled: false + state: stopped + masked: true + +- name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use" when: - - rhel9cis_rule_2_1_2 - - not system_is_container + - rhel9cis_rule_2_1_2 + - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" + tags: + - level1-server + - level2-workstation + - automated + - patch + - avahi + - NIST800-53R5_SI-4 + - rule_2.1.2 + block: + - name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use | Remove package" + when: + - not rhel9cis_avahi_server + - not rhel9cis_avahi_mask + ansible.builtin.package: + name: + - avahi-autoipd + - avahi + state: absent + + - name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use | Mask service" + when: + - not rhel9cis_avahi_server + - rhel9cis_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.1.3 | PATCH | Ensure dhcp server services are not in use" + when: + - "'dhcp-server' in ansible_facts.packages" + - rhel9cis_rule_2_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - dhcp + - NIST800-53R5_CM-7 + - rule_2.1.3 + block: + - name: "2.1.3 | PATCH | Ensure dhcp server services are not in use | Remove package" + when: + - not rhel9cis_dhcp_server + - not rhel9cis_dhcp_mask + ansible.builtin.package: + name: dhcp-server + state: absent + + - name: "2.1.3 | PATCH | Ensure dhcp server services are not in use | Mask service" + when: + - not rhel9cis_dhcp_server + - rhel9cis_dhcp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - dhcpd.service + - dhcpd6.service + +- name: "2.1.4 | PATCH | Ensure dns server services are not in use" + when: + - "'bind' in ansible_facts.packages" + - rhel9cis_rule_2_1_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - dns + - NIST800-53R5_CM-7 + - rule_2.1.4 + block: + - name: "2.1.4 | PATCH | Ensure dns server services are not in use | Remove package" + when: + - not rhel9cis_dns_server + - not rhel9cis_dns_mask + ansible.builtin.package: + name: bind + state: absent + + - name: "2.1.4 | PATCH | Ensure dns server services are not in use | Mask service" + when: + - not rhel9cis_dns_server + - rhel9cis_dns_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: named.service + enabled: false + state: stopped + masked: true + +- name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use" + when: + - "'dnsmasq' in ansible_facts.packages" + - rhel9cis_rule_2_1_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - dns + - NIST800-53R5_CM-7 + - rule_2.1.5 + block: + - name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use | Remove package" + when: + - not rhel9cis_dnsmasq_server + - not rhel9cis_dnsmasq_mask + ansible.builtin.package: + name: dnsmasq + state: absent + + - name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use | Mask service" + when: + - not rhel9cis_dnsmasq_server + - rhel9cis_dnsmasq_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: dnsmasq.service + enabled: false + state: stopped + masked: true + +- name: "2.1.6 | PATCH | Ensure samba file server services are not in use" + when: + - "'samba' in ansible_facts.packages" + - rhel9cis_rule_2_1_6 + tags: + - level1-server + - level1-workstation + - automated + - patch + - samba + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.6 + block: + - name: "2.1.6 | PATCH | Ensure samba file server services are not in use | Remove package" + when: + - not rhel9cis_samba_server + - not rhel9cis_samba_mask + ansible.builtin.package: + name: samba + state: absent + + - name: "2.1.6 | PATCH | Ensure samba file server services are not in use | Mask service" + when: + - not rhel9cis_samba_server + - rhel9cis_samba_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: smb.service + enabled: false + state: stopped + masked: true + +- name: "2.1.7 | PATCH | Ensure ftp server services are not in use" + when: + - "'ftp' in ansible_facts.packages" + - rhel9cis_rule_2_1_7 + tags: + - level1-server + - level1-workstation + - automation + - patch + - ftp + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.7 + block: + - name: "2.1.7 | PATCH | Ensure ftp server services are not in use | Remove package" + when: + - not rhel9cis_ftp_server + - not rhel9cis_ftp_mask + ansible.builtin.package: + name: vsftpd + state: absent + + - name: "2.1.7 | PATCH | Ensure ftp server services are not in use | Mask service" + when: + - not rhel9cis_ftp_server + - rhel9cis_ftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: vsftpd.service + enabled: false + state: stopped + masked: true + +- name: "2.1.8 | PATCH | Ensure message access server services are not in use" + when: + - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" + - rhel9cis_rule_2_1_8 + tags: + - level1-server + - level1-workstation + - automated + - patch + - dovecot + - imap + - pop3 + - NIST800-53R5_CM-7 + - rule_2.1.8 + block: + - name: "2.1.8 | PATCH | Ensure message access server services are not in use | Remove package" + when: + - not rhel9cis_message_server + - not rhel9cis_message_mask + ansible.builtin.package: + name: + - dovecot + - cyrus-imapd + state: absent + + - name: "2.1.8 | PATCH | Ensure message access server services are not in use | Mask service" + when: + - not rhel9cis_message_server + - rhel9cis_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.1.9 | PATCH | Ensure network file system services are not in use" + when: + - "'nfs-utils' in ansible_facts.packages" + - rhel9cis_rule_2_1_9 + tags: + - level1-server + - level1-workstation + - automated + - patch + - nfs + - services + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.9 + block: + - name: "2.1.9 | PATCH | Ensure network file system services are not in use | Remove package" + when: + - not rhel9cis_nfs_server + - not rhel9cis_nfs_mask + ansible.builtin.package: + name: nfs-utils + state: absent + + - name: "2.1.9 | PATCH | Ensure network file system services are not in use | Mask service" + when: + - not rhel9cis_nfs_server + - rhel9cis_nfs_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: nfs-server.service + enabled: false + state: stopped + masked: true + +- name: "2.1.10 | PATCH | Ensure nis server services are not in use" + when: + - "'ypserv' in ansible_facts.packages" + - rhel9cis_rule_2_1_10 + tags: + - level1-server + - level1-workstation + - automated + - patch + - nis + - NIST800-53R5_CM-7 + - rule_2.1.10 + notify: Systemd_daemon_reload + block: + - name: "2.1.10 | PATCH | Ensure nis server services are not in use | Remove package" + when: + - not rhel9cis_nis_server + - not rhel9cis_nis_mask + ansible.builtin.package: + name: ypserv + state: absent + + - name: "2.1.10 | PATCH | Ensure nis server services are not in use | Mask service" + when: + - not rhel9cis_nis_server + - rhel9cis_nis_mask + ansible.builtin.systemd: + name: ypserv.service + enabled: false + state: stopped + masked: true + +- name: "2.1.11 | PATCH | Ensure print server services are not in use" + when: + - "'cups' in ansible_facts.packages" + - rhel9cis_rule_2_1_11 + tags: + - level1-server + - automated + - patch + - cups + - NIST800-53R5_CM-7 + - rule_2.1.11 + block: + - name: "2.1.11 | PATCH | Ensure print server services are not in use | Remove package" + when: + - not rhel9cis_print_server + - not rhel9cis_print_mask + ansible.builtin.package: + name: cups + state: absent + + - name: "2.1.11 | PATCH | Ensure print server services are not in use | Mask service" + when: + - not rhel9cis_print_server + - rhel9cis_print_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - "cups.socket" + - "cups.service" + +- name: "2.1.12 | PATCH | Ensure rpcbind services are not in use" + when: + - "'rpcbind' in ansible_facts.packages" + - rhel9cis_rule_2_1_12 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rpc + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.12 + block: + - name: "2.1.12 | PATCH | Ensure rpcbind services are not in use | Remove package" + when: + - not rhel9cis_rpc_server + - not rhel9cis_rpc_mask + ansible.builtin.package: + name: rpcbind + state: absent + + - name: "2.1.12 | PATCH | Ensure rpcbind services are not in use | Mask service" + when: + - not rhel9cis_rpc_server + - rhel9cis_rpc_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - rpcbind.service + - rpcbind.socket + +- name: "2.1.13 | PATCH | Ensure rsync services are not in use" + when: + - "'rsync-daemon' in ansible_facts.packages" + - rhel9cis_rule_2_1_13 + tags: + - level1-server + - level1-workstation + - automated + - patch + - rsync + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.13 + block: + - name: "2.1.13 | PATCH | Ensure rsync services are not in use | Remove package" + when: + - not rhel9cis_rsync_server + - not rhel9cis_rsync_mask + ansible.builtin.package: + name: rsync-daemon + state: absent + + - name: "2.1.13 | PATCH | Ensure rsync services are not in use | Mask service" + when: + - not rhel9cis_rsync_server + - rhel9cis_rsync_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'rsyncd.socket' + - 'rsyncd.service' + +- name: "2.1.14 | PATCH | Ensure snmp services are not in use" + when: + - "'net-snmp' in ansible_facts.packages" + - rhel9cis_rule_2_1_14 tags: - level1-server - level1-workstation + - automation - patch - - rule_2.1.2 + - snmp + - NIST800-53R5_CM-7 + - rule_2.1.14 + block: + - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Remove package" + when: + - not rhel9cis_net_snmp_server + - not rhel9cis_net_snmp_mask + ansible.builtin.package: + name: net-snmp + state: absent + + - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Mask service" + when: + - not rhel9cis_net_snmp_server + - rhel9cis_net_snmp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: snmpd.service + enabled: false + state: stopped + masked: true + +- name: "2.1.15 | PATCH | Ensure telnet server services are not in use" + when: + - "'telnet-server' in ansible_facts.packages" + - rhel9cis_rule_2_1_15 + tags: + - level1-server + - level1-workstation + - automated + - patch + - telnet + - NIST800-53R5_CM-7 + - NIST800-53R5_CM-11 + - rule_2.1.15 + block: + - name: "2.1.15 | PATCH | Ensure telnet server services are not in use | Remove package" + when: + - not rhel9cis_telnet_server + - not rhel9cis_telnet_mask + ansible.builtin.package: + name: telnet-server + state: absent + + - name: "2.1.15 | PATCH | Ensure telnet server services are not in use | Mask service" + when: + - not rhel9cis_telnet_server + - rhel9cis_telnet_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: telnet.socket + enabled: false + state: stopped + masked: true + +- name: "2.1.16 | PATCH | Ensure tftp server services are not in use" + when: + - "'tftp-server' in ansible_facts.packages" + - rhel9cis_rule_2_1_16 + tags: + - level1-server + - level1-workstation + - automated + - patch + - tftp + - NIST800-53R5_CM-7 + - rule_2.1.16 + block: + - name: "2.1.16 | PATCH | Ensure tftp server services are not in use | Remove package" + when: + - not rhel9cis_tftp_server + - not rhel9cis_tftp_mask + ansible.builtin.package: + name: tftp-server + state: absent + + - name: "2.1.16 | PATCH | Ensure tftp server services are not in use | Mask service" + when: + - not rhel9cis_tftp_server + - rhel9cis_tftp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: "{{ item }}" + enabled: false + state: stopped + masked: true + loop: + - 'tftp.socket' + - 'tftp.service' + +- name: "2.1.17 | PATCH | Ensure web proxy server services are not in use" + when: + - "'squid' in ansible_facts.packages" + - rhel9cis_rule_2_117 + tags: + - level1-server + - level1-workstation + - automation + - patch + - squid + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - rule_2.1.17 + block: + - name: "2.1.17 | PATCH | Ensure web proxy server services are not in use | Remove package" + when: + - not rhel9cis_squid_server + - not rhel9cis_squid_mask + ansible.builtin.package: + name: squid + state: absent + + - name: "2.1.17 | PATCH | Ensure web proxy server services are not in use | Mask service" + when: + - not rhel9cis_squid_server + - rhel9cis_squid_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: squid.service + enabled: false + state: stopped + masked: true + +- name: "2.1.18 | PATCH | Ensure web server services are not in use" + when: + - rhel9cis_rule_2_1_18 + tags: + - level1-server + - level1-workstation + - automated + - patch + - httpd + - nginx + - webserver + - NIST800-53R5_CM-7 + - rule_2.1.18 + block: + - name: "2.1.18 | PATCH | Ensure web server services are not in use | Remove httpd server" + when: + - not rhel9cis_httpd_server + - not rhel9cis_httpd_mask + - "'httpd' in ansible_facts.packages" + ansible.builtin.package: + name: httpd + state: absent + + - name: "2.1.18 | PATCH | Ensure web server services are not in use | Remove nginx server" + when: + - not rhel9cis_nginx_server + - not rhel9cis_nginx_mask + - "'nginx' in ansible_facts.packages" + ansible.builtin.package: + name: nginx + state: absent + + - name: "2.1.18 | PATCH | Ensure web server services are not in use | Mask httpd service" + when: + - not rhel9cis_httpd_server + - rhel9cis_httpd_mask + - "'httpd' in ansible_facts.packages" + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: httpd.service + enabled: false + state: stopped + masked: true + + - name: "2.1.18 | PATCH | Ensure web server services are not in use | Mask nginx service" + when: + - not rhel9cis_nginx_server + - rhel9cis_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.1.19 | PATCH | Ensure xinetd services are not in use" + when: + - "'xinetd' in ansible_facts.packages" + - rhel9cis_rule_2_1_19 + tags: + - level1-server + - level1-workstation + - automated + - patch + - xinetd + - NIST800-53R5_CM-7 + - rule_2.1.19 + block: + - name: "2.1.19 | PATCH | Ensure xinetd services are not in use | Remove package" + when: + - not rhel9cis_xinetd_server + - not rhel9cis_xinetd_mask + ansible.builtin.package: + name: xinetd + state: absent + + - name: "2.1.19 | PATCH | Ensure xinetd services are not in use | Mask service" + when: + - not rhel9cis_xinetd_server + - rhel9cis_xinetd_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: xinetd.service + enabled: false + state: stopped + masked: true + +- name: "2.1.20 | PATCH | Ensure X window server services are not in use" + when: + - not rhel9cis_xwindow_server + - "'xorg-x11-server-common' in ansible_facts.packages" + - rhel9cis_rule_2_1_20 + tags: + - level1-server + - level1-workstation + - automated + - patch + - xwindow + - NIST800-53R5_CM-11 + - rule_2.1.20 + ansible.builtin.package: + name: xorg-x11-server-common + state: absent + +- name: "2.1.21 | PATCH | Ensure mail transfer agents are configured for local-only mode" + when: + - not rhel9cis_is_mail_server + - "'postfix' in ansible_facts.packages" + - rhel9cis_rule_2_1_21 + tags: + - level1-server + - level1-workstation + - automated + - patch + - postfix + - NIST800-53R5_CM-7 + - rule_2.1.21 + notify: Restart_postfix + ansible.builtin.lineinfile: + path: /etc/postfix/main.cf + regexp: "^(#)?inet_interfaces" + line: "inet_interfaces = loopback-only" + +- name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface" + when: + - rhel9cis_rule_2_1_22 + tags: + - level1-server + - level1-workstation + - manual + - audit + - services + - NIST800-53R5_CM-7 + - rule_2.1.22 + vars: + warn_control_id: '2.1.22' + block: + - name: "2.1.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.1.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.1.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.2.x.yml b/tasks/section_2/cis_2.2.x.yml index 563ec4b..cdd03b8 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -1,348 +1,86 @@ --- -- name: "2.2.1 | PATCH | Ensure xorg-x11-server-common is not installed" +- name: "2.2.1 | PATCH | Ensure ftp client is not installed" + when: + - not rhel9cis_ftp_client + - "'ftp' in ansible_facts.packages" + - rhel9cis_rule_2_2_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - ftp + - NIST800-53R5_CM-7 + - rule_2.2.1 ansible.builtin.package: - name: xorg-x11-server-common - state: absent - when: - - rhel9cis_rule_2_2_1 - - "'xorg-x11-server-common' in ansible_facts.packages" - - not rhel9cis_gui - tags: - - level1-server - - patch - - x11 - - rule_2.2.1 + name: ftp + state: absent -- name: "2.2.2 | PATCH | Ensure Avahi Server is not installed" +- name: "2.2.2 | PATCH | Ensure ldap client is not installed" + when: + - not rhel9cis_openldap_clients_required + - "'openldap-clients' in ansible_facts.packages" + - rhel9cis_rule_2_2_2 + tags: + - level2-server + - level2-workstation + - automated + - patch + - ldap + - NIST800-53R5_CM-7 + - rule_2.2.2 ansible.builtin.package: - name: - - avahi-autoipd - - avahi - state: absent - when: - - rhel9cis_rule_2_2_2 - - not rhel9cis_avahi_server - - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" - tags: - - level1-server - - level2-workstation - - patch - - avahi - - rule_2.2.2 + name: openldap-clients + state: absent -- name: "2.2.3 | PATCH | Ensure CUPS is not installed" +- name: "2.2.3 | PATCH | Ensure nis client is not installed" + when: + - not rhel9cis_ypbind_required + - "'ypbind' in ansible_facts.packages" + - rhel9cis_rule_2_2_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - nis + - NIST800-53R5_CM-7 + - rule_2.2.3 ansible.builtin.package: - name: cups - state: absent - when: - - not rhel9cis_cups_server - - "'cups' in ansible_facts.packages" - - rhel9cis_rule_2_2_3 - tags: - - level1-server - - patch - - cups - - rule_2.2.3 + name: ypbind + state: absent -- name: "2.2.4 | PATCH | Ensure DHCP Server is not installed" +- name: "2.2.4 | PATCH | Ensure telnet client is not installed" + when: + - not rhel9cis_telnet_required + - "'telnet' in ansible_facts.packages" + - rhel9cis_rule_2_2_4 + tags: + - level1-server + - level1-workstation + - automated + - patch + - telnet + - NIST800-53R5_CM-7 + - rule_2.2.4 ansible.builtin.package: - name: dhcp-server - state: absent - when: - - not rhel9cis_dhcp_server - - "'dhcp-server' in ansible_facts.packages" - - rhel9cis_rule_2_2_4 - tags: - - level1-server - - level1-workstation - - patch - - dhcp - - rule_2.2.4 + name: telnet + state: absent -- name: "2.2.5 | PATCH | Ensure DNS Server is not installed" +- name: "2.2.5 | PATCH | Ensure TFTP client is not installed" + when: + - not rhel9cis_tftp_client + - "'tftp' in ansible_facts.packages" + - rhel9cis_rule_2_2_5 + tags: + - level1-server + - level1-workstation + - automated + - patch + - tftp + - NIST800-53R5_CM-7 + - rule_2.2.5 ansible.builtin.package: - name: bind - state: absent - when: - - not rhel9cis_dns_server - - "'bind' in ansible_facts.packages" - - rhel9cis_rule_2_2_5 - tags: - - level1-server - - level1-workstation - - patch - - dns - - rule_2.2.5 - -- name: "2.2.6 | PATCH | Ensure VSFTP Server is not installed" - ansible.builtin.package: - name: vsftpd - state: absent - when: - - not rhel9cis_vsftpd_server - - "'vsftpd' in ansible_facts.packages" - - rhel9cis_rule_2_2_6 - tags: - - level1-server - - level1-workstation - - patch - - vsftpd - - rule_2.2.6 - -- name: "2.2.7 | PACH | Ensure TFTP Server is not installed" - ansible.builtin.package: - name: tftp-server - state: absent - when: - - not rhel9cis_tftp_server - - "'tftp-server' in ansible_facts.packages" - - rhel9cis_rule_2_2_7 - tags: - - level1-server - - level1-workstation - - patch - - tftp - - rule_2.2.7 - -- name: "2.2.8 | PATCH | Ensure a web server is not installed" - block: - - name: "2.2.8 | PATCH | Ensure a web server is not installed | Remove httpd server" - ansible.builtin.package: - name: httpd - state: absent - when: - - not rhel9cis_httpd_server - - "'httpd' in ansible_facts.packages" - - - name: "2.2.8 | PATCH | Ensure a web server is not installed | Remove nginx server" - ansible.builtin.package: - name: nginx - state: absent - when: - - not rhel9cis_nginx_server - - "'nginx' in ansible_facts.packages" - when: - - rhel9cis_rule_2_2_8 - tags: - - level1-server - - level1-workstation - - patch - - httpd - - nginx - - webserver - - rule_2.2.8 - -- name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed" - block: - - name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed" - ansible.builtin.package: - name: - - dovecot - state: absent - when: - - not rhel9cis_dovecot_server - - "'dovecot' in ansible_facts.packages" - - - name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed" - ansible.builtin.package: - name: - - cyrus-imapd - state: absent - when: - - not rhel9cis_imap_server - - "'cyrus-imapd' in ansible_facts.packages" - - when: - - rhel9cis_rule_2_2_9 - tags: - - level1-server - - level1-workstation - - patch - - dovecot - - imap - - pop3 - - rule_2.2.9 - -- name: "2.2.10 | PATCH | Ensure Samba is not enabled" - ansible.builtin.package: - name: samba - state: absent - when: - - not rhel9cis_samba_server - - "'samba' in ansible_facts.packages" - - rhel9cis_rule_2_2_10 - tags: - - level1-server - - level1-workstation - - patch - - samba - - rule_2.2.10 - -- name: "2.2.11 | PATCH | Ensure HTTP Proxy Server is not installed" - ansible.builtin.package: - name: squid - state: absent - when: - - not rhel9cis_squid_server - - "'squid' in ansible_facts.packages" - - rhel9cis_rule_2_2_11 - tags: - - level1-server - - level1-workstation - - patch - - squid - - rule_2.2.11 - -- name: "2.2.12 | PATCH | Ensure net-snmp is not installed" - ansible.builtin.package: - name: net-snmp - state: absent - when: - - not rhel9cis_snmp_server - - "'net-snmp' in ansible_facts.packages" - - rhel9cis_rule_2_2_12 - tags: - - level1-server - - level1-workstation - - patch - - snmp - - rule_2.2.12 - -- name: "2.2.13 | PATCH | Ensure telnet-server is not installed" - ansible.builtin.package: - name: telnet-server - state: absent - when: - - not rhel9cis_telnet_server - - "'telnet-server' in ansible_facts.packages" - - rhel9cis_rule_2_2_13 - tags: - - level1-server - - level1-workstation - - patch - - telnet - - rule_2.2.13 - -- name: "2.2.14 | PATCH | Ensure dnsmasq is not installed" - ansible.builtin.package: - name: dnsmasq - state: absent - when: - - not rhel9cis_dnsmasq_server - - "'dnsmasq' in ansible_facts.packages" - - rhel9cis_rule_2_2_14 - tags: - - level1-server - - level1-workstation - - patch - - dnsmasq - - rule_2.2.14 - -- name: "2.2.15 | 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 - when: - - not rhel9cis_is_mail_server - - "'postfix' in ansible_facts.packages" - - rhel9cis_rule_2_2_15 - tags: - - level1-server - - level1-workstation - - patch - - postfix - - rule_2.2.15 - -# The name title of the service says mask the service, but the fix allows for both options -# Options available in default/main if to remove the package default is false just mask the server service -- name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked" - block: - - name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | remove package" - ansible.builtin.package: - name: nfs-utils - state: absent - when: - - not rhel9cis_use_nfs_server - - not rhel9cis_use_nfs_service - - - name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | mask service" - ansible.builtin.systemd: - name: nfs-server - masked: true - state: stopped - when: - - rhel9cis_use_nfs_server - - not rhel9cis_use_nfs_service - when: - - "'nfs-utils' in ansible_facts.packages" - - rhel9cis_rule_2_2_16 - tags: - - level1-server - - level1-workstation - - patch - - nfs - - services - - rule_2.2.16 - -# The name title of the service says mask the service, but the fix allows for both options -# Options available in default/main if to remove the package default is false just mask the server service -- name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked" - block: - - name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | remove package" - ansible.builtin.package: - name: rpcbind - state: absent - when: - - not rhel9cis_use_rpc_server - - not rhel9cis_use_rpc_service - - - name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | mask service" - ansible.builtin.systemd: - name: rpcbind.socket - masked: true - state: stopped - when: - - rhel9cis_use_rpc_server - - not rhel9cis_use_rpc_service - when: - - "'rpcbind' in ansible_facts.packages" - - rhel9cis_rule_2_2_17 - tags: - - level1-server - - level1-workstation - - patch - - rpc - - rule_2.2.17 - -# The name title of the service says mask the service, but the fix allows for both options -# Options available in default/main if to remove the package default is false just mask the server service -- name: "2.2.18 | PATCH | Ensure rsync service is not enabled " - block: - - name: "2.2.18 | PATCH | Ensure rsync-daemon is not installed or the rsync service is masked | remove package" - ansible.builtin.package: - name: rsync-daemon - state: absent - when: - - not rhel9cis_use_rsync_server - - not rhel9cis_use_rsync_service - - - name: "2.2.18 | PATCH | Ensure rsync service is not enabled | mask service" - ansible.builtin.systemd: - name: rsyncd - masked: true - state: stopped - when: - - rhel9cis_use_rsync_server - - not rhel9cis_use_rsync_service - when: - - "'rsync' in ansible_facts.packages" - - rhel9cis_rule_2_2_18 - tags: - - level1-server - - level1-workstation - - patch - - rsync - - rule_2.2.18 + name: tftp + state: absent diff --git a/tasks/section_2/cis_2.3.x.yml b/tasks/section_2/cis_2.3.x.yml index c576a65..dacd624 100644 --- a/tasks/section_2/cis_2.3.x.yml +++ b/tasks/section_2/cis_2.3.x.yml @@ -1,61 +1,51 @@ --- -- name: "2.3.1 | PATCH | Ensure telnet client is not installed" - ansible.builtin.package: - name: telnet - state: absent +- name: "2.3.1 | PATCH | Ensure time synchronization is in use" when: - - not rhel9cis_telnet_required - - "'telnet' in ansible_facts.packages" - - rhel9cis_rule_2_3_1 + - rhel9cis_rule_2_3_1 + - not system_is_container tags: - - level1-server - - level1-workstation - - patch - - telnet - - rule_2.3.1 + - level1-server + - level1-workstation + - patch + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - rule_2.3.1 + ansible.builtin.package: + name: chrony + state: present -- name: "2.3.2 | PATCH | Ensure LDAP client is not installed" - ansible.builtin.package: - name: openldap-clients - state: absent +- name: "2.3.2 | PATCH | Ensure chrony is configured" when: - - not rhel9cis_openldap_clients_required - - "'openldap-clients' in ansible_facts.packages" - - rhel9cis_rule_2_3_2 + - rhel9cis_rule_2_3_2 + - not system_is_container tags: - - level1-server - - level1-workstation - - patch - - ldap - - rule_2.3.2 + - level1-server + - level1-workstation + - patch + - rule_2.3.2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + ansible.builtin.template: + src: etc/chrony.conf.j2 + dest: /etc/chrony.conf + owner: root + group: root + mode: '0644' -- name: "2.3.3 | PATCH | Ensure TFTP client is not installed" - ansible.builtin.package: - name: tftp - state: absent +- name: "2.3.3 | PATCH | Ensure chrony is not run as the root user" when: - - not rhel9cis_tftp_client - - "'tftp' in ansible_facts.packages" - - rhel9cis_rule_2_3_3 + - rhel9cis_rule_2_3_3 + - not system_is_container tags: - - level1-server - - level1-workstation - - patch - - tftp - - rule_2.3.3 - -- name: "2.3.4 | PATCH | Ensure FTP client is not installed" - ansible.builtin.package: - name: ftp - state: absent - when: - - not rhel9cis_ftp_client - - "'ftp' in ansible_facts.packages" - - rhel9cis_rule_2_3_4 - tags: - - level1-server - - level1-workstation - - patch - - ftp - - rule_2.3.4 + - level1-server + - level1-workstation + - patch + - rule_2.3.3 + ansible.builtin.lineinfile: + path: /etc/sysconfig/chronyd + regexp: '^OPTIONS="(?!.* -u chrony.*)(.*)"' + line: OPTIONS="\1 -u chrony" + create: true + backrefs: true + mode: '0644' diff --git a/tasks/section_2/cis_2.4.yml b/tasks/section_2/cis_2.4.yml deleted file mode 100644 index 15048f6..0000000 --- a/tasks/section_2/cis_2.4.yml +++ /dev/null @@ -1,40 +0,0 @@ ---- - -- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked" - block: - - name: "2.4 | AUDIT | Ensure nonessential services listening on the system 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: rhel9cis_2_4_services - - - name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Get list of sockets" - ansible.builtin.shell: systemctl list-units --type=socket - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_2_4_sockets - - - name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Display list of services" - ansible.builtin.debug: - msg: - - "Warning!! Below are the list of services and sockets, both active and inactive" - - "Please review to make sure all are essential" - - "{{ rhel9cis_2_4_services.stdout_lines }}" - - "{{ rhel9cis_2_4_sockets.stdout_lines }}" - - - name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Warn Count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '2.4' - when: - - rhel9cis_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 3e8996a..02ae663 100644 --- a/tasks/section_2/main.yml +++ b/tasks/section_2/main.yml @@ -1,17 +1,17 @@ --- -- name: "SECTION | 2.1 | Time Synchronization" +- name: "SECTION | 2.1 | Special Purpose Services" ansible.builtin.import_tasks: file: cis_2.1.x.yml -- name: "SECTION | 2.2 | Special Purpose Services" +- name: "SECTION | 2.2 | Service Clients" ansible.builtin.import_tasks: file: cis_2.2.x.yml -- name: "SECTION | 2.3 | Service Clients" +- name: "SECTION | 2.3 | Time Synchronization" ansible.builtin.import_tasks: file: cis_2.3.x.yml -- name: "SECTION | 2.4 | Nonessential services removed" +- name: "SECTION | 2.4 | Job Schedulers" ansible.builtin.import_tasks: - file: cis_2.4.yml + file: cis_2.4.x.yml From a53569a474995be8e7babcefcd8ab6cbb71c70d4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 22 Jul 2024 12:43:35 +0100 Subject: [PATCH 013/327] section 2 v2.0.0 update Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 + tasks/section_2/cis_2.4.x.yml | 182 ++++++++++++++++++++++++++++++++++ templates/etc/chrony.conf.j2 | 101 +++++-------------- 3 files changed, 207 insertions(+), 78 deletions(-) create mode 100644 tasks/section_2/cis_2.4.x.yml diff --git a/tasks/main.yml b/tasks/main.yml index b2c2695..e13477d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -117,6 +117,8 @@ - rhel9cis_crypto_policy_module | length > 0 tags: - rule_1.6.1 + - crypto + - NIST800-53R5_SC-6 ansible.builtin.assert: that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules fail_msg: "Crypto policy module is not a permitted version" diff --git a/tasks/section_2/cis_2.4.x.yml b/tasks/section_2/cis_2.4.x.yml new file mode 100644 index 0000000..072fa0b --- /dev/null +++ b/tasks/section_2/cis_2.4.x.yml @@ -0,0 +1,182 @@ +--- + +- name: "2.4.1.1 | PATCH | Ensure cron daemon is enabled" + when: + - rhel9cis_rule_2_4_1_1 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.service: + name: crond + enabled: true + +- name: "2.4.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" + when: + - rhel9cis_rule_2_4_1_2 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/crontab + owner: root + group: root + mode: og-rwx + +- name: "2.4.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" + when: + - rhel9cis_rule_2_4_1_3 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/cron.hourly + state: directory + owner: root + group: root + mode: og-rwx + +- name: "2.4.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" + when: + - rhel9cis_rule_2_4_1_4 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.4 + ansible.builtin.file: + path: /etc/cron.daily + state: directory + owner: root + group: root + mode: og-rwx + +- name: "2.4.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" + when: + - rhel9cis_rule_2_4_1_5 + tags: + - level1-server + - level1-workstation + - patch + - rule_2.4.1.5 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/cron.weekly + state: directory + owner: root + group: root + mode: og-rwx + +- name: "2.4.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" + when: + - rhel9cis_rule_2_4_1_6 + tags: + - level1-server + - level1-workstation + - patch + - rule_2.4.1.6 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/cron.monthly + state: directory + owner: root + group: root + mode: og-rwx + +- name: "2.4.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" + when: + - rhel9cis_rule_2_4_1_7 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/cron.d + state: directory + owner: root + group: root + mode: '0700' + +- name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users" + when: + - rhel9cis_rule_2_4_1_8 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.1.8 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + block: + - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Remove cron.deny" + ansible.builtin.file: + path: /etc/cron.deny + state: absent + + - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Check if cron.allow exists" + ansible.builtin.stat: + path: "/etc/cron.allow" + register: rhel9cis_2_4_1_8_cron_allow_state + + - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Ensure cron.allow is restricted to authorized users" + ansible.builtin.file: + path: /etc/cron.allow + state: '{{ "file" if rhel9cis_2_4_1_8_cron_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: u-x,g-wx,o-rwx + +- name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users" + when: + - rhel9cis_rule_2_4_2_1 + tags: + - level1-server + - level1-workstation + - patch + - cron + - rule_2.4.2.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + block: + - name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Remove at.deny" + ansible.builtin.file: + path: /etc/at.deny + state: absent + + - name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" + ansible.builtin.stat: + path: "/etc/at.allow" + register: rhel9cis_rule_2_4_2_1_at_allow_state + + - name: "2.4.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 rhel9cis_rule_2_4_2_1_at_allow_state.stat.exists else "touch" }}' + owner: root + group: root + mode: u-x,g-wx,o-rwx diff --git a/templates/etc/chrony.conf.j2 b/templates/etc/chrony.conf.j2 index a1837a9..cc5cd84 100644 --- a/templates/etc/chrony.conf.j2 +++ b/templates/etc/chrony.conf.j2 @@ -1,97 +1,42 @@ -## {{ ansible_managed }} - -# This the default chrony.conf file for the Debian chrony package. After -# editing this file use the command 'invoke-rc.d chrony restart' to make -# your changes take effect. John Hasler 1998-2008 - -# See www.pool.ntp.org for an explanation of these servers. Please -# consider joining the project if possible. If you can't or don't want to -# use these servers I suggest that you try your ISP's nameservers. We mark -# the servers 'offline' so that chronyd won't try to connect when the link -# is down. Scripts in /etc/ppp/ip-up.d and /etc/ppp/ip-down.d use chronyc -# commands to switch it on when a dialup link comes up and off when it goes -# down. Code in /etc/init.d/chrony attempts to determine whether or not -# the link is up at boot time and set the online status accordingly. If -# you have an always-on connection such as cable omit the 'offline' -# directive and chronyd will default to online. -# -# Note that if Chrony tries to go "online" and dns lookup of the servers -# fails they will be discarded. Thus under some circumstances it is -# better to use IP numbers than host names. +{{ ansible_managed | comment }} +# Use public servers from the pool.ntp.org project. +# Please consider joining the pool (http://www.pool.ntp.org/join.html). {% for server in rhel9cis_time_synchronization_servers -%} server {{ server }} {{ rhel9cis_chrony_server_options }} {% endfor %} -# Look here for the admin password needed for chronyc. The initial -# password is generated by a random process at install time. You may -# change it if you wish. - -keyfile /etc/chrony.keys - # Record the rate at which the system clock gains/losses time. driftfile /var/lib/chrony/drift # Allow the system clock to be stepped in the first three updates # if its offset is larger than 1 second. -makestep {{ rhel9cis_chrony_server_makestep }} +makestep 1.0 3 # Enable kernel synchronization of the real-time clock (RTC). -{% if not rhel9cis_chrony_server_rtcsync %}#{% endif %}rtcsync +rtcsync + +# Enable hardware timestamping on all interfaces that support it. +#hwtimestamp * # Increase the minimum number of selectable sources required to adjust # the system clock. -minsources {{ rhel9cis_chrony_server_minsources }} +#minsources 2 -# Comment this line out to turn off logging. +# Allow NTP client access from local network. +#allow 192.168.0.0/16 -log tracking measurements statistics +# Serve time even if not synchronized to a time source. +#local stratum 10 + +# Specify file containing keys for NTP authentication. +keyfile /etc/chrony.keys + +# Get TAI-UTC offset and leap seconds from the system tz database. +leapsectz right/UTC + +# Specify directory for log files. logdir /var/log/chrony -# Stop bad estimates upsetting machine clock. - -maxupdateskew 100.0 - -# Dump measurements when daemon exits. - -dumponexit - -# Specify directory for dumping measurements. - -dumpdir /var/lib/chrony - -# Let computer be a server when it is unsynchronised. - -local stratum 10 - -# Allow computers on the unrouted nets to use the server. - -#allow 10/8 -#allow 192.168/16 -#allow 172.16/12 - -# This directive forces `chronyd' to send a message to syslog if it -# makes a system clock adjustment larger than a threshold value in seconds. - -logchange 0.5 - -# This directive defines an email address to which mail should be sent -# if chronyd applies a correction exceeding a particular threshold to the -# system clock. - -# mailonchange root@localhost 0.5 - -# This directive tells chrony to regulate the real-time clock and tells it -# Where to store related data. It may not work on some newer motherboards -# that use the HPET real-time clock. It requires enhanced real-time -# support in the kernel. I've commented it out because with certain -# combinations of motherboard and kernel it is reported to cause lockups. - -# rtcfile /var/lib/chrony/chrony.rtc - -# If the last line of this file reads 'rtconutc' chrony will assume that -# the CMOS clock is on UTC (GMT). If it reads '# rtconutc' or is absent -# chrony will assume local time. The line (if any) was written by the -# chrony postinst based on what it found in /etc/default/rcS. You may -# change it if necessary. -rtconutc +# Select which information is logged. +#log measurements statistics tracking From 3a027af3048ca18102b1f9ceba7cb07688672032 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 23 Jul 2024 08:20:09 +0100 Subject: [PATCH 014/327] section 2 updates Signed-off-by: Mark Bolwell --- defaults/main.yml | 252 ++++++++++++++++------------------------------ 1 file changed, 89 insertions(+), 163 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 3ce2c46..12ca4a2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -28,7 +28,7 @@ os_check: true # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. # If you do not want the tasks from that section to get executed you simply set the variable to "false". rhel9cis_section1: true -rhel9cis_section2: false +rhel9cis_section2: true rhel9cis_section3: false rhel9cis_section4: false rhel9cis_section5: false @@ -229,31 +229,54 @@ rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true # Section 2 rules are controling Services (Special Purpose Services, and service clients) +## Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true +rhel9cis_rule_2_1_3: true +rhel9cis_rule_2_1_4: true +rhel9cis_rule_2_1_5: true +rhel9cis_rule_2_1_6: true +rhel9cis_rule_2_1_7: true +rhel9cis_rule_2_1_8: true +rhel9cis_rule_2_1_9: true +rhel9cis_rule_2_1_10: true +rhel9cis_rule_2_1_11: true +rhel9cis_rule_2_1_12: true +rhel9cis_rule_2_1_13: true +rhel9cis_rule_2_1_14: true +rhel9cis_rule_2_1_15: true +rhel9cis_rule_2_1_16: true +rhel9cis_rule_2_1_17: true +rhel9cis_rule_2_1_18: true +rhel9cis_rule_2_1_19: true +rhel9cis_rule_2_1_20: true +rhel9cis_rule_2_1_21: true +rhel9cis_rule_2_1_22: true + +## Configure Client Services rhel9cis_rule_2_2_1: true rhel9cis_rule_2_2_2: true rhel9cis_rule_2_2_3: true rhel9cis_rule_2_2_4: true rhel9cis_rule_2_2_5: true -rhel9cis_rule_2_2_6: true -rhel9cis_rule_2_2_7: true -rhel9cis_rule_2_2_8: true -rhel9cis_rule_2_2_9: true -rhel9cis_rule_2_2_10: true -rhel9cis_rule_2_2_11: true -rhel9cis_rule_2_2_12: true -rhel9cis_rule_2_2_13: true -rhel9cis_rule_2_2_14: true -rhel9cis_rule_2_2_15: true -rhel9cis_rule_2_2_16: true -rhel9cis_rule_2_2_17: true -rhel9cis_rule_2_2_18: true + +## Configure Time Synchronization rhel9cis_rule_2_3_1: true rhel9cis_rule_2_3_2: true rhel9cis_rule_2_3_3: true -rhel9cis_rule_2_3_4: true -rhel9cis_rule_2_4: true + +## Job Schedulers +### cron +rhel9cis_rule_2_4_1_1: true +rhel9cis_rule_2_4_1_2: true +rhel9cis_rule_2_4_1_3: true +rhel9cis_rule_2_4_1_4: true +rhel9cis_rule_2_4_1_5: true +rhel9cis_rule_2_4_1_6: true +rhel9cis_rule_2_4_1_7: true +rhel9cis_rule_2_4_1_8: true +### at +rhel9cis_rule_2_4_2_1: true # Section 3 rules are used for securely configuring the network configuration(kernel params, ACL, Firewall settings) rhel9cis_rule_3_1_1: true @@ -562,6 +585,9 @@ rhel9cis_selinux_enforce: enforcing # Whether or not to run tasks related to auditing/patching the desktop environment + +## 1.8 GDM graphical interface +rhel9cis_gui: false ## Section 2. Services ## Section 2.1 Time Synchronization @@ -597,162 +623,62 @@ rhel9cis_chrony_server_makestep: "1.0 3" # improve the reliability, because multiple sources will need to correspond with each other. rhel9cis_chrony_server_minsources: 2 -## Section 2.2 Special Purposes -# Service configuration variables (boolean). -# Set the respective variable to true to keep the service, -# otherwise the service is stopped and disabled - -## Control 1.8.10-10, 2.2.1 -# This variable governs whether rules dealing with GUI specific packages(and/or their settings) should -# be executed either to: -# - secure GDM, if GUI is needed('rhel9cis_gui: true') -# - or remove GDM and X-Windows-system, if no GUI is needed('rhel9cis_gui: false') -rhel9cis_gui: false -## Control 2.2.2 - Ensure Avahi Server is not installed -# This variable, when set to false, will specify that Avahi Server packages should be uninstalled. +# 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 +rhel9cis_autofs_services: false +rhel9cis_autofs_mask: true rhel9cis_avahi_server: false -## Control 2.2.3 - Ensure CUPS is not installed -# This variable, when set to false, will specify that CUPS(Common UNIX Printing System) package should be uninstalled. -rhel9cis_cups_server: false -## Control 2.2.4 - Ensure DHCP Server is not installed -# This variable, when set to false, will specify that DHCP server package should be uninstalled. +rhel9cis_avahi_mask: false rhel9cis_dhcp_server: false -## Control 2.2.5 - Ensure DNS Server is not installed -# This variable, when set to false, will specify that DNS server package should be uninstalled. +rhel9cis_dhcp_mask: false rhel9cis_dns_server: false -## Control 2.2.14 - Ensure dnsmasq is not installed -# This variable, when set to false, will specify that dnsmasq package should be uninstalled. +rhel9cis_dns_mask: false rhel9cis_dnsmasq_server: false -## Control 2.2.6 - Ensure VSFTP Server is not installed -# This variable, when set to false, will specify that VSFTP server package should be uninstalled. -rhel9cis_vsftpd_server: false -## Control 2.2.7 - Ensure TFTP Server is not installed -# This variable, when set to false, will specify that TFTP server package should be uninstalled. -rhel9cis_tftp_server: false -## Control 2.2.8 - Ensure a web server is not installed - HTTPD -# This variable, when set to false, will specify that webserver packages(HTTPD) should be uninstalled. -rhel9cis_httpd_server: false -## Control 2.2.8 - Ensure a web server is not installed - NGINX -# This variable, when set to false, will specify that webserver packages(NGINX) should be uninstalled. -rhel9cis_nginx_server: false -## Control 2.2.9 - Ensure IMAP and POP3 server is not installed - dovecot -# This variable, when set to false, will specify that IMAP and POP3 servers(dovecot) should be uninstalled. -rhel9cis_dovecot_server: false -## Control 2.2.9 - Ensure IMAP and POP3 server is not installed - cyrus-imapd -# This variable, when set to false, will specify that IMAP and POP3 servers(cyrus-imapd) should be uninstalled. -rhel9cis_imap_server: false -## Control 2.2.10 - Ensure Samba is not enabled -# This variable, when set to false, will specify that 'samba' package should be uninstalled. +rhel9cis_dnsmasq_mask: false rhel9cis_samba_server: false -## Control 2.2.11 - Ensure HTTP Proxy Server is not installed -# This variable, when set to false, will specify that 'squid' package should be uninstalled. -rhel9cis_squid_server: false -## Control 2.2.12 - Ensure net-snmp is not installed -# This variable, when set to false, will specify that 'net-snmp' package should be uninstalled. -rhel9cis_snmp_server: false -## Control 2.2.13 - Ensure telnet-server is not installed -# This variable, when set to false, will specify that 'telnet-server' package should be uninstalled. +rhel9cis_samba_mask: false +rhel9cis_ftp_server: false +rhel9cis_ftp_mask: false +rhel9cis_message_server: false # This is for messaging dovecot and cyrus-imap +rhel9cis_message_mask: false +rhel9cis_nfs_server: true +rhel9cis_nfs_mask: true +rhel9cis_nis_server: true # set to mask if nis client required +rhel9cis_nis_mask: false +rhel9cis_print_server: false # replaces cups +rhel9cis_print_mask: false +rhel9cis_rpc_server: true +rhel9cis_rpc_mask: true +rhel9cis_rsync_server: false +rhel9cis_rsync_mask: false +rhel9cis_net_snmp_server: false +rhel9cis_net_snmp_mask: false rhel9cis_telnet_server: false -## Control 2.2.15 - Ensure mail transfer agent is configured for local-only mode -# This variable, when system is NOT a mailserver, will configure Postfix to listen only on the loopback interface(the virtual -# network interface that the server uses to communicate internally. +rhel9cis_telnet_mask: false +rhel9cis_tftp_server: false +rhel9cis_tftp_mask: false +rhel9cis_squid_server: false +rhel9cis_squid_mask: false +rhel9cis_httpd_server: false +rhel9cis_httpd_mask: false +rhel9cis_nginx_server: false +rhel9cis_nginx_mask: false +rhel9cis_xinetd_server: false +rhel9cis_xinetd_mask: false +rhel9cis_xwindow_server: false # will remove mask not an option rhel9cis_is_mail_server: false -# Note the options -# Client package configuration variables. -# Packages are used for client services and Server- only remove if you dont use the client service -# Set the respective variable to `true` to keep the -# client package, otherwise it is uninstalled (false). - -## Control 2.2.16 - Ensure nfs-utils is not installed or the nfs-server service is masked" -# This variable specifies if the usage of NFS SERVER is needed. Execution of the rule which secures (by uninstalling or masking service) -# NFS(if it's NOT needed) will depend on the var used in conjunction('rhel9cis_use_nfs_service') with current one, respectively: -# - if Server IS NOT needed('false') and: -# - Service IS NOT needed('rhel9cis_use_nfs_service: false'): 'nfs-utils' package will be removed -# - Service IS needed('rhel9cis_use_nfs_service: true'): impossible to need the service without the server -# - if Server IS needed('true') and: -# - Service IS NOT needed('rhel9cis_use_nfs_service: false'): 'nfs-server' service will be masked -# - Service IS needed('rhel9cis_use_nfs_service: true'): Rule will be SKIPPED. -# | Server | Service | Result | -# |---------|---------|-----------------------------------------------------------| -# | false | false | Remove package | -# | false | true | Needing 'service' without needing 'server' makes no sense | -# | true | false | Mask 'service' | -# | true | true | SKIP RULE, BOTH 'service' and 'server' are required | -rhel9cis_use_nfs_server: false -## Control 2.2.16 - Ensure nfs-utils is not installed or the nfs-server service is masked. -# This variable specifies if the usage of NFS SERVICE is needed. If it's: -# - needed('true'): rule which uninstalls/masks-service WILL NOT be executed at all -# - not needed('false'): rule which uninstalls/masks-service WILL be executed, its behavior being -# controlled by the var used in conjunction with current one: -# - removing 'nfs-utils' package('rhel9cis_use_nfs_server' set to 'false') -# - masking the 'nfs-server' service('rhel9cis_use_nfs_server' set to 'true') -rhel9cis_use_nfs_service: false - -## Control 2.2.17 - Ensure rpcbind is not installed or the rpcbind services are masked -# This variable specifies if the usage of RPC SERVER is needed. Execution of the rule which secures (by uninstalling or masking service) -# RPC(if it's NOT needed) will depend on the var used in conjunction('rhel9cis_use_rpc_service') with current one, respectively: -# - if Server IS NOT needed('false') and: -# - Service IS NOT needed('rhel9cis_use_rpc_service: false'): 'rpcbind' package will be removed -# - Service IS needed('rhel9cis_use_rpc_service: true'): impossible to need the service without the server -# - if Server IS needed('true') and: -# - Service IS NOT needed('rhel9cis_use_rpc_service: false'): 'rpcbind.socket' service will be masked -# - Service IS needed('rhel9cis_use_rpc_service: true'): Rule will be SKIPPED. -# | Server | Service | Result | -# |---------|---------|-----------------------------------------------------------| -# | false | false | Remove package | -# | false | true | Needing 'service' without needing 'server' makes no sense | -# | true | false | Mask 'service' | -# | true | true | SKIP RULE, BOTH 'service' and 'server' are required | -rhel9cis_use_rpc_server: false -## Control 2.2.17 - Ensure rpcbind is not installed or the rpcbind services are masked -# This variable specifies if the usage of RPC SERVICE is needed. If it's: -# - needed('true'): rule which uninstalls/masks-service WILL NOT be executed at all -# - not needed('false'): rule which uninstalls/masks-service WILL be executed, its behavior being controlled by the var -# used in conjunction with current one: -# - removing 'rpcbind' package('rhel9cis_use_rpc_server' set to 'false') -# - masking the 'rpcbind.socket' service('rhel9cis_use_rpc_server' set to 'true') -rhel9cis_use_rpc_service: false - -## Control 2.2.18 - Ensure rsync service is not enabled -# This variable specifies if the usage of RSYNC SERVER is needed. Execution of the rule which secures (by uninstalling or masking service) -# RSYNC(if it's NOT needed) will depend on the var used in conjunction('rhel9cis_use_rsync_service') with current one, respectively: -# - if Server IS NOT needed('false') and: -# - Service IS NOT needed('rhel9cis_use_rsync_service: false'): 'rsync-daemon' package will be removed -# - Service IS needed('rhel9cis_use_rsync_service: true'): impossible to need the service without the server -# - if Server IS needed('true') and: -# - Service IS NOT needed('rhel9cis_use_rsync_service: false'): 'rsyncd' service will be masked -# - Service IS needed('rhel9cis_use_rsync_service: true'): Rule will be SKIPPED. -# | Server | Service | Result | -# |---------|---------|-----------------------------------------------------------| -# | false | false | Remove package | -# | false | true | Needing 'service' without needing 'server' makes no sense | -# | true | false | Mask 'service' | -# | true | true | SKIP RULE, BOTH 'service' and 'server' are required | -rhel9cis_use_rsync_server: false -## Control 2.2.18 - Ensure rsync service is not enabled -# This variable specifies if the usage of RSYNC SERVICE is needed. If it's: -# - needed('true'): rule which uninstalls/masks-service WILL NOT be executed at all -# - not needed('false'): rule which uninstalls/masks-service WILL be executed, its behavior being controlled by the var -# used in conjunction with current one: -# - removing 'rsync-daemon' package('rhel9cis_use_rsync_server' set to 'false') -# - masking the 'rsyncd' service('rhel9cis_use_rsync_server' set to 'true') -rhel9cis_use_rsync_service: false - ## Section 2.3 Service clients -## Control - 2.3.1 - Ensure telnet client is not installed -# Set this variable to `true` to keep package `telnet`; otherwise, the package is uninstalled. -rhel9cis_telnet_required: false -## Control - 2.3.2 - Ensure LDAP client is not installed -# Set this variable to `true` to keep package `openldap-clients`; otherwise, the package is uninstalled. -rhel9cis_openldap_clients_required: false -## Control - 2.3.3 - Ensure FTP client is not installed -# Set this variable to `true` to keep package `tftp`; otherwise, the package is uninstalled. -rhel9cis_tftp_client: false -## Control - 2.3.4 - Ensure FTP client is not installed -# Set this variable to `true` to keep package `ftp`; otherwise, the package is uninstalled. rhel9cis_ftp_client: false +rhel9cis_openldap_clients_required: false +rhel9cis_ypbind_required: false # Same package as NIS server +rhel9cis_telnet_required: false +rhel9cis_tftp_client: false ## Section 3 vars ## Sysctl @@ -1113,7 +1039,7 @@ rhel9cis_pam_faillock: # UID settings for interactive users # These are discovered via logins.def if set true -discover_int_uid: false +rhel9cis_discover_int_uid: true ### Controls: # - 5.6.2 - Ensure system accounts are secured # - 6.2.10 - Ensure local interactive user home directories exist @@ -1226,7 +1152,7 @@ rhel9cis_no_world_write_adjust: true # This boolean variable governs if current role should follow filesystem links for changes to # user home directory. rhel_09_6_2_16_home_follow_symlinks: false -# thanks to @dulin-gnet and community for rhel8-cis feedback. +# thanks to @dulin-gnet and community for rhel9-cis feedback. #### Goss Configuration Settings #### # Set correct env for the run_audit.sh script from https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" From e1579c8127cbe76601597bdab43a9cf030bf3023 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 23 Jul 2024 08:46:27 +0100 Subject: [PATCH 015/327] fix typo Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 12ca4a2..ee4ff2e 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -208,7 +208,7 @@ rhel9cis_rule_1_6_5: true rhel9cis_rule_1_6_6: true rhel9cis_rule_1_6_7: true -# Coomand line warning banners +# Command line warning banners rhel9cis_rule_1_7_1: true rhel9cis_rule_1_7_2: true rhel9cis_rule_1_7_3: true From aa0f4d0f6dabdad205aafb68034c1f690aed7778 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 13:57:29 +0100 Subject: [PATCH 016/327] section4 v2 initial Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.1.1.x.yml | 101 ----------- tasks/section_4/cis_4.1.2.x.yml | 66 -------- tasks/section_4/cis_4.1.3.x.yml | 292 -------------------------------- tasks/section_4/cis_4.1.4.x.yml | 183 -------------------- tasks/section_4/cis_4.1.x.yml | 59 +++++++ tasks/section_4/cis_4.2.1.x.yml | 215 ----------------------- tasks/section_4/cis_4.2.2.x.yml | 200 ---------------------- tasks/section_4/cis_4.2.3.yml | 31 ---- tasks/section_4/cis_4.2.x.yml | 45 +++++ tasks/section_4/cis_4.3.x.yml | 189 +++++++++++++++++++++ tasks/section_4/cis_4.3.yml | 56 ------ tasks/section_4/main.yml | 38 +---- 12 files changed, 301 insertions(+), 1174 deletions(-) delete mode 100644 tasks/section_4/cis_4.1.1.x.yml delete mode 100644 tasks/section_4/cis_4.1.2.x.yml delete mode 100644 tasks/section_4/cis_4.1.3.x.yml delete mode 100644 tasks/section_4/cis_4.1.4.x.yml create mode 100644 tasks/section_4/cis_4.1.x.yml delete mode 100644 tasks/section_4/cis_4.2.1.x.yml delete mode 100644 tasks/section_4/cis_4.2.2.x.yml delete mode 100644 tasks/section_4/cis_4.2.3.yml create mode 100644 tasks/section_4/cis_4.2.x.yml create mode 100644 tasks/section_4/cis_4.3.x.yml delete mode 100644 tasks/section_4/cis_4.3.yml diff --git a/tasks/section_4/cis_4.1.1.x.yml b/tasks/section_4/cis_4.1.1.x.yml deleted file mode 100644 index 3d0082a..0000000 --- a/tasks/section_4/cis_4.1.1.x.yml +++ /dev/null @@ -1,101 +0,0 @@ ---- - -- 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' - when: - - rhel9cis_rule_4_1_1_1 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.1.1 - -- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" - block: - - name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby existence of current value" - ansible.builtin.shell: grubby --info=ALL | grep args | sed -n 's/.*audit=\([[:alnum:]]\+\).*/\1/p' - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_4_1_1_2_grubby_curr_value_audit_linux - - - name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby update, if needed" - ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1" - when: - - rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout == '' or - '0' in rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout or - 'off' in rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout|lower - when: - - rhel9cis_rule_4_1_1_2 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - grub - - rule_4.1.1.2 - -- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" - block: - - name: "4.1.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby existence of current value" - ansible.builtin.shell: - cmd: 'grubby --info=ALL | grep args | grep -o -E "audit_backlog_limit=([[:digit:]])+" | grep -o -E "([[:digit:]])+"' - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux - - - name: "4.1.1.3 | AUDIT | Check to see if limits are set" - ansible.builtin.set_fact: - rhel9cis_4_1_1_3_reset_backlog_limits: true - when: - - rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux is not defined or - rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux.stdout_lines == [] - - - name: "4.1.1.3 | AUDIT | Check to see if any limits are too low" - ansible.builtin.set_fact: - rhel9cis_4_1_1_3_reset_backlog_limits: true - when: - - (item | int < rhel9cis_audit_back_log_limit) - loop: "{{ rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux.stdout_lines }}" - - - name: "4.1.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" - ansible.builtin.shell: - cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' - when: - - rhel9cis_4_1_1_3_reset_backlog_limits is defined - when: - - rhel9cis_rule_4_1_1_3 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - grub - - rule_4.1.1.3 - -- name: "4.1.1.4 | PATCH | Ensure auditd service is enabled" - ansible.builtin.systemd: - name: auditd - state: started - enabled: true - when: - - rhel9cis_rule_4_1_1_4 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.1.4 diff --git a/tasks/section_4/cis_4.1.2.x.yml b/tasks/section_4/cis_4.1.2.x.yml deleted file mode 100644 index 8370114..0000000 --- a/tasks/section_4/cis_4.1.2.x.yml +++ /dev/null @@ -1,66 +0,0 @@ ---- - -- 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 = {{ rhel9cis_auditd['max_log_file'] }}" - notify: Restart auditd - when: - - rhel9cis_rule_4_1_2_1 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.2.1 - -- 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 = {{ rhel9cis_auditd['max_log_file_action'] }}" - notify: Restart auditd - when: - - rhel9cis_rule_4_1_2_2 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.2.2 - -- 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 - loop: - - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel9cis_auditd.admin_space_left_action }}' } - - { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel9cis_auditd.action_mail_acct }}' } - - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel9cis_auditd.space_left_action }}' } - when: - - rhel9cis_rule_4_1_2_3 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.2.3 - -- name: PATCH | Configure other keys for auditd.conf - ansible.builtin.lineinfile: - path: /etc/audit/auditd.conf - regexp: "^{{ item }}( |=)" - line: "{{ item }} = {{ rhel9cis_auditd_extra_conf[item] }}" - loop: "{{ rhel9cis_auditd_extra_conf.keys() }}" - notify: Restart auditd - when: - - rhel9cis_auditd_extra_conf.keys() | length > 0 - - rhel9cis_auditd_extra_conf_usage - tags: - - level2-server - - level2-workstation - - patch - - auditd diff --git a/tasks/section_4/cis_4.1.3.x.yml b/tasks/section_4/cis_4.1.3.x.yml deleted file mode 100644 index 2c8746a..0000000 --- a/tasks/section_4/cis_4.1.3.x.yml +++ /dev/null @@ -1,292 +0,0 @@ ---- - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_1 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.1 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.2 | PATCH | Ensure actions as another user are always logged" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_2 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.2 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.3 | PATCH | Ensure events that modify the sudo log file are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_3 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.3 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.4 | PATCH | Ensure events that modify date and time information are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_4 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.4 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.5 | PATCH | Ensure events that modify the system's network environment are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_5 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.5 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" - block: - - name: "4.1.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 - - - name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected" - ansible.builtin.set_fact: - update_audit_template: true - notify: update auditd - when: - - rhel9cis_rule_4_1_3_6 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.6 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_7 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.7 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.8 | PATCH | Ensure events that modify user/group information are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_8 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.8 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_9 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.9 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.10 | PATCH | Ensure successful file system mounts are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_10 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.10 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.11 | PATCH | Ensure session initiation information is collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_11 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.11 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.12 | PATCH | Ensure login and logout events are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_12 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.12 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.13 | PATCH | Ensure file deletion events by users are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_13 - tags: - - level2-server - - level2-workstation - - auditd - - patch - - rule_4.1.3.13 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_14 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.14 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_15 - tags: - - level2-server - - level2- workstation - - patch - - auditd - - rule_4.1.3.15 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_16 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.16 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_17 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.17 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_18 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.18 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.19 | PATCH | Ensure kernel module loading and unloading is collected" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_19 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.19 - -# All changes selected are managed by the POST audit and handlers to update -- name: "4.1.3.20 | PATCH | Ensure the audit configuration is immutable" - ansible.builtin.set_fact: - update_audit_template: true - when: - - rhel9cis_rule_4_1_3_20 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.3.20 - -- 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" - when: - - rhel9cis_rule_4_1_3_21 - tags: - - level2-server - - level2-workstation - - manual - - patch - - auditd - - rule_4.1.3.21 - -- name: Auditd | 4.1.3 | Auditd controls updated - 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_4/cis_4.1.4.x.yml b/tasks/section_4/cis_4.1.4.x.yml deleted file mode 100644 index c42f876..0000000 --- a/tasks/section_4/cis_4.1.4.x.yml +++ /dev/null @@ -1,183 +0,0 @@ ---- - -- name: | - "4.1.4.1 | PATCH | Ensure audit log files are mode 0640 or less permissive" - "4.1.4.2 | PATCH | Ensure only authorized users own audit log files" - "4.1.4.3 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" - - block: - - name: "4.1.4.1 | AUDIT | 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: audit_discovered_logfile - - - name: "4.1.4.1 | AUDIT | Ensure audit log files are mode 0640 or less permissive | stat file" - ansible.builtin.stat: - path: "{{ audit_discovered_logfile.stdout }}" - changed_when: false - register: auditd_logfile - - - name: | - "4.1.4.1 | PATCH | Ensure audit log files are mode 0640 or less permissive" - "4.1.4.2 | PATCH | Ensure only authorized users own audit log files" - "4.1.4.3 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" - ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout }}" - mode: "{% if auditd_logfile.stat.mode != '0600' %}0640{% endif %}" - owner: root - group: root - when: - - rhel9cis_rule_4_1_4_1 or - rhel9cis_rule_4_1_4_2 or - rhel9cis_rule_4_1_4_3 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.1 - - rule_4.1.4.2 - - rule_4.1.4.3 - -- name: "4.1.4.4 | PATCH | Ensure the audit log directory is 0750 or more restrictive" - block: - - name: "4.1.4.4 | AUDIT | Ensure the audit log directory is 0750 or more restrictive | get current permissions" - ansible.builtin.stat: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - register: auditlog_dir - - - name: "4.1.4.4 | PATCH | Ensure the audit log directory is 0750 or more restrictive | set" - ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - state: directory - mode: '0750' - when: not auditlog_dir.stat.mode is match('07(0|5)0') - when: - - rhel9cis_rule_4_1_4_4 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.4 - -- name: "4.1.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" - ansible.builtin.file: - path: "{{ item.path }}" - mode: "{{ '0600' if item.mode == '0600' else '0640' }}" - loop: "{{ auditd_conf_files.files }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel9cis_rule_4_1_4_5 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.5 - -- name: "4.1.4.6 | PATCH | Ensure audit configuration files are owned by root" - ansible.builtin.file: - path: "{{ item.path }}" - owner: root - loop: "{{ auditd_conf_files.files | default([]) }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel9cis_rule_4_1_4_6 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.6 - -- name: "4.1.4.7 | PATCH | Ensure audit configuration files belong to group root" - ansible.builtin.file: - path: "{{ item.path }}" - group: root - loop: "{{ auditd_conf_files.files | default([]) }}" - loop_control: - label: "{{ item.path }}" - when: - - rhel9cis_rule_4_1_4_7 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.7 - -- name: "4.1.4.8 | PATCH | Ensure audit tools are 755 or more restrictive" - block: - - name: "4.1.4.8 | AUDIT | Get audit binary file stat | get current mode" - ansible.builtin.stat: - path: "{{ item }}" - register: "audit_bins" - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules - - - name: "4.1.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required" - ansible.builtin.file: - path: "{{ item.item }}" - mode: '0750' - - loop: "{{ audit_bins.results }}" - loop_control: - label: "{{ item.item }}" - when: not item.stat.mode is match('07(0|5)0') - when: - - rhel9cis_rule_4_1_4_8 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.8 - -- name: "4.1.4.9 | PATCH | Ensure audit tools are owned by root" - ansible.builtin.file: - path: "{{ item }}" - owner: root - group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules - when: - - rhel9cis_rule_4_1_4_9 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.9 - -- name: "4.1.4.10 | PATCH | Ensure audit tools belong to group root" - ansible.builtin.file: - path: "{{ item }}" - group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules - when: - - rhel9cis_rule_4_1_4_10 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.10 diff --git a/tasks/section_4/cis_4.1.x.yml b/tasks/section_4/cis_4.1.x.yml new file mode 100644 index 0000000..f0a6636 --- /dev/null +++ b/tasks/section_4/cis_4.1.x.yml @@ -0,0 +1,59 @@ +--- + +- name: "4.1.1 | PATCH | Ensure nftables is installed" + when: + - rhel9cis_rule_4_1_1 + - rhel9cis_firewall == 'nftables' + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.1.1 + - NIST800-53R5_CA-9 + ansible.builtin.package: + name: + - nftables + state: present + +- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use" + when: + - rhel9cis_rule_4_1_2 + tags: + - level1-server + - level1-workstation + - patch + - firewalld + - nftables + - rule_4.1.2 + block: + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables" + when: + - item in ansible_facts.packages + - rhel9cis_firewall == 'nftables' + ansible.builtin.systemd: + name: "{{ item }}" + masked: true + loop: + - firewalld + + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld" + when: + - item in ansible_facts.packages + - rhel9cis_firewall == 'firewalld' + ansible.builtin.systemd: + name: "{{ item }}" + masked: true + loop: + - nftables + + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | package installed" + ansible.builtin.package: + name: "{{ rhel9cis_firewall }}" + state: installed + + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" + ansible.builtin.systemd: + name: "{{ rhel9cis_firewall }}" + enabled: true + state: started diff --git a/tasks/section_4/cis_4.2.1.x.yml b/tasks/section_4/cis_4.2.1.x.yml deleted file mode 100644 index 740f820..0000000 --- a/tasks/section_4/cis_4.2.1.x.yml +++ /dev/null @@ -1,215 +0,0 @@ ---- - -- name: "4.2.1.1 | PATCH | Ensure rsyslog installed" - ansible.builtin.package: - name: rsyslog - state: present - when: - - "'rsyslog' not in ansible_facts.packages" - - rhel9cis_rule_4_2_1_1 - tags: - - level1-server - - level1-workstation - - patch - - rsyslog - - rule_4.2.1.1 - -- name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled" - ansible.builtin.systemd: - name: rsyslog - enabled: true - when: - - rhel9cis_rule_4_2_1_2 - tags: - - level1-server - - level1-workstation - - patch - - rsyslog - - rule_4.2.1.2 - -- name: "4.2.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 rsyslog - when: - - rhel9cis_rule_4_2_1_3 - tags: - - level1-server - - level1-workstation - - patch - - rule_4.2.1.3 - -- name: "4.2.1.4 | PATCH | Ensure rsyslog default file permissions configured" - ansible.builtin.lineinfile: - path: /etc/rsyslog.conf - regexp: '^\$FileCreateMode' - line: '$FileCreateMode 0640' - notify: Restart rsyslog - when: - - rhel9cis_rule_4_2_1_4 - tags: - - level1-server - - level1-workstation - - patch - - rsyslog - - rule_4.2.1.4 - -- name: "4.2.1.5 | PATCH | Ensure logging is configured" - block: - - name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" - ansible.builtin.shell: cat /etc/rsyslog.conf | grep -Ev "^#|^$" - changed_when: false - failed_when: false - check_mode: false - register: rhel_09_4_2_1_5_audit - - - name: "4.2.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_09_4_2_1_5_audit.stdout_lines }}" - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | mail.* log setting" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown" - block: | - # mail logging additions to meet CIS standards - mail.* -/var/log/mail - mail.info -/var/log/mail.info - 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: rhel9cis_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 - CIS benchmark - Ansible-lockdown" - 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 - when: rhel9cis_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 - 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: rhel9cis_rsyslog_ansiblemanaged - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Local log settings" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown" - block: | - # local log settings to meet CIS standards - local0,local1.* -/var/log/localmessages - local2,local3.* -/var/log/localmessages - local4,local5.* -/var/log/localmessages - local6,local7.* -/var/log/localmessages - *.emrg :omusrmsg:* - insertafter: '#### RULES ####' - notify: Restart rsyslog - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Auth Settings" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown" - block: | - # Private settings to meet CIS standards - auth,authpriv.* /var/log/secure - insertafter: '#### RULES ####' - notify: Restart rsyslog - - - name: "4.2.1.5 | PATCH | Ensure logging is configured | Cron Settings" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - marker: "#{mark} Cron SETTINGS - CIS benchmark - Ansible-lockdown" - block: | - # Cron settings to meet CIS standards - cron.* /var/log/cron - insertafter: '#### RULES ####' - notify: Restart rsyslog - when: - - rhel9cis_rule_4_2_1_5 - tags: - - level1-server - - level1-workstation - - 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" - ansible.builtin.blockinfile: - path: /etc/rsyslog.conf - state: present - block: | - # target can be IP or FQDN - *.* action(type="omfwd" target="{{ rhel9cis_remote_log_host }}" port="{{ rhel9cis_remote_log_port }}" protocol="{{ rhel9cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel9cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel9cis_remote_log_queuesize }}") - insertafter: EOF - register: result - failed_when: - - result is failed - - result.rc != 257 - notify: Restart rsyslog - when: - - rhel9cis_rule_4_2_1_6 - - rhel9cis_remote_log_server - tags: - - level1-server - - level1-workstation - - 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" - block: - - name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" - ansible.builtin.replace: - path: /etc/rsyslog.conf - regexp: '{{ item }}' - replace: '#\1' - notify: Restart rsyslog - loop: - - '^(\$ModLoad imtcp)' - - '^(\$InputTCPServerRun)' - - '^(module\(load="imtcp"\))' - - '^(input\(type="imtcp")' - when: not rhel9cis_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" - ansible.builtin.replace: - path: /etc/rsyslog.conf - regexp: '^#(.*{{ item }}.*)' - replace: '\1' - notify: Restart rsyslog - loop: - - 'ModLoad imtcp' - - 'InputTCPServerRun' - when: rhel9cis_system_is_log_server - when: - - rhel9cis_rule_4_2_1_7 - tags: - - level1-server - - level1-workstation - - patch - - rsyslog - - rule_4.2.1.7 diff --git a/tasks/section_4/cis_4.2.2.x.yml b/tasks/section_4/cis_4.2.2.x.yml deleted file mode 100644 index cf4b011..0000000 --- a/tasks/section_4/cis_4.2.2.x.yml +++ /dev/null @@ -1,200 +0,0 @@ ---- - -- name: "4.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" - ansible.builtin.package: - name: systemd-journal-remote - state: present - when: - - rhel9cis_rule_4_2_2_1_1 - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.1.1 - -- name: "4.2.2.1.2 | PATCH | Ensure systemd-journal-remote is configured" - ansible.builtin.lineinfile: - path: /etc/systemd/journal-upload.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - notify: Restart journald - loop: - - { regexp: 'URL=', line: 'URL={{ rhel9cis_journal_upload_url }}'} - - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel9cis_journal_upload_serverkeyfile }}'} - - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'} - - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'} - when: - - rhel9cis_rule_4_2_2_1_2 - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.1.2 - -- name: "4.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled" - ansible.builtin.systemd: - name: systemd-journal-upload - state: started - enabled: true - when: - - rhel9cis_system_is_log_server - - rhel9cis_rule_4_2_2_1_3 - tags: - - level1-server - - level1-workstation - - manual - - 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" - ansible.builtin.systemd: - name: systemd-journal-remote.socket - state: stopped - enabled: false - masked: true - when: - - not rhel9cis_system_is_log_server - - rhel9cis_rule_4_2_2_1_4 - tags: - - level1-server - - level1-workstation - - patch - - journald - - rule_4.2.2.1.4 - -- name: "4.2.2.2 | PATCH | Ensure journald service is enabled" - block: - - name: "4.2.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" - ansible.builtin.shell: systemctl is-enabled systemd-journald.service - changed_when: false - failed_when: false - register: rhel9cis_4_2_2_2_status - - - name: "4.2.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 rhel9cis_4_2_2_2_status.stdout" - - - name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Warn Count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: "'static' not in rhel9cis_4_2_2_2_status.stdout" - vars: - warn_control_id: '4.2.2.2' - when: - - rhel9cis_rule_4_2_2_2 - tags: - - level1-server - - level1-workstation - - audit - - journald - - rule_4.2.2.2 - -- name: "4.2.2.3 | PATCH | Ensure journald is configured to compress large log files" - ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - regexp: "^#Compress=|^Compress=" - line: Compress=yes - notify: Restart journald - when: - - rhel9cis_rule_4_2_2_3 - tags: - - level1-server - - level1-workstation - - patch - - journald - - rule_4.2.2.3 - -- name: "4.2.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk" - ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - regexp: "^#Storage=|^Storage=" - line: Storage=persistent - notify: Restart journald - when: - - rhel9cis_rule_4_2_2_4 - tags: - - level1-server - - level1-workstation - - 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" - ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - regexp: "^ForwardToSyslog=" - line: "#ForwardToSyslog=yes" - notify: Restart journald - when: - - rhel9cis_rule_4_2_2_5 - tags: - - level1-server - - level2-workstation - - manual - - patch - - journald - - rule_4.2.2.5 - -- name: "4.2.2.6 | PATCH | Ensure journald log rotation is configured per site policy" - ansible.builtin.lineinfile: - path: /etc/systemd/journald.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - notify: Restart journald - loop: - - { regexp: '^#SystemMaxUse=|^SystemMaxUse=', line: 'SystemMaxUse={{ rhel9cis_journald_systemmaxuse }}'} - - { regexp: '^#SystemKeepFree=|^SystemKeepFree=', line: 'SystemKeepFree={{ rhel9cis_journald_systemkeepfree }}' } - - { regexp: '^#RuntimeMaxUse=|^RuntimeMaxUse=', line: 'RuntimeMaxUse={{ rhel9cis_journald_runtimemaxuse }}'} - - { regexp: '^#RuntimeKeepFree=|^RuntimeKeepFree=', line: 'RuntimeKeepFree={{ rhel9cis_journald_runtimekeepfree }}'} - - { regexp: '^#MaxFileSec=|^MaxFileSec=', line: 'MaxFileSec={{ rhel9cis_journald_maxfilesec }}'} - when: - - rhel9cis_rule_4_2_2_6 - 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.stat: - path: /etc/tmpfiles.d/systemd.conf - register: rhel9cis_4_2_2_7_override - - - name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Set live file" - ansible.builtin.set_fact: - systemd_conf_file: /etc/tmpfiles.d/systemd.conf - when: rhel9cis_4_2_2_7_override.stat.exists - - - name: "4.2.2.7 | PATCH | Ensure journald default file permissions configured | Set permission" - ansible.builtin.lineinfile: - path: "{{ systemd_conf_file | default('/usr/lib/tmpfiles.d/systemd.conf') }}" - regexp: '^z \/var\/log\/journal\/%m\/system.journal (!?06(0|4)0) root' - line: 'z /var/log/journal/%m/system.journal 0640 root systemd-journal - -' - - when: - - rhel9cis_rule_4_2_2_7 - tags: - - level1-server - - level1-workstation - - manual - - patch - - journald - - rule_4.2.2.7 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 823975a..0000000 --- a/tasks/section_4/cis_4.2.3.yml +++ /dev/null @@ -1,31 +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.find: - paths: "/var/log" - file_type: file - recurse: true - hidden: true - register: logfiles - - - name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured | change permissions" - ansible.builtin.file: - path: "{{ item.path }}" - mode: "{{ '0600' if item.mode == '0600' else '0640' }}" - loop: "{{ logfiles.files }}" - loop_control: - label: "{{ item.path }}" - when: - - item.path != "/var/log/btmp" - - item.path != "/var/log/utmp" - - item.path != "/var/log/wtmp" - when: - - rhel9cis_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 0000000..01fd1eb --- /dev/null +++ b/tasks/section_4/cis_4.2.x.yml @@ -0,0 +1,45 @@ +--- + +- name: "4.2.1 | AUDIT | Ensure firewalld drops unnecessary services and ports" + when: + - rhel9cis_rule_4_2_1 + tags: + - level1-server + - level1-workstation + - manual + - audit + - rule_4.2.1 + - NIST800-55_CA-9 + block: + - name: "4.2.1 | 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: rhel9cis_4_2_5_servicesport + + - name: "4.2.1 | 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" + - "{{ rhel9cis_4_2_5_servicesport.stdout_lines }}" + +- name: "4.2.2 | PATCH | Ensure firewalld loopback traffic is configured | firewalld" + when: + - rhel9cis_rule_4_2_2 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.2.2 + - NIST800-55_CA-9 + ansible.posix.firewalld: + rich_rule: "{{ item }}" + zone: "{{ rhel9cis_default_zone }}" + 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 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 0000000..09e8979 --- /dev/null +++ b/tasks/section_4/cis_4.3.x.yml @@ -0,0 +1,189 @@ +--- + +- name: "4.3.1 | PATCH | Ensure nftables base chains exist" + when: + - rhel9cis_rule_4_3_1 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.3.1 + - NIST800-55_CA-9 + block: + - name: "4.3.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: rhel9cis_4_3_1_input_chains + + - name: "4.3.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: rhel9cis_4_3_1_forward_chains + + - name: "4.3.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: rhel9cis_4_3_1_output_chains + + - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Display chains for review" + when: not rhel9cis_nft_tables_autochaincreate + ansible.builtin.debug: + msg: + - "Below are the current INPUT chains" + - "{{ rhel9cis_4_3_1_input_chains.stdout_lines }}" + - "Below are the current FORWARD chains" + - "{{ rhel9cis_4_3_1_forward_chains.stdout_lines }}" + - "Below are teh current OUTPUT chains" + - "{{ rhel9cis_4_3_1_output_chains.stdout_lines }}" + + - name: "4.3.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" + when: rhel9cis_nft_tables_autochaincreate + ansible.builtin.shell: "{{ item }}" + failed_when: false + loop: + - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } + - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; } + - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } + +- name: "4.3.2 | PATCH | Ensure nftables established connections are configured" + when: + - rhel9cis_rule_4_3_2 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.3.2 + - NIST800-55_CA-9 + block: + - name: "4.3.2 | 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: rhel9cis_4_3_2_inconnectionrule + + - name: "4.3.2| 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: rhel9cis_4_3_2_outconnectionrule + + - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" + when: '"ip protocol tcp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + + - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" + when: '"ip protocol udp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept + + - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" + when: '"ip protocol icmp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept + + - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" + when: '"ip protocol tcp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept + + - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" + when: '"ip protocol udp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept + + - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" + when: '"ip protocol icmp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept + +- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy" + when: + - rhel9cis_rule_4_3_3 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.3.3 + - NIST800-55_CA-9 + block: + - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" + ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' + failed_when: false + changed_when: false + register: rhel9cis_4_3_3_inputpolicy + + - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" + ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' + failed_when: false + changed_when: false + register: rhel9cis_4_3_3_forwardpolicy + + - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" + ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' + failed_when: false + changed_when: false + register: rhel9cis_4_3_3_outputpolicy + + - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" + ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' + failed_when: false + changed_when: false + register: rhel9cis_4_3_3_sshallowcheck + + - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" + when: '"tcp dport ssh accept" not in rhel9cis_4_3_3_sshallowcheck.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept + + - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" + when: '"type filter hook input priority 0; policy drop;" not in rhel9cis_4_3_3_inputpolicy.stdout' + ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; } + + - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" + when: '"type filter hook forward priority 0; policy drop;" not in rhel9cis_4_3_3_forwardpolicy.stdout' + ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; } + + - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" + when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_4_3_3_outputpolicy.stdout' + ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } + +- name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured" + when: + - rhel9cis_rule_4_3_4 + tags: + - level1-server + - level1-workstation + - patch + - nftables + - rule_4.3.4 + - NIST800-55_CA-9 + block: + - name: "4.3.4 | AUDIT | Ensure nftables 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: rhel9cis_4_3_4_iiflo + + - name: "4.3.4 | AUDIT | Ensure nftables 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: rhel9cis_4_3_4_ipsaddr + + - name: "4.3.4 | AUDIT | Ensure nftables 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: rhel9cis_4_3_4_ip6saddr + + - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule | nftables" + when: '"iif \"lo\" accept" not in rhel9cis_4_3_4_iiflo.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept + + - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule | nftables" + when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel9cis_4_3_4_ipsaddr.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop + + - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule | nftables" + when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_4_3_4_ip6saddr.stdout' + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop diff --git a/tasks/section_4/cis_4.3.yml b/tasks/section_4/cis_4.3.yml deleted file mode 100644 index 7da565e..0000000 --- a/tasks/section_4/cis_4.3.yml +++ /dev/null @@ -1,56 +0,0 @@ ---- - -- name: "4.3 | PATCH | Ensure logrotate is configured" - block: - - name: "4.3 | PATCH | Ensure logrotate is configured | installed" - ansible.builtin.package: - name: rsyslog-logrotate - state: present - - - name: "4.3 | PATCH | Ensure logrotate is configured | scheduled" - ansible.builtin.systemd: - name: logrotate.timer - state: started - enabled: true - - - name: "4.3 | PATCH | Ensure logrotate is configured | set default conf" - ansible.builtin.replace: - path: "/etc/logrotate.conf" - regexp: '^(\s*)(daily|weekly|monthly|yearly)$' - replace: "\\1{{ rhel9cis_logrotate }}" - - - name: "4.3 | AUDIT | Ensure logrotate is configured | Get non default logrotate settings" - ansible.builtin.find: - paths: /etc/logrotate.d/ - contains: '^(\s*)(?!{{ rhel9cis_logrotate }})(daily|weekly|monthly|yearly)$' - register: log_rotates - - - name: "4.3 | AUDIT | Ensure logrotate is configured" - block: - - name: "4.3 | AUDIT | Ensure logrotate is configured | generate file list" - ansible.builtin.set_fact: - logrotate_non_def_conf: "{{ log_rotates.files | map(attribute='path') | join (', ') }}" - - - name: "4.3 | AUDIT | Ensure logrotate is configured | List configured files" - ansible.builtin.debug: - msg: | - "Warning!! The following files are not covered by default logrotate settings ensure they match site policy" - "{{ logrotate_non_def_conf }}" - loop: "{{ log_rotates.files }}" - - - name: "4.3 | AUDIT | Ensure logrotate is configured | Warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '4.3' - when: log_rotates.matched > 0 - - when: - - rhel9cis_rule_4_3 - tags: - - level1-server - - level1-workstation - - manual - - patch - - logrotate - - rule_4.3 diff --git a/tasks/section_4/main.yml b/tasks/section_4/main.yml index d3b6b8d..5acc222 100644 --- a/tasks/section_4/main.yml +++ b/tasks/section_4/main.yml @@ -1,37 +1,15 @@ --- -- name: "SECTION | 4.1 | Configure System Accounting (auditd)" +- name: "SECTION | 4.1.x | Configure a firewall" ansible.builtin.import_tasks: - file: cis_4.1.1.x.yml - when: - - not system_is_container + file: cis_4.1.x.yml -- name: "SECTION | 4.1.2 | Configure Data Retention" +- name: "SECTION | 4.2.x | Configure FirewallD" + when: rhel9cis_firewall == "firewalld" ansible.builtin.import_tasks: - file: cis_4.1.2.x.yml + file: cis_4.2.x.yml -- name: "SECTION | 4.1.3 | Configure Auditd rules" +- name: "SECTION | 4.3.x | Configure nftables" + when: rhel9cis_firewall == "nftables" ansible.builtin.import_tasks: - file: cis_4.1.3.x.yml - -- name: "SECTION | 4.1.4 | Configure Audit files" - ansible.builtin.import_tasks: - file: cis_4.1.4.x.yml - -- name: "SECTION | 4.2.1 | Configure rsyslog" - ansible.builtin.import_tasks: - file: cis_4.2.1.x.yml - when: rhel9cis_syslog == 'rsyslog' - -- name: "SECTION | 4.2.2 | Configure journald" - ansible.builtin.import_tasks: - file: cis_4.2.2.x.yml - when: rhel9cis_syslog == 'journald' - -- name: "SECTION | 4.2.3 | Configure logile perms" - ansible.builtin.import_tasks: - file: cis_4.2.3.yml - -- name: "SECTION | 4.3 | Configure logrotate" - ansible.builtin.import_tasks: - file: cis_4.3.yml + file: cis_4.3.x.yml From f1c4d964122c29c40a36282d106b304332e9803c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:00:00 +0100 Subject: [PATCH 017/327] lint updates Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.1.x.yml | 4 +- tasks/section_1/cis_1.1.2.1.x.yml | 1 - tasks/section_1/cis_1.1.2.3.x.yml | 6 +- tasks/section_1/cis_1.1.2.4.x.yml | 6 +- tasks/section_1/cis_1.1.2.5.x.yml | 8 +- tasks/section_1/cis_1.1.2.6.x.yml | 12 +- tasks/section_1/cis_1.1.2.7.x.yml | 26 +- tasks/section_1/cis_1.3.x.yml_AIDE | 78 ----- tasks/section_1/cis_1.6.x.yml | 17 +- tasks/section_1/cis_1.8.x.yml | 1 - tasks/section_2/cis_2.1.x.yml | 80 ++--- tasks/section_2/main.yml | 8 +- tasks/section_3/cis_3.1.x.yml | 149 ++++----- tasks/section_3/cis_3.2.x.yml | 159 +++++++--- tasks/section_3/cis_3.3.x.yml | 478 ++++++++++++++++++----------- tasks/section_3/cis_3.4.1.x.yml | 59 ---- tasks/section_3/cis_3.4.2.x.yml | 301 ------------------ tasks/section_3/main.yml | 20 +- 18 files changed, 578 insertions(+), 835 deletions(-) delete mode 100644 tasks/section_1/cis_1.3.x.yml_AIDE delete mode 100644 tasks/section_3/cis_3.4.1.x.yml delete mode 100644 tasks/section_3/cis_3.4.2.x.yml diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index 4381911..fb0f119 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -297,14 +297,14 @@ failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ] register: discovered_fs_modules_loaded - - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning" + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning" when: discovered_fs_modules_loaded.stdout | length > 0 ansible.builtin.debug: msg: | "Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task {{ discovered_fs_modules_loaded.stdout_lines}}" - - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" + - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" when: discovered_fs_modules_loaded.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 770753e..d64c3a7 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -86,4 +86,3 @@ group: root mode: '0644' notify: Systemd restart tmp.mount - diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 6fd1303..cf45245 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -12,8 +12,8 @@ - rule_1_1_2.3.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.3.1' - required_mount: '/home' + 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 | Absent" ansible.builtin.debug: @@ -40,7 +40,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.builtin.mount: + ansible.posix.mount: name: /home src: "{{ item.device }}" fstype: "{{ item.fstype }}" diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 85df1b2..a2b0695 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -25,8 +25,8 @@ # 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" + "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: - item.mount == "/var" - rhel9cis_rule_1_1_2_4_2 or @@ -40,7 +40,7 @@ - rule_1_1_2.4.3 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.builtin.mount: + ansible.posix.mount: name: /var src: "{{ item.device }}" fstype: "{{ item.fstype }}" diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index dba75f5..6e630e4 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -26,9 +26,9 @@ # 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" + "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: - item.mount == "/var/tmp" - rhel9cis_rule_1_1_2_5_2 or @@ -44,7 +44,7 @@ - rule_1_1_2.5.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.builtin.mount: + ansible.posix.mount: name: /var/tmp src: "{{ item.device }}" fstype: "{{ item.fstype }}" diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index 00e0711..dea5d85 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -12,8 +12,8 @@ - rule_1_1_2.6.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.6.1' - required_mount: '/var/log' + 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 | Absent" ansible.builtin.debug: @@ -24,9 +24,9 @@ file: warning_facts.yml - 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" + "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: - item.mount == "/var/log" - rhel9cis_rule_1_1_2_6_2 or @@ -42,7 +42,7 @@ - rule_1_1_2.6.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.builtin.mount: + ansible.posix.mount: name: /var/log src: "{{ item.device }}" fstype: "{{ item.fstype }}" diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 8e59fe6..2747e49 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -24,19 +24,9 @@ file: warning_facts.yml - 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" - ansible.builtin.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_7_4 %}noexec{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + "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: - item.mount == "/var/log/audit" - rhel9cis_rule_1_1_2_7_2 or @@ -52,3 +42,13 @@ - rule_1_1_2.7.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + ansible.posix.mount: + name: /var/log/audit + src: "{{ item.device }}" + fstype: "{{ item.fstype }}" + state: present + opts: defaults,{% if rhel9cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_7_4 %}noexec{% endif %} + loop: "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.device }}" + notify: Change_requires_reboot diff --git a/tasks/section_1/cis_1.3.x.yml_AIDE b/tasks/section_1/cis_1.3.x.yml_AIDE deleted file mode 100644 index fa2d6a5..0000000 --- a/tasks/section_1/cis_1.3.x.yml_AIDE +++ /dev/null @@ -1,78 +0,0 @@ ---- - -- 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 | Build AIDE DB" - ansible.builtin.shell: /usr/sbin/aide --init - args: - creates: /var/lib/aide/aide.db.new.gz - when: not ansible_check_mode - - - name: "1.3.1 | PATCH | Ensure AIDE is installed | Wait for file before continuing" - ansible.builtin.wait_for: - path: /var/lib/aide/aide.db.new.gz - - - name: "1.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 - when: - - rhel9cis_config_aide - - rhel9cis_rule_1_3_1 - tags: - - level1-server - - level1-workstation - - aide - - patch - - 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: "{{ rhel9cis_aide_cron['cron_file'] }}" - user: "{{ rhel9cis_aide_cron['cron_user'] }}" - minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}" - hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}" - day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}" - month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}" - weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}" - job: "{{ rhel9cis_aide_cron['aide_job'] }}" - when: - - rhel9cis_rule_1_3_2 - - not system_is_ec2 - tags: - - level1-server - - level1-workstation - - aide - - file_integrity - - patch - - rule_1.3.2 - -- name: "1.3.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" - 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/augenrules 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/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 - /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 - validate: aide -D --config %s - when: - - rhel9cis_rule_1_3_3 - - not system_is_ec2 - tags: - - level1-server - - level1-workstation - - aide - - file_integrity - - patch - - rule_1.3.3 diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 7c015a2..259e106 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -15,8 +15,8 @@ msg: "Captured in prelim to ensure not LEGACY. Runs handler to update" changed_when: true notify: - - Update Crypto Policy - - Set Crypto Policy + - Update Crypto Policy + - Set Crypto Policy - name: "1.6.2 | PATCH | Ensure system wide crypto policy is not set in sshd configuration" when: @@ -36,7 +36,7 @@ state: absent notify: Restart sshd -- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" +- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | Add submodule exclusion" when: - rhel9cis_rule_1_6_3 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" @@ -49,7 +49,7 @@ - rule_1.6.3 - NIST800-53R5_SC-6 block: - - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | Add submodule exclusion" + - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod @@ -92,7 +92,6 @@ ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-WEAKMAC' }}" - - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh" when: - rhel9cis_rule_1_6_5 @@ -124,7 +123,7 @@ - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh" when: - rhel9cis_rule_1_6_6 - - "'NO-SSHCHACHA20' not in rhel9cis_crypto_policy_module" + - "'NO-SSHWEAKMAC' not in rhel9cis_crypto_policy_module" tags: - level1-server - level1-workstation @@ -136,8 +135,8 @@ block: - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" ansible.builtin.template: - src: etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 - dest: /etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod + src: etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod owner: root group: root mode: '0640' @@ -147,7 +146,7 @@ - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCHACHA20' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKMAC' }}" - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh" when: diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index b29aa15..427eb79 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -51,7 +51,6 @@ mode: '0644' notify: Reload dconf - - name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" when: - rhel9cis_rule_1_8_3 diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 34e57f2..a3df3eb 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -51,8 +51,8 @@ - not rhel9cis_avahi_mask ansible.builtin.package: name: - - avahi-autoipd - - avahi + - avahi-autoipd + - avahi state: absent - name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use | Mask service" @@ -255,8 +255,8 @@ - not rhel9cis_message_mask ansible.builtin.package: name: - - dovecot - - cyrus-imapd + - dovecot + - cyrus-imapd state: absent - name: "2.1.8 | PATCH | Ensure message access server services are not in use | Mask service" @@ -451,32 +451,32 @@ - "'net-snmp' in ansible_facts.packages" - rhel9cis_rule_2_1_14 tags: - - level1-server - - level1-workstation - - automation - - patch - - snmp - - NIST800-53R5_CM-7 - - rule_2.1.14 + - level1-server + - level1-workstation + - automation + - patch + - snmp + - NIST800-53R5_CM-7 + - rule_2.1.14 block: - - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Remove package" - when: - - not rhel9cis_net_snmp_server - - not rhel9cis_net_snmp_mask - ansible.builtin.package: - name: net-snmp - state: absent + - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Remove package" + when: + - not rhel9cis_net_snmp_server + - not rhel9cis_net_snmp_mask + ansible.builtin.package: + name: net-snmp + state: absent - - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Mask service" - when: - - not rhel9cis_net_snmp_server - - rhel9cis_net_snmp_mask - notify: Systemd_daemon_reload - ansible.builtin.systemd: - name: snmpd.service - enabled: false - state: stopped - masked: true + - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Mask service" + when: + - not rhel9cis_net_snmp_server + - rhel9cis_net_snmp_mask + notify: Systemd_daemon_reload + ansible.builtin.systemd: + name: snmpd.service + enabled: false + state: stopped + masked: true - name: "2.1.15 | PATCH | Ensure telnet server services are not in use" when: @@ -669,20 +669,20 @@ - name: "2.1.20 | PATCH | Ensure X window server services are not in use" when: - - not rhel9cis_xwindow_server - - "'xorg-x11-server-common' in ansible_facts.packages" - - rhel9cis_rule_2_1_20 + - not rhel9cis_xwindow_server + - "'xorg-x11-server-common' in ansible_facts.packages" + - rhel9cis_rule_2_1_20 tags: - - level1-server - - level1-workstation - - automated - - patch - - xwindow - - NIST800-53R5_CM-11 - - rule_2.1.20 + - level1-server + - level1-workstation + - automated + - patch + - xwindow + - NIST800-53R5_CM-11 + - rule_2.1.20 ansible.builtin.package: - name: xorg-x11-server-common - state: absent + name: xorg-x11-server-common + state: absent - name: "2.1.21 | PATCH | Ensure mail transfer agents are configured for local-only mode" when: diff --git a/tasks/section_2/main.yml b/tasks/section_2/main.yml index 02ae663..6e373fa 100644 --- a/tasks/section_2/main.yml +++ b/tasks/section_2/main.yml @@ -2,16 +2,16 @@ - name: "SECTION | 2.1 | Special Purpose Services" ansible.builtin.import_tasks: - file: cis_2.1.x.yml + file: cis_2.1.x.yml - name: "SECTION | 2.2 | Service Clients" ansible.builtin.import_tasks: - file: cis_2.2.x.yml + file: cis_2.2.x.yml - name: "SECTION | 2.3 | Time Synchronization" ansible.builtin.import_tasks: - file: cis_2.3.x.yml + file: cis_2.3.x.yml - name: "SECTION | 2.4 | Job Schedulers" ansible.builtin.import_tasks: - file: cis_2.4.x.yml + file: cis_2.4.x.yml diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 3f93858..5c76ab6 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -3,82 +3,93 @@ # The CIS Control wants IPv6 disabled if not in use. # We are using the rhel9cis_ipv6_required to specify if you have IPv6 in use - name: "3.1.1 | PATCH | Ensure IPv6 status is identified" - block: - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv6_route: true - - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" when: - - not rhel9cis_ipv6_required - - rhel9cis_rule_3_1_1 + - not rhel9cis_ipv6_required + - rhel9cis_rule_3_1_1 tags: - - level1-server - - level1-workstation - - manual - - patch - - ipv6 - - networking - - rule_3.1.1 + - level1-server + - level1-workstation + - manual + - patch + - ipv6 + - networking + - rule_3.1.1 + - NIST800-53R5_CM-7 + block: + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv6_route: true + + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" - block: - - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available | if wlan exists" - ansible.builtin.shell: rpm -q NetworkManager - changed_when: false - failed_when: false - check_mode: false - register: rhel_09_nmcli_available - - - name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled" - ansible.builtin.shell: nmcli radio wifi - register: rhel_09_wifi_enabled - changed_when: rhel_09_wifi_enabled.stdout != "disabled" - failed_when: false - when: rhel_09_nmcli_available.rc == 0 - - - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled" - ansible.builtin.shell: nmcli radio all off - changed_when: false - failed_when: false - when: rhel_09_wifi_enabled is changed # noqa no-handler when: - - rhel9cis_rule_3_1_2 - - "'wlan' in ansible_facts.interfaces" + - rhel9cis_rule_3_1_2 + - discover_wireless_adapters.rc == 0 tags: - - level1-server - - patch - - wireless - - rule_3.1.2 - -- name: "3.1.3 | PATCH | Ensure TIPC is disabled" + - level1-server + - patch + - rule_3.1.2 + - wireless + - NIST800-53R5_CM-7 + vars: + warn_control_id: '3.1.2' block: - - name: "3.1.3 | PATCH | Ensure TIPC is disabled" - ansible.builtin.template: - src: "etc/modprobe.d/modprobe.conf.j2" - dest: "/etc/modprobe.d/{{ item }}.conf" - mode: '0600' - owner: root - group: root - loop: - - tipc - # note the item used in the template + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" + when: "'network-manager' in ansible_facts.packages" + ansible.builtin.shell: nmcli radio wifi + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_3_1_2_wifi_status - - name: "3.1.3 | PATCH | Ensure TIPC is disabled | blacklist" - ansible.builtin.lineinfile: - path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist tipc(\\s|$)" - line: "blacklist tipc" - create: true - mode: '0600' + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed" + when: + - "'network-manager' in ansible_facts.packages" + - "'enabled' in rhel9cis_3_1_2_wifi_status.stdout" + ansible.builtin.shell: nmcli radio all off + changed_when: rhel9cis_3_1_2_nmcli_radio_off.rc == 0 + register: rhel9cis_3_1_2_nmcli_radio_off + + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed" + when: "'network-manager' not in ansible_facts.packages" + ansible.builtin.debug: + msg: "Warning!! You need to disable wireless interfaces manually since network-manager is not installed" + + - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Set warning count" + when: "'network-manager' not in ansible_facts.packages" + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use" when: - - rhel9cis_rule_3_1_3 + - rhel9cis_rule_3_1_3 tags: - - level2-server - - level2-workstation - - patch - - tipc - - rule_3.1.3 + - level1-server + - level2-workstation + - patch + - bluetooth + - rule_3.1.3 + - NIST800-53R5_CM-7 + block: + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | pkg" + when: + - not rhel9cis_bluetooth_service + - not rhel9cis_bluetooth_mask + ansible.builtin.package: + name: bluez + state: absent + + - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | mask" + when: + - not rhel9cis_bluetooth_service + - rhel9cis_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 cc5567f..bc210ae 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -1,52 +1,121 @@ --- -- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled" - block: - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | IPv6" - block: - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding | Set Fact" - ansible.builtin.set_fact: - rhel9cis_flush_ipv6_route: true - - - name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - - when: rhel9cis_ipv6_required +- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available" when: - - not rhel9cis_is_router - - rhel9cis_rule_3_2_1 + - rhel9cis_rule_3_2_1 tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.2.1 - -- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" + - level2-server + - level2-workstation + - patch + - rule_3.2.1 + - dccp + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 block: - - name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | modprobe" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/dccp.conf + regexp: '^(#)?install dccp(\\s|$)' + line: "{{ item }}" + create: true + loop: + - install dccp /bin/true + - blacklist dccp + + - name: "3.2.1 | PATCH | Ensure dccp 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' + +- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" when: - - not rhel9cis_is_router - - rhel9cis_rule_3_2_2 + - rhel9cis_rule_3_2_2 tags: - - level1-server - - level1-workstation - - patch - - sysctl - - rule_3.2.2 + - level2-server + - level2-workstation + - patch + - rule_3.2.2 + - tipc + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + block: + - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | modprobe" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/tipc.conf + regexp: '^(#)?install tipc(\\s|$)' + line: "{{ item }}" + create: true + loop: + - install tipc /bin/true + - blacklist tipc + + - 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: + - rhel9cis_rule_3_2_3 + tags: + - level2-server + - level2-workstation + - patch + - rule_3.2.3 + - rds + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + block: + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | modprobe" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/rds.conf + regexp: '^(#)?install rds(\\s|$)' + line: "{{ item }}" + create: true + loop: + - install rds /bin/true + - blacklist rds + + - name: "3.2.3 | PATCH | Ensure rds kernel module is not available | blacklist" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/blacklist.conf + regexp: "^(#)?blacklist rds(\\s|$)" + line: "blacklist rds" + create: true + mode: '0600' + +- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" + when: + - rhel9cis_rule_3_2_4 + tags: + - level2-server + - level2-workstation + - patch + - rule_3.2.4 + - sctp + - NIST800-53R5_CM-7 + - NIST800-53R5_SI-4 + block: + - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | modprobe" + ansible.builtin.lineinfile: + path: /etc/modprobe.d/sctp.conf + regexp: '^(#)?install sctp(\\s|$)' + line: "{{ item }}" + create: true + loop: + - install sctp /bin/true + - blacklist sctp + + - 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 e8f3a5f..2f73979 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -1,194 +1,306 @@ --- -- 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 | IPv4 | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv4" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6" - block: - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6 | Set Fact" - ansible.builtin.set_fact: - rhel9cis_flush_ipv6_route: true - - - name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - when: rhel9cis_ipv6_required +- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled" when: - - rhel9cis_rule_3_3_1 + - not rhel9cis_is_router + - rhel9cis_rule_3_3_1 tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.1 - -- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted" + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 block: - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4 | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6" - block: - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6 | Set Fact" - ansible.builtin.set_fact: - rhel9cis_flush_ipv6_route: true - - - name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - when: rhel9cis_ipv6_required - when: - - rhel9cis_rule_3_3_2 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.2 - -- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" - block: - - name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_3 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.3 - -- name: "3.3.4 | PATCH | Ensure suspicious packets are logged" - block: - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_4 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.4 - -- name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" - block: - - name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: 3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_5 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.5 - -- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" - block: - - name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_6 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.6 - -- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" - block: - - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_7 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.7 - -- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" - block: - - name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true - rhel9cis_flush_ipv4_route: true - - - name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - when: - - rhel9cis_rule_3_3_8 - tags: - - level1-server - - level1-workstation - - sysctl - - patch - - rule_3.3.8 - -- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted" - block: - - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6 | Set Fact" - ansible.builtin.set_fact: - rhel9cis_sysctl_update: true + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | IPv6" + when: rhel9cis_ipv6_required + block: + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding | Set Fact" + ansible.builtin.set_fact: rhel9cis_flush_ipv6_route: true - - name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6" - ansible.builtin.debug: - msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl" + - name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" + +- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled" when: - - rhel9cis_ipv6_required - - rhel9cis_rule_3_3_9 + - not rhel9cis_is_router + - rhel9cis_rule_3_3_2 tags: - - level2-server - - level2-workstation - - sysctl - - patch - - rule_3.3.9 + - level1-server + - level1-workstation + - patch + - sysctl + - rule_3.3.2 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + - name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored" + when: + - rhel9cis_rule_3_3_3 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.3 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored" + when: + - rhel9cis_rule_3_3_4 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.4 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: 3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted" + when: + - rhel9cis_rule_3_3_5 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.5 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6" + when: rhel9cis_ipv6_required + block: + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_flush_ipv6_route: true + + - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" + +- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted" + when: + - rhel9cis_rule_3_3_6 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.6 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv4 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv4" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + + - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6" + when: rhel9cis_ipv6_required + block: + - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_flush_ipv6_route: true + + - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" + +- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" + when: + - rhel9cis_rule_3_3_7 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.7 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted" + when: + - rhel9cis_rule_3_3_8 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.8 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv4 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv4" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6" + when: rhel9cis_ipv6_required + block: + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_flush_ipv6_route: true + + - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" + +- name: "3.3.9 | PATCH | Ensure suspicious packets are logged" + when: + - rhel9cis_rule_3_3_9 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.9 + - NIST800-53R5_AU-3 + block: + - name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled" + when: + - rhel9cis_rule_3_3_10 + tags: + - level1-server + - level1-workstation + - sysctl + - patch + - rule_3.3.10 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv4_route: true + + - name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" + +- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted" + when: + - rhel9cis_ipv6_required + - rhel9cis_rule_3_3_11 + tags: + - level2-server + - level2-workstation + - sysctl + - patch + - rule_3.3.11 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6 | Set Fact" + ansible.builtin.set_fact: + rhel9cis_sysctl_update: true + rhel9cis_flush_ipv6_route: true + + - name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6" + ansible.builtin.debug: + msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl" diff --git a/tasks/section_3/cis_3.4.1.x.yml b/tasks/section_3/cis_3.4.1.x.yml deleted file mode 100644 index 8a7e721..0000000 --- a/tasks/section_3/cis_3.4.1.x.yml +++ /dev/null @@ -1,59 +0,0 @@ ---- - -- name: "3.4.1.1 | PATCH | Ensure nftables is installed" - ansible.builtin.package: - name: - - nftables - state: present - when: - - rhel9cis_rule_3_4_1_1 - - rhel9cis_firewall == 'nftables' - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.1.1 - -- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use" - block: - - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables" - ansible.builtin.systemd: - name: "{{ item }}" - masked: true - loop: - - firewalld - when: - - item in ansible_facts.packages - - rhel9cis_firewall == 'nftables' - - - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld" - ansible.builtin.systemd: - name: "{{ item }}" - masked: true - loop: - - nftables - when: - - item in ansible_facts.packages - - rhel9cis_firewall == 'firewalld' - - - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | package installed" - ansible.builtin.package: - name: "{{ rhel9cis_firewall }}" - state: installed - - - name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" - ansible.builtin.systemd: - name: "{{ rhel9cis_firewall }}" - enabled: true - state: started - - when: - - rhel9cis_rule_3_4_1_2 - tags: - - level1-server - - level1-workstation - - patch - - firewalld - - nftables - - rule_3.4.1.2 diff --git a/tasks/section_3/cis_3.4.2.x.yml b/tasks/section_3/cis_3.4.2.x.yml deleted file mode 100644 index ee57e5b..0000000 --- a/tasks/section_3/cis_3.4.2.x.yml +++ /dev/null @@ -1,301 +0,0 @@ ---- - -- name: "3.4.2.1 | PATCH | Ensure firewalld default zone is set" - block: - - name: "3.4.2.1 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.shell: "firewall-cmd --get-default-zone | grep {{ rhel9cis_default_zone }}" - changed_when: false - failed_when: ( firewalld_zone_set.rc not in [ 0, 1 ] ) - register: firewalld_zone_set - - - name: "3.4.2.1 | AUDIT | Ensure firewalld default zone is set" - ansible.builtin.command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}" - when: firewalld_zone_set.rc != 0 - when: - - rhel9cis_firewall == "firewalld" - - rhel9cis_rule_3_4_2_1 - tags: - - level1-server - - level1-workstation - - patch - - firewalld - - rule_3.4.2.1 - -- name: "3.4.2.2 | AUDIT | Ensure at least one nftables table exists" - block: - - name: "3.4.2.2 | AUDIT | Ensure a table exists | Check for tables" - ansible.builtin.command: nft list tables - changed_when: false - failed_when: false - register: rhel9cis_3_4_2_2_nft_tables - - - name: "3.4.2.2 | AUDIT | Ensure an nftables table exists | Show existing tables" - ansible.builtin.debug: - msg: - - "Below are the current nft tables, please review" - - "{{ rhel9cis_3_4_2_2_nft_tables.stdout_lines }}" - when: rhel9cis_3_4_2_2_nft_tables.stdout | length > 0 - - - name: "3.4.2.2 | 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: - - rhel9cis_3_4_2_2_nft_tables.stdout | length == 0 - - not rhel9cis_nft_tables_autonewtable - - - name: "3.4.2.2 | AUDIT | Ensure an nftables table exists | Alert on no tables | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: - - rhel9cis_3_4_2_2_nft_tables.stdout | length == 0 - - not rhel9cis_nft_tables_autonewtable - - - name: "3.4.2.2 | PATCH | Ensure a table exists | Create table if needed" - ansible.builtin.command: nft create table inet "{{ rhel9cis_nft_tables_tablename }}" - failed_when: false - when: rhel9cis_nft_tables_autonewtable - vars: - warn_control_id: '3.4.2.2' - when: - - rhel9cis_firewall == "nftables" - - rhel9cis_rule_3_4_2_2 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.2 - -- name: "3.4.2.3 | PATCH | Ensure nftables base chains exist" - block: - - name: "3.4.2.3 | 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: rhel9cis_3_4_2_3_input_chains - - - name: "3.4.2.3 | 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: rhel9cis_3_4_2_3_forward_chains - - - name: "3.4.2.3 | 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: rhel9cis_3_4_2_3_output_chains - - - name: "3.4.2.3 | AUDIT | Ensure nftables base chains exist | Display chains for review" - ansible.builtin.debug: - msg: - - "Below are the current INPUT chains" - - "{{ rhel9cis_3_4_2_3_input_chains.stdout_lines }}" - - "Below are the current FORWARD chains" - - "{{ rhel9cis_3_4_2_3_forward_chains.stdout_lines }}" - - "Below are teh current OUTPUT chains" - - "{{ rhel9cis_3_4_2_3_output_chains.stdout_lines }}" - when: not rhel9cis_nft_tables_autochaincreate - - - name: "3.4.2.3 | PATCH | Ensure nftables base chains exist | Create chains if needed" - ansible.builtin.shell: "{{ item }}" - failed_when: false - loop: - - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } - - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; } - - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } - when: rhel9cis_nft_tables_autochaincreate - when: - - rhel9cis_firewall == "nftables" - - rhel9cis_rule_3_4_2_3 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.3 - -- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured" - block: - - name: "3.4.2.4 | 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: rhel9cis_3_4_2_4_iiflo - - - name: "3.4.2.4 | 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: rhel9cis_3_4_2_4_ipsaddr - - - name: "3.4.2.4 | 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: rhel9cis_3_4_2_4_ip6saddr - - - name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set iif lo accept rule | nftables" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept - when: '"iif \"lo\" accept" not in rhel9cis_3_4_2_4_iiflo.stdout' - - - name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip sddr rule | nftables" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_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 rhel9cis_3_4_2_4_ipsaddr.stdout' - - - name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip6 saddr rule | nftables" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop - when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_2_4_ip6saddr.stdout' - when: - - rhel9cis_firewall == "nftables" - - rhel9cis_rule_3_4_2_4 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.4 - -- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | firewalld" - ansible.posix.firewalld: - rich_rule: "{{ item }}" - zone: "{{ rhel9cis_default_zone }}" - 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 - when: - - rhel9cis_firewall == "firewalld" - - rhel9cis_rule_3_4_2_4 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.4 - -- name: "3.4.2.5 | AUDIT | Ensure firewalld drops unnecessary services and ports" - block: - - name: "3.4.2.5 | 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: rhel9cis_3_4_2_5_servicesport - - - name: "3.4.2.5 | 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" - - "{{ rhel9cis_3_4_2_5_servicesport.stdout_lines }}" - when: - - rhel9cis_rule_3_4_2_5 - - rhel9cis_firewall == "firewalld" - tags: - - level1-server - - level1-workstation - - manual - - audit - - rule_3.4.2.5 - -- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured" - block: - - name: "3.4.2.6 | 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: rhel9cis_3_4_2_6_inconnectionrule - - - name: "3.4.2.6| 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: rhel9cis_3_4_2_6_outconnectionrule - - - name: "3.4.2.6| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - when: '"ip protocol tcp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout' - - - name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept - when: '"ip protocol udp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout' - - - name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept - when: '"ip protocol icmp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout' - - - name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_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 rhel9cis_3_4_2_6_outconnectionrule.stdout' - - - name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_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 rhel9cis_3_4_2_6_outconnectionrule.stdout' - - - name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_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 rhel9cis_3_4_2_6_outconnectionrule.stdout' - when: - - rhel9cis_firewall == "nftables" - - rhel9cis_rule_3_4_2_6 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.6 - -- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy" - block: - - name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' - failed_when: false - changed_when: false - register: rhel9cis_3_4_2_7_inputpolicy - - - name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' - failed_when: false - changed_when: false - register: rhel9cis_3_4_2_7_forwardpolicy - - - name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' - failed_when: false - changed_when: false - register: rhel9cis_3_4_2_7_outputpolicy - - - name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' - failed_when: false - changed_when: false - register: rhel9cis_3_4_2_7_sshallowcheck - - - name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept - when: '"tcp dport ssh accept" not in rhel9cis_3_4_2_7_sshallowcheck.stdout' - - - name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" - ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; } - when: '"type filter hook input priority 0; policy drop;" not in rhel9cis_3_4_2_7_inputpolicy.stdout' - - - name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" - ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; } - when: '"type filter hook forward priority 0; policy drop;" not in rhel9cis_3_4_2_7_forwardpolicy.stdout' - - - name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" - ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } - when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_3_4_2_7_outputpolicy.stdout' - when: - - rhel9cis_firewall == "nftables" - - rhel9cis_rule_3_4_2_7 - tags: - - level1-server - - level1-workstation - - patch - - nftables - - rule_3.4.2.7 diff --git a/tasks/section_3/main.yml b/tasks/section_3/main.yml index 34553d7..bd4442d 100644 --- a/tasks/section_3/main.yml +++ b/tasks/section_3/main.yml @@ -1,21 +1,13 @@ --- -- name: "SECTION | 3.1.x | Disable unused network protocols and devices" +- name: "SECTION | 3.1.x | Configure Network Devices" ansible.builtin.import_tasks: - file: cis_3.1.x.yml + file: cis_3.1.x.yml -- name: "SECTION | 3.2.x | Network Parameters (Host Only)" +- name: "SECTION | 3.2.x | Configure Network Kernel Modules" ansible.builtin.import_tasks: - file: cis_3.2.x.yml + file: cis_3.2.x.yml -- name: "SECTION | 3.3.x | Network Parameters (host and Router)" +- name: "SECTION | 3.3.x | Configure Network Kernel Parameters" ansible.builtin.import_tasks: - file: cis_3.3.x.yml - -- name: "SECTION | 3.4.1.x | Firewall configuration" - ansible.builtin.import_tasks: - file: cis_3.4.1.x.yml - -- name: "SECTION | 3.4.2.x | Configure firewall" - ansible.builtin.import_tasks: - file: cis_3.4.2.x.yml + file: cis_3.3.x.yml From 9755b0fb6256c5571f359ab66f3c92f4ff51d2f8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:00:45 +0100 Subject: [PATCH 018/327] section 5 v2 initial Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 645 +++++++++++++++++++++++------- tasks/section_5/cis_5.2.x.yml | 512 +++++++----------------- tasks/section_5/cis_5.3.1.x.yml | 55 +++ tasks/section_5/cis_5.3.2.x.yml | 200 +++++++++ tasks/section_5/cis_5.3.3.1.x.yml | 86 ++++ tasks/section_5/cis_5.3.3.2.x.yml | 204 ++++++++++ tasks/section_5/cis_5.3.3.3.x.yml | 79 ++++ tasks/section_5/cis_5.3.3.4.x.yml | 104 +++++ tasks/section_5/main.yml | 56 +-- 9 files changed, 1404 insertions(+), 537 deletions(-) create mode 100644 tasks/section_5/cis_5.3.1.x.yml create mode 100644 tasks/section_5/cis_5.3.2.x.yml create mode 100644 tasks/section_5/cis_5.3.3.1.x.yml create mode 100644 tasks/section_5/cis_5.3.3.2.x.yml create mode 100644 tasks/section_5/cis_5.3.3.3.x.yml create mode 100644 tasks/section_5/cis_5.3.3.4.x.yml diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index ce8bb58..0b4c63f 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -1,163 +1,518 @@ --- -- name: "5.1.1 | PATCH | Ensure cron daemon is enabled" - ansible.builtin.service: - name: crond - enabled: true +- name: "5.1.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" when: - - rhel9cis_rule_5_1_1 + - rhel9cis_rule_5_1_1 tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.1 - -- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" + - level1-server + - level1-workstation + - patch + - ssh + - permissions + - rule_5.1.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 ansible.builtin.file: - path: /etc/crontab - owner: root - group: root - mode: '0600' - when: - - rhel9cis_rule_5_1_2 - tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.2 + path: "/etc/ssh/sshd_config" + owner: root + group: root + mode: '0600' -- 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' +- name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured" when: - - rhel9cis_rule_5_1_3 + - rhel9cis_rule_5_1_2 tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_rule_5_1_4 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_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: - - rhel9cis_rule_5_1_6 - tags: - - level1-server - - level1-workstation - - 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: - - rhel9cis_rule_5_1_7 - tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.7 - -- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users" + - level1-server + - level1-workstation + - patch + - ssh + - permissions + - rule_5.1.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 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.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: rhel9cis_5_1_2_ssh_private_host_key - - 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: rhel9cis_5_1_8_cron_allow_state + - name: "5.1.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: 'u-x,go-rwx' + loop: "{{ rhel9cis_5_1_2_ssh_private_host_key.files }}" + loop_control: + label: "{{ item.path }}" - - 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 rhel9cis_5_1_8_cron_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: '0600' +- name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured" when: - - rhel9cis_rule_5_1_8 + - rhel9cis_rule_5_1_3 tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.8 - -- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users" + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 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.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: rhel9cis_5_1_3_ssh_public_host_key - - 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: rhel9cis_5_1_9_at_allow_state + - name: "5.1.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: 'u-x,go-wx' + loop: "{{ rhel9cis_5_1_3_ssh_public_host_key.files }}" + loop_control: + label: "{{ item.path }}" - - 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 rhel9cis_5_1_9_at_allow_state.stat.exists else "touch" }}' - owner: root - group: root - mode: '0600' +- name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured" when: - - rhel9cis_rule_5_1_9 + - rhel9cis_rule_5_1_4 + - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" tags: - - level1-server - - level1-workstation - - patch - - cron - - rule_5.1.9 + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.4 + - NIST800-53R5_SC-8 + block: + - name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKCIPHERS' }}" + +- name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel9cis_rule_5_1_5 + - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.5 + - NIST800-53R5_SC-6 + block: + - name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured" + when: + - rhel9cis_rule_5_1_6 + - "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module" + tags: + - level1-server + - level1-workstation + - automated + - patch + - crypto + - rule_5.1.6 + - NIST800-53R5_SC-6 + block: + - name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion" + ansible.builtin.template: + src: etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod + owner: root + group: root + mode: '0640' + notify: + - Update Crypto Policy + - Set Crypto Policy + + - name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + +- name: "5.1.7 | PATCH | Ensure sshd access is configured" + when: + - rhel9cis_rule_5_1_7 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + block: + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowusers" + when: "rhel9cis_sshd_allowusers | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^AllowUsers" + line: "AllowUsers {{ rhel9cis_sshd_allowusers }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowgroups" + when: "rhel9cis_sshd_allowgroups | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^AllowGroups" + line: "AllowGroups {{ rhel9cis_sshd_allowgroups }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denyusers" + when: "rhel9cis_sshd_denyusers'|default('') | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^DenyUsers" + line: "DenyUsers {{ rhel9cis_sshd_denyusers }}" + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denygroups" + when: "rhel9cis_sshd_denygroups|default('') | length > 0" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^DenyGroups" + line: "DenyGroups {{ rhel9cis_sshd_denygroups }}" + validate: sshd -t -f %s + notify: Restart sshd + +- name: "5.1.8 | PATCH | Ensure sshd Banner is configured" + when: + - rhel9cis_rule_5_1_8 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.8 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^Banner' + line: 'Banner /etc/issue.net' + +- name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured" + when: + - rhel9cis_rule_5_1_9 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.9 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^ClientAliveInterval' + line: "ClientAliveInterval {{ rhel9cis_sshd_clientaliveinterval }}" + validate: sshd -t -f %s + + - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^ClientAliveCountMax' + line: "ClientAliveCountMax {{ rhel9cis_sshd_clientalivecountmax }}" + validate: sshd -t -f %s + +- name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled" + when: + - rhel9cis_rule_5_1_10 + tags: + - level2-server + - level1-workstation + - patch + - ssh + - rule_5.1.10 + - NIST800-53R5_CM-7 + block: + - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | config file" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(#|)\s*DisableForwarding + line: 'DisableForwarding yes' + validate: sshd -t -f %s + + - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config.d/50-redhat.conf + regexp: ^(?i)(#|)\s*X11Forwarding + line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' + validate: sshd -t -f %s + +- name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled" + when: + - rhel9cis_rule_5_1_11 + tags: + - level1-server + - level1-workstation + - patch + - sshs + - rule_5.1.11 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*GSSAPIAuthentication + line: 'GSSAPIAuthentication no' + validate: sshd -t -f %s + +- name: "5.1.12 | PATCH | Ensure sshd HostbasedAuthentication is disabled" + when: + - rhel9cis_rule_5_1_12 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.12 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*HostbasedAuthentication + line: 'HostbasedAuthentication no' + validate: sshd -t -f %s + +- name: "5.1.13 | PATCH | Ensure sshd IgnoreRhosts is enabled" + when: + - rhel9cis_rule_5_1_13 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.13 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*IgnoreRhosts + line: 'IgnoreRhosts yes' + validate: sshd -t -f %s + +- name: "5.1.14 | PATCH | Ensure sshd LoginGraceTime is set to one minute or less" + when: + - rhel9cis_rule_5_1_14 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.14 + - NIST800-53R5_CM-6 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*LoginGraceTime + line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" + validate: sshd -t -f %s + +- name: "5.1.15 | PATCH | Ensure sshd LogLevel is appropriate" + when: + - rhel9cis_rule_5_1_15 + tags: + - level1-server + - level1-workstation + - patch + - sshs + - rule_5.1.15 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*LogLevel + line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' + validate: sshd -t -f %s + +- name: "5.1.16 | PATCH | Ensure sshd MaxAuthTries is set to 4 or less" + when: + - rhel9cis_rule_5_1_16 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.16 + - NIST800-53R5_AU-3 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: '^(#)?MaxAuthTries \d' + line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}' + validate: sshd -t -f %s + +- name: "5.1.17 | PATCH | Ensure sshd MaxStartups is configured" + when: + - rhel9cis_rule_5_1_17 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.17 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxStartups + line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' + validate: sshd -t -f %s + +- name: "5.1.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" + when: + - rhel9cis_rule_5_1_18 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.18 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxSessions + line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' + validate: sshd -t -f %s + +- name: "5.1.19 | PATCH | Ensure sshd PermitEmptyPasswords is disabled" + when: + - rhel9cis_rule_5_1_19 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.19 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*PermitEmptyPasswords + line: 'PermitEmptyPasswords no' + validate: sshd -t -f %s + +- name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled" + when: + - rhel9cis_rule_5_1_20 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.20 + - NIST800-53R5_AC-6 + block: + - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*PermitRootLogin + line: 'PermitRootLogin no' + validate: sshd -t -f %s + + - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | override file" + ansible.builtin.file: + path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf + state: absent + +- name: "5.1.21 | PATCH | Ensure sshd PermitUserEnvironment is disabled" + when: + - rhel9cis_rule_5_1_21 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.21 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" + line: 'PermitUserEnvironment no' + validate: sshd -t -f %s + +- name: "5.1.22 | PATCH | Ensure SSH PAM is enabled" + when: + - rhel9cis_rule_5_1_22 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + tags: + - level1-server + - level1-workstation + - patch + - ssh + - rule_5.1.22 + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*MaxStartupsUsePAM + line: 'UsePAM yes' + validate: sshd -t -f %s diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index ac62767..6bb0608 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -1,391 +1,165 @@ --- -- name: "5.2.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" - ansible.builtin.file: - path: "/etc/ssh/sshd_config" - owner: root - group: root - mode: '0600' +- name: "5.2.1 | PATCH | Ensure sudo is installed" when: - - rhel9cis_rule_5_2_1 + - rhel9cis_rule_5_2_1 tags: - - level1-server - - level1-workstation - - patch - - ssh - - permissions - - rule_5.2.1 + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.1 + - NIST800-53R5_AC-6 + ansible.builtin.package: + name: sudo + state: present -- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured" +- name: "5.2.2 | PATCH | Ensure sudo commands use pty" + when: + - rhel9cis_rule_5_2_2 + tags: + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.2 + - NIST800-53R5_AC-6 + ansible.builtin.lineinfile: + path: /etc/sudoers + line: "Defaults use_pty" + validate: '/usr/sbin/visudo -cf %s' + +- name: "5.2.3 | PATCH | Ensure sudo log file exists" + when: + - rhel9cis_rule_5_2_3 + tags: + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.3 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + ansible.builtin.lineinfile: + path: /etc/sudoers + regexp: '^Defaults logfile=' + line: 'Defaults logfile="{{ rhel9cis_sudolog_location }}"' + validate: '/usr/sbin/visudo -cf %s' + +- name: "5.2.4 | PATCH | Ensure users must provide password for escalation" + when: + - rhel9cis_rule_5_2_4 + tags: + - level2-server + - level2-workstation + - patch + - sudo + - rule_5.2.4 + - NIST800-53R5_AC-6 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: rhel9cis_5_2_2_ssh_private_host_key + - name: "5.2.4 | AUDIT | Ensure users must provide password for escalation | discover accts with NOPASSWD" + ansible.builtin.shell: grep -Ei '(nopasswd)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1 + become: true + changed_when: false + failed_when: false + register: rhel9cis_5_2_4_nopasswd - - 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' - loop: "{{ rhel9cis_5_2_2_ssh_private_host_key.files }}" - loop_control: - label: "{{ item.path }}" + - name: "5.2.4 | PATCH | Ensure users must provide password for escalation" + when: rhel9cis_5_2_4_nopasswd.std | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^((?!#|{% for name in rhel9cis_sudoers_exclude_nopasswd_list %}{{ name }}{% if not loop.last -%}|{%- endif -%}{% endfor %}).*)NOPASSWD(.*)' + replace: '\1PASSWD\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_4_nopasswd.stdout_lines }}" + +- name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" when: - - rhel9cis_rule_5_2_2 + - rhel9cis_rule_5_2_5 tags: - - level1-server - - level1-workstation - - patch - - ssh - - permissions - - rule_5.2.2 - -- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.5 + - NIST800-53R5_AC-6 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: rhel9cis_5_2_3_ssh_public_host_key + - name: "5.2.5 | AUDIT | Ensure re-authentication for privilege escalation is not disabled globally" + ansible.builtin.shell: grep -Ei '(!authenticate)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1 + become: true + changed_when: false + failed_when: false + register: rhel9cis_5_2_4_authenticate - - 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' - loop: "{{ rhel9cis_5_2_3_ssh_public_host_key.files }}" - loop_control: - label: "{{ item.path }}" + - name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" + when: rhel9cis_5_2_4_authenticate.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: '^([^#].*)!authenticate(.*)' + replace: '\1authenticate\2' + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_4_authenticate.stdout_lines }}" + +- name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly" when: - - rhel9cis_rule_5_2_3 + - rhel9cis_rule_5_2_6 tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.3 - -- name: "5.2.4 | PATCH | Ensure SSH access is limited" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.6 block: - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^AllowUsers" - line: "AllowUsers {{ rhel9cis_sshd['allowusers'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['allowusers']|default('') | length > 0" + - name: "5.2.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: rhel9cis_5_2_6_timeout_files - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^AllowGroups" - line: "AllowGroups {{ rhel9cis_sshd['allowgroups'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['allowgroups']|default('') | length > 0" + - name: "5.2.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={{ rhel9cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + when: rhel9cis_5_2_6_timeout_files.stdout | length == 0 - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^DenyUsers" - line: "DenyUsers {{ rhel9cis_sshd['denyusers'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['denyusers']|default('') | length > 0" + - name: "5.2.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={{ rhel9cis_sudo_timestamp_timeout }}" + validate: '/usr/sbin/visudo -cf %s' + loop: "{{ rhel9cis_5_2_6_timeout_files.stdout_lines }}" + when: rhel9cis_5_2_6_timeout_files.stdout | length > 0 - - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^DenyGroups" - line: "DenyGroups {{ rhel9cis_sshd['denygroups'] }}" - validate: sshd -t -f %s - notify: Restart sshd - when: "rhel9cis_sshd['denygroups']|default('') | length > 0" +- name: "5.2.7 | PATCH | Ensure access to the su command is restricted" when: - - rhel9cis_rule_5_2_4 + - rhel9cis_rule_5_2_7 tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.4 - -- name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#LogLevel|^LogLevel" - line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_5 - tags: - - level1-server - - level1-workstation - - patch - - sshs - - rule_5.2.5 - -- name: "5.2.6 | PATCH | Ensure SSH PAM is enabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#UsePAM|^UsePAM" - line: 'UsePAM yes' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_6 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.6 - -- name: "5.2.7 | PATCH | Ensure SSH root login is disabled" + - level1-server + - level1-workstation + - patch + - sudo + - rule_5.2.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 block: - - name: "5.2.7 | PATCH | Ensure SSH root login is disabled | config file" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitRootLogin|^PermitRootLogin" - line: 'PermitRootLogin no' - validate: sshd -t -f %s + - name: "5.2.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" + ansible.builtin.group: + name: "{{ rhel9cis_sugroup }}" + state: present + register: rhel9cis_5_2_7_sugroup - - name: "5.2.7 | PATCH | Ensure SSH root login is disabled | override file" - ansible.builtin.file: - path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf - state: absent - when: - - rhel9cis_rule_5_2_7 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.7 + - name: "5.2.7 | PATCH | Ensure access to the su command is restricted | remove users from group" + ansible.builtin.lineinfile: + path: /etc/group + regexp: '^{{ rhel9cis_sugroup }}(:.:.*:).*$' + line: '{{ rhel9cis_sugroup }}\g<1>' + backrefs: true -- name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#HostbasedAuthentication|^HostbasedAuthentication" - line: 'HostbasedAuthentication no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_8 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.8 - -- name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" - line: 'PermitEmptyPasswords no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_9 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.9 - -- name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" - line: 'PermitUserEnvironment no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_10 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.10 - -- name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#IgnoreRhosts|^IgnoreRhosts" - line: 'IgnoreRhosts yes' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_11 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.11 - -- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled" - block: - - - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | config file" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - validate: sshd -t -f %s - - - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | override" - ansible.builtin.lineinfile: - path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: "^#X11Forwarding|^X11Forwarding" - line: 'X11Forwarding no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_12 - tags: - - level2-server - - level1-workstation - - patch - - ssh - - rule_5.2.12 - -- name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" - line: 'AllowTcpForwarding no' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_13 - tags: - - level2-server - - level2-workstation - - 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 - changed_when: false - failed_when: ( ssh_crypto_discovery.rc not in [ 0, 1 ] ) - register: ssh_crypto_discovery - - - 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: ssh_crypto_discovery.stdout | length > 0 - when: - - rhel9cis_rule_5_2_14 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.14 - -- name: "5.2.15 | PATCH | Ensure SSH warning banner is configured" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^Banner' - line: 'Banner /etc/issue.net' - when: - - rhel9cis_rule_5_2_15 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.15 - -- name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^(#)?MaxAuthTries \d' - line: 'MaxAuthTries 4' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_16 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.16 - -- name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#MaxStartups|^MaxStartups" - line: 'MaxStartups 10:30:60' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_17 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.17 - -- name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#MaxSessions|^MaxSessions" - line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_18 - tags: - - level1-server - - level1-workstation - - 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: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#LoginGraceTime|^LoginGraceTime" - line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}" - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_19 - tags: - - level1-server - - level1-workstation - - 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: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^ClientAliveInterval' - line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}" - validate: sshd -t -f %s - - - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: '^ClientAliveCountMax' - line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}" - validate: sshd -t -f %s - when: - - rhel9cis_rule_5_2_20 - tags: - - level1-server - - level1-workstation - - patch - - ssh - - rule_5.2.20 + - name: "5.2.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={{ rhel9cis_sugroup }}' diff --git a/tasks/section_5/cis_5.3.1.x.yml b/tasks/section_5/cis_5.3.1.x.yml new file mode 100644 index 0000000..050a081 --- /dev/null +++ b/tasks/section_5/cis_5.3.1.x.yml @@ -0,0 +1,55 @@ +--- + +- name: "5.3.1.1 | PATCH | Ensure latest version of pam is installed" + when: + - rhel9cis_rule_5_3_1_1 + - ansible_facts.packages['pam'][0]['version'] is version('1.5.1-19', '<') or + "'pam' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.1 + ansible.builtin.package: + name: pam + state: latest + +- name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed" + when: + - rhel9cis_rule_5_3_1_2 + - rhel9cis_authselect_pkg_update + - ansible_facts.packages['authselect'][0]['version'] is version('1.2.6-2', '<') or + "'authselect' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.2 + block: + - name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed | Patch" + ansible.builtin.package: + name: authselect + state: latest + register: rhel9cis_authselect_update + + - name: "5.3.1.2 | AUDIT | Ensure latest version of authselect is installed | Patch" + when: rhel9cis_authselect_update.changed # noqa no-handler + ansible.builtin.set_fact: + authselect_update: OK + +- name: "5.3.1.3 | PATCH | Ensure libpwquality is installed" + when: + - rhel9cis_rule_5_3_1_3 + - ansible_facts.packages['libpwquality'][0]['version'] is version('1.4.4-8', '<') + "'libpwquality' not in ansible_facts.packages" + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.1.3 + ansible.builtin.package: + name: libpwquality + state: latest diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml new file mode 100644 index 0000000..3f318c9 --- /dev/null +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -0,0 +1,200 @@ +--- + +- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules" + when: + - rhel9cis_rule_5_3_2_1 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - manual + - patch + - authselect + - rule_5.3.2.1 + block: + - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" + when: + - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" + - rhel9cis_authselect_custom_profile_create + - not rhel9cis_5_3_2_1_profile.stat.exists + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }}" + args: + creates: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}" + + - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Select profiles" + when: + - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" + - rhel9cis_authselect_custom_profile_select + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force" + +- name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled" + when: + - rhel9cis_rule_5_3_2_2 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + 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_5.3.2.2 + notify: Update_authselect + block: + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep faillock + changed_when: false + failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current + + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" + when: rhel9cis_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-faillock" + +- name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" + when: + - rhel9cis_rule_5_3_2_3 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_5.3.2.3 + notify: Update_authselect + block: + - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep quality + changed_when: false + failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current + + - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" + when: rhel9cis_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-pwquality" + +# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" +# when: +# - rhel9cis_rule_5_3_2_3 +# - rhel9cis_disruption_high +# - rhel9cis_allow_authselect_updates +# tags: +# - level1-server +# - level1-workstation +# - automated +# - patch +# - NIST800-53R5_IA-5 +# - authselect +# - rule_5.3.2.3 +# notify: Update_authselect +# block: +# - name: "5.3.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: rhel9cis_pwquality_enabled.rc not in [ 0, 1 ] +# register: rhel9cis_pwquality_enabled + +# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" +# when: "'system-auth:password' not in rhel9cis_pwquality_enabled.stdout" +# ansible.builtin.lineinfile: +# path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth +# regexp: "{{ item.regexp }}" +# line: "{{ item.line }}" +# backrefs: true +# insertbefore: "{{ item.before | default (omit) }}" +# 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: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" +# when: "'password-auth:password' not in rhel9cis_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/{{ rhel9cis_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: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" + when: + - rhel9cis_rule_5_3_2_4 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_5.3.2.4 + notify: Update_authselect + block: + - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" + ansible.builtin.shell: authselect current | grep pwhistory + changed_when: false + failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current + + - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" + when: rhel9cis_authselect_current.rc != 0 + ansible.builtin.shell: "authselect enable-feature with-pwhistory" + +- name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" + when: + - rhel9cis_rule_5_3_2_5 + - rhel9cis_disruption_high + - rhel9cis_allow_authselect_updates + tags: + - level1-server + - level1-workstation + - automated + - patch + - NIST800-53R5_IA-5 + - authselect + - rule_5.3.2.5 + block: + - name: "5.3.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: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] + register: rhel9cis_authselect_pam_unix + + - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" + when: "'system-auth:password' not in rhel9cis_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + 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: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" + when: "'password-auth:password' not in rhel9cis_authselect_pam_unix.stdout" + ansible.builtin.lineinfile: + path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth + line: "{{ item.line }}" + regexp: "{{ item.regexp }}" + backrefs: true + insertafter: "{{ item.after | default (omit) }}" + insertbefore: "{{ item.before | default (omit) }}" + 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_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml new file mode 100644 index 0000000..67b8763 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -0,0 +1,86 @@ +--- + +- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" + when: + - rhel8cis_rule_5_3_3_1_1 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.1 + block: + - name: "5.3.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: "5.3.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: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured" + when: + - rhel8cis_rule_5_3_3_1_2 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.2 + block: + - name: "5.3.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: "5.3.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: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" + when: + - rhel9cis_rule_5_3_3_1_3 + tags: + - level1-server + - level1-workstation + - automated + - patch + - pam + - rule_5.3.3.1.3 + block: + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | configure faillock.conf" + ansible.builtin.lineinfile: + path: /etc/security/faillock.conf + regexp: '^{{ rhel9cis_pamroot_lock_option }}' + line: "{{ rhel9cis_pamroot_lock_string }}" + insertafter: '^# end of pam-auth-update config' + create: true + + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | pam_files" + when: not rhel9cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\4 + loop: + - password + - system diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml new file mode 100644 index 0000000..931f867 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -0,0 +1,204 @@ +--- + +- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured" + when: + - rhel9cis_rule_5_3_3_2_1 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.1 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from conf files except expected file" + when: + - item != rhel9cis_passwd_difok_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'difok\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - /etc/pam.d/*-auth + + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_difok_file }}.j2" + dest: "/{{ rhel9cis_passwd_difok_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.2 | PATCH | Ensure password length is configured" + when: + - rhel9cis_rule_5_3_3_2_2 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.2 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from conf files except expected file" + when: + - item != rhel9cis_passwd_minlen_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'minlen\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_minlen_file }}.j2" + dest: "/{{ rhel9cis_passwd_minlen_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured" + when: + - rhel9cis_rule_5_3_3_2_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.3 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove pwd complex settings from conf files except expected file" + when: + - item != rhel9cis_passwd_complex_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_complex_file }}.j2" + dest: "/{{ rhel9cis_passwd_complex_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured" + when: + - rhel9cis_rule_5_3_3_2_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.4 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file" + when: + - item != rhel9cis_passwd_maxrepeat_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'maxrepeat\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_maxrepeat_file }}.j2" + dest: "/{{ rhel9cis_passwd_maxrepeat_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is is configured" + when: + - rhel9cis_rule_5_3_3_2_5 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.5 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence settings from conf files except expected file" + when: + - item != rhel9cis_passwd_maxsequence_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'maxsequence\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_maxsequence_file }}.j2" + dest: "/{{ rhel9cis_passwd_maxsequence_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled" + when: + - rhel9cis_rule_5_3_3_2_6 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.6 + - NIST800-53R5_IA-5 + - pam + block: + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck settings from conf files except expected file" + when: + - item != rhel9cis_passwd_dictcheck_file + ansible.builtin.replace: + path: "{{ item }}" + regexp: 'dictcheck\s*=\s*\d+\b' + replace: '' + with_fileglob: + - '/etc/security/pwquality.conf' + - '/etc/security/pwquality.conf.d/*.conf' + - '/etc/pam.d/*-auth' + + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists" + ansible.builtin.template: + src: "{{ rhel9cis_passwd_dictcheck_file }}.j2" + dest: "/{{ rhel9cis_passwd_dictcheck_file }}" + owner: root + group: root + mode: '0600' + +- name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user" + when: + - rhel9cis_rule_5_3_3_2_7 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.2.7 + - NIST800-53R5_IA-5 + - pam + ansible.builtin.template: + src: "{{ rhel9cis_passwd_quality_enforce_root_file }}.j2" + dest: "/{{ rhel9cis_passwd_quality_enforce_root_file }}" + owner: root + group: root + mode: '0600' diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml new file mode 100644 index 0000000..659ea82 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -0,0 +1,79 @@ +--- + +- name: "5.3.3.3.1 | PATCH | Ensure password history remember is configured" + when: + - rhel9cis_rule_5_3_3_3_1 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.3.1 + - pam + block: + - name: "5.3.3.3.1 | AUDIT | Ensure password history remember is configured | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+([^#\n\r]+\s+)?remember=\d+\b' /etc/pam.d/password-auth /etc/pam.d/system-auth + register: rhel9_pwhistory_remember + changed_when: false + failed_when: rhel9_pwhistory_remember.rc not in [0, 1] + + - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set" + when: rhel9_pwhistory_remember.stdout | length > 0 + ansible.builtin.lineinfile: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" + regexp: ^(password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+)(.*)(remember=\d+) + line: '\1\2 remember={{ rhel9cis_pamd_pwhistory_remember }}' + backrefs: true + notify: Pam_auth_update_pwhistory + +- name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user" + when: + - rhel9cis_rule_5_3_3_3_2 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.3.2 + - pam + block: + - name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/common-password + register: rhel9_pwhistory_enforce_for_root + changed_when: false + failed_when: rhel9_pwhistory_enforce_for_root.rc not in [0, 1] + + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure remember is set" + when: rhel9_pwhistory_enforce_for_root.stdout | length > 0 + ansible.builtin.lineinfile: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" + regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root) + line: '\1\2\3 enforce_for_root' + backrefs: true + notify: Pam_auth_update_pwhistory + +- name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" + when: + - rhel9cis_rule_5_3_3_3_3 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.3.2 + - pam + block: + - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/common-password + register: rhel9_pwhistory_use_authtok + changed_when: false + failed_when: rhel9_pwhistory_use_authtok.rc not in [0, 1] + + - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure remember is set" + when: rhel9_pwhistory_use_authtok.stdout | length > 0 + ansible.builtin.lineinfile: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" + regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) + line: '\1\2\3 use_authtok' + backrefs: true + notify: Pam_auth_update_pwhistory diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml new file mode 100644 index 0000000..4faedb3 --- /dev/null +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -0,0 +1,104 @@ +--- + +- name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok" + when: + - rhel9cis_rule_5_3_3_4_1 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.3.3.4.1 + - pam + block: + - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" + ansible.builtin.shell: grep -E "pam_unix.so.*nullok" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq + changed_when: false + failed_when: rhel9cis_pam_nullok.rc not in [ 0, 1 ] + register: rhel9cis_pam_nullok + + - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | Ensure nullok removed" + when: rhel9cis_pam_nullok.stdout | length > 0 + ansible.builtin.replace: + path: "{{ item }}" + regexp: nullok + replace: '' + loop: "{{ rhel9cis_pam_nullok.stdout_lines }}" + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember" + when: + - rhel9cis_rule_5_3_3_4_2 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.2 + block: + - name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" + ansible.builtin.shell: grep -PH -- '^\h*^\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/common-{password,auth,account,session,session-noninteractive} | grep -Pv -- '\bremember=\d\b' + changed_when: false + failed_when: rhel9cis_pam_remember.rc not in [ 0, 1 ] + register: rhel9cis_pam_remember + + - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Ensure remember removed" + when: rhel9cis_pam_remember.stdout | length > 0 + ansible.builtin.replace: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" + regexp: remember=\d+ + replace: '' + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm" + when: + - rhel9cis_rule_5_3_3_4_3 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.3 + - NIST800-53R5_IA-5 + block: + - name: "5.3.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" + ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?("{{ rhel9cis_passwd_hash_algo }}")\b' /etc/pam.d/*-auth + changed_when: false + failed_when: rhel9cis_pam_pwhash.rc not in [ 0, 1 ] + register: rhel9cis_pam_pwhash + + - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Ensure hash algorithm set" + when: rhel9cis_pam_remember.stdout | length > 0 + ansible.builtin.replace: + path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" + regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)" + replace: '{{ rhel9cis_passwd_hash_algo }}' + notify: Pam_auth_update_pwunix + +- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok" + when: + - rhel9cis_rule_5_3_3_4_4 + tags: + - level1-server + - level1-workstation + - patch + - pam + - rule_5.3.3.4.4 + - NIST800-53R5_IA-5 + block: + - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" + ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth + changed_when: false + failed_when: rhel9cis_pam_authtok.rc not in [ 0, 1 ] + register: rhel9cis_pam_authtok + + - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" + when: + - rhel9cis_pam_authtok is defined + - rhel9cis_pam_authtok.stdout | length > 0 + ansible.builtin.lineinfile: + path: "{{ item }}" + regexp: ^(\s*password\s+[success=end.*]\s+pam_unix\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) + line: \1\2\3 use_authtok + backrefs: true + loop: "{{ rhel9cis_pam_authtok.stdout_lines }}" diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index be71ea5..ae908ac 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -2,38 +2,48 @@ # Access, Authentication, and Authorization -- name: "SECTION | 5.1 | Configure time-based job schedulers" - ansible.builtin.import_tasks: - file: cis_5.1.x.yml - -- name: "SECTION | 5.2 | Configure SSH Server" - ansible.builtin.import_tasks: - file: cis_5.2.x.yml +- name: "SECTION | 5.1 | Configure SSH Server" when: - - "'openssh-server' in ansible_facts.packages" - -- name: "SECTION | 5.3 | Configure privilege escalation" + - "'openssh-server' in ansible_facts.packages" ansible.builtin.import_tasks: - file: cis_5.3.x.yml + file: cis_5.1.x.yml -- name: "SECTION | 5.4 | Configure authselect" +- name: "SECTION | 5.2 | Configure privilege escalation" ansible.builtin.import_tasks: - file: cis_5.4.x.yml + file: cis_5.2.x.yml -- name: "SECTION | 5.5 | Configure PAM | not authselect" +- name: "SECTION | 5.3.1.x | Configure PAM software packages" ansible.builtin.import_tasks: - file: cis_5.5.x.yml - when: not rhel9cis_authselect_custom_profile_select + file: cis_5.3.1.x.yml -- name: "SECTION | 5.5 | Configure PAM | authselect" +- name: "SECTION | 5.3.2.x | Configure authselect" ansible.builtin.import_tasks: - file: cis_5.5.x_authselect.yml - when: rhel9cis_authselect_custom_profile_select + file: cis_5.3.2.x.yml -- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters" +- name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" ansible.builtin.import_tasks: - file: cis_5.6.1.x.yml + file: cis_5.3.3.1.x.yml -- name: "SECTION | 5.6.x | Misc. User Account Settings" +- name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" ansible.builtin.import_tasks: - file: cis_5.6.x.yml + file: cis_5.3.3.2.x.yml + +- name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" + ansible.builtin.import_tasks: + file: cis_5.3.3.3.x.yml + +- name: "SECTION | 5.3.3.4.x | Configure pam_unix module" + ansible.builtin.import_tasks: + file: cis_5.3.3.4.x.yml + +- name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" + ansible.builtin.import_tasks: + file: cis_5.4.1.x.yml + +- name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" + ansible.builtin.import_tasks: + file: cis_5.4.2.x.yml + +- name: "SECTION | 5.4.3.x | Configure user default environment" + ansible.builtin.import_tasks: + file: cis_5.4.3.x.yml From 06a1f2997c1a9eb846be25e8b58de1b8e9fd4914 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:01:10 +0100 Subject: [PATCH 019/327] section 7 v2 initial Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.1.x.yml | 321 +++++++++++++++++++++++++++++++ tasks/section_7/cis_7.2.x.yml | 346 ++++++++++++++++++++++++++++++++++ tasks/section_7/main.yml | 9 + 3 files changed, 676 insertions(+) create mode 100644 tasks/section_7/cis_7.1.x.yml create mode 100644 tasks/section_7/cis_7.2.x.yml create mode 100644 tasks/section_7/main.yml diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml new file mode 100644 index 0000000..7517062 --- /dev/null +++ b/tasks/section_7/cis_7.1.x.yml @@ -0,0 +1,321 @@ +--- + +- name: "7.1.1 | PATCH | Ensure permissions on /etc/passwd are configured" + when: + - rhel9cis_rule_7_1_1 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/passwd + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured" + when: + - rhel9cis_rule_7_1_2 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/passwd- + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.3 | PATCH | Ensure permissions on /etc/group are configured" + when: + - rhel9cis_rule_7_1_3 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/group + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.4 | PATCH | Ensure permissions on /etc/group- are configured" + when: + - rhel9cis_rule_7_1_4 + tags: + - level1-server + - level1-workstation + - patch + - permissionss + - rule_7.1.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/group- + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.5 | PATCH | Ensure permissions on /etc/shadow are configured" + when: + - rhel9cis_rule_7_1_5 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.5 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/shadow + owner: root + group: root + mode: '0000' + +- name: "7.1.6 | PATCH | Ensure permissions on /etc/shadow- are configured" + when: + - rhel9cis_rule_7_1_6 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.6 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/shadow- + owner: root + group: root + mode: '0000' + +- name: "7.1.7 | PATCH | Ensure permissions on /etc/gshadow are configured" + when: + - rhel9cis_rule_7_1_7 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.7 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/gshadow + owner: root + group: root + mode: '0000' + +- name: "7.1.8 | PATCH | Ensure permissions on /etc/gshadow- are configured" + when: + - rhel9cis_rule_7_1_8 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.8 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/gshadow- + owner: root + group: root + mode: '0000' + +- name: "7.1.9 | PATCH | Ensure permissions on /etc/shells are configured" + when: + - rhel9cis_rule_7_1_9 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.9 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/shells + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.10 | PATCH | Ensure permissions on /etc/security/opasswd are configured" + when: + - rhel9cis_rule_7_1_10 + tags: + - level1-server + - level1-workstation + - patch + - permissions + - rule_7.1.10 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.file: + path: /etc/security/opasswd + owner: root + group: root + mode: 'u-x,go-wx' + +- name: "7.1.11 | PATCH | Ensure world writable files and directories are secured" + when: + - rhel9cis_rule_7_1_11 + tags: + - level1-server + - level1-workstation + - patch + - files + - permissions + - rule_7.1.11 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + block: + - name: "7.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_09_7_1_11_perms_results + + - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" + when: + - rhel_09_7_1_11_perms_results.stdout_lines is defined + - rhel9cis_no_world_write_adjust + ansible.builtin.file: + path: '{{ item }}' + mode: o-w + state: touch + loop: "{{ rhel_09_7_1_11_perms_results.stdout_lines }}" + + - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable directories add sticky bit" + 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 + +- name: "7.1.12 | PATCH | Ensure no files or directories without an owner and a group exist" + when: + - rhel9cis_rule_7_1_12 + tags: + - level1-server + - level1-workstation + - patch + - rule_7.1.12 + - permissions + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + warn_control_id: '7.1.12' + block: + - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Get list files or directories" + ansible.builtin.shell: find {{ rhel9cis_exclude_unowned_search_path }} {{ item.mount }} -xdev \( -nouser -o -nogroup \) -not -fstype nfs + changed_when: false + failed_when: false + check_mode: false + register: discovered_unowned_files + with_items: + - "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" + + - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Flatten no_user_items results for easier use" + ansible.builtin.set_fact: + discovered_unowned_files_flatten: "{{ discovered_unowned_files.results | map(attribute='stdout_lines') | flatten }}" + + - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Alert on unowned files and directories" + when: + - not rhel9cis_ownership_adjust + - discovered_unowned_files_flatten | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! You have unowned files and are configured to not auto-remediate for this task" + - "Please review the files/directories below and assign an owner" + - "{{ discovered_unowned_files_flatten }}" + + - name: "7.1.12 | PATCH | Ensure no files or directories without an owner and a group exist | Set files/directories to configured owner and group" + when: + - rhel9cis_ownership_adjust + - discovered_unowned_files_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + owner: "{{ rhel9cis_unowned_owner }}" + group: "{{ rhel9cis_unowned_group }}" + with_items: + - "{{ udiscovered_unowned_files_flatten }}" + + - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Warn Count" + when: + - not rhel9cis_ownership_adjust + - discovered_unowned_files_flatten | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + +- name: "7.1.13 | AUDIT | Ensure SUID and SGID files are reviewed" + when: + - rhel9cis_rule_7_1_13 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.1.13 + - permissions + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + warn_control_id: '7.1.13' + block: + - name: "7.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find SUID and SGID" + ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm \( -02000 or -04000 \) -not -fstype nfs + changed_when: false + failed_when: false + check_mode: false + register: discovered_suid_sgid_files + with_items: + - "{{ ansible_facts.mounts }}" + loop_control: + label: "{{ item.mount }}" + + - name: "7.1.13 | AUDIT | Audit SUID executables | Flatten suid_executables results for easier use" + ansible.builtin.set_fact: + discovered_suid_sgid_files_flatten: "{{ discovered_suid_sgid_files.results | map(attribute='stdout_lines') | flatten }}" + + - name: "7.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist" + when: + - discovered_suid_sgid_files_flatten | length > 0 + - not rhel9cis_suid_sgid_adjust + ansible.builtin.debug: + msg: + - "Warning!! You have SUID executables" + - "The files are listed below, please confirm the integrity of these binaries" + - "{{ discovered_suid_sgid_files_flatten }}" + + - name: "7.1.13 | PATCH | Audit SUID executables | Remove SUID bit" + when: + - rhel9cis_suid_sgid_adjust + - discovered_suid_sgid_files_flatten | length > 0 + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-s' + with_items: + - "{{ discovered_suid_sgid_files_flatten }}" + + - name: "7.1.13 | AUDIT | Audit SUID executables | Warn Count" + ansible.builtin.import_tasks: + file: warning_facts.yml + when: + - discovered_suid_sgid_files_flatten | length > 0 + - not rhel9cis_suid_sgid_adjust diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml new file mode 100644 index 0000000..5cfbbc3 --- /dev/null +++ b/tasks/section_7/cis_7.2.x.yml @@ -0,0 +1,346 @@ +--- + +- name: "7.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords" + when: + - rhel9cis_rule_7_2_1 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.1 + - user_accounts + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.1' + block: + - name: "7.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 + register: discovered_nonshadowed_users + + - name: "7.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!! 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: "7.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: "7.2.2 | PATCH | Ensure /etc/shadow password fields are not empty" + when: + - rhel9cis_rule_7_2_2 + tags: + - level1-server + - level1-workstation + - patch + - rule_7.2.2 + - user + - permissions + - NIST800-53R5_IA-5 + block: + - name: "7.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 + check_mode: false + register: discovered_empty_password_acct + + - name: "7.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: "7.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" + when: + - rhel9cis_rule_7_2_3 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.3 + - groups + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.3' + block: + - name: "7.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 + check_mode: false + register: discovered_passwd_gid_check + + - name: "7.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 users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join (', ') }}" + + - name: "7.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: "7.2.4 | AUDIT | Ensure no duplicate UIDs exist" + when: + - rhel9cis_rule_7_2_4 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.4 + - user + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.4' + block: + - name: "7.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 + check_mode: false + register: discovered_user_uid_check + + - name: "7.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 users have UIDs that are duplicates: {{ discovered_user_uid_check.stdout_lines }}" + + - name: "7.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: "7.2.5 | AUDIT | Ensure no duplicate GIDs exist" + when: + - rhel9cis_rule_7_2_5 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.5 + - groups + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.5' + block: + - name: "7.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: discovered_user_gid_check + + - name: "7.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 groups have duplicate GIDs: {{ discovered_user_gid_check.stdout_lines }}" + + - name: "7.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: "7.2.6 | AUDIT | Ensure no duplicate user names exist" + vars: + warn_control_id: '7.2.6' + when: + - rhel9cis_rule_7_2_6 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.6 + - user + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "7.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: false + check_mode: false + register: discovered_username_check + + - name: "7.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: "Warning!! The following user names are duplicates: {{ discovered_user_username_check.stdout_lines }}" + + - name: "7.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: "7.2.7 | AUDIT | Ensure no duplicate group names exist" + when: + - rhel9cis_rule_7_2_7 + tags: + - level1-server + - level1-workstation + - audit + - rule_7.2.7 + - groups + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.7' + block: + - name: "7.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: "7.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: "7.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: "7.2.8 | PATCH | Ensure local interactive user home directories are configured" + when: + - rhel9cis_rule_7_2_8 + tags: + - level1-server + - level1-workstation + - patch + - users + - rule_7.2.8 + block: + - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Create dir if absent" + ansible.builtin.file: + path: "{{ item.dir }}" + state: directory + owner: "{{ item.id }}" + group: "{{ item.gid }}" + loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | list }}" + loop_control: + label: "{{ item.id }}" + + # set default ACLs so the homedir has an effective umask of 0027 + - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Set group ACL" + when: not system_is_container + ansible.posix.acl: + path: "{{ item }}" + default: true + etype: group + permissions: rx + state: present + loop: "{{ prelim_interactive_users_home.stdout_lines }}" + + - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Set other ACL" + when: not system_is_container + ansible.posix.acl: + path: "{{ item }}" + default: true + etype: other + permissions: 0 + state: present + loop: "{{ prelim_interactive_users_home.stdout_lines }}" + +- name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured" + when: + - rhel9cis_rule_7_2_9 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_7.2.9 + - user + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + vars: + warn_control_id: '7.2.9' + block: + - name: "7.2.9 | 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: discovered_homedir_dot_files.rc not in [ 0, 1 ] + check_mode: false + register: discovered_homedir_dot_files + + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" + when: + - discovered_homedir_dot_files.stdout | length > 0 + - rhel9cis_dotperm_ansiblemanaged + 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: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" + when: + - discovered_homedir_dot_files.stdout | length > 0 + - rhel9cis_dotperm_ansiblemanaged + ansible.builtin.import_tasks: + file: warning_facts.yml + + - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" + when: + - discovered_homedir_dot_files.stdout | length > 0 + - rhel9cis_dotperm_ansiblemanaged + ansible.builtin.file: + path: '{{ item }}' + mode: 'go-w' + with_items: "{{ discovered_homedir_dot_files.stdout_lines }}" + +- name: "7.2.4 | PATCH | Ensure shadow group is empty" + when: + - rhel9cis_rule_7_2_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_6.2.4 + - user + vars: + warn_control_id: '7.2.4' + block: + - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" + ansible.builtin.getent: + database: group + split: ':' + key: shadow + + - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" + ansible.builtin.debug: + msg: "Warning!! - You have users in the shadow group" + when: ansible_facts.getent_group.shadow[2] | length > 0 + + - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" + ansible.builtin.import_tasks: + file: warning_facts.yml + when: ansible_facts.getent_group.shadow[2] | length > 0 diff --git a/tasks/section_7/main.yml b/tasks/section_7/main.yml new file mode 100644 index 0000000..2d1247a --- /dev/null +++ b/tasks/section_7/main.yml @@ -0,0 +1,9 @@ +--- + +- name: "SECTION | 7.1 | System File Permissions" + ansible.builtin.import_tasks: + file: cis_7.1.x.yml + +- name: "SECTION | 7.2 | Local User and Group Settings" + ansible.builtin.import_tasks: + file: cis_7.2.x.yml From 42aa624d50dad0a526d4c4cd7bab016d710f1ee1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:01:40 +0100 Subject: [PATCH 020/327] updated Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 26 +++++++++++++------------- tasks/pre_remediation_audit.yml | 7 ++++--- vars/audit.yml | 4 ++-- vars/main.yml | 24 +++++++++++++++++------- 4 files changed, 36 insertions(+), 25 deletions(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 864f5bb..b7dad08 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,30 +1,30 @@ --- - name: Audit_Only | Create local Directories for hosts - ansible.builtin.file: - mode: '0755' - path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" - recurse: true - state: directory when: fetch_audit_files + ansible.builtin.file: + mode: '0755' + path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" + recurse: true + state: directory delegate_to: localhost become: false - name: Audit_only | Get audits from systems and put in group dir - ansible.builtin.fetch: - dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" - flat: true - mode: '0644' - src: "{{ pre_audit_outfile }}" when: fetch_audit_files + ansible.builtin.fetch: + dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" + flat: true + mode: '0644' + src: "{{ pre_audit_outfile }}" - name: Audit_only | Show Audit Summary when: - - audit_only + - 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: - - audit_only + - audit_only ansible.builtin.meta: end_play diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 266603e..4dc7c49 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -63,16 +63,17 @@ register: goss_available - name: Pre Audit Setup | If audit ensure goss is available + when: + - not goss_available.stat.exists ansible.builtin.assert: - that: goss_available.stat.exists 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 }}" diff --git a/vars/audit.yml b/vars/audit.yml index 9dc666a..151e9eb 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -26,8 +26,8 @@ post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchma ### Audit binary settings ### audit_bin_version: - release: v0.4.4 - AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' + release: v0.4.4 + AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json diff --git a/vars/main.yml b/vars/main.yml index 68fe21d..bbc105f 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -3,18 +3,28 @@ min_ansible_version: 2.10.1 rhel9cis_allowed_crypto_policies: - - 'DEFAULT' - - 'FUTURE' - - 'FIPS' + - 'DEFAULT' + - 'FUTURE' + - 'FIPS' rhel9cis_allowed_crypto_policies_modules: - - 'OSPP' - - 'AD-SUPPORT' - - 'AD-SUPPORT-LEGACY' - - 'NO-SHA1' + - 'OSPP' + - 'AD-SUPPORT' + - 'AD-SUPPORT-LEGACY' + - 'NO-SHA1' + - 'NO-SSHCBC' + - 'NO-SSHETM' + - 'NO-SSHWEAKCIPHER' + - 'NO-SSHWEAKMAC' + - 'NO-WEAKMAC' # Used to control warning summary warn_control_list: "" warn_count: 0 gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" + +## Control 6.3.3.x - Audit template +# This variable governs if the auditd logic should be executed(if value is true). +# NOTE: The current default value is likely to be overriden(via 'set_fact') by other further tasks(in sub-section 'Auditd rules'). +update_audit_template: false From a36a84c5ea023ebbee991c6d8d86e78c8d2ec180 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:02:05 +0100 Subject: [PATCH 021/327] lint and v2 initial Signed-off-by: Mark Bolwell --- defaults/main.yml | 1240 +++++++++++++++++++++++---------------------- handlers/main.yml | 40 +- meta/main.yml | 56 +- site.yml | 4 +- tasks/auditd.yml | 48 +- 5 files changed, 712 insertions(+), 676 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index ee4ff2e..dc5d401 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -23,6 +23,12 @@ system_is_ec2: false # Supported OSs will not need for this to be changed - see README e.g. CentOS os_check: true +# Disruption is high +## Run tests that are considered higher risk and could have a system impact if not properly tested +## Default false +## Will be fine if clean new unconfigured build +rhel9cis_disruption_high: false + ## Switching on/off specific baseline sections # These variables govern whether the tasks of a particular section are to be executed when running the role. # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. @@ -34,7 +40,7 @@ rhel9cis_section4: false rhel9cis_section5: false rhel9cis_section6: false -# This is used for audit purposes to run only specifc level use the tags +# This is used for audit purposes to run only specific level use the tags # e.g. # - level1-server # - level2-workstation @@ -49,14 +55,10 @@ rhel9cis_selinux_disable: false # UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: false -## Python Binary -## This is used for python3 Installations where python2 OS modules are used in ansible -python2_bin: /bin/python2.7 - ## Benchmark name used by audting control role # The audit variable found at the base ## metadata for Audit benchmark -benchmark_version: 'v1.0.0' +benchmark_version: 'v2.0.0' benchmark: RHEL9-CIS @@ -67,6 +69,10 @@ skip_reboot: true # default value will change to true but wont reboot if not enabled but will error change_requires_reboot: false +### +### Settings for associated Audit role using Goss +### + ########################################### ### Goss is required on the remote host ### ### vars/auditd.yml for other settings ### @@ -278,12 +284,17 @@ rhel9cis_rule_2_4_1_8: true ### at rhel9cis_rule_2_4_2_1: true -# Section 3 rules are used for securely configuring the network configuration(kernel params, ACL, Firewall settings) +# Section 3 Network +## Network Devices rhel9cis_rule_3_1_1: true rhel9cis_rule_3_1_2: true rhel9cis_rule_3_1_3: true +## Network Kernel Modules rhel9cis_rule_3_2_1: true rhel9cis_rule_3_2_2: true +rhel9cis_rule_3_2_3: true +rhel9cis_rule_3_2_4: true +# Network Kernel Parameters rhel9cis_rule_3_3_1: true rhel9cis_rule_3_3_2: true rhel9cis_rule_3_3_3: true @@ -293,78 +304,24 @@ rhel9cis_rule_3_3_6: true rhel9cis_rule_3_3_7: true rhel9cis_rule_3_3_8: true rhel9cis_rule_3_3_9: true -rhel9cis_rule_3_4_1_1: true -rhel9cis_rule_3_4_1_2: true -rhel9cis_rule_3_4_2_1: true -rhel9cis_rule_3_4_2_2: true -rhel9cis_rule_3_4_2_3: true -rhel9cis_rule_3_4_2_4: true -rhel9cis_rule_3_4_2_5: true -rhel9cis_rule_3_4_2_6: true -rhel9cis_rule_3_4_2_7: true +rhel9cis_rule_3_3_10: true +rhel9cis_rule_3_3_11: true -# Section 4 rules are Logging and Auditing (Configure System Accounting (auditd), -# Configure Data Retention, and Configure Logging) -rhel9cis_rule_4_1_1_1: true -rhel9cis_rule_4_1_1_2: true -rhel9cis_rule_4_1_1_3: true -rhel9cis_rule_4_1_1_4: true -rhel9cis_rule_4_1_2_1: true -rhel9cis_rule_4_1_2_2: true -rhel9cis_rule_4_1_2_3: true -rhel9cis_rule_4_1_3_1: true -rhel9cis_rule_4_1_3_2: true -rhel9cis_rule_4_1_3_3: true -rhel9cis_rule_4_1_3_4: true -rhel9cis_rule_4_1_3_5: true -rhel9cis_rule_4_1_3_6: true -rhel9cis_rule_4_1_3_7: true -rhel9cis_rule_4_1_3_8: true -rhel9cis_rule_4_1_3_9: true -rhel9cis_rule_4_1_3_10: true -rhel9cis_rule_4_1_3_11: true -rhel9cis_rule_4_1_3_12: true -rhel9cis_rule_4_1_3_13: true -rhel9cis_rule_4_1_3_14: true -rhel9cis_rule_4_1_3_15: true -rhel9cis_rule_4_1_3_16: true -rhel9cis_rule_4_1_3_17: true -rhel9cis_rule_4_1_3_18: true -rhel9cis_rule_4_1_3_19: true -rhel9cis_rule_4_1_3_20: true -rhel9cis_rule_4_1_3_21: true -rhel9cis_rule_4_1_4_1: true -rhel9cis_rule_4_1_4_2: true -rhel9cis_rule_4_1_4_3: true -rhel9cis_rule_4_1_4_4: true -rhel9cis_rule_4_1_4_5: true -rhel9cis_rule_4_1_4_6: true -rhel9cis_rule_4_1_4_7: true -rhel9cis_rule_4_1_4_8: true -rhel9cis_rule_4_1_4_9: true -rhel9cis_rule_4_1_4_10: true -rhel9cis_rule_4_2_1_1: true -rhel9cis_rule_4_2_1_2: true -rhel9cis_rule_4_2_1_3: true -rhel9cis_rule_4_2_1_4: true -rhel9cis_rule_4_2_1_5: true -rhel9cis_rule_4_2_1_6: true -rhel9cis_rule_4_2_1_7: true -rhel9cis_rule_4_2_2_1_1: true -rhel9cis_rule_4_2_2_1_2: true -rhel9cis_rule_4_2_2_1_3: true -rhel9cis_rule_4_2_2_1_4: true -rhel9cis_rule_4_2_2_2: true -rhel9cis_rule_4_2_2_3: true -rhel9cis_rule_4_2_2_4: true -rhel9cis_rule_4_2_2_5: true -rhel9cis_rule_4_2_2_6: true -rhel9cis_rule_4_2_2_7: true -rhel9cis_rule_4_2_3: true -rhel9cis_rule_4_3: true +# Section 4 Firewalls +## Firewall utility +rhel9cis_rule_4_1_1: true +rhel9cis_rule_4_1_2: true +## Configure firewalld +rhel9cis_rule_4_2_1: true +rhel9cis_rule_4_2_2: true +# Configure nftables +rhel9cis_rule_4_3_1: true +rhel9cis_rule_4_3_2: true +rhel9cis_rule_4_3_3: true +rhel9cis_rule_4_3_4: true -# Section 5 rules control Access, Authentication, and Authorization (Configure time-based job schedulers, -# Configure sudo, Configure SSH Server, Configure PAM and User Accounts and Environment) +## Section 5 +## 5.1. Configure SSH Server rhel9cis_rule_5_1_1: true rhel9cis_rule_5_1_2: true rhel9cis_rule_5_1_3: true @@ -374,6 +331,19 @@ rhel9cis_rule_5_1_6: true rhel9cis_rule_5_1_7: true rhel9cis_rule_5_1_8: true rhel9cis_rule_5_1_9: true +rhel9cis_rule_5_1_10: true +rhel9cis_rule_5_1_11: true +rhel9cis_rule_5_1_12: true +rhel9cis_rule_5_1_13: true +rhel9cis_rule_5_1_14: true +rhel9cis_rule_5_1_15: true +rhel9cis_rule_5_1_16: true +rhel9cis_rule_5_1_17: true +rhel9cis_rule_5_1_18: true +rhel9cis_rule_5_1_19: true +rhel9cis_rule_5_1_20: true +rhel9cis_rule_5_1_21: true +## 5.2 Configure Privilege Escalation rhel9cis_rule_5_2_1: true rhel9cis_rule_5_2_2: true rhel9cis_rule_5_2_3: true @@ -381,75 +351,158 @@ rhel9cis_rule_5_2_4: true rhel9cis_rule_5_2_5: true rhel9cis_rule_5_2_6: true rhel9cis_rule_5_2_7: true -rhel9cis_rule_5_2_8: true -rhel9cis_rule_5_2_9: true -rhel9cis_rule_5_2_10: true -rhel9cis_rule_5_2_12: true -rhel9cis_rule_5_2_11: true -rhel9cis_rule_5_2_13: true -rhel9cis_rule_5_2_14: true -rhel9cis_rule_5_2_15: true -rhel9cis_rule_5_2_16: true -rhel9cis_rule_5_2_17: true -rhel9cis_rule_5_2_18: true -rhel9cis_rule_5_2_19: true -rhel9cis_rule_5_2_20: true -rhel9cis_rule_5_3_1: true -rhel9cis_rule_5_3_2: true -rhel9cis_rule_5_3_3: true -rhel9cis_rule_5_3_4: true -rhel9cis_rule_5_3_5: true -rhel9cis_rule_5_3_6: true -rhel9cis_rule_5_3_7: true -rhel9cis_rule_5_4_1: true -rhel9cis_rule_5_4_2: true -rhel9cis_rule_5_5_1: true -rhel9cis_rule_5_5_2: true -rhel9cis_rule_5_5_3: true -rhel9cis_rule_5_5_4: true -rhel9cis_rule_5_6_1_1: true -rhel9cis_rule_5_6_1_2: true -rhel9cis_rule_5_6_1_3: true -rhel9cis_rule_5_6_1_4: true -rhel9cis_rule_5_6_1_5: true -rhel9cis_rule_5_6_2: true -rhel9cis_rule_5_6_3: true -rhel9cis_rule_5_6_4: true -rhel9cis_rule_5_6_5: true -rhel9cis_rule_5_6_6: true +# 5.3.1.x Configure PAM software packages +rhel9cis_rule_5_3_1_1: true +rhel9cis_rule_5_3_1_2: true +rhel9cis_rule_5_3_1_3: true +# 5.3.2 Configure authselect +rhel9cis_rule_5_3_2_1: true +rhel9cis_rule_5_3_2_2: true +rhel9cis_rule_5_3_2_3: true +rhel9cis_rule_5_3_2_4: true +# 5.3.3.1 Configure pam_faillock module +rhel9cis_rule_5_3_3_1_1: true +rhel9cis_rule_5_3_3_1_2: true +rhel9cis_rule_5_3_3_1_3: true +# 5.3.3.2 Configure pam_pwquality module +rhel9cis_rule_5_3_3_2_1: true +rhel9cis_rule_5_3_3_2_2: true +rhel9cis_rule_5_3_3_2_3: true +rhel9cis_rule_5_3_3_2_4: true +rhel9cis_rule_5_3_3_2_5: true +rhel9cis_rule_5_3_3_2_6: true +rhel9cis_rule_5_3_3_2_7: true +rhel9cis_rule_5_3_3_2_8: true +# 5.3.3.3 Configure pam_pwhistory module +# This are added as part of 5.3.2.4 using jinja2 template +rhel9cis_rule_5_3_3_3_1: true +rhel9cis_rule_5_3_3_3_2: true +rhel9cis_rule_5_3_3_3_3: true +# 5.3.3.4 Configure pam_unix module +rhel9cis_rule_5_3_3_4_1: true +rhel9cis_rule_5_3_3_4_2: true +rhel9cis_rule_5_3_3_4_3: true +rhel9cis_rule_5_3_3_4_4: true +# 5.4 User Accounts and Environment +# 5.4.1 Configure shadow password suite parameters +rhel9cis_rule_5_4_1_1: true +rhel9cis_rule_5_4_1_2: true +rhel9cis_rule_5_4_1_3: true +rhel9cis_rule_5_4_1_4: true +rhel9cis_rule_5_4_1_5: true +rhel9cis_rule_5_4_1_6: true +# 5.4.2 Configure root and system accounts and environment +rhel9cis_rule_5_4_2_1: true +rhel9cis_rule_5_4_2_2: true +rhel9cis_rule_5_4_2_3: true +rhel9cis_rule_5_4_2_4: true +rhel9cis_rule_5_4_2_5: true +rhel9cis_rule_5_4_2_6: true +rhel9cis_rule_5_4_2_7: true +rhel9cis_rule_5_4_2_8: true +# 5.4.2 Configure user default environment +rhel9cis_rule_5_4_3_1: true +rhel9cis_rule_5_4_3_2: true +rhel9cis_rule_5_4_3_3: true -# Section 6 rules controls System Maintenance (System File Permissions and User and Group Settings) +# Section 6 Logging and Auditing +## 6.1 Configure Integrity Checking rhel9cis_rule_6_1_1: true rhel9cis_rule_6_1_2: true rhel9cis_rule_6_1_3: true -rhel9cis_rule_6_1_4: true -rhel9cis_rule_6_1_5: true -rhel9cis_rule_6_1_6: true -rhel9cis_rule_6_1_7: true -rhel9cis_rule_6_1_8: true -rhel9cis_rule_6_1_9: true -rhel9cis_rule_6_1_10: true -rhel9cis_rule_6_1_11: true -rhel9cis_rule_6_1_12: true -rhel9cis_rule_6_1_13: true -rhel9cis_rule_6_1_14: true -rhel9cis_rule_6_1_15: true -rhel9cis_rule_6_2_1: true -rhel9cis_rule_6_2_2: true -rhel9cis_rule_6_2_3: true -rhel9cis_rule_6_2_4: true -rhel9cis_rule_6_2_5: true -rhel9cis_rule_6_2_6: true -rhel9cis_rule_6_2_7: true -rhel9cis_rule_6_2_8: true -rhel9cis_rule_6_2_9: true -rhel9cis_rule_6_2_10: true -rhel9cis_rule_6_2_11: true -rhel9cis_rule_6_2_12: true -rhel9cis_rule_6_2_13: true -rhel9cis_rule_6_2_14: true -rhel9cis_rule_6_2_15: true -rhel9cis_rule_6_2_16: true +## 6.2.1 Configure systemd-journald service +rhel9cis_rule_6_2_1_1: true +rhel9cis_rule_6_2_1_2: true +rhel9cis_rule_6_2_1_3: true +rhel9cis_rule_6_2_1_4: true +## 6.2.2.x Configure journald +rhel9cis_rule_6_2_2_1_1: true +rhel9cis_rule_6_2_2_1_2: true +rhel9cis_rule_6_2_2_1_3: true +rhel9cis_rule_6_2_2_1_4: true +rhel9cis_rule_6_2_2_2: true +rhel9cis_rule_6_2_2_3: true +rhel9cis_rule_6_2_2_4: true +## 6.2.3 Configure rsyslog +rhel9cis_rule_6_2_3_1: true +rhel9cis_rule_6_2_3_2: true +rhel9cis_rule_6_2_3_3: true +rhel9cis_rule_6_2_3_4: true +rhel9cis_rule_6_2_3_5: true +rhel9cis_rule_6_2_3_6: true +rhel9cis_rule_6_2_3_7: true +## 6.2.4 Configure Logfiles +rhel9cis_rule_6_2_4_1: true +## 6.3 Configure Auditing +## 6.3.1 Configure auditd Service +rhel9cis_rule_6_3_1_1: true +rhel9cis_rule_6_3_1_2: true +rhel9cis_rule_6_3_1_3: true +rhel9cis_rule_6_3_1_4: true +## 6.3.2 Configure Data Retention +rhel9cis_rule_6_3_2_1: true +rhel9cis_rule_6_3_2_2: true +rhel9cis_rule_6_3_2_3: true +rhel9cis_rule_6_3_2_4: true +## 6.3.3 Configure auditd Rules +rhel9cis_rule_6_3_3_1: true +rhel9cis_rule_6_3_3_2: true +rhel9cis_rule_6_3_3_3: true +rhel9cis_rule_6_3_3_4: true +rhel9cis_rule_6_3_3_5: true +rhel9cis_rule_6_3_3_6: true +rhel9cis_rule_6_3_3_7: true +rhel9cis_rule_6_3_3_8: true +rhel9cis_rule_6_3_3_9: true +rhel9cis_rule_6_3_3_10: true +rhel9cis_rule_6_3_3_11: true +rhel9cis_rule_6_3_3_12: true +rhel9cis_rule_6_3_3_13: true +rhel9cis_rule_6_3_3_14: true +rhel9cis_rule_6_3_3_15: true +rhel9cis_rule_6_3_3_16: true +rhel9cis_rule_6_3_3_17: true +rhel9cis_rule_6_3_3_18: true +rhel9cis_rule_6_3_3_19: true +rhel9cis_rule_6_3_3_20: true +rhel9cis_rule_6_3_3_21: true +## 6.3.4 Configure auditd File Access +rhel9cis_rule_6_3_4_1: true +rhel9cis_rule_6_3_4_2: true +rhel9cis_rule_6_3_4_3: true +rhel9cis_rule_6_3_4_4: true +rhel9cis_rule_6_3_4_5: true +rhel9cis_rule_6_3_4_6: true +rhel9cis_rule_6_3_4_7: true +rhel9cis_rule_6_3_4_8: true +rhel9cis_rule_6_3_4_9: true +rhel9cis_rule_6_3_4_10: true + +# Section 7 System Maintenance +## 7.1 System File Permissions +rhel9cis_rule_7_1_1: true +rhel9cis_rule_7_1_2: true +rhel9cis_rule_7_1_3: true +rhel9cis_rule_7_1_4: true +rhel9cis_rule_7_1_5: true +rhel9cis_rule_7_1_6: true +rhel9cis_rule_7_1_7: true +rhel9cis_rule_7_1_8: true +rhel9cis_rule_7_1_9: true +rhel9cis_rule_7_1_10: true +rhel9cis_rule_7_1_11: true +rhel9cis_rule_7_1_12: true +rhel9cis_rule_7_1_13: true +## 7.2 Local User and Group Settings +rhel9cis_rule_7_2_1: true +rhel9cis_rule_7_2_2: true +rhel9cis_rule_7_2_3: true +rhel9cis_rule_7_2_4: true +rhel9cis_rule_7_2_5: true +rhel9cis_rule_7_2_6: true +rhel9cis_rule_7_2_7: true +rhel9cis_rule_7_2_8: true +rhel9cis_rule_7_2_9: true ## Section 1 vars @@ -475,97 +528,7 @@ rhel9cis_rhel_default_repo: true # support it(like RedHat), installation of packages will fail. rhel9cis_rule_enable_repogpg: true -## Control 1.4.1 -# This variable will store the hashed GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value -# must be changed to a value that may be generated with this command 'grub2-mkpasswd-pbkdf2' and must comply with -# this format: 'grub.pbkdf2.sha512...' -rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - -## Control 1.4.1 -# This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. -rhel9cis_set_boot_pass: true - -## Control 1.8.x - Settings for GDM -# This variable specifies the GNOME configuration database file to which configurations are written. -# (See "https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en") -# The default database is 'local'. -rhel9cis_dconf_db_name: local -# This variable governs the number of seconds of inactivity before the screen goes blank. -# Set max value for idle-delay in seconds (between 1 and 900) -rhel9cis_screensaver_idle_delay: 900 -# This variable governs the number of seconds the screen remains blank before it is locked. -# Set max value for lock-delay in seconds (between 0 and 5) -rhel9cis_screensaver_lock_delay: 5 - -## Control 1.10 -# This variable contains the value to be set as the system-wide crypto policy. Current rule enforces NOT USING -# 'LEGACY' value(as it is less secure, it just ensures compatibility with legacy systems), therefore -# possible values for this variable are, as explained by RedHat docs: -# -'DEFAULT': reasonable default policy for today's standards (balances usability and security) -# -'FUTURE': conservative security level that is believed to withstand any near-term future attacks -# -'FIPS': A level that conforms to the FIPS140-2 requirements -rhel9cis_crypto_policy: 'DEFAULT' -## Control 1.10 -# This variable contains the value of the crypto policy module(combinations of policies and -# sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, -# using 'rhel9cis_allowed_crypto_policies_modules' variable. -rhel9cis_crypto_policy_module: '' - -# System network parameters (host only OR host and router) -# This variable governs whether specific CIS rules -# concerned with acceptance and routing of packages are skipped. -rhel9cis_is_router: false - -## IPv6 requirement toggle -# This variable governs whether ipv6 is enabled or disabled. -rhel9cis_ipv6_required: true - -## Control 1.3.1 - allow aide to be configured -# AIDE is a file integrity checking tool, similar in nature to Tripwire. -# While it cannot prevent intrusions, it can detect unauthorized changes -# to configuration files by alerting when the files are changed. Review -# the AIDE quick start guide and AIDE documentation before proceeding. -# By setting this variable to `true`, all of the settings related to AIDE will be applied! -rhel9cis_config_aide: true - -## Control 1.3.2 AIDE cron settings -# These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. -# The sub-settings of this variable provide the parameters required to configure -# the cron job on the target system. -# Cron is a time-based job scheduling program in Unix OS, which allows tasks to be scheduled -# and executed automatically at a certain point in time. -rhel9cis_aide_cron: - # This variable represents the user account under which the cron job for AIDE will run. - cron_user: root - # This variable represents the path to the AIDE crontab file. - cron_file: /etc/cron.d/aide_cron - # This variable represents the actual command or script that the cron job - # will execute for running AIDE. - aide_job: '/usr/sbin/aide --check' - # These variables define the schedule for the cron job - # This variable governs the minute of the time of day when the AIDE cronjob is run. - # It must be in the range `0-59`. - aide_minute: 0 - # This variable governs the hour of the time of day when the AIDE cronjob is run. - # It must be in the range `0-23`. - aide_hour: 5 - # This variable governs the day of the month when the AIDE cronjob is run. - # `*` signifies that the job is run on all days; furthermore, specific days - # can be given in the range `1-31`; several days can be concatenated with a comma. - # The specified day(s) can must be in the range `1-31`. - aide_day: '*' - # This variable governs months when the AIDE cronjob is run. - # `*` signifies that the job is run in every month; furthermore, specific months - # can be given in the range `1-12`; several months can be concatenated with commas. - # The specified month(s) can must be in the range `1-12`. - aide_month: '*' - # This variable governs the weekdays, when the AIDE cronjob is run. - # `*` signifies that the job is run on all weekdays; furthermore, specific weekdays - # can be given in the range `0-7` (both `0` and `7` represent Sunday); several weekdays - # can be concatenated with commas. - aide_weekday: '*' - -## Control 1.6.1.3|4|5 - SELinux policy settings +## Control 1.3.1.3|4|5 - SELinux policy settings # This selects type of policy; targeted or mls( multilevel ) # mls should not be used, since it will disable unconfined policy module # and may prevent some services from running. Requires SELinux not being disabled (by @@ -583,11 +546,52 @@ rhel9cis_selinux_pol: targeted # Even though logging still occurs. rhel9cis_selinux_enforce: enforcing -# Whether or not to run tasks related to auditing/patching the desktop environment +## Control 1.4.1 +# This variable will store the hashed GRUB bootloader password to be stored in '/boot/grub2/user.cfg' file. The default value +# must be changed to a value that may be generated with this command 'grub2-mkpasswd-pbkdf2' and must comply with +# this format: 'grub.pbkdf2.sha512...' +rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret +## Control 1.4.1 +# This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. +rhel9cis_set_boot_pass: true +## Control 1.6 +# This variable contains the value to be set as the system-wide crypto policy. Current rule enforces NOT USING +# 'LEGACY' value(as it is less secure, it just ensures compatibility with legacy systems), therefore +# possible values for this variable are, as explained by RedHat docs: +# -'DEFAULT': reasonable default policy for today's standards (balances usability and security) +# -'FUTURE': conservative security level that is believed to withstand any near-term future attacks +# -'FIPS': A level that conforms to the FIPS140-2 requirements +rhel9cis_crypto_policy: 'DEFAULT' +## Control 1.6 +# This variable contains the value of the crypto policy module(combinations of policies and +# sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, +# using 'rhel9cis_allowed_crypto_policies_modules' variable. +rhel9cis_crypto_policy_module: '' + +## Controls: +# - 1.7.1 - Ensure message of the day is configured properly +# - 1.7.2 - Ensure local login warning banner is configured properly +# - 1.7.3 - Ensure remote login warning banner is configured properly +# This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). +rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and reported. +# End Banner + +## Control 1.8.x - Settings for GDM ## 1.8 GDM graphical interface rhel9cis_gui: false +# This variable specifies the GNOME configuration database file to which configurations are written. +# (See "https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en") +# The default database is 'local'. +rhel9cis_dconf_db_name: local +# This variable governs the number of seconds of inactivity before the screen goes blank. +# Set max value for idle-delay in seconds (between 1 and 900) +rhel9cis_screensaver_idle_delay: 900 +# This variable governs the number of seconds the screen remains blank before it is locked. +# Set max value for lock-delay in seconds (between 0 and 5) +rhel9cis_screensaver_lock_delay: 5 + ## Section 2. Services ## Section 2.1 Time Synchronization @@ -599,10 +603,10 @@ rhel9cis_gui: false # The default setting for the `options` is `minpoll` but `iburst` can be used, please refer to the documentation # of the time synchronization mechanism you are using. rhel9cis_time_synchronization_servers: - - 0.pool.ntp.org - - 1.pool.ntp.org - - 2.pool.ntp.org - - 3.pool.ntp.org + - 0.pool.ntp.org + - 1.pool.ntp.org + - 2.pool.ntp.org + - 3.pool.ntp.org ## Control 2.1.2 - Time Synchronization servers # This variable should contain the default options to be used for every NTP server hostname defined # within the 'rhel9cis_time_synchronization_servers' var. @@ -625,10 +629,12 @@ rhel9cis_chrony_server_minsources: 2 # 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 +# Service +# - false - removes package +# - true - leaves package installed +# Mask +# - false - leaves service in current status +# - true - sets service name to masked rhel9cis_autofs_services: false rhel9cis_autofs_mask: true rhel9cis_avahi_server: false @@ -682,6 +688,25 @@ rhel9cis_tftp_client: false ## Section 3 vars ## Sysctl +# Service configuration +# Options are +# Service +# - false - removes package +# - true - leaves package installed +# Mask +# - false - leaves service in current status +# - true - sets service name to masked +rhel9cis_bluetooth_service: false +rhel9cis_bluetooth_mask: true + +## 3.1 IPv6 requirement toggle +# This variable governs whether ipv6 is enabled or disabled. +rhel9cis_ipv6_required: true + +# 3.3 System network parameters (host only OR host and router) +# This variable governs whether specific CIS rules +# concerned with acceptance and routing of packages are skipped. +rhel9cis_is_router: false # This variable governs if the task which updates sysctl(including sysctl reload) is executed. # NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). @@ -695,6 +720,7 @@ rhel9cis_flush_ipv4_route: false # NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv6_route: false +# Section 4 vars ### Firewall Service to install and configure - Options are: # 1) either 'firewalld' # 2) or 'nftables' @@ -704,221 +730,25 @@ rhel9cis_flush_ipv6_route: false #### masked = leave package if installed and mask the service rhel9cis_firewall: firewalld -## Control 3.4.2.1 - Ensure firewalld default zone is set +## Control 4.2.x - Ensure firewalld default zone is set # This variable will set the firewalld default zone(that is used for everything that is not explicitly bound/assigned # to another zone): if there is no zone assigned to a connection, interface or source, only the default zone is used. rhel9cis_default_zone: public -## Control 3.4.2.2 - Ensure at least one nftables table exists -# This variable governs if a table will be automatically created in nftables. Without a table (no default one), nftables -# will not filter network traffic, so if this variable is set to 'false' and no tables exist, an alarm will be triggered! -rhel9cis_nft_tables_autonewtable: true -## Controls 3.4.2.{2|3|4|6|7} nftables +## Controls 4.3.x nftables # This variable stores the name of the table to be used when configuring nftables(creating chains, configuring loopback # traffic, established connections, default deny). If 'rhel9cis_nft_tables_autonewtable' is set as true, a new table will # be created using as name the value stored by this variable. rhel9cis_nft_tables_tablename: filter -## Control 3.4.2.3 - Ensure nftables base chains exist +## Ensure nftables base chains exist # This variable governs if a nftables base chain(entry point for packets from the networking stack) will be automatically # created, if needed. Without a chain, a hook for input, forward, and delete, packets that would flow through those # chains will not be touched by nftables. rhel9cis_nft_tables_autochaincreate: true -## Controls: -# - 1.7.1 - Ensure message of the day is configured properly -# - 1.7.2 - Ensure local login warning banner is configured properly -# - 1.7.3 - Ensure remote login warning banner is configured properly -# This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). -rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and reported. -# End Banner - -## Section4 vars -### 4.1 Configure System Accounting -#### 4.1.2 Configure Data Retention -## Controls what actions, when log files fill up -# This variable controls how the audit system behaves when -# log files are getting too full and space is getting too low. -rhel9cis_auditd: - # This variable tells the system what action to take when the system has detected - # that it is starting to get low on disk space. Options are the same as for `admin_space_left_action`. - space_left_action: email - # This variable should contain a valid email address or alias(default value is root), - # which will be used to send a warning when configured action is 'email'. - action_mail_acct: root - # This variable determines the action the audit system should take when disk - # space runs low. - # The options for setting this variable are as follows: - # - `ignore`: the system does nothing when presented with the aforementioned issue; - # - `syslog`: a message is sent to the system log about disk space running low; - # - `suspend`: the system suspends recording audit events until more space is available; - # - `halt`: the system is halted when disk space is critically low. - # - `single`: the audit daemon will put the computer system in single user mode - # CIS prescribes either `halt` or `single`. - admin_space_left_action: halt - # The max_log_file parameter should be based on your sites policy. - max_log_file: 10 - # This variable determines what action the audit system should take when the maximum - # size of a log file is reached. - # The options for setting this variable are as follows: - # - `ignore`: the system does nothing when the size of a log file is full; - # - `syslog`: a message is sent to the system log indicating the problem; - # - `suspend`: the system suspends recording audit events until the log file is cleared or rotated; - # - `rotate`: the log file is rotated (archived) and a new empty log file is created; - # - `keep_logs`: the system attempts to keep as many logs as possible without violating disk space constraints. - # CIS prescribes the value `keep_logs`. - max_log_file_action: keep_logs - -# This value governs if the below extra-vars for auditd should be used by the role -rhel9cis_auditd_extra_conf_usage: false - -# This can be used to configure other keys in auditd.conf -# Example: -# rhel9cis_auditd_extra_conf: -# admin_space_left: '10%' - -# These variables governs the threshold(MegaBytes) under which the audit daemon should perform a -# specific action to alert that the system is running low on disk space. -rhel9cis_auditd_extra_conf: - # Must be lower than the 'space_left' variable. - admin_space_left: 50 - space_left: 75 - -## Control 4.1.1.4 - Ensure rhel9cis_audit_back_log_limit is sufficient -# This variable represents the audit backlog limit, i.e., the maximum number of audit records that the -# system can buffer in memory, if the audit subsystem is unable to process them in real-time. -# Buffering in memory is useful in situations, where the audit system is overwhelmed -# with incoming audit events, and needs to temporarily store them until they can be processed. -# This variable should be set to a sufficient value. The CIS baseline recommends at least `8192` as value. -rhel9cis_audit_back_log_limit: 8192 - -## Control 4.1.3.x - Audit template -# This variable governs if the auditd logic should be executed(if value is true). -# NOTE: The current default value is likely to be overriden(via 'set_fact') by other further tasks(in sub-section 'Auditd rules'). -update_audit_template: false - -## Advanced option found in auditd post -# This variable governs if defining user exceptions for auditd logging is acceptable. -rhel9cis_allow_auditd_uid_user_exclusions: false -# This variable contains a list of uids to be excluded(users whose actions are not logged by auditd) -rhel9cis_auditd_uid_exclude: - - 1999 - -## Preferred method of logging -## Whether rsyslog or journald preferred method for local logging -## Control 4.2.1 | Configure rsyslog -## Control 4.2.2 | Configure journald -# This variable governs which logging service should be used, choosing between 'rsyslog'(CIS recommendation) -# or 'journald'(only one is implemented) will trigger the execution of the associated subsection, as the-best -# practices are written wholly independent of each other. -rhel9cis_syslog: rsyslog -## Control 4.2.1.5 | PATCH | Ensure logging is configured -# This variable governs if current Ansible role should manage syslog settings -# in /etc/rsyslog.conf file, namely mail, news and misc(warn, messages) -rhel9cis_rsyslog_ansiblemanaged: true - -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable governs if 'rsyslog' service should be automatically configured to forward messages to a -# remote log server. If set to 'false', the configuration of the 'omfwd' plugin, used to provide forwarding -# over UDP or TCP, will not be performed. -rhel9cis_remote_log_server: false -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable configures the value of the 'target' parameter to be configured when enabling -# forwarding syslog messages to a remote log server, thus configuring the actual FQDN/IP address of the -# destination server. For this value to be reflected in the configuration, the variable which enables the -# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). -rhel9cis_remote_log_host: logagg.example.com -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable configures the value of the 'port' parameter to be configured when enabling -# forwarding syslog messages to a remote log server. The default value for this destination port is 514. -# For this value to be reflected in the configuration, the variable which enables the -# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). -rhel9cis_remote_log_port: 514 -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable configures the value("TCP"/"UDP") of the 'protocol' parameter to be configured when enabling -# forwarding syslog messages to a remote log server. The default value for the 'omfwd' plug-in is UDP. -# For this value to be reflected in the configuration, the variable which enables the -# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). -rhel9cis_remote_log_protocol: tcp -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable governs how often an action is retried(value is passed to 'action.resumeRetryCount' parameter) before -# it is considered to have failed(that roughly translates to discarded messages). The default value is 0, but -# when set to "-1"(eternal), this setting would prevent rsyslog from dropping messages when retrying to connect -# if server is not responding. For this value to be reflected in the configuration, the variable which enables the -# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). -rhel9cis_remote_log_retrycount: 100 -## Control 4.2.1.6 - Ensure rsyslog is configured to send logs to a remote log host -# This variable configures the maximum number of messages that can be hold(value is passed to 'queue.size' parameter). -# For this value to be reflected in the configuration, the variable which enables the automatic configuration -# of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). -rhel9cis_remote_log_queuesize: 1000 - -## Control 4.2.1.7 - Ensure rsyslog is not configured to receive logs from a remote client -# This variable expresses whether the system is used as a log server or not. If set to: -# - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. -# - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity -# from local attacks on remote clients) -rhel9cis_system_is_log_server: false - -## Control 4.2.2.1.2 - Ensure systemd-journal-remote is configured -# 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to -# URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port -# number may be specified after a colon (":"), otherwise 19532 will be used by default. -rhel9cis_journal_upload_url: 192.168.50.42 -## The paths below have the default paths/files, but allow user to create custom paths/filenames - -## Control 4.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to the private key file used by the remote journal -# server to authenticate itself to the client. This key is used alongside the server's -# public certificate to establish secure communication. -rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" -## Control 4.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to the public certificate file of the remote journal -# server. This certificate is used to verify the authenticity of the remote server. -rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" -## Control 4.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to a file containing one or more public certificates -# of certificate authorities (CAs) that the client trusts. These trusted certificates are used -# to validate the authenticity of the remote server's certificate. -rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" -# ATTENTION: Uncomment the keyword below when values are set! - -## Control 4.2.2.6 - Ensure journald log rotation is configured per site policy -# Current variable configures the max amount of disk space the logs will use(thus, journal files -# will not grow without bounds) -# The variables below related to journald, please set these to your site specific values -# These variable specifies how much disk space the journal may use up at most -# Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes. -# See https://www.freedesktop.org/software/systemd/man/journald.conf.html for more information. -rhel9cis_journald_systemmaxuse: 10M -## Control 4.2.2.6 - Ensure journald log rotation is configured per site policy -# Current variable configures the amount of disk space to keep free for other uses. -rhel9cis_journald_systemkeepfree: 100G -## Control 4.2.2.6 - Ensure journald log rotation is configured per site policy -# This variable configures how much disk space the journal may use up at most. -# Similar with 'rhel9cis_journald_systemmaxuse', but related to runtime space. -rhel9cis_journald_runtimemaxuse: 10M -## Control 4.2.2.6 - Ensure journald log rotation is configured per site policy -# This variable configures the actual amount of disk space to keep free -# Similar with 'rhel9cis_journald_systemkeepfree', but related to runtime space. -rhel9cis_journald_runtimekeepfree: 100G -## Control 4.2.2.6 - Ensure journald log rotation is configured per site policy -# Current variable governs the settings for log retention(how long the log files will be kept). -# Thus, it specifies the maximum time to store entries in a single journal -# file before rotating to the next one. Set to 0 to turn off this feature. -# The given values is interpreted as seconds, unless suffixed with the units -# `year`, `month`, `week`, `day`, `h` or `m` to override the default time unit of seconds. -# Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks -# ATTENTION: Uncomment the keyword below when values are set! -rhel9cis_journald_maxfilesec: 1month - -## Control 4.3 - Ensure logrotate is configured -# This variable defines the log file rotation period. -# Options are: daily, weekly, monthly, yearly. -rhel9cis_logrotate: "daily" - ## Section5 vars -## Section 5.2 - SSH +## Section 5.1 - SSH # This value, containing the absolute filepath of the produced 'sshd' config file, allows usage of # drop-in files('/etc/ssh/ssh_config.d/{ssh_drop_in_name}.conf', supported by RHEL9) when CIS adopts them. @@ -926,44 +756,51 @@ rhel9cis_logrotate: "daily" rhel9_cis_sshd_config_file: /etc/ssh/sshd_config ## Controls: -## - 5.2.4 - Ensure SSH access is limited -## - 5.2.19 - Ensure SSH LoginGraceTime is set to one minute or less -## - 5.2.20 - Ensure SSH Idle Timeout Interval is configured -rhel9cis_sshd: - # This variable sets the maximum number of unresponsive "keep-alive" messages - # that can be sent from the server to the client before the connection is considered - # inactive and thus, closed. - clientalivecountmax: 3 - # This variable sets the time interval in seconds between sending "keep-alive" - # messages from the server to the client. These types of messages are intended to - # keep the connection alive and prevent it being terminated due to inactivity. - clientaliveinterval: 15 - # This variable specifies the amount of seconds allowed for successful authentication to - # the SSH server. - logingracetime: 60 - # This variable, if specified, configures a list of USER name patterns, separated by spaces, to allow SSH - # access for users whose user name matches one of the patterns. This is done - # by setting the value of `AllowUsers` option in `/etc/ssh/sshd_config` file. - # If an USER@HOST format will be used, the specified user will be allowed only on that particular host. - # allowusers: "" +## - 5.1.7 - Ensure SSH access is limited +# This variable, if specified, configures a list of USER name patterns, separated by spaces, to allow SSH +# access for users whose user name matches one of the patterns. This is done +# by setting the value of `AllowUsers` option in `/etc/ssh/sshd_config` file. +# If an USER@HOST format will be used, the specified user will be allowed only on that particular host. +rhel9cis_sshd_allowusers: "{% if ansible_facts.user_id != 'root' %}{{ ansible_facts.user_id }}{% elif ansible_env.SUDO_USER is defined %}{{ ansible_env.SUDO_USER }}{% endif %}" - # (String) This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access - # for users whose primary group or supplementary group list matches one of the patterns. This is done - # by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. - # allowgroups: "wheel" +# (String) This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access +# for users whose primary group or supplementary group list matches one of the patterns. This is done +# by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. +# rhel9cis_sshd_allowgroups: "wheel" - # This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access - # for users whose user name matches one of the patterns. This is done - # by setting the value of `DenyUsers` option in `/etc/ssh/sshd_config` file. - # If an USER@HOST format will be used, the specified user will be restricted only on that particular host. - denyusers: "nobody" +# This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access +# for users whose user name matches one of the patterns. This is done +# by setting the value of `DenyUsers` option in `/etc/ssh/sshd_config` file. +# If an USER@HOST format will be used, the specified user will be restricted only on that particular host. +rhel9cis_sshd_denyusers: "nobody" - # This variable, if specified, configures a list of GROUP name patterns, separated by spaces, - # to prevent SSH access for users whose primary group or supplementary group list matches one of the patterns. This is done - # by setting the value of `DenyGroups` option in `/etc/ssh/sshd_config` file. - denygroups: "" +# This variable, if specified, configures a list of GROUP name patterns, separated by spaces, +# to prevent SSH access for users whose primary group or supplementary group list matches one of the patterns. This is done +# by setting the value of `DenyGroups` option in `/etc/ssh/sshd_config` file. +rhel9cis_sshd_denygroups: "" -## Control 5.2.5 - Ensure SSH LogLevel is appropriate +## - 5.1.9 - ClientAlive and CountMax +# default settings allow 45 seconds e.g. count x interval +# This variable sets the maximum number of unresponsive "keep-alive" messages +# that can be sent from the server to the client before the connection is considered +# inactive and thus, closed. +rhel9cis_sshd_clientalivecountmax: 3 +# This variable sets the time interval in seconds between sending "keep-alive" +# messages from the server to the client. These types of messages are intended to +# keep the connection alive and prevent it being terminated due to inactivity. +rhel9cis_sshd_clientaliveinterval: 15 + +## Control 5.1.12 - disable forwarding +# By Default this will also disablex11 forwarding +# set 'yes' if x11 is required this can be changed to run in /etc/ssh/ssh_config.d/50-redhat.conf +rhel9cis_sshd_x11forwarding: 'no' + +## - 5.2.14 - Ensure SSH LoginGraceTime is set to one minute or less +# This variable specifies the amount of seconds allowed for successful authentication to +# the SSH server. +rhel9cis_sshd_logingracetime: 60 + +## Control 5.2.15 - Ensure SSH LogLevel is appropriate # This variable is used to control the verbosity of the logging produced by the SSH server. # The options for setting it are as follows: # - `QUIET`: Minimal logging; @@ -975,16 +812,145 @@ rhel9cis_sshd: # - `DEBUG(x)`: Whereas x = debug level 1 to 3, DEBUG=DEBUG1. rhel9cis_ssh_loglevel: INFO -## Control 5.2.18 - Ensure SSH MaxSessions is set to 10 or less +## Control 5.1.16 MaxAuthTries configured +# The MaxAuthTries parameter specifies the maximum number of authentication +# attempts permitted per connection. When the login failure count reaches half the +# number, error messages will be written to the syslog file detailing the login failure. +rhel9cis_ssh_maxauthtries: '4' + +## Control 5.1.7 MaxStartups +# The MaxStartups parameter specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. +rhel9cis_ssh_maxstartups: '10:30:60' + +## Control 5.1.18 - Ensure SSH MaxSessions is set to 10 or less # This variable value specifies the maximum number of open sessions that are permitted from # a given location rhel9cis_ssh_maxsessions: 4 -## Control 5.6.1.4 - Ensure inactive password lock is 30 days or less +## Control 5.2.x - Ensure sudo log file exists +# By default, sudo logs through syslog(3). However, to specify a custom log file, the +# 'logfile' parameter will be used, setting it with current variable's value. +# This variable defines the path and file name of the sudo log file. +rhel9cis_sudolog_location: "/var/log/sudo.log" + +## Control 5.2.x -Ensure sudo authentication timeout is configured correctly +# This variable sets the duration (in minutes) during which a user's authentication credentials +# are cached after successfully authenticating using "sudo". This allows the user to execute +# multiple commands with elevated privileges without needing to re-enter their password for each +# command within the specified time period. CIS requires a value of at most 15 minutes. +rhel9cis_sudo_timestamp_timeout: 15 + +## Control 5.2.4 +# This will leave NOPASSWD intact for these users +rhel9cis_sudoers_exclude_nopasswd_list: + - ec2-user + - vagrant + +## Control 5.2 - Ensure access to the 'su' command is restricted +# This variable determines the name of the group of users that are allowed to use the su command. +# CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. +rhel9cis_sugroup: nosugroup + +## 5.3.x PAM and Authselect +# 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. +rhel9cis_allow_authselect_updates: false +## +rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install + +## Controls +# - 5.3.3. - Ensure lockout for failed password attempts is configured +# - 5.5.3 - Ensure password reuse is limited +# - 5.5.4 - Ensure password hashing algorithm is SHA-512 +# - 5.4.2 - Ensure authselect includes with-faillock +rhel9cis_pam_faillock: + # - 5.3.3.1.1 + # This variable sets the amount of tries a password can be entered, before a user is locked. + deny: 5 + # - 5.3.3.1.2 + # This variable sets the amount of time a user will be unlocked after the max amount of + # password failures. + unlock_time: 900 + # This variable represents the number of password change cycles, after which + # an user can re-use a password. + # CIS requires a value of 5 or more. + interval: 900 + root_unlock_time: 60 + # Choose options below for root options + root_option: even_deny_root + # root_option: "root_unlock_time = {{ root_unlock_time }}" + +## Control 5.3.3.2.x - Ensure password creation requirements are configured - PAM +rhel9cis_pam_password: + # - 5.3.3.2.1 + # The pwquality difok option sets the number of characters in a password that must not + # be present in the old password. + difok: 2 + # - 5.3.3.2.2 + # minlen - Minimum acceptable size for the new password (plus one if credits are not + # disabled which is the default). Cannot be set to lower value than 6. + minlen: 14 + # - 5.3.3.2.3 + # Password complexity can be set through + # This variable set password complexity,the minimum number of + # character types that must be used (i.e., uppercase, lowercase, digits, other) + # Set to 2, passwords cannot have all lower/upper case. + # Set to 3, passwords needs numbers. + # set to 4, passwords will have to include all four types of characters. + minclass: 4 + # - 5.3.3.2.4 + # The pwquality maxrepeat option sets the maximum number of allowed same + # consecutive characters in a new password. + maxrepeat: 3 + # - 5.3.3.2.5 + # The pwquality maxsequence option sets the maximum length of monotonic character + # sequences in the new password. Examples of such sequence are 12345 or fedcb. The + # check is disabled if the value is 0. + maxseq: 3 + +# 5.3.3.4.x +rhel9cis_passwd_hash_algo: sha512 + +## Section 5.4.1.x: Shadow Password Suite Parameters +rhel9cis_pass: + ## Control 5.6.1.1 - Ensure password expiration is 365 days or less + # This variable governs after how many days a password expires. + # CIS requires a value of 365 or less. + max_days: 365 + ## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more + # This variable specifies the minimum number of days allowed between changing + # passwords. CIS requires a value of at least 1. + min_days: 7 + ## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more + # This variable governs, how many days before a password expires, the user will be warned. + # CIS requires a value of at least 7. + warn_age: 7 + +## Control 5.4.1.x - Ensure inactive password lock is 30 days or less rhel9cis_inactivelock: - # This variable specifies the number of days of inactivity before an account will be locked. - # CIS requires a value of 30 days or less. - lock_days: 30 + # This variable specifies the number of days of inactivity before an account will be locked. + # CIS requires a value of 30 days or less. + lock_days: 30 + +## 5.4.1.x Allow the forcing of setting user_max_days for logins. +# This can break current connecting user access +rhel9cis_force_user_maxdays: false + +## 5.4.1.x Allow the force setting of minimum days between changing the password +# This can break current connecting user access +rhel9cis_force_user_mindays: false + +## 5.4.1.x Allow the forcing of of number of days before warning users of password expiry +# This can break current connecting user access +rhel9cis_force_user_warnage: false + +## Control 5.4.1.x - Ensure all users last password change date is in the past +# Allow ansible to expire password for account with a last changed date in the future. Setting it +# to 'false' will just display users in violation, while 'true' will expire those users passwords. +rhel9cis_futurepwchgdate_autofix: true ## Section 5.4 - Configure authselect: Custom authselect profile settings(name, profile to customize, options) ## Controls: @@ -993,11 +959,11 @@ rhel9cis_inactivelock: # Settings in place now will fail, they are placeholders 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. rhel9cis_authselect: - # This variable configures the name of the custom profile to be created and selected. - custom_profile_name: custom-profile - # This variable configures the ID of the existing profile that should be used as a base for the new profile. - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok + # This variable configures the name of the custom profile to be created and selected. + custom_profile_name: custom-profile + # This variable configures the ID of the existing profile that should be used as a base for the new profile. + default_file_to_copy: "sssd --symlink-meta" + options: with-sudo with-faillock without-nullok with-pwhistory ## Control 5.4.1 - Ensure custom authselect profile is used # This variable governs if an authselect custom profile should be automatically created, by copying and @@ -1010,40 +976,16 @@ rhel9cis_authselect_custom_profile_create: false # to the PAM templates and meta files in the original profile will be reflected in your custom profile, too.) rhel9cis_authselect_custom_profile_select: false -## Control 5.5.1 - Ensure password creation requirements are configured - PAM -rhel9cis_pam_password: - # This variable sets the minimum chars a password needs to be set. - minlen: 14 - # This variable set password complexity,the minimum number of - # character types that must be used (i.e., uppercase, lowercase, digits, other) - # Set to 2, passwords cannot have all lower/upper case. - # Set to 3, passwords needs numbers. - # set to 4, passwords will have to include all four types of characters. - minclass: 4 +# 5.4.2.x +rhel9cis_root_umask: '0027' # 0027 or more restrictive -## Controls -# - 5.5.2 - Ensure lockout for failed password attempts is configured -# - 5.5.3 - Ensure password reuse is limited -# - 5.5.4 - Ensure password hashing algorithm is SHA-512 -# - 5.4.2 - Ensure authselect includes with-faillock -rhel9cis_pam_faillock: - # This variable sets the amount of time a user will be unlocked after the max amount of - # password failures. - unlock_time: 900 - # This variable sets the amount of tries a password can be entered, before a user is locked. - deny: 5 - # This variable represents the number of password change cycles, after which - # an user can re-use a password. - # CIS requires a value of 5 or more. - remember: 5 - -# UID settings for interactive users -# These are discovered via logins.def if set true -rhel9cis_discover_int_uid: true ### Controls: # - 5.6.2 - Ensure system accounts are secured # - 6.2.10 - Ensure local interactive user home directories exist # - 6.2.11 - Ensure local interactive users own their home directories +# UID settings for interactive users +# These are discovered via logins.def if set true +rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID # Note that the value will be dynamically overwritten if variable `dicover_int_uid` has # been set to `true`. @@ -1056,93 +998,194 @@ min_int_uid: 1000 # been set to `true`. max_int_uid: 65533 -## Control 5.3.3 - Ensure sudo log file exists -# By default, sudo logs through syslog(3). However, to specify a custom log file, the -# 'logfile' parameter will be used, setting it with current variable's value. -# This variable defines the path and file name of the sudo log file. -rhel9cis_sudolog_location: "/var/log/sudo.log" - -## Control 5.3.6 -Ensure sudo authentication timeout is configured correctly -# This variable sets the duration (in minutes) during which a user's authentication credentials -# are cached after successfully authenticating using "sudo". This allows the user to execute -# multiple commands with elevated privileges without needing to re-enter their password for each -# command within the specified time period. CIS requires a value of at most 15 minutes. -rhel9cis_sudo_timestamp_timeout: 15 - -## Control 5.4.2 - authselect and faillock -## This option is used at your own risk it will enable faillock for users -## Only to be used on a new clean system if not using authselect -## THIS CAN BREAK ACCESS EVEN FOR ROOT - PLEASE UNDERSTAND RISKS ! -rhel9cis_add_faillock_without_authselect: false -# This needs to be set to 'ACCEPT'(as string), besides setting 'rhel9cis_add_faillock_without_authselect' -# to 'true', in order to include the 'with-failock' option to the current authselect profile. -rhel9cis_5_4_2_risks: NEVER - -## Section 5.6.1.x: Shadow Password Suite Parameters -rhel9cis_pass: - ## Control 5.6.1.1 - Ensure password expiration is 365 days or less - # This variable governs after how many days a password expires. - # CIS requires a value of 365 or less. - max_days: 365 - ## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more - # This variable specifies the minimum number of days allowed between changing - # passwords. CIS requires a value of at least 1. - min_days: 7 - ## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more - # This variable governs, how many days before a password expires, the user will be warned. - # CIS requires a value of at least 7. - warn_age: 7 - -## Allow the forcing of setting user_max_days for logins. -# This can break current connecting user access -rhel9cis_force_user_maxdays: false - -## Allow the force setting of minimum days between changing the password -# This can break current connecting user access -rhel9cis_force_user_mindays: false - -## Allow the forcing of of number of days before warning users of password expiry -# This can break current connecting user access -rhel9cis_force_user_warnage: false - ## Control 5.6.3 - Ensure default user shell timeout is 900 seconds or less # Session timeout setting file (TMOUT setting can be set in multiple files) # Timeout value is in seconds. (60 seconds * 10 = 600) rhel9cis_shell_session_timeout: - # This variable specifies the path of the timeout setting file. - # (TMOUT setting can be set in multiple files, but only one is required for the - # rule to pass. Options are: - # - a file in `/etc/profile.d/` ending in `.s`, - # - `/etc/profile`, or - # - `/etc/bash.bashrc`. - file: /etc/profile.d/tmout.sh - # This variable represents the amount of seconds a command or process is allowed to - # run before being forcefully terminated. - # CIS requires a value of at most 900 seconds. - timeout: 600 - -## Control 5.6.1.5 - Ensure all users last password change date is in the past -# Allow ansible to expire password for account with a last changed date in the future. Setting it -# to 'false' will just display users in violation, while 'true' will expire those users passwords. -rhel9cis_futurepwchgdate_autofix: true - -## Control 5.3.7 - Ensure access to the 'su' command is restricted -# This variable determines the name of the group of users that are allowed to use the su command. -# CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. -rhel9cis_sugroup: nosugroup + # This variable specifies the path of the timeout setting file. + # (TMOUT setting can be set in multiple files, but only one is required for the + # rule to pass. Options are: + # - a file in `/etc/profile.d/` ending in `.s`, + # - `/etc/profile`, or + # - `/etc/bash.bashrc`. + file: /etc/profile.d/tmout.sh + # This variable represents the amount of seconds a command or process is allowed to + # run before being forcefully terminated. + # CIS requires a value of at most 900 seconds. + timeout: 600 ## Section6 vars -## Control 6.1.15 - Audit system file permissions | Create list and warning -# The RPM package-manager has many useful options. For example, using option: -# - '-V': RPM can automatically check if system packages are correctly installed -# - '-qf': RPM can be used to determine which package a particular file belongs to -# Auditing system file-permissions takes advantage of the combination of those two options and, therefore, is able to -# detect any discrepancy regarding installed packages, redirecting the output of this combined -# command into a specific file. If no output is returned, the package is installed correctly. -# Current variable stores the preferred absolute filepath for such a file, therefore if this file -# contains any lines, an alert message will be generated to warn about each discrepancy. -rhel9cis_rpm_audit_file: /var/tmp/rpm_file_check +## Control 6.1.1 - allow aide to be configured +# AIDE is a file integrity checking tool, similar in nature to Tripwire. +# While it cannot prevent intrusions, it can detect unauthorized changes +# to configuration files by alerting when the files are changed. Review +# the AIDE quick start guide and AIDE documentation before proceeding. +# By setting this variable to `true`, all of the settings related to AIDE will be applied! +rhel9cis_config_aide: true + +## Control 6.1.2 AIDE cron settings +# These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. +# The sub-settings of this variable provide the parameters required to configure +# the cron job on the target system. +# Cron is a time-based job scheduling program in Unix OS, which allows tasks to be scheduled +# and executed automatically at a certain point in time. +rhel9cis_aide_cron: + # This variable represents the user account under which the cron job for AIDE will run. + cron_user: root + # This variable represents the path to the AIDE crontab file. + cron_file: /etc/cron.d/aide_cron + # This variable represents the actual command or script that the cron job + # will execute for running AIDE. + aide_job: '/usr/sbin/aide --check' + # These variables define the schedule for the cron job + # This variable governs the minute of the time of day when the AIDE cronjob is run. + # It must be in the range `0-59`. + aide_minute: 0 + # This variable governs the hour of the time of day when the AIDE cronjob is run. + # It must be in the range `0-23`. + aide_hour: 5 + # This variable governs the day of the month when the AIDE cronjob is run. + # `*` signifies that the job is run on all days; furthermore, specific days + # can be given in the range `1-31`; several days can be concatenated with a comma. + # The specified day(s) can must be in the range `1-31`. + aide_day: '*' + # This variable governs months when the AIDE cronjob is run. + # `*` signifies that the job is run in every month; furthermore, specific months + # can be given in the range `1-12`; several months can be concatenated with commas. + # The specified month(s) can must be in the range `1-12`. + aide_month: '*' + # This variable governs the weekdays, when the AIDE cronjob is run. + # `*` signifies that the job is run on all weekdays; furthermore, specific weekdays + # can be given in the range `0-7` (both `0` and `7` represent Sunday); several weekdays + # can be concatenated with commas. + aide_weekday: '*' +# +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +## Control 6.2.3 | Configure rsyslog +## Control 6.2.1 | Configure journald +# This variable governs which logging service should be used, choosing between 'rsyslog'(CIS recommendation) +# or 'journald'(only one is implemented) will trigger the execution of the associated subsection, as the-best +# practices are written wholly independent of each other. +rhel9cis_syslog: journald + +## Control 6.2.2.x & 6.2.3.x - Ensure rsyslog is not configured to receive logs from a remote client +# This variable expresses whether the system is used as a log server or not. If set to: +# - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. +# - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity +# from local attacks on remote clients) +rhel9cis_system_is_log_server: false + +## Control 6.2.3.5 | PATCH | Ensure logging is configured +# This variable governs if current Ansible role should manage syslog settings +# in /etc/rsyslog.conf file, namely mail, news and misc(warn, messages) +rhel9cis_rsyslog_ansiblemanaged: true + +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable governs if 'rsyslog' service should be automatically configured to forward messages to a +# remote log server. If set to 'false', the configuration of the 'omfwd' plugin, used to provide forwarding +# over UDP or TCP, will not be performed. +rhel9cis_remote_log_server: false +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value of the 'target' parameter to be configured when enabling +# forwarding syslog messages to a remote log server, thus configuring the actual FQDN/IP address of the +# destination server. For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). +rhel9cis_remote_log_host: logagg.example.com +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value of the 'port' parameter to be configured when enabling +# forwarding syslog messages to a remote log server. The default value for this destination port is 514. +# For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). +rhel9cis_remote_log_port: 514 +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value("TCP"/"UDP") of the 'protocol' parameter to be configured when enabling +# forwarding syslog messages to a remote log server. The default value for the 'omfwd' plug-in is UDP. +# For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). +rhel9cis_remote_log_protocol: tcp +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable governs how often an action is retried(value is passed to 'action.resumeRetryCount' parameter) before +# it is considered to have failed(that roughly translates to discarded messages). The default value is 0, but +# when set to "-1"(eternal), this setting would prevent rsyslog from dropping messages when retrying to connect +# if server is not responding. For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). +rhel9cis_remote_log_retrycount: 100 +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the maximum number of messages that can be hold(value is passed to 'queue.size' parameter). +# For this value to be reflected in the configuration, the variable which enables the automatic configuration +# of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). +rhel9cis_remote_log_queuesize: 1000 + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to +# URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port +# number may be specified after a colon (":"), otherwise 19532 will be used by default. +rhel9cis_journal_upload_url: 192.168.50.42 +## The paths below have the default paths/files, but allow user to create custom paths/filenames + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the private key file used by the remote journal +# server to authenticate itself to the client. This key is used alongside the server's +# public certificate to establish secure communication. +rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the public certificate file of the remote journal +# server. This certificate is used to verify the authenticity of the remote server. +rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to a file containing one or more public certificates +# of certificate authorities (CAs) that the client trusts. These trusted certificates are used +# to validate the authenticity of the remote server's certificate. +rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" +# ATTENTION: Uncomment the keyword below when values are set! + +## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +# Current variable configures the max amount of disk space the logs will use(thus, journal files +# will not grow without bounds) +# The variables below related to journald, please set these to your site specific values +# These variable specifies how much disk space the journal may use up at most +# Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes. +# See https://www.freedesktop.org/software/systemd/man/journald.conf.html for more information. +rhel9cis_journald_systemmaxuse: 10M +## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +# Current variable configures the amount of disk space to keep free for other uses. +rhel9cis_journald_systemkeepfree: 100G +## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +# This variable configures how much disk space the journal may use up at most. +# Similar with 'rhel9cis_journald_systemmaxuse', but related to runtime space. +rhel9cis_journald_runtimemaxuse: 10M +## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +# This variable configures the actual amount of disk space to keep free +# Similar with 'rhel9cis_journald_systemkeepfree', but related to runtime space. +rhel9cis_journald_runtimekeepfree: 100G +## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +# Current variable governs the settings for log retention(how long the log files will be kept). +# Thus, it specifies the maximum time to store entries in a single journal +# file before rotating to the next one. Set to 0 to turn off this feature. +# The given values is interpreted as seconds, unless suffixed with the units +# `year`, `month`, `week`, `day`, `h` or `m` to override the default time unit of seconds. +# Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +# ATTENTION: Uncomment the keyword below when values are set! +rhel9cis_journald_maxfilesec: 1month + +# Control 6.3.1.3 - Ensure rhel9cis_audit_back_log_limit is sufficient +# This variable represents the audit backlog limit, i.e., the maximum number of audit records that the +# system can buffer in memory, if the audit subsystem is unable to process them in real-time. +# Buffering in memory is useful in situations, where the audit system is overwhelmed +# with incoming audit events, and needs to temporarily store them until they can be processed. +# This variable should be set to a sufficient value. The CIS baseline recommends at least `8192` as value. +rhel9cis_audit_back_log_limit: 8192 + +## Advanced option found in auditd post and used in tempate 98_auditd_exceptions.rules.j2 +# This variable governs if defining user exceptions for auditd logging is acceptable. +rhel9cis_allow_auditd_uid_user_exclusions: false +# This variable contains a list of uids to be excluded(users whose actions are not logged by auditd) +rhel9cis_auditd_uid_exclude: + - 1999 + +# Section 7 Vars ## Control 6.1.9 - Ensure no world writable files exist # Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable. @@ -1153,10 +1196,3 @@ rhel9cis_no_world_write_adjust: true # user home directory. rhel_09_6_2_16_home_follow_symlinks: false # thanks to @dulin-gnet and community for rhel9-cis feedback. - -#### Goss Configuration Settings #### -# Set correct env for the run_audit.sh script from https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git" -audit_run_script_environment: - AUDIT_BIN: "{{ audit_bin }}" - AUDIT_FILE: 'goss.yml' - AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}" diff --git a/handlers/main.yml b/handlers/main.yml index 69743d6..d4aaf2c 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -5,36 +5,36 @@ ansible.builtin.shell: sysctl --system - name: Sysctl flush ipv4 route table - ansible.posix.sysctl: - name: net.ipv4.route.flush - value: '1' - sysctl_set: true - ignore_errors: true # noqa ignore-errors when: - - rhel9cis_flush_ipv4_route - - not system_is_container + - rhel9cis_flush_ipv4_route + - not system_is_container + ansible.posix.sysctl: + name: net.ipv4.route.flush + value: '1' + sysctl_set: true + ignore_errors: true # noqa ignore-errors - name: Sysctl flush ipv6 route table - ansible.posix.sysctl: - name: net.ipv6.route.flush - value: '1' - sysctl_set: true when: - - rhel9cis_flush_ipv6_route - - not system_is_container + - rhel9cis_flush_ipv6_route + - not system_is_container + ansible.posix.sysctl: + name: net.ipv6.route.flush + value: '1' + sysctl_set: true - name: Systemd restart tmp.mount ansible.builtin.systemd: - name: tmp.mount - daemon_reload: true - enabled: true - masked: false - state: reloaded + name: tmp.mount + daemon_reload: true + enabled: true + masked: false + state: reloaded - name: Remount tmp ansible.posix.mount: - path: /tmp - state: remounted + path: /tmp + state: remounted - name: Update Crypto Policy ansible.builtin.set_fact: diff --git a/meta/main.yml b/meta/main.yml index 2d33a4a..8f8b65f 100644 --- a/meta/main.yml +++ b/meta/main.yml @@ -1,32 +1,32 @@ --- galaxy_info: - author: "MindPoint Group" - description: "Apply the RHEL 9 CIS" - company: "MindPoint Group" - license: MIT - role_name: rhel9_cis - namespace: mindpointgroup - min_ansible_version: 2.10.1 - platforms: - - name: EL - versions: - - "9" - galaxy_tags: - - system - - security - - stig - - hardening - - benchmark - - compliance - - redhat - - complianceascode - - disa - - rhel9 - - cis - - rocky - - alma + author: "MindPoint Group" + description: "Apply the RHEL 9 CIS" + company: "MindPoint Group" + license: MIT + role_name: rhel9_cis + namespace: mindpointgroup + min_ansible_version: 2.10.1 + platforms: + - name: EL + versions: + - "9" + galaxy_tags: + - system + - security + - stig + - hardening + - benchmark + - compliance + - redhat + - complianceascode + - disa + - rhel9 + - cis + - rocky + - alma collections: - - community.general - - community.crypto - - ansible.posix + - community.general + - community.crypto + - ansible.posix dependencies: [] diff --git a/site.yml b/site.yml index 16fe8c6..f3f0fae 100644 --- a/site.yml +++ b/site.yml @@ -1,7 +1,7 @@ --- -- name: Apply RHEL9 CIS hardening +- name: Apply ansible-lockdown hardening hosts: all become: true roles: - - role: "{{ playbook_dir }}" + - role: "{{ playbook_dir }}" diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 62f2794..ac5b8f8 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -2,46 +2,46 @@ - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: - path: /etc/audit/rules.d/99_auditd.rules + path: /etc/audit/rules.d/99_auditd.rules register: rhel9cis_auditd_file - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | setup file ansible.builtin.template: - src: audit/99_auditd.rules.j2 - dest: /etc/audit/rules.d/99_auditd.rules - owner: root - group: root - mode: '0640' + src: audit/99_auditd.rules.j2 + dest: /etc/audit/rules.d/99_auditd.rules + owner: root + group: root + mode: '0640' diff: "{{ rhel9cis_auditd_file.stat.exists }}" # Only run diff if not a new file register: rhel9cis_auditd_template_updated notify: - - Auditd immutable check - - Audit immutable fact - - Restart auditd + - Auditd immutable check + - Audit immutable fact + - Restart auditd - name: POST | AUDITD | Add Warning count for changes to template file | Warn Count # noqa no-handler - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: 'Auditd template updated, see diff output for details' when: - - rhel9cis_auditd_template_updated.changed - - rhel9cis_auditd_file.stat.exists + - rhel9cis_auditd_template_updated.changed + - rhel9cis_auditd_file.stat.exists + ansible.builtin.import_tasks: + file: warning_facts.yml + vars: + warn_control_id: 'Auditd template updated, see diff output for details' - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: - path: /etc/audit/rules.d/98_auditd_exceptions.rules + path: /etc/audit/rules.d/98_auditd_exceptions.rules register: rhel9cis_auditd_exception_file - name: POST | Set up auditd user logging exceptions | setup file + when: + - rhel9cis_allow_auditd_uid_user_exclusions + - rhel9cis_auditd_uid_exclude | length > 0 ansible.builtin.template: - src: audit/98_auditd_exception.rules.j2 - dest: /etc/audit/rules.d/98_auditd_exceptions.rules - owner: root - group: root - mode: '0640' + src: audit/98_auditd_exception.rules.j2 + dest: /etc/audit/rules.d/98_auditd_exceptions.rules + owner: root + group: root + mode: '0640' diff: "{{ rhel9cis_auditd_exception_file.stat.exists }}" notify: Restart auditd - when: - - rhel9cis_allow_auditd_uid_user_exclusions - - rhel9cis_auditd_uid_exclude | length > 0 From 5c5499fd72207c084697fa3e9e21d4624f24f542 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:02:51 +0100 Subject: [PATCH 022/327] Initial pmod templates for ssh control Signed-off-by: Mark Bolwell --- .../etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 | 2 +- .../etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 | 2 +- .../crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 | 5 ----- .../etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 | 2 +- .../policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 | 4 ++++ .../crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 | 4 ++++ .../etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 | 2 +- 7 files changed, 12 insertions(+), 9 deletions(-) delete mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 create mode 100644 templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 index 2a593d7..fd6eaff 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2 @@ -1,5 +1,5 @@ # This is a subpolicy dropping the SHA1 hash and signature support -# Carried out as part of CIS Benchmark +# Carried out as part of CIS Benchmark rule 1.6.3 hash = -SHA1 sign = -*-SHA1 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 index 8eb8ae8..9092036 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -1,5 +1,5 @@ # This is a subpolicy to disable all CBC mode ciphers # for the SSH protocol (libssh and OpenSSH) -# Carried out as part of CIS Benchmark +# Carried out as part of CIS Benchmark rule 1.6.5 cipher@SSH = -*-CBC diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 deleted file mode 100644 index 03fe414..0000000 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHCHACHA20.pmod.j2 +++ /dev/null @@ -1,5 +0,0 @@ -# This is a subpolicy to disable the chacha20-poly1305 ciphers -# for the SSH protocol (libssh and OpenSSH) -# Carried out as part of CIS Benchmark - -cipher@SSH = -CHACHA20-POLY1305 diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 index fe5fb7f..cebc2ad 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -1,5 +1,5 @@ # This is a subpolicy to disable Encrypt then MAC # for the SSH protocol (libssh and OpenSSH) -# Carried out as part of CIS Benchmark +# Carried out as part of CIS Benchmark rule 1.6.7 etm@SSH = DISABLE_ETM diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 new file mode 100644 index 0000000..d325a11 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 @@ -0,0 +1,4 @@ +# This is a subpolicy to disable weak ciphers +# for the SSH protocol (libssh and OpenSSH) +# Carried out as part of CIS Benchmark rules combined 1.6.6 and 5.1.4 +cipher@SSH ={% if rhel9cis_rule_1_6_6 %} -CHACHA20-POLY1305{% endif %}{% if rhel9cis_rule_5_1_5 %} -3DES-CBC -AES-128-CBC -AES-192-CBC -AES-256-CBC{% endif %} diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 new file mode 100644 index 0000000..f040399 --- /dev/null +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 @@ -0,0 +1,4 @@ +# This is a subpolicy to disable weak macs +# Carried out as part of CIS Benchmark control 5.1.6 + +mac@SSH = -HMAC-MD5* -UMAC-64* -UMAC-128* diff --git a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 index ace7fa0..0020e6d 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -1,4 +1,4 @@ # This is a subpolicy to disable weak macs -# Carried out as part of CIS Benchmark +# Carried out as part of CIS Benchmark rule 1.6.4 mac = -*-64 From 6ea105374a210df42084c32b683ba675f35cfc1f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:03:12 +0100 Subject: [PATCH 023/327] Initial v2 Signed-off-by: Mark Bolwell --- README.md | 2 +- tasks/check_prereqs.yml | 8 +- tasks/main.yml | 4 +- tasks/post.yml | 18 ++-- tasks/prelim.yml | 219 ++++++++++++++++++++++------------------ 5 files changed, 136 insertions(+), 115 deletions(-) diff --git a/README.md b/README.md index f8f3680..985dec7 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant -### Based on [ CIS RedHat Enterprise Linux 9 Benchmark v1.0.0 - 11-30-2022 ](https://www.cisecurity.org/cis-benchmarks/) +### Based on [ CIS RedHat Enterprise Linux 9 Benchmark v2.0.0 ](https://www.cisecurity.org/cis-benchmarks/) --- diff --git a/tasks/check_prereqs.yml b/tasks/check_prereqs.yml index dcfee57..159b72f 100644 --- a/tasks/check_prereqs.yml +++ b/tasks/check_prereqs.yml @@ -1,8 +1,8 @@ --- - name: "PREREQ | If required install libselinux package to manage file changes." - ansible.builtin.package: - name: libselinux-python3 - state: present when: - - '"libselinux-python3" not in ansible_facts.packages' + - '"libselinux-python3" not in ansible_facts.packages' + ansible.builtin.package: + name: libselinux-python3 + state: present diff --git a/tasks/main.yml b/tasks/main.yml index e13477d..2aee086 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -28,7 +28,7 @@ - user_passwd - rule_5.3.4 vars: - sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret + sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret block: - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" @@ -230,6 +230,6 @@ - name: If Warnings found Output count and control IDs affected when: warn_count != 0 tags: - - always + - 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/post.yml b/tasks/post.yml index 59766f5..b3909bf 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -13,18 +13,18 @@ - not system_is_container - "'procps-ng' in ansible_facts.packages" ansible.builtin.template: - src: "etc/sysctl.d/{{ item }}.j2" - dest: "/etc/sysctl.d/{{ item }}" - owner: root - group: root - mode: '0600' + src: "etc/sysctl.d/{{ item }}.j2" + dest: "/etc/sysctl.d/{{ item }}" + owner: root + group: root + mode: '0600' register: sysctl_updated notify: Reload sysctl loop: - - 60-kernel_sysctl.conf - - 60-disable_ipv6.conf - - 60-netipv4_sysctl.conf - - 60-netipv6_sysctl.conf + - 60-kernel_sysctl.conf + - 60-disable_ipv6.conf + - 60-netipv4_sysctl.conf + - 60-netipv6_sysctl.conf - name: Flush handlers ansible.builtin.meta: flush_handlers diff --git a/tasks/prelim.yml b/tasks/prelim.yml index aa85840..bd8bf48 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -18,7 +18,7 @@ - run_audit or audit_only - setup_audit tags: - - run_audit + - run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml - name: "PRELIM | AUDIT | Interactive Users" @@ -72,29 +72,33 @@ - passwords - name: "PRELIM | Ensure python3-libselinux is installed" + when: + - '"python3-libselinux" not in ansible_facts.packages' ansible.builtin.package: name: python3-libselinux state: present - when: - - '"python3-libselinux" not in ansible_facts.packages' - name: "PRELIM | Section 1.1 | Create list of mount points" ansible.builtin.set_fact: - mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" + mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" tags: - - level1-server - - level1-workstation + - level1-server + - level1-workstation - name: "PRELIM | Update to latest gpg keys" - ansible.builtin.package: - name: "{{ gpg_key_package }}" - state: latest when: - - rhel9cis_rule_1_2_1_1 - - ansible_facts.distribution != 'RedHat' - - ansible_facts.distribution != 'OracleLinux' + - rhel9cis_rule_1_2_1_1 + - ansible_facts.distribution != 'RedHat' + - ansible_facts.distribution != 'OracleLinux' + ansible.builtin.package: + name: "{{ gpg_key_package }}" + state: latest - name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not | RedHat Only" + when: + - rhel9cis_rule_1_2_1_1 + - rhel9cis_force_gpg_key_import + - ansible_facts.distribution == 'RedHat' block: - name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not" ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' @@ -103,26 +107,19 @@ register: check_gpg_imported - name: "PRELIM | Check key package matches RedHat" + when: "'not installed' in check_gpg_imported.stdout" ansible.builtin.shell: rpm -qi redhat-release | grep Signature changed_when: false failed_when: false register: os_gpg_package_valid - when: "'not installed' in check_gpg_imported.stdout" - name: "PRELIM | Force keys to be imported" - ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release when: - "'not installed' in check_gpg_imported.stdout" - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" - when: - - rhel9cis_rule_1_2_1_1 - - rhel9cis_force_gpg_key_import - - ansible_facts.distribution == 'RedHat' + ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release - name: "PRELIM | if systemd coredump" - ansible.builtin.stat: - path: /etc/systemd/coredump.conf - register: systemd_coredump when: - rhel9cis_rule_1_5_4 tags: @@ -130,8 +127,18 @@ - level1-workstation - rule_1.5.4 - systemd + ansible.builtin.stat: + path: /etc/systemd/coredump.conf + register: systemd_coredump - name: "PRELIM | Setup crypto-policy" + when: + - rhel9cis_rule_1_6_1 + tags: + - level1-server + - level1-workstation + - rule_1.6.1 + - crypto block: - name: "PRELIM | Install crypto-policies | pkgs present" ansible.builtin.package: @@ -151,16 +158,9 @@ current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" + when: "':' in rhel9cis_system_wide_crypto_policy.stdout" ansible.builtin.set_fact: current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" - when: "':' in rhel9cis_system_wide_crypto_policy.stdout" - when: - - rhel9cis_rule_1_6_1 - tags: - - level1-server - - level1-workstation - - rule_1.6.1 - - crypto - name: "PRELIM | Set facts based on boot type" block: @@ -170,15 +170,37 @@ register: rhel_09_efi_boot - name: "PRELIM | set legacy boot and grub path | Bios" + when: not rhel_09_efi_boot.stat.exists ansible.builtin.set_fact: rhel9cis_legacy_boot: true grub2_path: /etc/grub2.cfg - when: not rhel_09_efi_boot.stat.exists - name: "PRELIM | set grub fact | UEFI" + when: rhel_09_efi_boot.stat.exists ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg - when: rhel_09_efi_boot.stat.exists + +- name: "PRELIM | AUDIT | Wireless adapter pre-requisites" + when: + - rhel9cis_rule_3_1_2 + - not system_is_container + tags: + - always + block: + - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + ansible.builtin.shell: find /sys/class/net/*/ -type d -name wireless + register: discover_wireless_adapters + changed_when: false + failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] + + - name: "PRELIM | PATCH | Install Network-Manager | if wireless adpater present" + when: + - rhel9cis_install_network_manager + - discover_wireless_adapters.rc == 0 + - "'network-manager' not in ansible_facts.packages" + ansible.builtin.package: + name: network-manager + state: present - name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: @@ -196,105 +218,104 @@ - auditd - name: "PRELIM | 4.1.4.5 | Audit conf and rules files | list files" - ansible.builtin.find: - path: /etc/audit - file_type: file - recurse: true - patterns: '*.conf,*.rules' - register: auditd_conf_files when: - - rhel9cis_rule_4_1_4_5 or - rhel9cis_rule_4_1_4_6 or - rhel9cis_rule_4_1_4_7 + - rhel9cis_rule_4_1_4_5 or + rhel9cis_rule_4_1_4_6 or + rhel9cis_rule_4_1_4_7 tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.5 - - rule_4.1.4.6 - - rule_4.1.4.7 + - level2-server + - level2-workstation + - patch + - auditd + - rule_4.1.4.5 + - rule_4.1.4.6 + - rule_4.1.4.7 + ansible.builtin.find: + path: /etc/audit + file_type: file + recurse: true + patterns: '*.conf,*.rules' + register: auditd_conf_files - name: "PRELIM | Section 5.1 | Configure cron" - ansible.builtin.package: - name: cronie - state: present - become: true when: - - rhel9cis_rule_5_1_1 - - '"cronie" not in ansible_facts.packages' + - rhel9cis_rule_5_1_1 + - '"cronie" not in ansible_facts.packages' tags: - - level1-server - - level1-workstation - - rule_5.1.1 - - cron + - level1-server + - level1-workstation + - rule_5.1.1 + - cron + ansible.builtin.package: + name: cronie + state: present # Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config - name: "PRELIM | Section 5.2 | SSH" - ansible.builtin.file: - path: "{{ rhel9_cis_sshd_config_file }}" - owner: root - group: root - mode: '0600' - state: touch when: - - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' - - "'openssh-server' in ansible_facts.packages" + - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' + - "'openssh-server' in ansible_facts.packages" tags: - - ssh - - level1_server - - level1_workstation + - ssh + - level1_server + - level1_workstation + ansible.builtin.file: + path: "{{ rhel9_cis_sshd_config_file }}" + owner: root + group: root + mode: '0600' + state: touch - name: "PRELIM | 5.3.4 | Find all sudoers files." + when: + - rhel9cis_rule_5_3_4 or + rhel9cis_rule_5_3_5 + tags: + - rule_5.3.4 + - rule_5.3.5 ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" changed_when: false failed_when: false check_mode: false register: rhel9cis_sudoers_files - when: - - rhel9cis_rule_5_3_4 or - rhel9cis_rule_5_3_5 - tags: - - rule_5.3.4 - - rule_5.3.5 - name: "PRELIM | Gather UID 0 accounts other than root" + tags: + - rule_6.2.9 + - level1-server + - level1-workstation + - users 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: rhel9cis_uid_zero_accounts_except_root - tags: - - rule_6.2.9 - - level1-server - - level1-workstation - - users - name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" when: rhel9cis_discover_int_uid block: - - name: "PRELIM | Capture UID_MIN information from logins.def" - ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' - changed_when: false - register: uid_min_id + - name: "PRELIM | Capture UID_MIN information from logins.def" + ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' + changed_when: false + register: uid_min_id - - name: "PRELIM | Capture UID_MAX information from logins.def" - ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}' - changed_when: false - register: uid_max_id + - name: "PRELIM | Capture UID_MAX information from logins.def" + ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}' + changed_when: false + register: uid_max_id - - name: "PRELIM | Capture GID_MIN information from logins.def" - ansible.builtin.shell: grep -w "^GID_MIN" /etc/login.defs | awk '{print $NF}' - changed_when: false - register: gid_min_id + - name: "PRELIM | Capture GID_MIN information from logins.def" + ansible.builtin.shell: grep -w "^GID_MIN" /etc/login.defs | awk '{print $NF}' + changed_when: false + register: gid_min_id - - name: "PRELIM | set_facts for interactive uid/gid" - ansible.builtin.set_fact: - min_int_uid: "{{ uid_min_id.stdout }}" - max_int_uid: "{{ uid_max_id.stdout }}" - min_int_gid: "{{ gid_min_id.stdout }}" + - name: "PRELIM | set_facts for interactive uid/gid" + ansible.builtin.set_fact: + min_int_uid: "{{ uid_min_id.stdout }}" + max_int_uid: "{{ uid_max_id.stdout }}" + min_int_gid: "{{ gid_min_id.stdout }}" - name: "PRELIM | Gather the package facts after prelim" - ansible.builtin.package_facts: - manager: auto tags: - - always + - always + ansible.builtin.package_facts: + manager: auto From 3b346f7fe18c8257a5f4e466f5c800bf6051cd13 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:05:46 +0100 Subject: [PATCH 024/327] initial v2 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 423 +++++---------------------- tasks/section_6/cis_6.2.1.x.yml | 114 ++++++++ tasks/section_6/cis_6.2.2.1.x.yml | 162 +++++++++++ tasks/section_6/cis_6.2.3.x.yml | 293 +++++++++++++++++++ tasks/section_6/cis_6.2.4.1.yml | 62 ++++ tasks/section_6/cis_6.2.x.yml | 455 ------------------------------ tasks/section_6/cis_6.3.1.x.yml | 111 ++++++++ tasks/section_6/cis_6.3.2.x.yml | 76 +++++ tasks/section_6/cis_6.3.3.x.yml | 328 +++++++++++++++++++++ tasks/section_6/cis_6.3.4.x.yml | 167 +++++++++++ tasks/section_6/main.yml | 38 ++- 11 files changed, 1415 insertions(+), 814 deletions(-) create mode 100644 tasks/section_6/cis_6.2.1.x.yml create mode 100644 tasks/section_6/cis_6.2.2.1.x.yml create mode 100644 tasks/section_6/cis_6.2.3.x.yml create mode 100644 tasks/section_6/cis_6.2.4.1.yml delete mode 100644 tasks/section_6/cis_6.2.x.yml create mode 100644 tasks/section_6/cis_6.3.1.x.yml create mode 100644 tasks/section_6/cis_6.3.2.x.yml create mode 100644 tasks/section_6/cis_6.3.3.x.yml create mode 100644 tasks/section_6/cis_6.3.4.x.yml diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index ef3d3b3..7eba300 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -1,366 +1,79 @@ --- -- name: "6.1.1 | PATCH | Ensure permissions on /etc/passwd are configured" - ansible.builtin.file: - path: /etc/passwd - owner: root - group: root - mode: '0644' +- name: "6.1.1 | PATCH | Ensure AIDE is installed" when: - - rhel9cis_rule_6_1_1 + - rhel9cis_config_aide + - rhel9cis_rule_6_1_1 tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.1 - -- name: "6.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured" - ansible.builtin.file: - path: /etc/passwd- - owner: root - group: root - mode: '0644' - when: - - rhel9cis_rule_6_1_2 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.2 - -- name: "6.1.3 | PATCH | Ensure permissions on /etc/group are configured" - ansible.builtin.file: - path: /etc/group - owner: root - group: root - mode: '0644' - when: - - rhel9cis_rule_6_1_3 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.3 - -- name: "6.1.4 | PATCH | Ensure permissions on /etc/group- are configured" - ansible.builtin.file: - path: /etc/group- - owner: root - group: root - mode: '0644' - when: - - rhel9cis_rule_6_1_4 - tags: - - level1-server - - level1-workstation - - patch - - permissionss - - rule_6.1.4 - -- name: "6.1.5 | PATCH | Ensure permissions on /etc/shadow are configured" - ansible.builtin.file: - path: /etc/shadow - owner: root - group: root - mode: '0000' - when: - - rhel9cis_rule_6_1_5 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.5 - -- name: "6.1.6 | PATCH | Ensure permissions on /etc/shadow- are configured" - ansible.builtin.file: - path: /etc/shadow- - owner: root - group: root - mode: '0000' - when: - - rhel9cis_rule_6_1_6 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.6 - -- name: "6.1.7 | PATCH | Ensure permissions on /etc/gshadow are configured" - ansible.builtin.file: - path: /etc/gshadow - owner: root - group: root - mode: '0000' - when: - - rhel9cis_rule_6_1_7 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.7 - -- name: "6.1.8 | PATCH | Ensure permissions on /etc/gshadow- are configured" - ansible.builtin.file: - path: /etc/gshadow- - owner: root - group: root - mode: '0000' - when: - - rhel9cis_rule_6_1_8 - tags: - - level1-server - - level1-workstation - - patch - - permissions - - rule_6.1.8 - -- name: "6.1.9 | PATCH | Ensure no world writable files exist" + - level1-server + - level1-workstation + - aide + - patch + - rule_6.1.1 + - NIST800-53R5_AU-2 block: - - name: "6.1.9 | AUDIT | Ensure no world writable files exist | 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_09_6_1_9_perms_results + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Install AIDE" + ansible.builtin.package: + name: aide + state: present - - name: "6.1.9 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" - ansible.builtin.file: - path: '{{ item }}' - mode: o-w - state: touch - loop: "{{ rhel_09_6_1_9_perms_results.stdout_lines }}" - when: - - rhel_09_6_1_9_perms_results.stdout_lines is defined - - rhel9cis_no_world_write_adjust + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB" + when: not ansible_check_mode + ansible.builtin.shell: /usr/sbin/aide --init + args: + + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Wait for file before continuing" + ansible.builtin.wait_for: + path: /var/lib/aide/aide.db.new.gz + + - name: "6.1.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: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: - - rhel9cis_rule_6_1_9 + - rhel9cis_rule_6_1_2 + - not system_is_ec2 tags: - - level1-server - - level1-workstation - - patch - - files - - permissions - - rule_6.1.9 + - level1-server + - level1-workstation + - aide + - file_integrity + - patch + - rule_6.1.2 + - NIST800-53R5_AU-2 + ansible.builtin.cron: + name: Run AIDE integrity check + cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}" + user: "{{ rhel9cis_aide_cron['cron_user'] }}" + minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}" + hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}" + day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}" + month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}" + weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}" + job: "{{ rhel9cis_aide_cron['aide_job'] }}" -- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist" - block: - - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser - changed_when: false - failed_when: false - check_mode: false - register: rhel_09_6_1_10_audit - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.mount }}" - when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] - - - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | set fact" - ansible.builtin.set_fact: - rhel_09_6_1_10_unowned_files_found: true - loop: "{{ rhel_09_6_1_10_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 - - - name: "6.1.10 | 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_09_6_1_10_audit.stdout_lines }}" - when: rhel_09_6_1_10_unowned_files_found - - - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | warning" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.1.10' - when: rhel_09_6_1_10_unowned_files_found - vars: - rhel_09_6_1_10_unowned_files_found: false +- name: "6.1.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" when: - - rhel9cis_rule_6_1_10 + - rhel9cis_rule_6_1_3 + - not system_is_ec2 tags: - - level1-server - - level1-workstation - - audit - - files - - permissions - - rule_6.1.10 - -- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist" - block: - - name: "6.1.11 | 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_09_6_1_11_audit - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.mount }}" - when: - - item['device'].startswith('/dev') - - not 'bind' in item['options'] - - - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | set fact" - ansible.builtin.set_fact: - rhel_09_6_1_11_ungrouped_files_found: true - loop: "{{ rhel_09_6_1_11_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 - - - name: "6.1.11 | 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_09_6_1_11_audit.stdout_lines }}" - when: rhel_09_6_1_11_ungrouped_files_found - - - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | warning" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.1.11' - when: rhel_09_6_1_11_ungrouped_files_found - vars: - rhel_09_6_1_11_ungrouped_files_found: false - when: - - rhel9cis_rule_6_1_11 - tags: - - level1-server - - level1-workstation - - audit - - files - - permissions - - rule_6.1.11 - -- name: "6.1.12 | 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 - when: - - rhel9cis_rule_6_1_12 - tags: - - level1-server - - level1-workstation - - patch - - stickybits - - permissons - - rule_6.1.12 - -- name: "6.1.13 | AUDIT | Audit SUID executables" - block: - - name: "6.1.13 | AUDIT | Audit SUID executables | Find all SUID executables" - ansible.builtin.shell: "df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000" - failed_when: false - changed_when: false - register: rhel_09_6_1_13_suid_perms - - - name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist" - ansible.builtin.debug: - msg: "Warning!! SUID set on items in {{ rhel_09_6_1_13_suid_perms.stdout_lines }}" - when: - - rhel_09_6_1_13_suid_perms.stdout is defined - - rhel_09_6_1_13_suid_perms.stdout | length > 0 - - - name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist | warning" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.1.13' - when: - - rhel_09_6_1_13_suid_perms.stdout is defined - - rhel_09_6_1_13_suid_perms.stdout | length > 0 - vars: - rhel9_6_1_13_suid_found: false - when: - - rhel9cis_rule_6_1_13 - tags: - - level1-server - - level1-workstation - - manual - - audit - - files - - rule_6.1.13 - -- name: "6.1.14 | AUDIT | Audit SGID executables" - block: - - name: "6.1.14 | AUDIT | Audit SGID executables | Find all SGID executables" - ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000 - failed_when: false - changed_when: false - register: rhel_09_6_1_14_sgid_perms - - - name: "6.1.14 | AUDIT | Audit SGID executables | Alert SGID executables exist" - ansible.builtin.debug: - msg: "Warning!! SGID set on items in {{ rhel_09_6_1_14_sgid_perms.stdout_lines }}" - when: - - rhel_09_6_1_14_sgid_perms.stdout is defined - - rhel_09_6_1_14_sgid_perms.stdout | length > 0 - - - name: "6.1.14 | AUDIT | Audit SGID executables| warning" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.1.14' - when: - - rhel_09_6_1_14_sgid_perms.stdout is defined - - rhel_09_6_1_14_sgid_perms.stdout | length > 0 - vars: - rhel9_6_1_14_sgid_found: false - when: - - rhel9cis_rule_6_1_14 - tags: - - level1-server - - level1-workstation - - manual - - audit - - files - - rule_6.1.14 - -- name: "6.1.15 | AUDIT | Audit system file permissions" - block: - - name: "6.1.15 | AUDIT | Audit system file permissions | Audit the packages" - ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto - changed_when: false - failed_when: false - register: rhel9cis_6_1_15_packages_rpm - - - name: "6.1.15 | AUDIT | Audit system file permissions | Create list and warning" - block: - - name: "6.1.15 | AUDIT | Audit system file permissions | Add file discrepancy list to system" - ansible.builtin.copy: - dest: "{{ rhel9cis_rpm_audit_file }}" # noqa template-instead-of-copy - content: "{{ rhel9cis_6_1_15_packages_rpm.stdout }}" - owner: root - group: root - mode: '0640' - - - name: "6.1.15 | 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 {{ rhel9cis_rpm_audit_file }}" - - - name: "6.1.15 | AUDIT | Audit system file permissions | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.1.15' - when: rhel9cis_6_1_15_packages_rpm.stdout|length > 0 - when: - - rhel9cis_rule_6_1_15 - tags: - - level2-server - - level2-workstation - - manual - - audit - - permissions - - rule_6.1.15 + - level1-server + - level1-workstation + - aide + - file_integrity + - patch + - rule_6.1.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/augenrules 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/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512 + /usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 + validate: aide -D --config %s diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml new file mode 100644 index 0000000..603e471 --- /dev/null +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -0,0 +1,114 @@ +--- + +- name: "6.2.1.1 | PATCH | Ensure journald service is enabled and active" + when: + - rhel9cis_rule_6_2_1_1 + tags: + - level1-server + - level1-workstation + - audit + - journald + - rule_6.2.1.1 + ansible.builtin.systemd: + name: systemd-journald.service + masked: false + state: started + +- name: "6.2.1.2 | PATCH | Ensure journald log file access is configured" + when: + - rhel9cis_rule_6_2_1_2 + tags: + - level1-server + - level1-workstation + - audit + - journald + - rule_6.2.1.2 + block: + - name: "6.2.1.2 | PATCH | Ensure journald log file access is configured | Default file permissions" + ansible.builtin.file: + path: /usr/lib/tmpfiles.d/systemd.conf + mode: '0640' + + - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Check for override file" + ansible.builtin.stat: + path: /etc/tmpfiles.d/systemd.conf + register: tmpfile_override + + - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | If override file check for journal" + when: tmpfile_override.stat.exists + ansible.builtin.shell: grep -E 'z /var/log/journal/%m/system.journal \d*' /usr/lib/tmpfiles.d/systemd.conf + register: journald_fileperms_override + changed_when: false + failed_when: journald_fileperms_override.rc not in [ 0, 1 ] + + - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found" + when: + - tmpfile_override.stat.exists + - journald_fileperms_override.stdout | length > 0 + ansible.builtin.debug: + msg: "Warning!! - tmpfiles override found /usr/lib/tmpfiles.d/systemd.conf affecting journald files please confirm matches site policy" + + - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found" + when: + - tmpfile_override.stat.exists + - journald_fileperms_override.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + vars: + warn_control_id: '6.2.1.2' + +- name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured" + when: + - rhel9cis_rule_6_2_1_3 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.1.3 + notify: Restart journald + block: + - name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/rotation.conf.j2 + dest: /etc/systemd/journald.conf.d/rotation.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: "{{ item }}" + replace: '#\1' + loop: + - '^(\s*SystemMaxUse\s*=.*)' + - '^(\s*SystemKeepFree\s*=.*)' + - '^(\s*RuntimeMaxUse\s*=)' + - '^(\s*RuntimeKeepFree\s*=.*)' + - '^(\s*MaxFileSec\s*=.*)' + +- name: "6.2.1.4 | PATCH | Ensure only one logging system is in use" + when: + - rhel9cis_rule_6_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - journald + - syslog + - rule_6.2.1.4 + block: + - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when rsyslog" + when: rhel9cis_syslog == "rsyslog" + ansible.builtin.systemd: + name: systemd-journald + state: stopped + enabled: false + + - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when journald" + when: rhel9cis_syslog == "journald" + ansible.builtin.systemd: + name: rsyslog + state: stopped + enabled: false diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml new file mode 100644 index 0000000..4db5c29 --- /dev/null +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -0,0 +1,162 @@ +--- + +- name: "6.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" + when: + - ubtu22cis_rule_6_2_2_1_1 + - not ubtu22cis_system_is_log_server + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.1.1 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + ansible.builtin.package: + name: systemd-journal-remote + state: present + +- name: "6.2.2.1.2 | PATCH | Ensure systemd-journal-remote authentication is configured" + when: + - ubtu22cis_rule_6_2_2_1_2 + - not ubtu22cis_system_is_log_server + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.1.2 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + notify: Restart journald + ansible.builtin.lineinfile: + path: /etc/systemd/journal-upload.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + loop: + - { regexp: 'URL=', line: 'URL={{ ubtu22cis_remote_log_server }}'} + - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ ubtu22cis_journal_upload_serverkeyfile }}'} + - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ ubtu22cis_journal_servercertificatefile }}'} + - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ ubtu22cis_journal_trustedcertificatefile }}'} + +- name: "6.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled and active" + when: + - not ubtu22cis_system_is_log_server + - ubtu22cis_rule_6_2_2_1_3 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.1.3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + ansible.builtin.systemd: + name: systemd-journal-upload + masked: false + enabled: true + +- name: "6.2.2.1.4 | PATCH | Ensure systemd-journal-remote service is not in use" + when: + - not ubtu22cis_system_is_log_server + - ubtu22cis_rule_6_2_2_1_4 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.1.4 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + ansible.builtin.systemd: + name: "{{ item }}" + state: stopped + enabled: false + masked: true + loop: + - systemd-journal-remote.socket + - systemd-journal-remote.service + +- name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled" + when: + - ubtu22cis_rule_6_2_2_2 + tags: + - level1-server + - level2-workstation + - patch + - journald + - rule_6.2.2.2 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-6 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + notify: Restart journald + block: + - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 + dest: /etc/systemd/journald.conf.d/forwardtosyslog.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(\s*ForwardToSyslog) + replace: '#\1' + +- name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" + when: + - ubtu22cis_rule_6_2_2_3 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.3 + - NIST800-53R5_AU-4 + notify: Restart journald + block: + - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/storage.conf.j2 # Added to the same file as 6.2.1.1.4 + dest: /etc/systemd/journald.conf.d/storage.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(?i)(\s*compress=) + replace: '#\1' + +- name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" + when: + - ubtu22cis_rule_6_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.4 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + notify: Restart journald + block: + - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/storage.conf.j2 + dest: /etc/systemd/journald.conf.d/storage.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(?i)(\s*storage=) + replace: '#\1' diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml new file mode 100644 index 0000000..7e4dadc --- /dev/null +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -0,0 +1,293 @@ +--- + +- name: "6.2.3.1 | PATCH | Ensure rsyslog installed" + when: + - "'rsyslog' not in ansible_facts.packages" + - rhel9cis_rule_6_2_3_1 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.1 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + ansible.builtin.package: + name: rsyslog + state: present + +- name: "6.2.3.2 | PATCH | Ensure rsyslog Service is enabled and active" + when: + - rhel9cis_rule_6_2_3_2 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.2 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + ansible.builtin.systemd: + name: rsyslog + enabled: true + state: started + +- name: "6.2.3.3 | PATCH | Ensure journald is configured to send logs to rsyslog" + when: + - rhel9cis_rule_6_2_3_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_6.2.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-4 + - NIST800-53R5_AU-12 + - NIST800-53R5_MP-2 + ansible.builtin.lineinfile: + path: /etc/systemd/journald.conf + regexp: "^#ForwardToSyslog=|^ForwardToSyslog=" + line: ForwardToSyslog=yes + notify: Restart rsyslog + +- name: "6.2.3.4 | PATCH | Ensure rsyslog log file creation mode is configured" + when: + - rhel9cis_rule_6_2_3_4 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_AC-6 + - NIST800-53R5_MP-2 + ansible.builtin.lineinfile: + path: /etc/rsyslog.conf + regexp: '^\$FileCreateMode' + line: '$FileCreateMode 0640' + notify: Restart rsyslog + +- name: "6.2.3.5 | PATCH | Ensure logging is configured" + when: + - rhel9cis_rule_6_2_3_5 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.5 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + block: + - name: "6.2.3.5 | AUDIT | Ensure logging is configured | rsyslog current config message out" + ansible.builtin.shell: cat /etc/rsyslog.conf | grep -Ev "^#|^$" + changed_when: false + failed_when: false + check_mode: false + register: rhel_09_6_2_3_5_audit + + - name: "6.2.3.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_09_4_2_1_5_audit.stdout_lines }}" + + - name: "6.2.3.5 | PATCH | Ensure logging is configured | mail.* log setting" + when: rhel9cis_rsyslog_ansiblemanaged + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown" + block: | + # mail logging additions to meet CIS standards + mail.* -/var/log/mail + mail.info -/var/log/mail.info + mail.warning -/var/log/mail.warning + mail.err /var/log/mail.err + insertafter: '# Log all the mail messages in one place.' + notify: Restart rsyslog + + - name: "6.2.3.5 | PATCH | Ensure logging is configured | news.crit log setting" + when: rhel9cis_rsyslog_ansiblemanaged + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + marker: "# {mark} NEWS LOG SETTINGS - CIS benchmark - Ansible-lockdown" + 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: "6.2.3.5 | PATCH | Ensure logging is configured | Misc. log setting" + when: rhel9cis_rsyslog_ansiblemanaged + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + 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 + + - name: "6.2.3.5 | PATCH | Ensure logging is configured | Local log settings" + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown" + block: | + # local log settings to meet CIS standards + local0,local1.* -/var/log/localmessages + local2,local3.* -/var/log/localmessages + local4,local5.* -/var/log/localmessages + local6,local7.* -/var/log/localmessages + *.emrg :omusrmsg:* + insertafter: '#### RULES ####' + notify: Restart rsyslog + + - name: "6.2.3.5 | PATCH | Ensure logging is configured | Auth Settings" + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown" + block: | + # Private settings to meet CIS standards + auth,authpriv.* /var/log/secure + insertafter: '#### RULES ####' + notify: Restart rsyslog + + - name: "6.2.3.5 | PATCH | Ensure logging is configured | Cron Settings" + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + 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: "6.2.3.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host" + when: + - rhel9cis_rule_6_2_3_6 + - rhel9cis_remote_log_server + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.6 + - NIST800-53R5_AU-6 + ansible.builtin.blockinfile: + path: /etc/rsyslog.conf + state: present + block: | + # target can be IP or FQDN + *.* action(type="omfwd" target="{{ rhel9cis_remote_log_host }}" port="{{ rhel9cis_remote_log_port }}" protocol="{{ rhel9cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel9cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel9cis_remote_log_queuesize }}") + insertafter: EOF + register: result + failed_when: + - result is failed + - result.rc != 257 + notify: Restart rsyslog + +- name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" + when: + - rhel9cis_rule_6_2_3_7 + tags: + - level1-server + - level1-workstation + - patch + - rsyslog + - rule_6.2.3.7 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + - NIST800-53R5_CM-6 + block: + - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host" + when: not rhel9cis_system_is_log_server + ansible.builtin.replace: + path: /etc/rsyslog.conf + regexp: '{{ item }}' + replace: '#\1' + notify: Restart rsyslog + loop: + - '^(\$ModLoad imtcp)' + - '^(\$InputTCPServerRun)' + - '^(module\(load="imtcp"\))' + - '^(input\(type="imtcp")' + + - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host" + when: rhel9cis_system_is_log_server + ansible.builtin.replace: + path: /etc/rsyslog.conf + regexp: '^#(.*{{ item }}.*)' + replace: '\1' + notify: Restart rsyslog + loop: + - 'ModLoad imtcp' + - 'InputTCPServerRun' + +- name: "6.2.3.8 | PATCH | Ensure logrotate is configured" + when: + - rhel9cis_rule_6_2_3_8 + tags: + - level1-server + - level1-workstation + - manual + - patch + - logrotate + - rule_6.2.3.8 + - NIST800-53R5_AU-8 + block: + - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | installed" + ansible.builtin.package: + name: rsyslog-logrotate + state: present + + - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | scheduled" + ansible.builtin.systemd: + name: logrotate.timer + state: started + enabled: true + + - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | set default conf" + ansible.builtin.replace: + path: "/etc/logrotate.conf" + regexp: '^(\s*)(daily|weekly|monthly|yearly)$' + replace: "\\1{{ rhel9cis_logrotate }}" + + - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | Get non default logrotate settings" + ansible.builtin.find: + paths: /etc/logrotate.d/ + contains: '^(\s*)(?!{{ rhel9cis_logrotate }})(daily|weekly|monthly|yearly)$' + register: log_rotates + + - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured" + when: log_rotates.matched > 0 + vars: + warn_control_id: '6.2.3.8' + block: + - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | generate file list" + ansible.builtin.set_fact: + logrotate_non_def_conf: "{{ log_rotates.files | map(attribute='path') | join (', ') }}" + + - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | List configured files" + ansible.builtin.debug: + msg: | + "Warning!! The following files are not covered by default logrotate settings ensure they match site policy" + "{{ logrotate_non_def_conf }}" + loop: "{{ log_rotates.files }}" + + - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | Warning count" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml new file mode 100644 index 0000000..b86b014 --- /dev/null +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -0,0 +1,62 @@ +--- + +- name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured" + when: + - rhel9cis_rule_6_2_4_1 + tags: + - level1-server + - level1-workstation + - patch + - logfiles + - rule_6.2.4.1 + block: + - name: "6.2.4.1 | AUDIT | Ensure access to all logfiles has been configured | find log files" + ansible.builtin.shell: find /var/log/ -type f -exec ls {} \; + changed_when: false + failed_when: false + register: discovered_logfiles + + - name: "6.2.4.1 | AUDIT | Ensure access to all logfiles has been configured | set_fact" + when: + - discovered_logfiles.stdout_lines | length > 0 + - discovered_logfiles is defined + ansible.builtin.set_fact: + discovered_logfiles_flattened: "{{ discovered_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + when: + - discovered_logfiles_flattened is defined + - item == "/var/log/secure" + - item == "/var/log/auth.log" + - item == "/var/log/syslog" + - "'journal' in item" + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-x,g-wx,o-rwx' + loop: "{{ discovered_logfiles_flattened }}" + + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + when: + - discovered_logfiles_flattened is defined + - 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' + owner: root + group: root + loop: "{{ discovered_logfiles_flattened }}" + + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + when: + - discovered_logfiles_flattened is defined + - "'sssd' in item" + - 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_flattened }}" diff --git a/tasks/section_6/cis_6.2.x.yml b/tasks/section_6/cis_6.2.x.yml deleted file mode 100644 index 7be9ae9..0000000 --- a/tasks/section_6/cis_6.2.x.yml +++ /dev/null @@ -1,455 +0,0 @@ ---- - -- name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords" - block: - - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | discover" - ansible.builtin.shell: awk -F':' '($2 != "x" ) { print $1 " is not set to shadowed passwords "}' /etc/passwd - changed_when: false - register: shadow_passwd - - - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | Output" - ansible.builtin.debug: - msg: | - - "Warning!! Below are the accounts that do not have shadowed passwords set" - - "{{ shadow_passwd.stdout_line }}" - when: shadow_passwd.stdout | length > 0 - - - name: "6.2.1 | AUDIT | Ensure accounts in /etc/passwd use shadowed passwords | warning fact" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.2.1' - when: shadow_passwd.stdout | length >= 1 - - when: - - rhel9cis_rule_6_2_1 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - rule_6.2.1 - -- name: "6.2.2 | PATCH | Ensure password fields are not empty" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - loop: "{{ empty_password_accounts.stdout_lines }}" - when: - - empty_password_accounts.rc - - rhel9cis_rule_6_2_2 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - rule_6.2.2 - -- name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group" - block: - - 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 - check_mode: false - register: rhel9cis_6_2_3_passwd_gid_check - - - 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" - ansible.builtin.debug: - msg: "Warning!! The following users have non-existent GIDs (Groups): {{ rhel9cis_6_2_3_passwd_gid_check.stdout_lines | join (', ') }}" - when: rhel9cis_6_2_3_passwd_gid_check.stdout | length >= 1 - - - name: "6.2.3 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.2.3' - when: rhel9cis_6_2_3_passwd_gid_check.stdout | length >= 1 - when: - - rhel9cis_rule_6_2_3 - tags: - - level1-server - - level1-workstation - - audit - - accounts - - groups - - rule_6.2.3 - -- name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist" - block: - - 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: rhel9cis_6_2_4_user_uid_check - - - name: "6.2.4 | 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: {{ rhel9cis_6_2_4_user_uid_check.stdout_lines }}" - when: rhel9cis_6_2_4_user_uid_check.stdout | length >= 1 - - - name: "6.2.4 | AUDIT | Ensure no duplicate UIDs exist | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: rhel9cis_6_2_4_user_uid_check.stdout | length >= 1 - vars: - warn_control_id: '6.2.4' - when: - - rhel9cis_rule_6_2_4 - tags: - - level1-server - - level1-workstation - - audit - - accounts - - users - - rule_6.2.4 - -- name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist" - block: - - 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 - register: rhel9cis_6_2_5_user_user_check - - - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs" - ansible.builtin.debug: - msg: "Warning!! The following groups have duplicate GIDs: {{ rhel9cis_6_2_5_user_user_check.stdout_lines }}" - when: rhel9cis_6_2_5_user_user_check.stdout | length >= 1 - - - name: "6.2.5 | AUDIT | Ensure no duplicate GIDs exist | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.2.5' - when: rhel9cis_6_2_5_user_user_check.stdout_lines | length >= 1 - - when: - - rhel9cis_rule_6_2_5 - tags: - - level1-server - - level1-workstation - - audit - - accounts - - groups - - rule_6.2.5 - -- name: "6.2.6 | AUDIT | Ensure no duplicate user names exist" - block: - - 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: false - register: rhel9cis_6_2_6_user_username_check - - - name: "6.2.6 | AUDIT | Ensure no duplicate user names exist | Print warning about users with duplicate User Names" - ansible.builtin.debug: - msg: "Warning!! The following user names are duplicates: {{ rhel9cis_6_2_6_user_username_check.stdout_lines }}" - when: rhel9cis_6_2_6_user_username_check.stdout | length >= 1 - - - name: "6.2.6 | AUDIT | Ensure no duplicate user names exist | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.2.6' - when: rhel9cis_6_2_6_user_username_check.stdout | length >= 1 - when: - - rhel9cis_rule_6_2_6 - tags: - - level1-server - - level1-workstation - - audit - - accounts - - users - - rule_6.2.6 - -- name: "6.2.7 | AUDIT | Ensure no duplicate group names exist" - 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: rhel9cis_6_2_7_group_group_check - - - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names" - ansible.builtin.debug: - msg: "Warning!! The following group names are duplicates: {{ rhel9cis_6_2_7_group_group_check.stdout_lines }}" - when: rhel9cis_6_2_7_group_group_check.stdout is not defined - - - name: "6.2.7 | AUDIT | Ensure no duplicate group names exist | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - vars: - warn_control_id: '6.2.7' - when: rhel9cis_6_2_7_group_group_check.stdout is not defined - when: - - rhel9cis_rule_6_2_7 - tags: - - level1-server - - level1-workstation - - audit - - accounts - - groups - - rule_6.2.7 - -- name: "6.2.8 | PATCH | Ensure root PATH Integrity" - block: - - 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: rhel9cis_6_2_8_root_paths - - - 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: rhel9cis_6_2_8_root_paths_split - - - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set fact" - ansible.builtin.set_fact: - root_paths: "{{ rhel9cis_6_2_8_root_paths.stdout }}" - - - 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: root_path_empty_dir.rc not in [ 0, 1 ] - register: 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: root_path_trailing_colon.rc not in [ 0, 1 ] - register: 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: root_path_perms - loop: "{{ rhel9cis_6_2_8_root_paths_split.stdout_lines }}" - - - name: "6.2.8 | AUDIT | Ensure root PATH Integrity | Set permissions" - ansible.builtin.file: - path: "{{ item.stat.path }}" - state: directory - owner: root - group: root - mode: '0755' - follow: false - loop: "{{ root_path_perms.results }}" - loop_control: - label: "{{ item }}" - 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 - when: - - rhel9cis_rule_6_2_8 - tags: - - level1-server - - level1-workstation - - patch - - paths - - rule_6.2.8 - -- name: "6.2.9 | PATCH | Ensure root is the only UID 0 account" - ansible.builtin.shell: passwd -l {{ item }} - changed_when: false - failed_when: false - loop: "{{ rhel9cis_uid_zero_accounts_except_root.stdout_lines }}" - when: - - rhel9cis_uid_zero_accounts_except_root.rc - - rhel9cis_rule_6_2_9 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - users - - rule_6.2.9 - -- name: "6.2.10 | PATCH | Ensure local interactive user home directories exist" - block: - - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Create dir if absent" - ansible.builtin.file: - path: "{{ item.dir }}" - state: directory - owner: "{{ item.id }}" - group: "{{ item.gid }}" - register: rhel_09_6_2_10_home_dir - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | list }}" - loop_control: - label: "{{ item.id }}" - - # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.10 | PATCH | Ensure local interactive user home directories exist | Set group ACL" - ansible.posix.acl: - path: "{{ item }}" - default: true - etype: group - permissions: rx - state: present - 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 - when: - - rhel9cis_rule_6_2_10 - tags: - - level1-server - - level1-workstation - - patch - - users - - rule_6.2.10 - -- name: "6.2.11 | PATCH | Ensure local interactive users own their home directories" - ansible.builtin.file: - path: "{{ item.dir }}" - owner: "{{ item.id }}" - state: directory - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | list }}" - loop_control: - label: "{{ item.id }}" - when: - - item.id in discovered_interactive_usernames.stdout - - rhel9cis_rule_6_2_11 - tags: - - level1-server - - level1-workstation - - patch - - users - - rule_6.2.11 - -- name: "6.2.12 | PATCH | Ensure local interactive user home directories are mode 750 or more restrictive" - block: - - name: "6.2.12 | AUDIT | Ensure local interactive user home directories are mode 750 or more restrictive | get stat" - ansible.builtin.stat: - path: "{{ item }}" - register: rhel_09_6_2_12_home_dir_perms - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - - - name: "6.2.12 | PATCH | Ensure local interactive user home directories are mode 750 or more restrictive | amend if needed" - ansible.builtin.file: - path: "{{ item.stat.path }}" - state: directory - mode: '0750' - loop: "{{ rhel_09_6_2_12_home_dir_perms.results }}" - loop_control: - label: "{{ item }}" - when: - - item.stat.mode > '0750' - - # set default ACLs so the homedir has an effective umask of 0027 - - name: "6.2.12 | PATCH | Ensure local interactive user home directories are mode 750 or more restrictive | Set group ACL" - ansible.posix.acl: - path: "{{ item }}" - default: true - etype: group - permissions: rx - state: present - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - when: not system_is_container - - - name: "6.2.12 | PATCH | Ensure local interactive user home directories are mode 750 or more restrictive | 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 - when: - - rhel9cis_rule_6_2_12 - tags: - - level1-server - - level1-workstation - - patch - - users - - permissions - - rule_6.2.12 - -- name: "6.2.13 | PATCH | Ensure no local interactive user has .netrc files" - ansible.builtin.file: - path: "{{ item }}/.netrc" - state: absent - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - when: - - rhel9cis_rule_6_2_13 - tags: - - level1-server - - level1-workstation - - patch - - users - - permissions - - rule_6.2.13 - -- name: "6.2.14 | PATCH | Ensure no local interactive user has .forward files" - ansible.builtin.file: - path: "{{ item }}/.forward" - state: absent - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - when: - - rhel9cis_rule_6_2_14 - tags: - - level1-server - - level1-workstation - - patch - - users - - files - - rule_6.2.14 - -- name: "6.2.15 | PATCH | Ensure no local interactive user has .rhosts files" - ansible.builtin.file: - path: "~{{ item }}/.rhosts" - state: absent - loop: "{{ discovered_interactive_users_home.stdout_lines }}" - when: - - rhel9cis_rule_6_2_15 - tags: - - level1-server - - level1-workstation - - patch - - users - - files - - rule_6.2.15 - -- name: "6.2.16 | PATCH | Ensure local interactive user dot files are not group or world writable" - block: - - name: "6.2.16 | AUDIT | Ensure local interactive user dot files are not group or world writable | Check for files" - ansible.builtin.find: - path: /home - depth: 3 - patterns: ".*" - hidden: true - recurse: true - file_type: file - register: user_dot_files - - - name: "6.2.16 | AUDIT | Ensure local interactive user dot files are not group or world writable | update permissions" - ansible.builtin.file: - path: "{{ item.path }}" - mode: go-w - follow: "{{ rhel_09_6_2_16_home_follow_symlinks }}" - loop: "{{ user_dot_files.files }}" - loop_control: - label: "{{ item.path }}" - - when: - - rhel9cis_rule_6_2_16 - tags: - - level1-server - - level1-workstation - - patch - - users - - permissions - - rule_6.2.16 diff --git a/tasks/section_6/cis_6.3.1.x.yml b/tasks/section_6/cis_6.3.1.x.yml new file mode 100644 index 0000000..b25ab69 --- /dev/null +++ b/tasks/section_6/cis_6.3.1.x.yml @@ -0,0 +1,111 @@ +--- + +- name: "6.3.1.1 | PATCH | Ensure auditd is installed" + when: + - rhel9cis_rule_6_3_1_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.1.1 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + block: + - name: "6.3.1.1 | PATCH | Ensure auditd is installed | Install auditd packages" + when: '"auditd" not in ansible_facts.packages' + ansible.builtin.package: + name: audit + state: present + + - name: "6.3.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages" + when: '"auditd-lib" not in ansible_facts.packages' + ansible.builtin.package: + name: audit-libs + state: present + +- name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" + when: + - rhel9cis_rule_6_3_1_2 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - grub + - rule_6.3.1.2 + block: + - name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby existence of current value" + ansible.builtin.shell: grubby --info=ALL | grep args | sed -n 's/.*audit=\([[:alnum:]]\+\).*/\1/p' + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_6_3_1_2_grubby_curr_value_audit_linux + + - name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby update, if needed" + when: + - rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout == '' or + '0' in rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout or + 'off' in rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout|lower + ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1" + +- name: "6.3.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" + when: + - rhel9cis_rule_6_3_1_3 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - grub + - rule_6.3.1.3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + block: + - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby existence of current value" + ansible.builtin.shell: + cmd: 'grubby --info=ALL | grep args | grep -o -E "audit_backlog_limit=([[:digit:]])+" | grep -o -E "([[:digit:]])+"' + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux + + - name: "6.3.1.3 | AUDIT | Check to see if limits are set" + when: + - rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux is not defined or + rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux.stdout_lines == [] + ansible.builtin.set_fact: + rhel9cis_6_3_1_3_reset_backlog_limits: true + + - name: "6.3.1.3 | AUDIT | Check to see if any limits are too low" + when: + - (item | int < rhel9cis_audit_back_log_limit) + ansible.builtin.set_fact: + rhel9cis_6_3_1_3_reset_backlog_limits: true + loop: "{{ rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux.stdout_lines }}" + + - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" + when: + - rhel9cis_6_3_1_3_reset_backlog_limits is defined + ansible.builtin.shell: + cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' + +- name: "6.3.1.4 | PATCH | Ensure auditd service is enabled and active" + when: + - rhel9cis_rule_6_3_1_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.1.4 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.systemd: + name: auditd + state: started + enabled: true diff --git a/tasks/section_6/cis_6.3.2.x.yml b/tasks/section_6/cis_6.3.2.x.yml new file mode 100644 index 0000000..dd9df94 --- /dev/null +++ b/tasks/section_6/cis_6.3.2.x.yml @@ -0,0 +1,76 @@ +--- + +- name: "6.3.2.1 | PATCH | Ensure audit log storage size is configured" + when: + - rhel9cis_rule_6_3_2_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.2.1 + - NIST800-53R5_AU-8 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^max_log_file( |=)" + line: "max_log_file = {{ rhel9cis_auditd['max_log_file'] }}" + notify: Restart auditd + +- name: "6.3.2.2 | PATCH | Ensure audit logs are not automatically deleted" + when: + - rhel9cis_rule_6_3_2_2 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.2.2 + - NIST800-53R5_AU-8 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^max_log_file_action" + line: "max_log_file_action = {{ rhel9cis_auditd['max_log_file_action'] }}" + notify: Restart auditd + +- name: "6.3.2.3 | PATCH | Ensure system is disabled when audit logs are full" + when: + - rhel9cis_rule_6_3_2_3 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.2.3 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + 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 = {{ rhel9cis_auditd.admin_space_left_action }}' } + - { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel9cis_auditd.action_mail_acct }}' } + - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel9cis_auditd.space_left_action }}' } + +- name: PATCH | Configure other keys for auditd.conf + when: + - rhel9cis_auditd_extra_conf.keys() | length > 0 + - rhel9cis_auditd_extra_conf_usage + tags: + - level2-server + - level2-workstation + - patch + - auditd + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "^{{ item }}( |=)" + line: "{{ item }} = {{ rhel9cis_auditd_extra_conf[item] }}" + loop: "{{ rhel9cis_auditd_extra_conf.keys() }}" + notify: Restart auditd diff --git a/tasks/section_6/cis_6.3.3.x.yml b/tasks/section_6/cis_6.3.3.x.yml new file mode 100644 index 0000000..7e7e479 --- /dev/null +++ b/tasks/section_6/cis_6.3.3.x.yml @@ -0,0 +1,328 @@ +--- + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" + when: + - rhel9cis_rule_6_3_3_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.1 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.2 | PATCH | Ensure actions as another user are always logged" + when: + - rhel9cis_rule_6_3_3_2 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.2 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.3 | PATCH | Ensure events that modify the sudo log file are collected" + when: + - rhel9cis_rule_6_3_3_3 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.4 | PATCH | Ensure events that modify date and time information are collected" + when: + - rhel9cis_rule_6_3_3_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.4 + - NIST800-53R5_AU-3 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.5 | PATCH | Ensure events that modify the system's network environment are collected" + when: + - rhel9cis_rule_6_3_3_5 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.5 + - NIST800-53R5_AU-3 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.6 | PATCH | Ensure use of privileged commands is collected" + when: + - rhel9cis_rule_6_3_3_6 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.6 + - NIST800-53R5_AU-3 + block: + - name: "6.3.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 + + - name: "6.3.3.6 | PATCH | Ensure use of privileged commands is collected" + ansible.builtin.set_fact: + update_audit_template: true + notify: update auditd + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.7 | PATCH | Ensure unsuccessful file access attempts are collected" + when: + - rhel9cis_rule_6_3_3_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.7 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.8 | PATCH | Ensure events that modify user/group information are collected" + when: + - rhel9cis_rule_6_3_3_8 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.8 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" + when: + - rhel9cis_rule_6_3_3_9 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.9 + - NIST800-53R5_AU-3 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.10 | PATCH | Ensure successful file system mounts are collected" + when: + - rhel9cis_rule_6_3_3_10 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.10 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.11 | PATCH | Ensure session initiation information is collected" + when: + - rhel9cis_rule_6_3_3_11 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.11 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.12 | PATCH | Ensure login and logout events are collected" + when: + - rhel9cis_rule_6_3_3_12 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.12 + - NIST800-53R5_AU-3 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.13 | PATCH | Ensure file deletion events by users are collected" + when: + - rhel9cis_rule_6_3_3_13 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.13 + - NIST800-53R5_AU-12 + - NIST800-53R5_SC-7 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" + when: + - rhel9cis_rule_6_3_3_14 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.14 + - NIST800-53R5_AU-3 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" + when: + - rhel9cis_rule_6_3_3_15 + tags: + - level2-server + - level2- workstation + - patch + - auditd + - rule_6.3.3.15 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" + when: + - rhel9cis_rule_6_3_3_16 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.16 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" + when: + - rhel9cis_rule_6_3_3_17 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.17 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" + when: + - rhel9cis_rule_6_3_3_18 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.18 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.19 | PATCH | Ensure kernel module loading and unloading and modification is collected" + when: + - rhel9cis_rule_6_3_3_19 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.19 + - NIST800-53R5_AU-3 + - NIST800-53R5_CM-6 + ansible.builtin.set_fact: + update_audit_template: true + +# All changes selected are managed by the POST audit and handlers to update +- name: "6.3.3.20 | PATCH | Ensure the audit configuration is immutable" + when: + - rhel9cis_rule_6_3_3_20 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.3.20 + - NIST800-53R5_AC-3 + - NIST800-53R5_AU-3 + - NIST800-53R5_MP-2 + ansible.builtin.set_fact: + update_audit_template: true + +- name: "6.3.3.21 | AUDIT | Ensure the running and on disk configuration is the same" + when: + - rhel9cis_rule_6_3_3_21 + tags: + - level2-server + - level2-workstation + - manual + - patch + - auditd + - rule_6.3.3.21 + - NIST800-53R5_AU-3 + ansible.builtin.debug: + msg: + - "Please run augenrules --load if you suspect there is a configuration that is not active" + +- name: Auditd | 6.3.3.x | 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 diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml new file mode 100644 index 0000000..144adec --- /dev/null +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -0,0 +1,167 @@ +--- + +- name: "6.3.4.1 | PATCH | Ensure the audit log file directory mode is configured" + when: + - rhel9cis_rule_6_3_4_1 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.1 + - NIST800-53R5_AU-3 + block: + - name: "6.3.4.1 | AUDIT | Ensure the audit log file directory mode is configured | get current permissions" + ansible.builtin.stat: + path: "{{ audit_discovered_logfile.stdout | dirname }}" + register: auditlog_dir + + - name: "6.3.4.1 | PATCH | Ensure the audit log file directory mode is configured | set" + ansible.builtin.file: + path: "{{ audit_discovered_logfile.stdout | dirname }}" + state: directory + mode: 'g-w,o-rwx' + +- name: | + "6.3.4.2 | PATCH | Ensure audit log files mode is configured" + "6.3.4.3 | PATCH | Ensure audit log files owner is configured" + "6.3.4.4 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" + when: + - rhel9cis_rule_6_3_4_2 or + rhel9cis_rule_6_3_4_3 or + rhel9cis_rule_6_3_4_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.1 + - rule_6.3.4.2 + - rule_6.3.4.3 + - NIST800-53R5_AU-3 + block: + - name: "6.3.4.2 | AUDIT | Ensure audit log files mode is configured | discover file" + ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' + changed_when: false + register: audit_discovered_logfile + + - name: | + "6.3.4.2 | PATCH | Ensure audit log files mode is configured" + "6.3.4.3 | PATCH | Ensure audit log files owner is configured" + "6.3.4.4 | PATCH | Ensure audit log files group owner is configured" + ansible.builtin.file: + path: "{{ audit_discovered_logfile.stdout }}" + mode: 'o-x,g-wx,o-rwx' + owner: root + group: root + +- name: "6.3.4.5 | PATCH | Ensure audit configuration files mode is configured" + when: + - rhel9cis_rule_6_3_4_5 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.5 + ansible.builtin.file: + path: "{{ item.path }}" + mode: 'u-x,g-wx,o-rwx' + loop: "{{ auditd_conf_files.files }}" + loop_control: + label: "{{ item.path }}" + +- name: "6.3.4.6 | PATCH | Ensure audit configuration files owner is configured" + when: + - rhel9cis_rule_6_3_4_6 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.6 + ansible.builtin.file: + path: "{{ item.path }}" + owner: root + loop: "{{ auditd_conf_files.files | default([]) }}" + loop_control: + label: "{{ item.path }}" + +- name: "6.3.4.7 | PATCH | Ensure audit configuration files group owner is configured" + when: + - rhel9cis_rule_6_3_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.7 + ansible.builtin.file: + path: "{{ item.path }}" + group: root + loop: "{{ auditd_conf_files.files | default([]) }}" + loop_control: + label: "{{ item.path }}" + +- name: "6.3.4.8 | PATCH | Ensure audit tools mode is configured" + when: + - rhel9cis_rule_6_3_4_8 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.8 + - NIST800-53R5_AU-3 + ansible.builtin.file: + path: "{{ item.item }}" + mode: 'go-w' + loop: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules + +- name: "6.3.4.9 | PATCH | Ensure audit tools owner is configured" + when: + - rhel9cis_rule_6_3_4_9 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.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: "6.3.4.10 | PATCH | Ensure audit tools group owner is configured" + when: + - rhel9cis_rule_6_3_4_10 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.10 + - NIST800-53R5_AU-3 + 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_6/main.yml b/tasks/section_6/main.yml index b194fdc..c75ebed 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -1,9 +1,39 @@ --- -- name: "SECTION | 6.1 | System File Permissions" +- name: "SECTION | 6.1 | Configure Integrity Checking" ansible.builtin.import_tasks: - file: cis_6.1.x.yml + file: cis_6.1.x.yml -- name: "SECTION | 6.2 | User and Group Settings" +- name: "SECTION | 6.2.1 | Configure systemd-journald service" ansible.builtin.import_tasks: - file: cis_6.2.x.yml + file: cis_6.2.1.x.yml + +- name: "SECTION | 6.2.2 | Configure journald" + when: rhel9cis_syslog == 'journald' + ansible.builtin.import_tasks: + file: cis_6.2.2.1.x.yml + +- name: "SECTION | 6.2.3 | Configure rsyslog" + when: rhel9cis_syslog == 'rsyslog' + ansible.builtin.import_tasks: + file: cis_6.2.3.x.yml + +- name: "SECTION | 6.2.4.1 | Configure Logfiles" + ansible.builtin.import_tasks: + file: cis_6.2.4.1.yml + +- name: "SECTION | 6.3.1 | Configure auditd Service" + ansible.builtin.import_tasks: + file: cis_6.3.1.x.yml + +- name: "SECTION | 6.3.2 | Configure Data Retention" + ansible.builtin.import_tasks: + file: cis_6.3.2.x.yml + +- name: "SECTION | 6.3.3 | Configure auditd Rules" + ansible.builtin.import_tasks: + file: cis_6.3.3.x.yml + +- name: "SECTION | 6.3.4 | Configure auditd File Access" + ansible.builtin.import_tasks: + file: cis_6.3.4.x.yml From b5361df285659679cbadc05c886e71efd51dd166 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:05:57 +0100 Subject: [PATCH 025/327] updated for v2 Signed-off-by: Mark Bolwell --- .../etc/sysctl.d/60-netipv4_sysctl.conf.j2 | 38 +++++++++---------- .../etc/sysctl.d/60-netipv6_sysctl.conf.j2 | 19 ++++++---- 2 files changed, 30 insertions(+), 27 deletions(-) diff --git a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 index 8bafbf9..336071c 100644 --- a/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv4_sysctl.conf.j2 @@ -1,42 +1,32 @@ ## This file is managed by Ansible, YOUR CHANGES WILL BE LOST! # IPv4 Network sysctl -{% if rhel9cis_rule_3_2_1 %} -# CIS 3.2.1 -net.ipv4.ip_forward = 0 -{% endif %} -{% if rhel9cis_rule_3_2_2 %} -# CIS 3.2.2 -net.ipv4.conf.all.send_redirects = 0 -net.ipv4.conf.default.send_redirects = 0 -{% endif %} {% if rhel9cis_rule_3_3_1 %} # CIS 3.3.1 -net.ipv4.conf.all.accept_source_route = 0 -net.ipv4.conf.default.accept_source_route = 0 +net.ipv4.ip_forward = 0 {% endif %} {% if rhel9cis_rule_3_3_2 %} # CIS 3.3.2 -net.ipv4.conf.all.accept_redirects = 0 -net.ipv4.conf.default.accept_redirects = 0 +net.ipv4.conf.all.send_redirects = 0 +net.ipv4.conf.default.send_redirects = 0 {% endif %} {% if rhel9cis_rule_3_3_3 %} # CIS 3.3.3 -net.ipv4.conf.all.secure_redirects = 0 -net.ipv4.conf.default.secure_redirects = 0 +net.ipv4.icmp_ignore_bogus_error_responses = 1 {% endif %} {% if rhel9cis_rule_3_3_4 %} # CIS 3.3.4 -net.ipv4.conf.all.log_martians = 1 -net.ipv4.conf.default.log_martians = 1 +net.ipv4.icmp_echo_ignore_broadcasts = 1 {% endif %} {% if rhel9cis_rule_3_3_5 %} # CIS 3.3.5 -net.ipv4.icmp_echo_ignore_broadcasts = 1 +net.ipv4.conf.all.accept_redirects = 0 +net.ipv4.conf.default.accept_redirects = 0 {% endif %} {% if rhel9cis_rule_3_3_6 %} # CIS 3.3.6 -net.ipv4.icmp_ignore_bogus_error_responses = 1 +net.ipv4.conf.all.secure_redirects = 0 +net.ipv4.conf.default.secure_redirects = 0 {% endif %} {% if rhel9cis_rule_3_3_7 %} # CIS 3.3.7 @@ -45,5 +35,15 @@ net.ipv4.conf.default.rp_filter = 1 {% endif %} {% if rhel9cis_rule_3_3_8 %} # CIS 3.3.8 +net.ipv4.conf.all.accept_source_route = 0 +net.ipv4.conf.default.accept_source_route = 0 +{% endif %} +{% if rhel9cis_rule_3_3_9 %} +# CIS 3.3.9 +net.ipv4.conf.all.log_martians = 1 +net.ipv4.conf.default.log_martians = 1 +{% endif %} +{% if rhel9cis_rule_3_3_10 %} +# CIS 3.3.10 net.ipv4.tcp_syncookies = 1 {% endif %} diff --git a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 index 5e63a01..07e045d 100644 --- a/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 +++ b/templates/etc/sysctl.d/60-netipv6_sysctl.conf.j2 @@ -2,19 +2,22 @@ # IPv6 Network sysctl {% if rhel9cis_ipv6_required %} -{% if rhel9cis_rule_3_2_1 %} +{% if rhel9cis_rule_3_3_1 %} +# CIS 3.3.1 net.ipv6.conf.all.forwarding = 0 {% endif %} -{% if rhel9cis_rule_3_3_1 %} -net.ipv6.conf.all.accept_source_route = 0 -net.ipv6.conf.default.accept_source_route = 0 -{% endif %} -{% if rhel9cis_rule_3_3_2 %} +{% if rhel9cis_rule_3_3_5 %} +# CIS 3.3.5 net.ipv6.conf.all.accept_redirects = 0 net.ipv6.conf.default.accept_redirects = 0 {% endif %} -{% if rhel9cis_rule_3_3_9 %} -# CIS 3.3.9 +{% if rhel9cis_rule_3_3_8 %} +# CIS 3.3.8 +net.ipv6.conf.all.accept_source_route = 0 +net.ipv6.conf.default.accept_source_route = 0 +{% endif %} +{% if rhel9cis_rule_3_3_11 %} +# CIS 3.3.11 net.ipv6.conf.all.accept_ra = 0 net.ipv6.conf.default.accept_ra = 0 {% endif %} From a345a2c02fa07212d1184a886db798ef78d57abd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 24 Jul 2024 14:06:02 +0100 Subject: [PATCH 026/327] updated Signed-off-by: Mark Bolwell --- .yamllint | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.yamllint b/.yamllint index 65faae6..27d8aee 100644 --- a/.yamllint +++ b/.yamllint @@ -11,7 +11,7 @@ ignore: | rules: indentation: # Requiring 4 space indentation - spaces: 4 + spaces: 2 # Requiring consistent indentation within a file, either indented or not indent-sequences: consistent braces: From 6d2c9e67e91fd06bb466cc72f93db83e591b7c7b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 6 Aug 2024 17:28:39 +0100 Subject: [PATCH 027/327] Added new options rsyslog logrotate Signed-off-by: Mark Bolwell --- defaults/main.yml | 17 +++++++++ tasks/section_6/cis_6.2.3.x.yml | 44 ++++++----------------- templates/etc/logrotate.d/rsyslog.conf.j2 | 11 ++++++ 3 files changed, 38 insertions(+), 34 deletions(-) create mode 100644 templates/etc/logrotate.d/rsyslog.conf.j2 diff --git a/defaults/main.yml b/defaults/main.yml index dc5d401..2029bd4 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1118,6 +1118,23 @@ rhel9cis_remote_log_retrycount: 100 # of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). rhel9cis_remote_log_queuesize: 1000 +## Control 6.2.3.8 rsyslog log rotate option +# These variable allow you to change accordint to site policy settings +# When to rotate options: hourly, daily, weekly, monthly, yearly +rhel9cis_rsyslog_logrotate_rotated: weekly +# Number of backlog files to keep +rhel9cis_rsyslog_logrotate_keep: 4 +# compress file once rotated, false will not compress +rhel9cis_rsyslog_logrotate_compress: true +# If the log file is missing, go on to the next one without issuing an error message +rhel9cis_rsyslog_logrotate_missingok: +# Dont rotate file if has no contents, false will still rotate +rhel9cis_rsyslog_logrotate_notifempty: true +# rhel9cis_rsyslog_logrotate_create give the options to create permissions and ownerships +# allows create iption to be used and sets options below based on mode owner group +rhel9cis_rsyslog_logrotate_create: false +rhel9cis_rsyslog_logrotate_create_opts: 0640 root root + ## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured # 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to # URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 7e4dadc..86cef8a 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -237,7 +237,7 @@ - 'ModLoad imtcp' - 'InputTCPServerRun' -- name: "6.2.3.8 | PATCH | Ensure logrotate is configured" +- name: "6.2.3.8 | PATCH | Ensure rsyslog logrotate is configured" when: - rhel9cis_rule_6_2_3_8 tags: @@ -249,45 +249,21 @@ - rule_6.2.3.8 - NIST800-53R5_AU-8 block: - - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | installed" + - name: "6.2.3.8 | PATCH | Ensure rsyslog logrotate is configured | installed" ansible.builtin.package: name: rsyslog-logrotate state: present - - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | scheduled" + - name: "6.2.3.8 | PATCH | Ensure rsyslog logrotate is configured | scheduled" ansible.builtin.systemd: name: logrotate.timer state: started enabled: true - - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | set default conf" - ansible.builtin.replace: - path: "/etc/logrotate.conf" - regexp: '^(\s*)(daily|weekly|monthly|yearly)$' - replace: "\\1{{ rhel9cis_logrotate }}" - - - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | Get non default logrotate settings" - ansible.builtin.find: - paths: /etc/logrotate.d/ - contains: '^(\s*)(?!{{ rhel9cis_logrotate }})(daily|weekly|monthly|yearly)$' - register: log_rotates - - - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured" - when: log_rotates.matched > 0 - vars: - warn_control_id: '6.2.3.8' - block: - - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | generate file list" - ansible.builtin.set_fact: - logrotate_non_def_conf: "{{ log_rotates.files | map(attribute='path') | join (', ') }}" - - - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | List configured files" - ansible.builtin.debug: - msg: | - "Warning!! The following files are not covered by default logrotate settings ensure they match site policy" - "{{ logrotate_non_def_conf }}" - loop: "{{ log_rotates.files }}" - - - name: "6.2.3.8 | AUDIT | Ensure logrotate is configured | Warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml + - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | set rsyslog conf" + ansible.builtin.template: + src: etc/logrotate.d/rsyslog.conf.j2 + dest: /etc/logrotate.d/rsyslog.conf + owner: root + group: root + mode: '0640' diff --git a/templates/etc/logrotate.d/rsyslog.conf.j2 b/templates/etc/logrotate.d/rsyslog.conf.j2 new file mode 100644 index 0000000..2423b24 --- /dev/null +++ b/templates/etc/logrotate.d/rsyslog.conf.j2 @@ -0,0 +1,11 @@ +/var/log/rsyslog/*.log { + {{ rhel9cis_rsyslog_logrotate_rotated }} + rotate {{ rhel9cis_rsyslog_logrotate_keep }} + {% if rhel9cis_rsyslog_logrotate_compress %}compress{% else %}nocompress{% endif %} + {% if rhel9cis_rsyslog_logrotate_missingok %}missingok{% else %}missingok{% endif %} + {% if rhel9cis_rsyslog_logrotate_notifempty %}notifempty{% else %}ifempty{% endif %} + {% if rhel9cis_rsyslog_logrotate_create %}create {{ rhel9cis_rsyslog_logrotate_create_opts }}{% endif %} + postrotate + /usr/bin/systemctl reload rsyslog.service >/dev/null || true + endscript +} From 64abf8c475a85ad8df5b6602615280f82a964f95 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 6 Aug 2024 17:28:57 +0100 Subject: [PATCH 028/327] removed files not required Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.x.yml | 138 ------------------------- tasks/section_5/cis_5.6.1.x.yml | 173 -------------------------------- 2 files changed, 311 deletions(-) delete mode 100644 tasks/section_5/cis_5.3.x.yml delete mode 100644 tasks/section_5/cis_5.6.1.x.yml diff --git a/tasks/section_5/cis_5.3.x.yml b/tasks/section_5/cis_5.3.x.yml deleted file mode 100644 index 2f63b23..0000000 --- a/tasks/section_5/cis_5.3.x.yml +++ /dev/null @@ -1,138 +0,0 @@ ---- - -- name: "5.3.1 | PATCH | Ensure sudo is installed" - ansible.builtin.package: - name: sudo - state: present - when: - - rhel9cis_rule_5_3_1 - tags: - - level1-server - - level1-workstation - - 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" - validate: '/usr/sbin/visudo -cf %s' - when: - - rhel9cis_rule_5_3_2 - tags: - - level1-server - - level1-workstation - - patch - - sudo - - rule_5.3.2 - -- name: "5.3.3 | PATCH | Ensure sudo log file exists" - ansible.builtin.lineinfile: - path: /etc/sudoers - regexp: '^Defaults logfile=' - line: 'Defaults logfile="{{ rhel9cis_sudolog_location }}"' - validate: '/usr/sbin/visudo -cf %s' - when: - - rhel9cis_rule_5_3_3 - tags: - - level1-server - - level1-workstation - - 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' - validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_sudoers_files.stdout_lines }}" - when: - - rhel9cis_rule_5_3_4 - tags: - - level2-server - - level2-workstation - - 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' - validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_sudoers_files.stdout_lines }}" - when: - - rhel9cis_rule_5_3_5 - tags: - - level1-server - - level1-workstation - - 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 - changed_when: false - failed_when: false - register: rhel9cis_5_3_6_timeout_files - - - 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={{ rhel9cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - when: rhel9cis_5_3_6_timeout_files.stdout | length == 0 - - - 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={{ rhel9cis_sudo_timestamp_timeout }}" - validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_5_3_6_timeout_files.stdout_lines }}" - when: rhel9cis_5_3_6_timeout_files.stdout | length > 0 - when: - - rhel9cis_rule_5_3_6 - tags: - - level1-server - - level1-workstation - - patch - - sudo - - rule_5.3.6 - -- name: "5.3.7 | PATCH | Ensure access to the su command is restricted" - block: - - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists" - ansible.builtin.group: - name: "{{ rhel9cis_sugroup }}" - state: present - register: rhel9cis_5_3_7_sugroup - - - name: "5.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group" - ansible.builtin.lineinfile: - path: /etc/group - regexp: '^{{ rhel9cis_sugroup }}(:.:.*:).*$' - line: '{{ rhel9cis_sugroup }}\g<1>' - backrefs: true - - - 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={{ rhel9cis_sugroup }}' - when: - - rhel9cis_rule_5_3_7 - tags: - - level1-server - - level1-workstation - - patch - - sudo - - rule_5.3.7 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 7abe1d1..0000000 --- a/tasks/section_5/cis_5.6.1.x.yml +++ /dev/null @@ -1,173 +0,0 @@ ---- - -- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less" - block: - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MAX_DAYS' - line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}" - - - name: "5.6.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS" - ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass['max_days'] }} || $5< {{ rhel9cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow" - changed_when: false - failed_when: false - register: discovered_max_days - - - name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" - ansible.builtin.user: - name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass['max_days'] }}" - loop: "{{ discovered_max_days.stdout_lines }}" - when: - - discovered_max_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout - - rhel9cis_force_user_maxdays - when: - - rhel9cis_rule_5_6_1_1 - tags: - - level1-server - - level1-workstation - - 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 | PATCH | Ensure minimum days between password changes is configured | set login.defs" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_MIN_DAYS' - line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}" - - - name: "5.6.1.2 | AUDIT | Ensure minimum days between password changes is configured | Get existing users PASS_MIN_DAYS" - ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass['min_days'] }} {print $1}' /etc/shadow" - changed_when: false - failed_when: false - register: discovered_min_days - - - name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is configured | Set existing users PASS_MIN_DAYS" - ansible.builtin.user: - name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass['min_days'] }}" - loop: "{{ discovered_min_days.stdout_lines }}" - when: - - discovered_min_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout - - rhel9cis_force_user_mindays - when: - - rhel9cis_rule_5_6_1_2 - tags: - - level1-server - - level1-workstation - - 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 | PATCH | Ensure password expiration warning days is 7 or more | set login.defs" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^PASS_WARN_AGE' - line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}" - - - name: "5.6.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | Get existing users WARN_DAYS" - ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass['warn_age'] }} {print $1}' /etc/shadow" - changed_when: false - failed_when: false - register: discovered_warn_days - - - name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Set existing users WARN_DAYS" - ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" - loop: "{{ discovered_warn_days.stdout_lines }}" - when: - - discovered_warn_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout - - rhel9cis_force_user_warnage - when: - - rhel9cis_rule_5_6_1_3 - tags: - - level1-server - - level1-workstation - - 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 | Check current settings" - ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_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 {{ rhel9cis_inactivelock.lock_days }} - when: rhel9cis_5_6_1_4_inactive_settings.stdout | length == 0 - - - 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: rhel9cis_5_6_1_4_user_list - - - 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 {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" - loop: "{{ rhel9cis_5_6_1_4_user_list.stdout_lines }}" - when: item in discovered_interactive_usernames.stdout - when: - - rhel9cis_rule_5_6_1_4 - tags: - - level1-server - - level1-workstation - - 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: rhel9cis_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>{{ rhel9cis_5_6_1_5_currentut.stdout }})print$1}'" - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_5_6_1_5_user_list - - - 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: {{ rhel9cis_5_6_1_5_user_list.stdout_lines }}" - when: - - rhel9cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel9cis_futurepwchgdate_autofix - - - name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: - - rhel9cis_5_6_1_5_user_list.stdout | length > 0 - - not rhel9cis_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: - - rhel9cis_5_6_1_5_user_list.stdout | length > 0 - - rhel9cis_futurepwchgdate_autofix - loop: "{{ rhel9cis_5_6_1_5_user_list.stdout_lines }}" - vars: - warn_control_id: '5.6.1.5' - when: - - rhel9cis_rule_5_6_1_5 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.6.1.5 From abc363f3b36cb9fdd47fb32d0656cf3c0ec71974 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 6 Aug 2024 17:29:06 +0100 Subject: [PATCH 029/327] Initial Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.1.x.yml | 193 +++++++++++++++++++++++++ tasks/section_5/cis_5.4.2.x.yml | 243 ++++++++++++++++++++++++++++++++ tasks/section_5/cis_5.4.3.x.yml | 62 ++++++++ 3 files changed, 498 insertions(+) create mode 100644 tasks/section_5/cis_5.4.1.x.yml create mode 100644 tasks/section_5/cis_5.4.2.x.yml create mode 100644 tasks/section_5/cis_5.4.3.x.yml diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml new file mode 100644 index 0000000..fb30e24 --- /dev/null +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -0,0 +1,193 @@ +--- + +- name: "5.4.1.1 | PATCH | Ensure password expiration is configured" + when: + - rhel9cis_rule_5_4_1_1 + tags: + - level1-server + - level1-workstation + - patch + - password + - rule_5.4.1.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.4.1.1 | PATCH | Ensure password expiration is configured" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MAX_DAYS' + line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}" + + - name: "5.4.1.1 | AUDIT | Ensure password expiration is configured | Get existing users PASS_MAX_DAYS" + ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass['max_days'] }} || $5< {{ rhel9cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_max_days + + - name: "5.4.1.1 | PATCH | Ensure password expiration is configured | Set existing users PASS_MAX_DAYS" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ rhel9cis_pass['max_days'] }}" + loop: "{{ discovered_max_days.stdout_lines }}" + when: + - discovered_max_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - rhel9cis_force_user_maxdays + +- name: "5.4.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" + when: + - rhel9cis_rule_5_4_1_2 + tags: + - level2-server + - level2-workstation + - patch + - password + - rule_5.4.1.2 + block: + - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_MIN_DAYS' + line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}" + + - name: "5.4.1.2 | AUDIT | Ensure minimum password days is configured | Get existing users PASS_MIN_DAYS" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass['min_days'] }} {print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_min_days + + - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" + ansible.builtin.user: + name: "{{ item }}" + password_expire_max: "{{ rhel9cis_pass['min_days'] }}" + loop: "{{ discovered_min_days.stdout_lines }}" + when: + - discovered_min_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - rhel9cis_force_user_mindays + +- name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" + when: + - rhel9cis_rule_5_4_1_3 + tags: + - level1-server + - level1-workstation + - patch + - password + - rule_5.4.1.3 + block: + - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | set login.defs" + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^PASS_WARN_AGE' + line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}" + + - name: "5.4.1.3 | AUDIT | Ensure password expiration warning days is configured | Get existing users WARN_DAYS" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass['warn_age'] }} {print $1}' /etc/shadow" + changed_when: false + failed_when: false + register: discovered_warn_days + + - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" + ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + loop: "{{ discovered_warn_days.stdout_lines }}" + when: + - discovered_warn_days.stdout_lines | length > 0 + - item in discovered_interactive_usernames.stdout + - rhel9cis_force_user_warnage + +- name: "5.4.1.4 | PATCH | Ensure strong password hashing algorithm is configured" + when: + - rhel9cis_rule_5_4_1_4 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.4.1.4 + - pam + - NIST800-53R5_IA-5 + ansible.builtin.lineinfile: + path: /etc/login.defs + regexp: '^ENCRYPT_METHOD' + line: 'ENCRYPT_METHOD {{ rhel9cis_passwd_hash_algo | upper }}' + +- name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured" + when: + - rhel9cis_rule_5_4_1_5 + tags: + - level1-server + - level1-workstation + - patch + - password + - rule_5.4.1.5 + block: + - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | Check current settings" + ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_5_4_1_5_inactive_settings + + - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting" + ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} + when: rhel9cis_5_4_1_5_inactive_settings.stdout | length == 0 + + - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | 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: rhel9cis_5_4_1_5_user_list + + - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Apply Inactive setting to existing accounts" + ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" + loop: "{{ rhel9cis_5_4_1_5_user_list.stdout_lines }}" + when: item in discovered_interactive_usernames.stdout + +- name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past" + when: + - rhel9cis_rule_5_4_1_6 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.4.1.6 + vars: + warn_control_id: '5.4.1.6' + block: + - name: "5.4.1.6 | 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: rhel9cis_5_4_1_6_currentut + + - name: "5.4.1.6 | 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>{{ rhel9cis_5_4_1_6_currentut.stdout }})print$1}'" + changed_when: false + failed_when: false + check_mode: false + register: rhel9cis_5_4_1_6_user_list + + - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" + when: + - rhel9cis_5_4_1_6_user_list.stdout | length > 0 + - not rhel9cis_futurepwchgdate_autofix + ansible.builtin.debug: + msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel9cis_5_4_1_5_user_list.stdout_lines }}" + + - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count" + when: + - rhel9cis_5_4_1_6_user_list.stdout | length > 0 + - not rhel9cis_futurepwchgdate_autofix + ansible.builtin.import_tasks: + file: warning_facts.yml + + - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future" + when: + - rhel9cis_5_4_1_6_user_list.stdout | length > 0 + - rhel9cis_futurepwchgdate_autofix + ansible.builtin.shell: passwd --expire {{ item }} + loop: "{{ rhel9cis_5_4_1_6_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml new file mode 100644 index 0000000..d22e4d0 --- /dev/null +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -0,0 +1,243 @@ +--- + +- name: "5.4.2.1 | PATCH | Ensure root is the only UID 0 account" + when: + - rhel9cis_rule_5_4_2_1 + - prelim_uid_zero_accounts_except_root.rc + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - accounts + - users + - rule_5.4.2.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.shell: passwd -l {{ item }} + changed_when: false + failed_when: false + loop: "{{ prelim_uid_zero_accounts_except_root.stdout_lines }}" + +- name: "5.4.2.2 | PATCH | Ensure root is the only GID 0 account" + when: + - rhel9cis_rule_5_4_2_2 + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - rule_5.4.2.2 + - user + - system + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.4.2.2 | AUDIT | Ensure root is the only GID 0 account | Get members of gid 0" + ansible.builtin.shell: "awk -F: '($1 !~ /^(sync|shutdown|halt|operator)/ && $4==\"0\") {print $1}' /etc/passwd | grep -wv 'root'" + register: discovered_gid0_members + changed_when: false + failed_when: discovered_gid0_members.rc not in [ 0, 1 ] + + - name: "5.4.2.2 | PATCH | Ensure root is the only GID 0 account | Remove users not root from gid 0" + when: + - discovered_gid0_members is defined + - discovered_gid0_members.stdout | length > 0 + ansible.builtin.user: + name: "{{ item }}" + gid: 0 + state: absent + loop: + - discovered_gid0_members.stdout_lines + +- name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group" + when: + - rhel9cis_rule_5_4_2_3 + tags: + - level1-server + - level1-workstation + - patch + - rule_5.4.2.2 + - user + - system + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group | Get groups with gid 0" + ansible.builtin.shell: "awk -F: '$3==\"0\"{print $1}' /etc/group | grep -vw 'root'" + register: discovered_gid0_groups + changed_when: false + failed_when: discovered_gid0_groups.rc not in [ 0, 1 ] + + - name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group | Warning if others gid 0 groups" + when: + - discovered_gid0_groups is defined + - discovered_gid0_groups.stdout | length > 0 + ansible.builtin.debug: + msg: + - "Warning!! You have other groups assigned to GID 0 - Please resolve" + - "{{ discovered_gid0_groups.stdout_lines }}" + + - name: "5.4.2.3 | WARN | Ensure group root is the only GID 0 group | warn_count" + when: + - discovered_gid0_groups is defined + - discovered_gid0_groups.stdout | length > 0 + ansible.builtin.import_tasks: + file: warning_facts.yml + vars: + warn_control_id: '5.4.2.3' + +- name: "5.4.2.4 | PATCH | Ensure root account access is controlled" + when: + - rhel9cis_rule_5_4_2_4 + tags: + - level1-server + - level1-workstation + - patch + - shadow_suite + - rule_5.4.2.4 + ansible.builtin.debug: + msg: "This is set as an assert in tasks/main" + +- name: "5.4.2.5 | PATCH | Ensure root PATH Integrity" + when: + - rhel9cis_rule_5_4_2_5 + tags: + - level1-server + - level1-workstation + - patch + - paths + - rule_5.4.2.5 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + block: + - name: "5.4.2.5 | 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: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Get root paths" + when: discovered_root_paths is defined + ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 | tr ":" "\n" + changed_when: false + register: discovered_root_paths_split + + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Set fact" + when: discovered_root_paths is defined + ansible.builtin.set_fact: + root_paths: "{{ discovered_root_paths.stdout }}" + + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" + when: discovered_root_paths is defined + 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: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for trailing ':'" + when: discovered_root_paths is defined + 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: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions" + when: discovered_root_paths is defined + block: + - name: "5.4.2.5 | 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: "5.4.2.5 | 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 rhel9cis_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: "5.4.2.6 | PATCH | Ensure root user umask is configured" + when: + - rhel9cis_rule_5_4_2_6 + tags: + - level1-server + - level1-workstation + - patch + - shadow_suite + - rule_5.4.2.6 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.lineinfile: + path: /root/.bash_profile + regexp: \s*umask + line: "umask {{ rhel9cis_root_umask }}" + create: true + +- name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" + when: + - rhel9cis_rule_5_4_2_7 + - "item.id not in prelim_interactive_usernames.stdout" + - "'root' not in item.id" + - rhel9cis_disruption_high + tags: + - level1-server + - level1-workstation + - patch + - shadow_suite + - rule_5.4.2.7 + - NIST800-53R5_AC-2 + - NIST800-53R5_AC-3 + - NIST800-53R5_AC-11 + - NIST800-53R5_MP-2 + ansible.builtin.user: + name: "{{ item.id }}" + shell: /usr/sbin/nologin + loop: "{{ rhel9cis_passwd }}" + loop_control: + label: "{{ item.id }}" + +- name: "5.4.2.8 | PATCH | Ensure accounts without a valid login shell are locked | Lock accounts" + when: + - rhel9cis_rule_5_4_2_8 + - rhel9cis_disruption_high + - "item.id not in prelim_interactive_usernames.stdout" + - "'root' not in item.id" + tags: + - level1-server + - level1-workstation + - patch + - shadow_suite + - rule_5.4.2.8 + - NIST800-53R5_AC-2 + - NIST800-53R5_AC-3 + - NIST800-53R5_AC-11 + - NIST800-53R5_MP-2 + ansible.builtin.user: + name: "{{ item.id }}" + password_lock: true + loop: "{{ rhel9cis_passwd }}" + loop_control: + label: "{{ item.id }}" diff --git a/tasks/section_5/cis_5.4.3.x.yml b/tasks/section_5/cis_5.4.3.x.yml new file mode 100644 index 0000000..15e8e12 --- /dev/null +++ b/tasks/section_5/cis_5.4.3.x.yml @@ -0,0 +1,62 @@ +--- + +- name: "5.4.3.1 | PATCH | Ensure nologin is not listed in /etc/shells" + when: + - rhel9cis_rule_5_4_3_1 + tags: + - level2-server + - level2-workstation + - patch + - shells + - rule_5.4.3.1 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 + ansible.builtin.replace: + path: /etc/shells + regexp: nologin + replace: "" + +- name: "5.4.3.2 | PATCH | Ensure default user shell timeout is configured" + when: + - rhel9cis_rule_5_4_3_2 + tags: + - level1-server + - level1-workstation + - patch + - shell + - rule_5.4.3.2 + ansible.builtin.blockinfile: + path: "{{ item.path }}" + state: "{{ item.state }}" + marker: "# {mark} - CIS benchmark - Ansible-lockdown" + create: true + mode: '0644' + block: | + TMOUT={{ rhel9cis_shell_session_timeout }} + readonly TMOUT + export TMOUT + loop: + - { path: "{{ rhel9cis_shell_session_file }}", state: present } + - { path: /etc/profile, state: "{{ (rhel9cis_shell_session_file == '/etc/profile') | ternary('present', 'absent') }}" } + +- name: "5.4.3.3 | PATCH | Ensure default user umask is configured" + when: + - rhel9cis_rule_5_4_3_3 + tags: + - level1-server + - level1-workstation + - patch + - umask + - rule_5.4.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + ansible.builtin.replace: + path: "{{ item.path }}" + regexp: (?i)(umask\s+\d\d\d) + replace: '{{ item.line }} {{ rhel9cis_bash_umask }}' + loop: + - { path: '/etc/profile', line: 'umask' } + - { path: '/etc/login.defs', line: 'UMASK' } From 7c2a6a2a89878f40e2160c65c321936f6402fde0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 6 Aug 2024 17:34:08 +0100 Subject: [PATCH 030/327] removed jmespath dependency Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.4.1.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index b86b014..68799c8 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -21,7 +21,7 @@ - discovered_logfiles.stdout_lines | length > 0 - discovered_logfiles is defined ansible.builtin.set_fact: - discovered_logfiles_flattened: "{{ discovered_logfiles | json_query('stdout_lines[*]') | flatten }}" # noqa: jinja[invalid] + discovered_logfiles_flattened: "{{ discovered_logfiles.stdout_lines | flatten }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" when: From 0fc418a222c0b2605ab175998f89409c1a8f54ae Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 10:29:03 +0100 Subject: [PATCH 031/327] v2 improvements Signed-off-by: Mark Bolwell --- defaults/main.yml | 298 +++++++++++++---------- tasks/section_5/cis_5.1.x.yml | 14 +- tasks/section_5/cis_5.3.1.x.yml | 2 +- tasks/section_5/cis_5.3.3.1.x.yml | 67 ++++- tasks/section_5/cis_5.3.3.2.x.yml | 155 ++++++++++++ tasks/section_5/cis_5.3.3.3.x.yml | 56 ++++- tasks/section_5/cis_5.3.3.4.x.yml | 77 +++++- tasks/section_5/cis_5.4.1.x.yml | 56 ++--- tasks/section_5/cis_5.4.2.x.yml | 7 +- tasks/section_5/cis_5.4.3.x.yml | 2 +- tasks/section_5/cis_5.4.x.yml | 89 ------- tasks/section_5/cis_5.5.x.yml | 135 ---------- tasks/section_5/cis_5.5.x_authselect.yml | 144 ----------- tasks/section_5/cis_5.6.x.yml | 149 ------------ 14 files changed, 542 insertions(+), 709 deletions(-) delete mode 100644 tasks/section_5/cis_5.4.x.yml delete mode 100644 tasks/section_5/cis_5.5.x.yml delete mode 100644 tasks/section_5/cis_5.5.x_authselect.yml delete mode 100644 tasks/section_5/cis_5.6.x.yml diff --git a/defaults/main.yml b/defaults/main.yml index 2029bd4..04f8f71 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -35,10 +35,11 @@ rhel9cis_disruption_high: false # If you do not want the tasks from that section to get executed you simply set the variable to "false". rhel9cis_section1: true rhel9cis_section2: true -rhel9cis_section3: false -rhel9cis_section4: false -rhel9cis_section5: false -rhel9cis_section6: false +rhel9cis_section3: true +rhel9cis_section4: true +rhel9cis_section5: true +rhel9cis_section6: true +rhel9cis_section7: true # This is used for audit purposes to run only specific level use the tags # e.g. @@ -343,6 +344,7 @@ rhel9cis_rule_5_1_18: true rhel9cis_rule_5_1_19: true rhel9cis_rule_5_1_20: true rhel9cis_rule_5_1_21: true +rhel9cis_rule_5_1_22: true ## 5.2 Configure Privilege Escalation rhel9cis_rule_5_2_1: true rhel9cis_rule_5_2_2: true @@ -360,6 +362,7 @@ rhel9cis_rule_5_3_2_1: true rhel9cis_rule_5_3_2_2: true rhel9cis_rule_5_3_2_3: true rhel9cis_rule_5_3_2_4: true +rhel9cis_rule_5_3_2_5: true # 5.3.3.1 Configure pam_faillock module rhel9cis_rule_5_3_3_1_1: true rhel9cis_rule_5_3_3_1_2: true @@ -635,6 +638,8 @@ rhel9cis_chrony_server_minsources: 2 # Mask # - false - leaves service in current status # - true - sets service name to masked +# +# Setting both Service and Mask to false will remove the package if exists rhel9cis_autofs_services: false rhel9cis_autofs_mask: true rhel9cis_avahi_server: false @@ -696,13 +701,19 @@ rhel9cis_tftp_client: false # Mask # - false - leaves service in current status # - true - sets service name to masked +# +# Setting both Service and Mask to false will remove the package if exists +# rhel9cis_bluetooth_service: false -rhel9cis_bluetooth_mask: true +rhel9cis_bluetooth_mask: false ## 3.1 IPv6 requirement toggle # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: true +## 3.1.2 wireless network requirements +# if wireless adapetr found allow network manager to be installed +rhel9cis_install_network_manager: false # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules # concerned with acceptance and routing of packages are skipped. @@ -766,7 +777,7 @@ rhel9cis_sshd_allowusers: "{% if ansible_facts.user_id != 'root' %}{{ ansible_fa # (String) This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access # for users whose primary group or supplementary group list matches one of the patterns. This is done # by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. -# rhel9cis_sshd_allowgroups: "wheel" +rhel9cis_sshd_allowgroups: "" # This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access # for users whose user name matches one of the patterns. This is done @@ -818,7 +829,7 @@ rhel9cis_ssh_loglevel: INFO # number, error messages will be written to the syslog file detailing the login failure. rhel9cis_ssh_maxauthtries: '4' -## Control 5.1.7 MaxStartups +## Control 5.1.17 MaxStartups # The MaxStartups parameter specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. rhel9cis_ssh_maxstartups: '10:30:60' @@ -866,53 +877,62 @@ rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD # - 5.5.3 - Ensure password reuse is limited # - 5.5.4 - Ensure password hashing algorithm is SHA-512 # - 5.4.2 - Ensure authselect includes with-faillock -rhel9cis_pam_faillock: - # - 5.3.3.1.1 - # This variable sets the amount of tries a password can be entered, before a user is locked. - deny: 5 - # - 5.3.3.1.2 - # This variable sets the amount of time a user will be unlocked after the max amount of - # password failures. - unlock_time: 900 - # This variable represents the number of password change cycles, after which - # an user can re-use a password. - # CIS requires a value of 5 or more. - interval: 900 - root_unlock_time: 60 - # Choose options below for root options - root_option: even_deny_root - # root_option: "root_unlock_time = {{ root_unlock_time }}" +# - 5.3.3.1.1 +# This variable sets the amount of tries a password can be entered, before a user is locked. +rhel9cis_pam_faillock_deny: 5 +# - 5.3.3.1.2 +# This variable sets the amount of time a user will be unlocked after the max amount of +# password failures. +rhel9cis_pam_faillock_unlock_time: 900 +# This variable represents the number of password change cycles, after which +# an user can re-use a password. +# CIS requires a value of 5 or more. +# 5.3.3.1.3 Locking even deny root or root unlock times +# rhel9cis_pamroot_lock_option options are +# even_deny_root +# root_unlock_time = {{ rhel9cis_root_unlock_time }} +rhel9cis_root_unlock_time: 60 +rhel9cis_pamroot_lock_option: even_deny_root +# rhel9cis_pamroot_lock_option: "root_unlock_time = {{ rhel9cis_root_unlock_time }}" -## Control 5.3.3.2.x - Ensure password creation requirements are configured - PAM -rhel9cis_pam_password: - # - 5.3.3.2.1 - # The pwquality difok option sets the number of characters in a password that must not - # be present in the old password. - difok: 2 - # - 5.3.3.2.2 - # minlen - Minimum acceptable size for the new password (plus one if credits are not - # disabled which is the default). Cannot be set to lower value than 6. - minlen: 14 - # - 5.3.3.2.3 - # Password complexity can be set through - # This variable set password complexity,the minimum number of - # character types that must be used (i.e., uppercase, lowercase, digits, other) - # Set to 2, passwords cannot have all lower/upper case. - # Set to 3, passwords needs numbers. - # set to 4, passwords will have to include all four types of characters. - minclass: 4 - # - 5.3.3.2.4 - # The pwquality maxrepeat option sets the maximum number of allowed same - # consecutive characters in a new password. - maxrepeat: 3 - # - 5.3.3.2.5 - # The pwquality maxsequence option sets the maximum length of monotonic character - # sequences in the new password. Examples of such sequence are 12345 or fedcb. The - # check is disabled if the value is 0. - maxseq: 3 +# 5.3.3.2.1 - password difok +rhel9cis_passwd_difok_file: etc/security/pwquality.conf.d/50-pwdifok.conf # pragma: allowlist secret +rhel9cis_passwd_difok_value: 2 + +# 5.3.3.2.2 - password minlength +rhel9cis_passwd_minlen_file: etc/security/pwquality.conf.d/50-pwlength.conf # pragma: allowlist secret +rhel9cis_passwd_minlen_value: 14 + +# 5.3.3.2.3 - password complex +rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # pragma: allowlist secret +rhel9cis_passwd_minclass: 3 +rhel9cis_passwd_dcredit: -1 +rhel9cis_passwd_ucredit: -2 +rhel9cis_passwd_ocredit: 0 +rhel9cis_passwd_lcredit: -2 + +# 5.3.3.2.4 - password maxrepeat +rhel9cis_passwd_maxrepeat_file: etc/security/pwquality.conf.d/50-pwrepeat.conf # pragma: allowlist secret +rhel9cis_passwd_maxrepeat_value: 3 + +# 5.3.3.2.5 - password maxsequence +rhel9cis_passwd_maxsequence_file: etc/security/pwquality.conf.d/50-pwmaxsequence.conf # pragma: allowlist secret +rhel9cis_passwd_maxsequence_value: 3 + +# 5.3.3.2.6 - password dictcheck +rhel9cis_passwd_dictcheck_file: etc/security/pwquality.conf.d/50-pwdictcheck.conf # pragma: allowlist secret +rhel9cis_passwd_dictcheck_value: 1 + +# 5.3.3.2.7 - password quality enforce +rhel9cis_passwd_quality_enforce_file: etc/security/pwquality.conf.d/50-pwquality_enforce.conf # pragma: allowlist secret +rhel9cis_passwd_quality_enforce_value: 1 + +# 5.3.3.2.8 - password quality enforce for root included with 5.3.3.2.7 +rhel9cis_passwd_quality_enforce_root_file: etc/security/pwquality.conf.d/50-pwroot.conf # pragma: allowlist secret +rhel9cis_passwd_quality_enforce_root_value: enforce_for_root # pragma: allowlist secret # 5.3.3.4.x -rhel9cis_passwd_hash_algo: sha512 +rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret ## Section 5.4.1.x: Shadow Password Suite Parameters rhel9cis_pass: @@ -952,33 +972,26 @@ rhel9cis_force_user_warnage: false # to 'false' will just display users in violation, while 'true' will expire those users passwords. rhel9cis_futurepwchgdate_autofix: true -## Section 5.4 - Configure authselect: Custom authselect profile settings(name, profile to customize, options) -## Controls: -# - 5.4.1 - Ensure custom authselect profile is used('custom_profile_name', 'default_file_to_copy' subsettings) -# - 5.4.2 - Ensure authselect includes with-faillock | with auth select profile('custom_profile_name') -# Settings in place now will fail, they are placeholders 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. -rhel9cis_authselect: - # This variable configures the name of the custom profile to be created and selected. - custom_profile_name: custom-profile - # This variable configures the ID of the existing profile that should be used as a base for the new profile. - default_file_to_copy: "sssd --symlink-meta" - options: with-sudo with-faillock without-nullok with-pwhistory - -## Control 5.4.1 - Ensure custom authselect profile is used -# This variable governs if an authselect custom profile should be automatically created, by copying and -# customizing one of the default profiles. The default profiles include: sssd, winbind, or the nis. This profile can then be -# customized to follow site specific requirements. -rhel9cis_authselect_custom_profile_create: false - -## Control 5.4.2 - Ensure authselect includes with-faillock | Create custom profiles -# This variable governs if the existing custom profile should be selected(Note: please keep in mind that all future updates -# to the PAM templates and meta files in the original profile will be reflected in your custom profile, too.) -rhel9cis_authselect_custom_profile_select: false - # 5.4.2.x rhel9cis_root_umask: '0027' # 0027 or more restrictive +## Control 5.4.3.2 - Configuring user shell timeout +# This dictionary is related to ensuring the rule about user shell timeout +# This variable represents the amount of seconds a command or process is allowed to +# run before being forcefully terminated. +# CIS requires a value of at most 900 seconds. +rhel9cis_shell_session_timeout: 900 +# This variable specifies the path of the timeout setting file. +# (TMOUT setting can be set in multiple files, but only one is required for the +# rule to pass. Options are: +# - a file in `/etc/profile.d/` ending in `.s`, +# - `/etc/profile`, or +# - `/etc/bash.bashrc`. +rhel9cis_shell_session_file: /etc/profile.d/tmout.sh + +## Control 5.4.3.2 bash umask +rhel9cis_bash_umask: '0027' # 0027 or more restrictive + ### Controls: # - 5.6.2 - Ensure system accounts are secured # - 6.2.10 - Ensure local interactive user home directories exist @@ -991,29 +1004,13 @@ rhel9cis_discover_int_uid: true # been set to `true`. min_int_uid: 1000 ### Controls: -# - 6.2.10 - Ensure local interactive user home directories exist -# - 6.2.11 - Ensure local interactive users own their home directories +# - Ensure local interactive user home directories exist +# - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID # Note that the value will be dynamically overwritten if variable `dicover_int_uid` has # been set to `true`. max_int_uid: 65533 -## Control 5.6.3 - Ensure default user shell timeout is 900 seconds or less -# Session timeout setting file (TMOUT setting can be set in multiple files) -# Timeout value is in seconds. (60 seconds * 10 = 600) -rhel9cis_shell_session_timeout: - # This variable specifies the path of the timeout setting file. - # (TMOUT setting can be set in multiple files, but only one is required for the - # rule to pass. Options are: - # - a file in `/etc/profile.d/` ending in `.s`, - # - `/etc/profile`, or - # - `/etc/bash.bashrc`. - file: /etc/profile.d/tmout.sh - # This variable represents the amount of seconds a command or process is allowed to - # run before being forcefully terminated. - # CIS requires a value of at most 900 seconds. - timeout: 600 - ## Section6 vars ## Control 6.1.1 - allow aide to be configured @@ -1118,23 +1115,6 @@ rhel9cis_remote_log_retrycount: 100 # of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). rhel9cis_remote_log_queuesize: 1000 -## Control 6.2.3.8 rsyslog log rotate option -# These variable allow you to change accordint to site policy settings -# When to rotate options: hourly, daily, weekly, monthly, yearly -rhel9cis_rsyslog_logrotate_rotated: weekly -# Number of backlog files to keep -rhel9cis_rsyslog_logrotate_keep: 4 -# compress file once rotated, false will not compress -rhel9cis_rsyslog_logrotate_compress: true -# If the log file is missing, go on to the next one without issuing an error message -rhel9cis_rsyslog_logrotate_missingok: -# Dont rotate file if has no contents, false will still rotate -rhel9cis_rsyslog_logrotate_notifempty: true -# rhel9cis_rsyslog_logrotate_create give the options to create permissions and ownerships -# allows create iption to be used and sets options below based on mode owner group -rhel9cis_rsyslog_logrotate_create: false -rhel9cis_rsyslog_logrotate_create_opts: 0640 root root - ## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured # 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to # URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port @@ -1158,7 +1138,7 @@ rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" # ATTENTION: Uncomment the keyword below when values are set! -## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # Current variable configures the max amount of disk space the logs will use(thus, journal files # will not grow without bounds) # The variables below related to journald, please set these to your site specific values @@ -1166,18 +1146,18 @@ rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" # Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes. # See https://www.freedesktop.org/software/systemd/man/journald.conf.html for more information. rhel9cis_journald_systemmaxuse: 10M -## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # Current variable configures the amount of disk space to keep free for other uses. rhel9cis_journald_systemkeepfree: 100G -## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # This variable configures how much disk space the journal may use up at most. # Similar with 'rhel9cis_journald_systemmaxuse', but related to runtime space. rhel9cis_journald_runtimemaxuse: 10M -## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # This variable configures the actual amount of disk space to keep free # Similar with 'rhel9cis_journald_systemkeepfree', but related to runtime space. rhel9cis_journald_runtimekeepfree: 100G -## Control 6.2.2.6 - Ensure journald log rotation is configured per site policy +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # Current variable governs the settings for log retention(how long the log files will be kept). # Thus, it specifies the maximum time to store entries in a single journal # file before rotating to the next one. Set to 0 to turn off this feature. @@ -1187,7 +1167,7 @@ rhel9cis_journald_runtimekeepfree: 100G # ATTENTION: Uncomment the keyword below when values are set! rhel9cis_journald_maxfilesec: 1month -# Control 6.3.1.3 - Ensure rhel9cis_audit_back_log_limit is sufficient +## Control 6.3.2.1 - Ensure audit_backlog_limit is sufficient # This variable represents the audit backlog limit, i.e., the maximum number of audit records that the # system can buffer in memory, if the audit subsystem is unable to process them in real-time. # Buffering in memory is useful in situations, where the audit system is overwhelmed @@ -1195,21 +1175,91 @@ rhel9cis_journald_maxfilesec: 1month # This variable should be set to a sufficient value. The CIS baseline recommends at least `8192` as value. rhel9cis_audit_back_log_limit: 8192 -## Advanced option found in auditd post and used in tempate 98_auditd_exceptions.rules.j2 +## Controls 6.3.2.x - What to do when log files fill up +## Control 6.3.2.1 - Ensure audit log storage size is configured +# This variable specifies the maximum size in MB that an audit log file can reach +# before it is archived or deleted to make space for the new audit data. +# This should be set based on your sites policy. CIS does not provide a specific value. +rhel9cis_auditd_max_log_file_size: 10 + +## Control 6.3.2.2 +# This variable determines what action the audit system should take when the maximum +# size of a log file is reached. +# The options for setting this variable are as follows: +# - `ignore`: the system does nothing when the size of a log file is full; +# - `syslog`: a message is sent to the system log indicating the problem; +# - `suspend`: the system suspends recording audit events until the log file is cleared or rotated; +# - `rotate`: the log file is rotated (archived) and a new empty log file is created; +# - `keep_logs`: the system attempts to keep as many logs as possible without violating disk space constraints. +# CIS prescribes the value `keep_logs`. +rhel9cis_auditd_max_log_file_action: keep_logs + +## Control 6.3.2.3 +# This variable determines how the system should act in case of issues with disk +# The disk_full_action parameter tells the system what action to take when no free space is available on the partition that holds the audit log files. +# Valid values are ignore, syslog, rotate, exec, suspend, single, and halt. +# +# The disk_error_action parameter tells the system what action to take when an error is detected on the partition that holds the audit log files. +# Valid values are ignore, syslog, exec, suspend, single, and halt. +# +# CIS prescribes +# disk_full_action parameter: +# Set to halt - the auditd daemon will shutdown the system when the disk partition containing the audit logs becomes full. +# Set to single - the auditd daemon will put the computer system in single user mode when the disk partition containing the audit logs becomes full. +# +# disk_error_action parameter: +# Set to halt - the auditd daemon will shutdown the system when an error is detected on the partition that holds the audit log files. +# Set to single - the auditd daemon will put the computer system in single user mode when an error is detected on the partition that holds the audit log files. +# Set to syslog - the auditd daemon will issue no more than 5 consecutive warnings to syslog when an error is detected on the partition that holds the audit log files. +rhel9cis_auditd_disk_full_action: halt +rhel9cis_auditd_disk_error_action: syslog + +# Control 6.3.2.4 +# Wait to do when space left is low. +# The space_left_action parameter tells the system what action to take when the system has detected that it is starting to get low on disk space. +# Valid values are ignore, syslog, rotate, email, exec, suspend, single, and halt. +# The admin_space_left_action parameter tells the system what action to take when the system has detected that it is low on disk space. +# Valid values are ignore, syslog, rotate, email, exec, suspend, single, and halt. +rhel9cis_auditd_space_left_action: email +rhel9cis_auditd_admin_space_left_action: halt + +# This value governs if the below extra-vars for auditd should be used by the role +rhel9cis_auditd_extra_conf_usage: false + +# 6.3.3.x allow exceptions for UID in auditd config +## Advanced option found in auditd post # This variable governs if defining user exceptions for auditd logging is acceptable. rhel9cis_allow_auditd_uid_user_exclusions: false # This variable contains a list of uids to be excluded(users whose actions are not logged by auditd) rhel9cis_auditd_uid_exclude: - 1999 +# This can be used to configure other keys in auditd.conf +# Example: +rhel9cis_auditd_extra_conf: + admin_space_left: '10%' + # Section 7 Vars -## Control 6.1.9 - Ensure no world writable files exist +# 7.1.12 Ensure no files or directories without an owner and a group exist +rhel9cis_exclude_unowned_search_path: (! -path "/run/user/*" -a ! -path "/proc/*" -a ! -path "*/containerd/*" -a ! -path "*/kubelet/pods/*" -a ! -path "*/kubelet/plugins/*" -a ! -path "/sys/fs/cgroup/memory/*" -a ! -path "/var/*/private/*") + +# Control 7.1.12 +# The value of this variable specifies the owner that will be set for unowned files and directories. +rhel9cis_unowned_owner: root +rhel9cis_ungrouped_group: root +# This variable is a toggle for enabling/disabling the automated +# setting of an owner (specified in variable `rhel9cis_unowned_owner`) +# for all unowned files and directories. +# Possible values are `true` and `false`. +rhel9cis_ownership_adjust: true + +## Control 7.1.13 +# This variable is a toggle for enabling/disabling the automated removal +# of the SUID bit from all files on all mounts. +# Possible values are `true` and `false`. +rhel9cis_suid_sgid_adjust: false + +## Control 7.1.11 - Ensure no world writable files exist # Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable. rhel9cis_no_world_write_adjust: true - -## Control 6.2.16 - Ensure local interactive user dot files are not group or world writable -# This boolean variable governs if current role should follow filesystem links for changes to -# user home directory. -rhel_09_6_2_16_home_follow_symlinks: false -# thanks to @dulin-gnet and community for rhel9-cis feedback. diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 0b4c63f..62c3af9 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -194,7 +194,7 @@ notify: Restart sshd - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denyusers" - when: "rhel9cis_sshd_denyusers'|default('') | length > 0" + when: "rhel9cis_sshd_denyusers | length > 0" ansible.builtin.lineinfile: path: "{{ rhel9_cis_sshd_config_file }}" regexp: "^DenyUsers" @@ -203,7 +203,7 @@ notify: Restart sshd - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denygroups" - when: "rhel9cis_sshd_denygroups|default('') | length > 0" + when: "rhel9cis_sshd_denygroups | length > 0" ansible.builtin.lineinfile: path: "{{ rhel9_cis_sshd_config_file }}" regexp: "^DenyGroups" @@ -500,17 +500,17 @@ - name: "5.1.22 | PATCH | Ensure SSH PAM is enabled" when: - rhel9cis_rule_5_1_22 - - NIST800-53R5_CM-1 - - NIST800-53R5_CM-2 - - NIST800-53R5_CM-6 - - NIST800-53R5_CM-7 - - NIST800-53R5_IA-5 tags: - level1-server - level1-workstation - patch - ssh - rule_5.1.22 + - NIST800-53R5_CM-1 + - NIST800-53R5_CM-2 + - NIST800-53R5_CM-6 + - NIST800-53R5_CM-7 + - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9_cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*MaxStartupsUsePAM diff --git a/tasks/section_5/cis_5.3.1.x.yml b/tasks/section_5/cis_5.3.1.x.yml index 050a081..b8a5576 100644 --- a/tasks/section_5/cis_5.3.1.x.yml +++ b/tasks/section_5/cis_5.3.1.x.yml @@ -42,7 +42,7 @@ - name: "5.3.1.3 | PATCH | Ensure libpwquality is installed" when: - rhel9cis_rule_5_3_1_3 - - ansible_facts.packages['libpwquality'][0]['version'] is version('1.4.4-8', '<') + - ansible_facts.packages['libpwquality'][0]['version'] is version('1.4.4-8', '<') or "'libpwquality' not in ansible_facts.packages" tags: - level1-server diff --git a/tasks/section_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 67b8763..8206074 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -2,7 +2,7 @@ - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" when: - - rhel8cis_rule_5_3_3_1_1 + - rhel9cis_rule_5_3_3_1_1 tags: - level1-server - level1-workstation @@ -16,10 +16,12 @@ path: /etc/security/faillock.conf state: present regexp: '^(#|)\s*deny\s*=\s*\d' - line: "deny = {{ rhel8cis_pam_faillock['deny'] }}" + line: "deny = {{ rhel9cis_pam_faillock_deny }}" - - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | pam_files" - when: not rhel8cis_allow_authselect_updates + - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | remove deny from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high 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+(.*$) @@ -28,9 +30,22 @@ - password - system + - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | remove deny from AuthSelect config" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_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 + notify: Authselect update + - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured" when: - - rhel8cis_rule_5_3_3_1_2 + - rhel9cis_rule_5_3_3_1_2 tags: - level1-server - level1-workstation @@ -44,10 +59,12 @@ path: /etc/security/faillock.conf state: present regexp: '^(#|)\s*unlock_time\s*=\s*\d' - line: "unlock_time = {{ rhel8cis_pam_faillock['unlock_time'] }}" + line: "unlock_time = {{ rhel9cis_pam_faillock_unlock_time }}" - - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | pam_files" - when: not rhel8cis_allow_authselect_updates + - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | remove unlock from pam files NOT AuthSelect" + when: + - rhel9cis_disruption_high + - not rhel9cis_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+(.*$) @@ -56,6 +73,19 @@ - password - system + - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | remove unlock from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_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 + notify: Authselect update + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" when: - rhel9cis_rule_5_3_3_1_3 @@ -71,12 +101,14 @@ ansible.builtin.lineinfile: path: /etc/security/faillock.conf regexp: '^{{ rhel9cis_pamroot_lock_option }}' - line: "{{ rhel9cis_pamroot_lock_string }}" + line: "{{ rhel9cis_pamroot_lock_option }}" insertafter: '^# end of pam-auth-update config' create: true - - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | pam_files" - when: not rhel9cis_allow_authselect_updates + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files NOT AuthSelect" + when: + - rhel9cis_disruption_high + - not rhel9cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/pam.d/{{ item }}-auth" regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$) @@ -84,3 +116,16 @@ loop: - password - system + + - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$) + replace: \1\2\4 + loop: + - password + - system + notify: Authselect update diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index 931f867..9317326 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -14,6 +14,7 @@ - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from conf files except expected file" when: - item != rhel9cis_passwd_difok_file + - rhel9cis_disruption_high ansible.builtin.replace: path: "{{ item }}" regexp: 'difok\s*=\s*\d+\b' @@ -31,6 +32,31 @@ group: root mode: '0600' + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from pam files Not AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdifok=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdifok=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.2 | PATCH | Ensure password length is configured" when: - rhel9cis_rule_5_3_3_2_2 @@ -45,6 +71,7 @@ - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from conf files except expected file" when: - item != rhel9cis_passwd_minlen_file + - rhel9cis_disruption_high ansible.builtin.replace: path: "{{ item }}" regexp: 'minlen\s*=\s*\d+\b' @@ -62,6 +89,31 @@ group: root mode: '0600' + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sminlen=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sminlen=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured" when: - rhel9cis_rule_5_3_3_2_3 @@ -76,6 +128,7 @@ - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove pwd complex settings from conf files except expected file" when: - item != rhel9cis_passwd_complex_file + - rhel9cis_disruption_high ansible.builtin.replace: path: "{{ item }}" regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' @@ -93,6 +146,31 @@ group: root mode: '0600' + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove complexity from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s(minclass=[0-3]|[dulo]credit=[^-]\d*)(.*$) + replace: \1\2\4 + loop: + - password + - system + + - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove complexity from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s(minclass=[0-3]|[dulo]credit=[^-]\d*)(.*$) + replace: \1\2\4 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured" when: - rhel9cis_rule_5_3_3_2_4 @@ -124,6 +202,31 @@ group: root mode: '0600' + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxrepeat\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxrepeat\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is is configured" when: - rhel9cis_rule_5_3_3_2_5 @@ -138,6 +241,7 @@ - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence settings from conf files except expected file" when: - item != rhel9cis_passwd_maxsequence_file + - rhel9cis_disruption_high ansible.builtin.replace: path: "{{ item }}" regexp: 'maxsequence\s*=\s*\d+\b' @@ -155,6 +259,31 @@ group: root mode: '0600' + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxsequence\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxsequence\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled" when: - rhel9cis_rule_5_3_3_2_6 @@ -186,6 +315,32 @@ group: root mode: '0600' + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdictcheck\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + + - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdictcheck\s*=\s*\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user" when: - rhel9cis_rule_5_3_3_2_7 diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index 659ea82..ffb1bff 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -3,7 +3,6 @@ - name: "5.3.3.3.1 | PATCH | Ensure password history remember is configured" when: - rhel9cis_rule_5_3_3_3_1 - - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -18,7 +17,9 @@ failed_when: rhel9_pwhistory_remember.rc not in [0, 1] - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set" - when: rhel9_pwhistory_remember.stdout | length > 0 + when: + - rhel9_pwhistory_remember.stdout | length > 0 + - not rhel9cis_allow_authselect_updates ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+)(.*)(remember=\d+) @@ -26,6 +27,31 @@ backrefs: true notify: Pam_auth_update_pwhistory + - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files NOT AuthSelect" + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/pam.d/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\sremember=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + + - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\sremember=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user" when: - rhel9cis_rule_5_3_3_3_2 @@ -38,13 +64,15 @@ - pam block: - name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files" - ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/common-password + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/{system,password}-auth register: rhel9_pwhistory_enforce_for_root changed_when: false failed_when: rhel9_pwhistory_enforce_for_root.rc not in [0, 1] - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure remember is set" - when: rhel9_pwhistory_enforce_for_root.stdout | length > 0 + when: + - not rhel9cis_allow_authselect_updates + - rhel9_pwhistory_enforce_for_root.stdout | length > 0 ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root) @@ -64,16 +92,32 @@ - pam block: - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" - ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/common-password + ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{system,password}-auth register: rhel9_pwhistory_use_authtok changed_when: false failed_when: rhel9_pwhistory_use_authtok.rc not in [0, 1] - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure remember is set" - when: rhel9_pwhistory_use_authtok.stdout | length > 0 + when: + - not rhel9cis_allow_authselect_updates + - rhel9_pwhistory_use_authtok.stdout | length > 0 ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) line: '\1\2\3 use_authtok' backrefs: true notify: Pam_auth_update_pwhistory + + - name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + - rhel9cis_disruption_high + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\suse_authtok(.*$) + line: \1\2 use_authtok\3 + backrefs: true + loop: + - password + - system + notify: Authselect update diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml index 4faedb3..89f39cc 100644 --- a/tasks/section_5/cis_5.3.3.4.x.yml +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -18,17 +18,31 @@ register: rhel9cis_pam_nullok - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | Ensure nullok removed" - when: rhel9cis_pam_nullok.stdout | length > 0 + when: + - rhel9cis_pam_nullok.stdout | length > 0 + - not rhel9cis_allow_authselect_updates ansible.builtin.replace: path: "{{ item }}" regexp: nullok replace: '' loop: "{{ rhel9cis_pam_nullok.stdout_lines }}" - notify: Pam_auth_update_pwunix + + - name: "5.3.3.4.1 | PATCH | Ensure password number of changed characters is configured | Remove nullok from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\snullok(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember" when: - rhel9cis_rule_5_3_3_4_2 + - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -37,22 +51,36 @@ - rule_5.3.3.4.2 block: - name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" - ansible.builtin.shell: grep -PH -- '^\h*^\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/common-{password,auth,account,session,session-noninteractive} | grep -Pv -- '\bremember=\d\b' + ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P -- '\bremember\b' changed_when: false failed_when: rhel9cis_pam_remember.rc not in [ 0, 1 ] register: rhel9cis_pam_remember - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Ensure remember removed" - when: rhel9cis_pam_remember.stdout | length > 0 + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_pam_remember.stdout | length > 0 ansible.builtin.replace: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" regexp: remember=\d+ replace: '' - notify: Pam_auth_update_pwunix + + - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Remove remember from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\sremember\s*=\s*=\d*(.*$) + replace: \1\2\3 + loop: + - password + - system + notify: Authselect update - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm" when: - rhel9cis_rule_5_3_3_4_3 + - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -68,16 +96,31 @@ register: rhel9cis_pam_pwhash - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Ensure hash algorithm set" - when: rhel9cis_pam_remember.stdout | length > 0 + when: + - not rhel9cis_allow_authselect_updates + - rhel9cis_pam_remember.stdout | length > 0 ansible.builtin.replace: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)" replace: '{{ rhel9cis_passwd_hash_algo }}' - notify: Pam_auth_update_pwunix + + - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Remove remember from pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)(.*$) + line: \1\2 {{ rhel9cis_passwd_hash_algo }}\4 + backrefs: true + loop: + - password + - system + notify: Authselect update - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok" when: - rhel9cis_rule_5_3_3_4_4 + - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -87,18 +130,32 @@ - NIST800-53R5_IA-5 block: - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" - ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{password,system}-auth + ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -Pv -- '\buse_authtok\b' changed_when: false failed_when: rhel9cis_pam_authtok.rc not in [ 0, 1 ] register: rhel9cis_pam_authtok - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" when: + - not rhel9cis_allow_authselect_updates - rhel9cis_pam_authtok is defined - rhel9cis_pam_authtok.stdout | length > 0 ansible.builtin.lineinfile: path: "{{ item }}" - regexp: ^(\s*password\s+[success=end.*]\s+pam_unix\.so)(.*)\s+use_authtok\s*=\s*\S+(.*$) - line: \1\2\3 use_authtok + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)use_authtok(.*$) + line: \1\2 use_authtok\3 backrefs: true loop: "{{ rhel9cis_pam_authtok.stdout_lines }}" + + - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | Add use_authtok pam files AuthSelect" + when: + - rhel9cis_allow_authselect_updates + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)use_authtok(.*$) + line: \1\2 use_authtok\3 + backrefs: true + loop: + - password + - system + notify: Authselect update diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index fb30e24..9da1ed0 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -1,6 +1,6 @@ --- -- name: "5.4.1.1 | PATCH | Ensure password expiration is configured" +- name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less" when: - rhel9cis_rule_5_4_1_1 tags: @@ -15,34 +15,34 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 block: - - name: "5.4.1.1 | PATCH | Ensure password expiration is configured" + - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less" ansible.builtin.lineinfile: path: /etc/login.defs regexp: '^PASS_MAX_DAYS' line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}" - - name: "5.4.1.1 | AUDIT | Ensure password expiration is configured | Get existing users PASS_MAX_DAYS" + - name: "5.4.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS" ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass['max_days'] }} || $5< {{ rhel9cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow" changed_when: false failed_when: false register: discovered_max_days - - name: "5.4.1.1 | PATCH | Ensure password expiration is configured | Set existing users PASS_MAX_DAYS" + - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" + when: + - discovered_max_days.stdout_lines | length > 0 + - item in prelim_interactive_usernames.stdout + - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" password_expire_max: "{{ rhel9cis_pass['max_days'] }}" loop: "{{ discovered_max_days.stdout_lines }}" - when: - - discovered_max_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout - - rhel9cis_force_user_maxdays -- name: "5.4.1.2 | PATCH | Ensure minimum days between password changes is 7 or more" +- name: "5.4.1.2 | PATCH | Ensure minimum password days is configured" when: - rhel9cis_rule_5_4_1_2 tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - patch - password - rule_5.4.1.2 @@ -60,14 +60,14 @@ register: discovered_min_days - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" + when: + - discovered_min_days.stdout_lines | length > 0 + - item in prelim_interactive_usernames.stdout + - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" password_expire_max: "{{ rhel9cis_pass['min_days'] }}" loop: "{{ discovered_min_days.stdout_lines }}" - when: - - discovered_min_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout - - rhel9cis_force_user_mindays - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" when: @@ -92,12 +92,12 @@ register: discovered_warn_days - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" - ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" - loop: "{{ discovered_warn_days.stdout_lines }}" when: - discovered_warn_days.stdout_lines | length > 0 - - item in discovered_interactive_usernames.stdout + - item in prelim_interactive_usernames.stdout - rhel9cis_force_user_warnage + ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + loop: "{{ discovered_warn_days.stdout_lines }}" - name: "5.4.1.4 | PATCH | Ensure strong password hashing algorithm is configured" when: @@ -135,16 +135,16 @@ ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} when: rhel9cis_5_4_1_5_inactive_settings.stdout | length == 0 - - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | Getting user list" + - name: "5.4.1.5 | 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: rhel9cis_5_4_1_5_user_list - - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Apply Inactive setting to existing accounts" + - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" + when: item in prelim_interactive_usernames.stdout ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" loop: "{{ rhel9cis_5_4_1_5_user_list.stdout_lines }}" - when: item in discovered_interactive_usernames.stdout - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past" when: @@ -172,22 +172,22 @@ register: rhel9cis_5_4_1_6_user_list - name: "5.4.1.6 | 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: {{ rhel9cis_5_4_1_6_user_list.stdout_lines }}" when: - rhel9cis_5_4_1_6_user_list.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix - ansible.builtin.debug: - msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel9cis_5_4_1_5_user_list.stdout_lines }}" - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count" + ansible.builtin.import_tasks: + file: warning_facts.yml when: - rhel9cis_5_4_1_6_user_list.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix - ansible.builtin.import_tasks: - file: warning_facts.yml - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future" - when: - - rhel9cis_5_4_1_6_user_list.stdout | length > 0 - - rhel9cis_futurepwchgdate_autofix ansible.builtin.shell: passwd --expire {{ item }} + when: + - rhel9cis_5_4_1_5_user_list.stdout | length > 0 + - rhel9cis_futurepwchgdate_autofix loop: "{{ rhel9cis_5_4_1_6_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index d22e4d0..4d75928 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -51,10 +51,9 @@ - discovered_gid0_members.stdout | length > 0 ansible.builtin.user: name: "{{ item }}" - gid: 0 + group: root state: absent - loop: - - discovered_gid0_members.stdout_lines + loop: "{{ discovered_gid0_members.stdout_lines }}" - name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group" when: @@ -96,7 +95,7 @@ vars: warn_control_id: '5.4.2.3' -- name: "5.4.2.4 | PATCH | Ensure root account access is controlled" +- name: "5.4.2.4 | PATCH | Ensure root account access is controlled " when: - rhel9cis_rule_5_4_2_4 tags: diff --git a/tasks/section_5/cis_5.4.3.x.yml b/tasks/section_5/cis_5.4.3.x.yml index 15e8e12..7816938 100644 --- a/tasks/section_5/cis_5.4.3.x.yml +++ b/tasks/section_5/cis_5.4.3.x.yml @@ -55,7 +55,7 @@ - NIST800-53R5_MP-2 ansible.builtin.replace: path: "{{ item.path }}" - regexp: (?i)(umask\s+\d\d\d) + regexp: (?i)(umask\s+\d*) replace: '{{ item.line }} {{ rhel9cis_bash_umask }}' loop: - { path: '/etc/profile', line: 'umask' } 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 e463998..0000000 --- a/tasks/section_5/cis_5.4.x.yml +++ /dev/null @@ -1,89 +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' - failed_when: false - changed_when: false - check_mode: false - register: rhel9cis_5_4_1_current_profile - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles" - ansible.builtin.shell: authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }} - when: - - rhel9cis_authselect_custom_profile_create - - "rhel9cis_authselect.custom_profile_name not in rhel9cis_5_4_1_current_profile.stdout" - - - name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Force custom profile creates backup" - ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} --force --backup=rhel9cis_5_4_1_{{ ansible_date_time.epoch}}" - register: authselect_5_4_1_select - when: - - rhel9cis_authselect_custom_profile_create - - "rhel9cis_authselect.custom_profile_name not in rhel9cis_5_4_1_current_profile.stdout" - - when: - - rhel9cis_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 | Get Authselect profile options" - 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: rhel9cis_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" - - "{{ rhel9cis_5_4_2_profiles_faillock.stdout_lines }}" - - - name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Authselect add options" - ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force" - when: rhel9cis_authselect_custom_profile_select - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not Authselect 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 silent deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', '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 deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', '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: - - rhel9cis_add_faillock_without_authselect - - rhel9cis_5_4_2_risks == 'ACCEPT' - - - name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not Authselect profile" - ansible.builtin.lineinfile: - path: "/etc/pam.d/system-auth" - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - insertbefore: "{{ item.before | default(omit)}}" - insertafter: "{{ item.after | default(omit)}}" - loop: - - { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line':'auth required pam_faillock.so preauth silent deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', '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 deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', '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: - - rhel9cis_add_faillock_without_authselect - - rhel9cis_5_4_2_risks == 'ACCEPT' - when: - - rhel9cis_rule_5_4_2 - tags: - - level1-server - - level1-workstation - - 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 57ad96b..0000000 --- a/tasks/section_5/cis_5.5.x.yml +++ /dev/null @@ -1,135 +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.name }} - line: "{{ item.name }} = {{ item.value }}" - loop: - - { name: minlen, value: "{{ rhel9cis_pam_password.minlen }}" } - - { name: minclass, value: "{{ rhel9cis_pam_password.minclass }}" } - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings | not Authselect" - ansible.builtin.lineinfile: - path: /etc/pam.d/system-auth - 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 ?' - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set password-auth retry settings | not Authselect" - ansible.builtin.lineinfile: - path: /etc/pam.d/password-auth - 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 ?' - when: - - rhel9cis_rule_5_5_1 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.1 - -- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured" - block: - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set faillock.conf configs" - ansible.builtin.lineinfile: - path: /etc/security/faillock.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - loop: - - { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = {{ rhel9cis_pam_faillock.deny }}' } - - { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = {{ rhel9cis_pam_faillock.unlock_time }}' } - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set preauth" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*preauth(.*)' - line: "auth required pam_faillock.so preauth silent audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}" - insertafter: 'auth\s*(sufficient|required)\s*pam_env.so$' - loop: - - "/etc/pam.d/system-auth" - - "/etc/pam.d/password-auth" - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set authfail" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*authfail(.*)' - line: "auth required pam_faillock.so authfail audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}" - insertbefore: 'auth\s*(sufficient|required)\s*pam_deny.so$' - loop: - - "/etc/pam.d/system-auth" - - "/etc/pam.d/password-auth" - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Load account faillock.so" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^account\s*(sufficient|required)\s*pam_faillock.so$' - line: "account required pam_faillock.so" - insertbefore: '^account\s*(sufficient|required)\s*pam_unix.so$' - loop: - - "/etc/pam.d/system-auth" - - "/etc/pam.d/password-auth" - when: - - rhel9cis_rule_5_5_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.2 - -- name: "5.5.3 | PATCH | Ensure password reuse is limited | pwquality" - block: - - name: "5.5.3 | PATCH | Ensure password reuse is limited | Set system-auth remember Settings" - ansible.builtin.lineinfile: - path: /etc/pam.d/system-auth - line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - - - name: "5.5.3 | PATCH | Ensure password reuse is limited | Set password-auth remember Settings" - ansible.builtin.lineinfile: - path: /etc/pam.d/password-auth - line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - when: - - rhel9cis_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 or yescrypt" - block: - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf" - ansible.builtin.replace: - path: /etc/libuser.conf - regexp: '^crypt_style\s*=\s*.*$' - replace: 'crypt_style = sha512' - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | login.defs" - ansible.builtin.replace: - path: /etc/login.defs - regexp: '^ENCRYPT_METHOD.*' - replace: 'ENCRYPT_METHOD SHA512' - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | password-auth" - ansible.builtin.replace: - path: /etc/pam.d/password-auth - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}' - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | system-auth" - ansible.builtin.replace: - path: /etc/pam.d/system-auth - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}' - when: - - rhel9cis_rule_5_5_4 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.4 diff --git a/tasks/section_5/cis_5.5.x_authselect.yml b/tasks/section_5/cis_5.5.x_authselect.yml deleted file mode 100644 index 0d1811b..0000000 --- a/tasks/section_5/cis_5.5.x_authselect.yml +++ /dev/null @@ -1,144 +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.name }} - line: "{{ item.name }} = {{ item.value }}" - loop: - - { name: minlen, value: "{{ rhel9cis_pam_password.minlen }}" } - - { name: minclass, value: "{{ rhel9cis_pam_password.minclass }}" } - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings | not Authselect" - ansible.builtin.lineinfile: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - 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 ?' - notify: Apply_authselect - - - name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set password-auth retry settings | not Authselect" - ansible.builtin.lineinfile: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - 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 ?' - notify: Apply_authselect - when: - - rhel9cis_rule_5_5_1 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.1 - -- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured" - block: - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set faillock.conf configs" - ansible.builtin.lineinfile: - path: /etc/security/faillock.conf - regexp: "{{ item.regexp }}" - line: "{{ item.line }}" - loop: - - { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = {{ rhel9cis_pam_faillock.deny }}' } - - { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = {{ rhel9cis_pam_faillock.unlock_time }}' } - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set preauth" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*preauth(.*)' - line: "auth required pam_faillock.so preauth silent audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}" - insertafter: 'auth\s*(sufficient|required)\s*pam_env.so$' - loop: - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - notify: Apply_authselect - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set authfail" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*authfail(.*)' - line: "auth required pam_faillock.so authfail audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}" - insertbefore: 'auth\s*(sufficient|required)\s*pam_deny.so$' - loop: - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - notify: Apply_authselect - - - name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Load account faillock.so" - ansible.builtin.lineinfile: - path: "{{ item }}" - regexp: '^account\s*(sufficient|required)\s*pam_faillock.so$' - line: "account required pam_faillock.so" - insertbefore: '^account\s*(sufficient|required)\s*pam_unix.so$' - loop: - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - - "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - notify: Apply_authselect - when: - - rhel9cis_rule_5_5_2 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.2 - -- name: "5.5.3 | PATCH | Ensure password reuse is limited | pwquality" - block: - - name: "5.5.3 | PATCH | Ensure password reuse is limited | Set system-auth remember Settings" - ansible.builtin.lineinfile: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - notify: Apply_authselect - - - name: "5.5.3 | PATCH | Ensure password reuse is limited | Set password-auth remember Settings" - ansible.builtin.lineinfile: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}" - insertafter: '^password\s*requisite\s*pam_pwquality.so' - notify: Apply_authselect - when: - - rhel9cis_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 or yescrypt" - block: - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf" - ansible.builtin.replace: - path: /etc/libuser.conf - regexp: '^crypt_style\s*=\s*.*$' - replace: 'crypt_style = sha512' - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | login.defs" - ansible.builtin.replace: - path: /etc/login.defs - regexp: '^ENCRYPT_METHOD.*' - replace: 'ENCRYPT_METHOD SHA512' - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | password-auth" - ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth" - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}' - notify: Apply_authselect - - - name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | system-auth" - ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth" - regexp: '^password\s*sufficient\s*pam_unix.so.*$' - replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}' - notify: Apply_authselect - when: - - rhel9cis_rule_5_5_4 - tags: - - level1-server - - level1-workstation - - patch - - rule_5.5.4 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 5271388..0000000 --- a/tasks/section_5/cis_5.6.x.yml +++ /dev/null @@ -1,149 +0,0 @@ ---- - -- name: "5.6.2 | PATCH | Ensure system accounts are secured" - block: - - name: "5.6.2 | PATCH | Ensure system accounts are secured | Set nologin" - ansible.builtin.user: - name: "{{ item.id }}" - shell: /usr/sbin/nologin - loop: "{{ rhel9cis_passwd }}" - when: - - item.id != "root" - - item.id != "sync" - - item.id != "shutdown" - - item.id != "halt" - - item.id != "nfsnobody" - - item.uid < min_int_uid | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - - item.shell != "/sbin/nologin" - - item.shell != "/dev/null" - 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 - loop: "{{ rhel9cis_passwd }}" - when: - - item.id != "halt" - - item.id != "shutdown" - - item.id != "sync" - - item.id != "root" - - item.id != "nfsnobody" - - item.uid < min_int_uid | int - - item.shell != "/bin/false" - - item.shell != "/usr/sbin/nologin" - - item.shell != "/sbin/nologin" - - item.shell != "/dev/null" - loop_control: - label: "{{ item.id }}" - when: - - rhel9cis_rule_5_6_2 - tags: - - level1-server - - level1-workstation - - 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 }}" - marker: "# {mark} - CIS benchmark - Ansible-lockdown" - create: true - mode: '0644' - block: | - TMOUT={{ rhel9cis_shell_session_timeout.timeout }} - export TMOUT - readonly TMOUT - loop: - - { path: "{{ rhel9cis_shell_session_timeout.file }}", state: present } - - { path: /etc/profile, state: "{{ (rhel9cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" } - when: - - rhel9cis_rule_5_6_3 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - rule_5.6.3 - -- name: "5.6.4 | PATCH | Ensure default group for the root account is GID 0" - ansible.builtin.user: - name: root - group: 0 - when: - - rhel9cis_rule_5_6_4 - tags: - - level1-server - - level1-workstation - - 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: "{{ item.path }}" - regexp: (?i)(umask\s+\d\d\d) - replace: '{{ item.line }} 027' - with_items: - - { path: '/etc/bashrc', line: 'umask' } - - { path: '/etc/profile', line: 'umask' } - - { path: '/etc/login.defs', line: 'UMASK' } - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc" - ansible.builtin.lineinfile: - path: /etc/login.defs - regexp: '^USERGROUPS_ENAB' - line: USERGROUPS_ENAB no - - - name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Add umask sessions for pamd" - community.general.pamd: - name: "{{ item }}" - type: session - control: required - module_path: pam_limits.so - new_type: session - new_module_path: pam_umask.so - new_control: optional - state: before - register: rhel9cis_pamd_umask_added - loop: - - system-auth - - password-auth - - - name: "5.6.5 | AUDIT | Ensure default user umask is 027 or more restrictive | update umask settings if required" - ansible.builtin.replace: - path: "/etc/pam.d/{{ item }}" - regexp: ^(session\s+)(requisite|required)(\s+pam_umask.so)$ - replace: \1optional\3 - loop: - - system-auth - - password-auth - - when: - - rhel9cis_rule_5_6_5 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - rule_5.6.5 - -- name: "5.6.6 | PATCH | Ensure root password is set" - ansible.builtin.debug: - msg: "The root password has been set as per the assert in early stages" - when: - - rhel9cis_rule_5_6_6 - tags: - - level1-server - - level1-workstation - - patch - - accounts - - root - - rule_5.6.6 From 4f566974c9f431e12664be75e4030fbf969ce182 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 10:30:08 +0100 Subject: [PATCH 032/327] improvments v2 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.6.x.yml | 7 +- tasks/section_6/cis_6.1.x.yml | 28 ++++--- templates/audit/99_auditd.rules.j2 | 82 +++++++++---------- ...WEAKMAC.pmod.j2 => NO-SSHWEAKMACS.pmod.j2} | 0 .../pwquality.conf.d/50-pwcomplexity.conf.j2 | 7 ++ .../pwquality.conf.d/50-pwdictcheck.conf.j2 | 3 + .../pwquality.conf.d/50-pwdifok.conf.j2 | 3 + .../pwquality.conf.d/50-pwlength.conf.j2 | 3 + .../pwquality.conf.d/50-pwmaxsequence.conf.j2 | 3 + .../50-pwquality_enforce.conf.j2 | 3 + .../pwquality.conf.d/50-pwrepeat.conf.j2 | 3 + .../pwquality.conf.d/50-pwroot.conf.j2 | 3 + .../journald.conf.d/forwardtosyslog.conf.j2 | 4 + .../systemd/journald.conf.d/rotation.conf.j2 | 8 ++ .../systemd/journald.conf.d/storage.conf.j2 | 11 +++ 15 files changed, 110 insertions(+), 58 deletions(-) rename templates/etc/crypto-policies/policies/modules/{NO-SSHWEAKMAC.pmod.j2 => NO-SSHWEAKMACS.pmod.j2} (100%) create mode 100644 templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 create mode 100644 templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 create mode 100644 templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 create mode 100644 templates/etc/systemd/journald.conf.d/rotation.conf.j2 create mode 100644 templates/etc/systemd/journald.conf.d/storage.conf.j2 diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 259e106..f941d47 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -13,7 +13,6 @@ - NIST800-53R5_SC-6 ansible.builtin.debug: msg: "Captured in prelim to ensure not LEGACY. Runs handler to update" - changed_when: true notify: - Update Crypto Policy - Set Crypto Policy @@ -135,8 +134,8 @@ block: - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" ansible.builtin.template: - src: etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 - dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod + src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 + dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod owner: root group: root mode: '0640' @@ -146,7 +145,7 @@ - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKMAC' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKCIPHERS' }}" - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh" when: diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 7eba300..5ff643b 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -12,25 +12,27 @@ - rule_6.1.1 - NIST800-53R5_AU-2 block: - - name: "6.1.1 | PATCH | Ensure AIDE is installed | Install AIDE" + - name: "6.1.1 | PATCH | Ensure AIDE is installed" ansible.builtin.package: name: aide state: present + register: aide_installed - - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB" - when: not ansible_check_mode - ansible.builtin.shell: /usr/sbin/aide --init - args: + - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" + when: aide_installed.changed # noqa: no-handler + block: + - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" + ansible.builtin.shell: /usr/sbin/aide --init - - name: "6.1.1 | PATCH | Ensure AIDE is installed | Wait for file before continuing" - ansible.builtin.wait_for: - path: /var/lib/aide/aide.db.new.gz + - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB | Wait for file before continuing" + ansible.builtin.wait_for: + path: /var/lib/aide/aide.db.new.gz - - name: "6.1.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: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB |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: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 6f7c388..20eb5df 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -4,23 +4,23 @@ ### 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 rhel9cis_rule_4_1_3_1 %} +{% if rhel9cis_rule_6_3_3_1 %} -w /etc/sudoers -p wa -k scope -w /etc/sudoers.d -p wa -k scope {% endif %} -{% if rhel9cis_rule_4_1_3_2 %} +{% if rhel9cis_rule_6_3_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 rhel9cis_rule_4_1_3_3 %} +{% if rhel9cis_rule_6_3_3_3 %} -w {{ rhel9cis_sudolog_location }} -p wa -k sudo_log_file {% endif %} -{% if rhel9cis_rule_4_1_3_4 %} +{% if rhel9cis_rule_6_3_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 rhel9cis_rule_4_1_3_5 %} +{% if rhel9cis_rule_6_3_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 @@ -29,70 +29,70 @@ -w /etc/sysconfig/network -p wa -k system-locale -w /etc/sysconfig/network-scripts -p wa -k system-locale {% endif %} -{% if rhel9cis_rule_4_1_3_6 %} +{% if rhel9cis_rule_6_3_3_6 %} {% for proc in priv_procs.stdout_lines -%} --a always,exit -F path={{ proc }} -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k privileged +-a always,exit -F path={{ proc }} -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k privileged {% endfor %} {% endif %} -{% if rhel9cis_rule_4_1_3_7 %} --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ min_int_uid }} -F auid!=unset -k access +{% if rhel9cis_rule_6_3_3_7 %} +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access {% endif %} -{% if rhel9cis_rule_4_1_3_8 %} +{% if rhel9cis_rule_6_3_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 rhel9cis_rule_4_1_3_9 %} --a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ min_int_uid }} -F auid!=unset -F key=perm_mod +{% if rhel9cis_rule_6_3_3_9 %} +-a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +-a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod {% endif %} -{% if rhel9cis_rule_4_1_3_10 %} --a always,exit -F arch=b32 -S mount -F auid>={{ min_int_uid }} -F auid!=unset -k mounts --a always,exit -F arch=b64 -S mount -F auid>={{ min_int_uid }} -F auid!=unset -k mounts +{% if rhel9cis_rule_6_3_3_10 %} +-a always,exit -F arch=b32 -S mount -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts +-a always,exit -F arch=b64 -S mount -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts {% endif %} -{% if rhel9cis_rule_4_1_3_11 %} +{% if rhel9cis_rule_6_3_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 rhel9cis_rule_4_1_3_12 %} +{% if rhel9cis_rule_6_3_3_12 %} -w /var/log/lastlog -p wa -k logins -w /var/run/faillock -p wa -k logins {% endif %} -{% if rhel9cis_rule_4_1_3_13 %} --a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ min_int_uid }} -F auid!=unset -F key=delete --a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ min_int_uid }} -F auid!=unset -F key=delete +{% if rhel9cis_rule_6_3_3_13 %} +-a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=delete +-a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=delete {% endif %} -{% if rhel9cis_rule_4_1_3_14 %} +{% if rhel9cis_rule_6_3_3_14 %} -w /etc/selinux -p wa -k MAC-policy -w /usr/share/selinux -p wa -k MAC-policy {% endif %} -{% if rhel9cis_rule_4_1_3_15 %} --a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k perm_chng +{% if rhel9cis_rule_6_3_3_15 %} +-a always,exit -F path=/usr/bin/chcon -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel9cis_rule_4_1_3_16 %} --a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k perm_chng +{% if rhel9cis_rule_6_3_3_16 %} +-a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_chng {% endif %} -{% if rhel9cis_rule_4_1_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k priv_cmd +{% if rhel9cis_rule_6_3_3_17 %} +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k priv_cmd {% endif %} -{% if rhel9cis_rule_4_1_3_18 %} --a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k usermod +{% if rhel9cis_rule_6_3_3_18 %} +-a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k usermod {% endif %} -{% if rhel9cis_rule_4_1_3_19 %} --a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ min_int_uid }} -F auid!=unset -k kernel_modules --a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ min_int_uid }} -F auid!=unset -k kernel_modules +{% if rhel9cis_rule_6_3_3_19 %} +-a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules +-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% endif %} -{% if rhel9cis_rule_4_1_3_20 %} +{% if rhel9cis_rule_6_3_3_20 %} -e 2 {% endif %} diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 similarity index 100% rename from templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMAC.pmod.j2 rename to templates/etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2 diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 new file mode 100644 index 0000000..0c12e7a --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -0,0 +1,7 @@ +# CIS Configurations +# 5.3.3.2.3 Ensure password complexity is configured +minclass = {{ rhel9cis_passwd_minclass }} +dcredit = {{rhel9cis_passwd_dcredit }} +ucredit = {{ rhel9cis_passwd_ucredit }} +ocredit = {{ rhel9cis_passwd_ocredit }} +lcredit = {{ rhel9cis_passwd_lcredit }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 new file mode 100644 index 0000000..09b6ee3 --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwdictcheck.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.6 Ensure password dictionary check is enabled +dictcheck = {{ rhel9cis_passwd_dictcheck_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 new file mode 100644 index 0000000..2e8ae2d --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwdifok.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.1 Ensure password number of changed characters is configured +difok = {{ rhel9cis_passwd_difok_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 new file mode 100644 index 0000000..9e874ee --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwlength.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.2 Ensure minimum password length is configured +minlen = {{ rhel9cis_passwd_minlen_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 new file mode 100644 index 0000000..a561fec --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwmaxsequence.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.5 Ensure password maximum sequential characters is configured +maxsequence = {{ rhel9cis_passwd_maxsequence_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 new file mode 100644 index 0000000..6fea8db --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwquality_enforce.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.7 Ensure password quality checking is enforced +enforcing = {{ rhel9cis_passwd_quality_enforce_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 new file mode 100644 index 0000000..28b8dde --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwrepeat.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.4 Ensure password same consecutive characters is configured +maxrepeat = {{ rhel9cis_passwd_maxrepeat_value }} diff --git a/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 new file mode 100644 index 0000000..9effdae --- /dev/null +++ b/templates/etc/security/pwquality.conf.d/50-pwroot.conf.j2 @@ -0,0 +1,3 @@ +# CIS Configurations +# 5.3.3.2.8 Ensure password quality is enforced for the root user +{{ rhel9cis_passwd_quality_enforce_root_value }} diff --git a/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 b/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 new file mode 100644 index 0000000..3b00ce1 --- /dev/null +++ b/templates/etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 @@ -0,0 +1,4 @@ +# File created for CIS benchmark +# CIS rule 6_2_2_2 +[Journal] +ForwardToSyslog=no diff --git a/templates/etc/systemd/journald.conf.d/rotation.conf.j2 b/templates/etc/systemd/journald.conf.d/rotation.conf.j2 new file mode 100644 index 0000000..07eedba --- /dev/null +++ b/templates/etc/systemd/journald.conf.d/rotation.conf.j2 @@ -0,0 +1,8 @@ +# File created for CIS benchmark +# CIS rule 6_2_1_3 +[Journal] +SystemMaxUse={{ rhel9cis_journald_systemmaxuse }} +SystemKeepFree={{ rhel9cis_journald_systemkeepfree }} +RuntimeMaxUse={{ rhel9cis_journald_runtimemaxuse }} +RuntimeKeepFree={{ rhel9cis_journald_runtimekeepfree }} +MaxFileSec={{ rhel9cis_journald_maxfilesec }} diff --git a/templates/etc/systemd/journald.conf.d/storage.conf.j2 b/templates/etc/systemd/journald.conf.d/storage.conf.j2 new file mode 100644 index 0000000..214f9db --- /dev/null +++ b/templates/etc/systemd/journald.conf.d/storage.conf.j2 @@ -0,0 +1,11 @@ +# File created for CIS benchmark +[Journal] +{% if rhel9cis_rule_6_2_2_3 %} +# Set compress CIS rule 6_2_2_3 +Compress=yes +{% endif %} + +{% if rhel9cis_rule_6_2_2_4 %} +# Set persistent storage CIS rule 6_2_2_4 +Storage=persistent +{% endif %} From 9196e916fc6c3d8613f899720e1920e9183d61b0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 10:30:45 +0100 Subject: [PATCH 033/327] update var naming Signed-off-by: Mark Bolwell --- handlers/main.yml | 8 ++------ tasks/section_1/cis_1.5.x.yml | 2 +- tasks/section_6/cis_6.2.2.1.x.yml | 30 ++++++++++++++-------------- tasks/section_6/cis_6.3.2.x.yml | 33 +++++++++++++++++++++++++------ 4 files changed, 45 insertions(+), 28 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index d4aaf2c..125586c 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -42,7 +42,7 @@ notify: Set Crypto Policy - name: Set Crypto Policy - when: rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy + when: prelim_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy ansible.builtin.shell: | update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" update-crypto-policies @@ -91,13 +91,9 @@ ansible.builtin.systemd: daemon-reload: true -- name: Apply_authselect - when: not rhel9cis_rule_5_4_2 +- name: Authselect update ansible.builtin.shell: authselect apply-changes -- name: Apply_authselect - when: rhel9cis_rule_5_4_2 - ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}" ## Auditd tasks note order for handlers to run - name: Auditd immutable check diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 05d4b6e..1184603 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -56,7 +56,7 @@ - name: "1.5.4 | PATCH | Ensure core dump storage is disabled" when: - rhel9cis_rule_1_5_4 - - systemd_coredump.stat.exists + - prelim_systemd_coredump.stat.exists tags: - level1-server - level1-workstation diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml index 4db5c29..20b148b 100644 --- a/tasks/section_6/cis_6.2.2.1.x.yml +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -2,8 +2,8 @@ - name: "6.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed" when: - - ubtu22cis_rule_6_2_2_1_1 - - not ubtu22cis_system_is_log_server + - rhel9cis_rule_6_2_2_1_1 + - not rhel9cis_system_is_log_server tags: - level1-server - level1-workstation @@ -19,8 +19,8 @@ - name: "6.2.2.1.2 | PATCH | Ensure systemd-journal-remote authentication is configured" when: - - ubtu22cis_rule_6_2_2_1_2 - - not ubtu22cis_system_is_log_server + - rhel9cis_rule_6_2_2_1_2 + - not rhel9cis_system_is_log_server tags: - level1-server - level1-workstation @@ -35,15 +35,15 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" loop: - - { regexp: 'URL=', line: 'URL={{ ubtu22cis_remote_log_server }}'} - - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ ubtu22cis_journal_upload_serverkeyfile }}'} - - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ ubtu22cis_journal_servercertificatefile }}'} - - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ ubtu22cis_journal_trustedcertificatefile }}'} + - { regexp: 'URL=', line: 'URL={{ rhel9cis_remote_log_server }}'} + - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel9cis_journal_upload_serverkeyfile }}'} + - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'} + - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'} - name: "6.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled and active" when: - - not ubtu22cis_system_is_log_server - - ubtu22cis_rule_6_2_2_1_3 + - not rhel9cis_system_is_log_server + - rhel9cis_rule_6_2_2_1_3 tags: - level1-server - level1-workstation @@ -59,8 +59,8 @@ - name: "6.2.2.1.4 | PATCH | Ensure systemd-journal-remote service is not in use" when: - - not ubtu22cis_system_is_log_server - - ubtu22cis_rule_6_2_2_1_4 + - not rhel9cis_system_is_log_server + - rhel9cis_rule_6_2_2_1_4 tags: - level1-server - level1-workstation @@ -81,7 +81,7 @@ - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled" when: - - ubtu22cis_rule_6_2_2_2 + - rhel9cis_rule_6_2_2_2 tags: - level1-server - level2-workstation @@ -110,7 +110,7 @@ - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" when: - - ubtu22cis_rule_6_2_2_3 + - rhel9cis_rule_6_2_2_3 tags: - level1-server - level1-workstation @@ -136,7 +136,7 @@ - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" when: - - ubtu22cis_rule_6_2_2_4 + - rhel9cis_rule_6_2_2_4 tags: - level1-server - level1-workstation diff --git a/tasks/section_6/cis_6.3.2.x.yml b/tasks/section_6/cis_6.3.2.x.yml index dd9df94..08a5365 100644 --- a/tasks/section_6/cis_6.3.2.x.yml +++ b/tasks/section_6/cis_6.3.2.x.yml @@ -13,7 +13,7 @@ ansible.builtin.lineinfile: path: /etc/audit/auditd.conf regexp: "^max_log_file( |=)" - line: "max_log_file = {{ rhel9cis_auditd['max_log_file'] }}" + line: "max_log_file = {{ rhel9cis_auditd_max_log_file_size }}" notify: Restart auditd - name: "6.3.2.2 | PATCH | Ensure audit logs are not automatically deleted" @@ -29,7 +29,7 @@ ansible.builtin.lineinfile: path: /etc/audit/auditd.conf regexp: "^max_log_file_action" - line: "max_log_file_action = {{ rhel9cis_auditd['max_log_file_action'] }}" + line: "max_log_file_action = {{ rhel9cis_auditd_max_log_file_action }}" notify: Restart auditd - name: "6.3.2.3 | PATCH | Ensure system is disabled when audit logs are full" @@ -51,11 +51,32 @@ line: "{{ item.line }}" notify: Restart auditd loop: - - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel9cis_auditd.admin_space_left_action }}' } - - { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel9cis_auditd.action_mail_acct }}' } - - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel9cis_auditd.space_left_action }}' } + - { regexp: '^disk_full_action', line: 'disk_full_action = {{ rhel9cis_auditd_disk_full_action }}' } + - { regexp: '^disk_error_action', line: 'disk_error_action = {{ rhel9cis_auditd_disk_error_action }}' } -- name: PATCH | Configure other keys for auditd.conf +- name: "6.3.2.4 | PATCH | Ensure system warns when audit logs are low on space" + when: + - rhel9cis_rule_6_3_2_4 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.2.4 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-8 + - NIST800-53R5_AU-12 + - NIST800-53R5_SI-5 + ansible.builtin.lineinfile: + path: /etc/audit/auditd.conf + regexp: "{{ item.regexp }}" + line: "{{ item.line }}" + notify: Restart auditd + loop: + - { regexp: '^space_left_action', line: 'space_left_action = {{ rhel9cis_auditd_space_left_action }}' } + - { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel9cis_auditd_admin_space_left_action }}' } + +- name: "PATCH | Configure other keys for auditd.conf" when: - rhel9cis_auditd_extra_conf.keys() | length > 0 - rhel9cis_auditd_extra_conf_usage From 47dc0c5b4c3cf0bd5b5b24662e65ff6eacf64cf7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 10:30:59 +0100 Subject: [PATCH 034/327] updated Signed-off-by: Mark Bolwell --- molecule/default/converge.yml | 2 +- molecule/localhost/converge.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/molecule/default/converge.yml b/molecule/default/converge.yml index a4685bc..27172b2 100644 --- a/molecule/default/converge.yml +++ b/molecule/default/converge.yml @@ -9,7 +9,7 @@ ansible_user: root system_is_container: true rhel9cis_selinux_disable: true - rhel9cis_rule_5_3_4: false + rhel9cis_rule_5_2_4: false rhel9cis_rule_1_1_10: false rhel9cis_firewall: "none" rhel9cis_rule_4_1_1_1: false diff --git a/molecule/localhost/converge.yml b/molecule/localhost/converge.yml index aebb717..e40f70d 100644 --- a/molecule/localhost/converge.yml +++ b/molecule/localhost/converge.yml @@ -8,7 +8,7 @@ vars: ansible_user: "{{ lookup('env', 'USER') }}" role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}" - rhel9cis_rule_5_3_4: false + rhel9cis_rule_5_2_4: false pre_tasks: tasks: From 2a7d08da0892502f9dcf39771e1fee761354c6a1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 10:31:31 +0100 Subject: [PATCH 035/327] improvements Signed-off-by: Mark Bolwell --- tasks/main.yml | 174 +++++++++++------------ tasks/prelim.yml | 238 +++++++++++++++----------------- tasks/section_6/cis_6.3.4.x.yml | 43 ++---- tasks/section_7/cis_7.1.x.yml | 8 +- tasks/section_7/cis_7.2.x.yml | 32 +---- 5 files changed, 211 insertions(+), 284 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 2aee086..6a28be4 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -1,7 +1,7 @@ --- # tasks file for RHEL9-CIS -- name: Check OS version and family +- name: "Check OS version and family" ansible.builtin.assert: that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported." @@ -11,7 +11,7 @@ tags: - always -- name: Check ansible version +- name: "Check ansible version" ansible.builtin.assert: that: ansible_version.full is version_compare(min_ansible_version, '>=') fail_msg: "You must use Ansible {{ min_ansible_version }} or greater" @@ -19,16 +19,67 @@ tags: - always +- 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: + system_is_container: true + + - name: "Load variable for container" + ansible.builtin.include_vars: + file: "{{ container_vars_file }}" + + - name: "Output if discovered is a container" + when: + - system_is_container + ansible.builtin.debug: + msg: system has been discovered as a container + +- name: "Check crypto-policy input" + ansible.builtin.assert: + that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies + fail_msg: "Crypto policy is not a permitted version" + success_msg: "Crypto policy is a permitted version" + +- name: "Check rhel9cis_bootloader_password_hash variable has been changed" + when: + - rhel9cis_set_boot_pass + - rhel9cis_rule_1_4_1 + tags: + - always + ansible.builtin.assert: + that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret + msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" + +- name: "Check crypto-policy module input" + when: + - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_module | length > 0 + tags: + - rule_1.6.1 + - crypto + - NIST800-53R5_SC-6 + ansible.builtin.assert: + that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules + fail_msg: "Crypto policy module is not a permitted version" + success_msg: "Crypto policy module is a permitted version" + - name: "Check password set for {{ ansible_env.SUDO_USER }}" when: - - rhel9cis_rule_5_3_4 + - rhel9cis_rule_5_2_4 - ansible_env.SUDO_USER is defined - not system_is_ec2 tags: - user_passwd - - rule_5.3.4 + - rule_5.2.4 vars: - sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret + sudo_password_rule: rhel9cis_rule_5_2_4 # pragma: allowlist secret block: - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" @@ -61,173 +112,108 @@ fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" -- name: Ensure root password is set +- name: "Ensure root password is set" when: - - rhel9cis_rule_5_6_6 + - rhel9cis_rule_5_4_2_4 tags: - level1-server - level1-workstation - patch - accounts - root - - rule_5.6.6 + - rule_5.4.2.4 block: - - name: Ensure root password is set + - name: "Ensure root password is set" ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" changed_when: false register: root_passwd_set - - name: Ensure root password is set + - name: "Ensure root password is set" ansible.builtin.assert: that: root_passwd_set.rc == 0 - fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set" + fail_msg: "You have rule 5.4.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: - system_is_container: true - - - name: Load variable for container - ansible.builtin.include_vars: - file: "{{ container_vars_file }}" - - - name: Output if discovered is a container - when: - - system_is_container - ansible.builtin.debug: - msg: system has been discovered as a container - -- name: Check crypto-policy input - ansible.builtin.assert: - that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies - fail_msg: "Crypto policy is not a permitted version" - success_msg: "Crypto policy is a permitted version" - -- name: Check crypto-policy module input - when: - - rhel9cis_rule_1_6_1 - - rhel9cis_crypto_policy_module | length > 0 - tags: - - rule_1.6.1 - - crypto - - NIST800-53R5_SC-6 - ansible.builtin.assert: - that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules - fail_msg: "Crypto policy module is not a permitted version" - success_msg: "Crypto policy module is a permitted version" - -- name: Check rhel9cis_bootloader_password_hash variable has been changed - when: - - rhel9cis_set_boot_pass - - rhel9cis_rule_1_4_1 - tags: - - always - ansible.builtin.assert: - that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret - msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" - -- name: Gather the package facts +- name: "Gather the package facts" tags: - always ansible.builtin.package_facts: manager: auto -- name: Include OS specific variables +- name: "Include OS specific variables" tags: - always ansible.builtin.include_vars: file: "{{ ansible_facts.distribution }}.yml" -- name: Include preliminary steps +- name: "Include preliminary steps" tags: - prelim_tasks - always ansible.builtin.import_tasks: file: prelim.yml -- name: Run Section 1 tasks +- name: "Run Section 1 tasks" when: rhel9cis_section1 - tags: - - rhel9cis_section1 ansible.builtin.import_tasks: file: section_1/main.yml -- name: Run Section 2 tasks +- name: "Run Section 2 tasks" when: rhel9cis_section2 - tags: - - rhel9cis_section2 ansible.builtin.import_tasks: file: section_2/main.yml -- name: Run Section 3 tasks +- name: "Run Section 3 tasks" when: rhel9cis_section3 - tags: - - rhel9cis_section3 ansible.builtin.import_tasks: file: section_3/main.yml -- name: Run Section 4 tasks +- name: "Run Section 4 tasks" when: rhel9cis_section4 - tags: - - rhel9cis_section4 ansible.builtin.import_tasks: file: section_4/main.yml -- name: Run Section 5 tasks +- name: "Run Section 5 tasks" when: rhel9cis_section5 - tags: - - rhel9cis_section5 ansible.builtin.import_tasks: file: section_5/main.yml -- name: Run Section 6 tasks +- name: "Run Section 6 tasks" when: rhel9cis_section6 - tags: - - rhel9cis_section6 ansible.builtin.import_tasks: file: section_6/main.yml -# - name: Run Section 7 tasks -# when: rhel9cis_section7 -# tags: -# - rhel9cis_section7 -# ansible.builtin.import_tasks: -# file: section_7/main.yml +- name: "Run Section 7 tasks" + when: rhel9cis_section7 + ansible.builtin.import_tasks: + file: section_7/main.yml -- name: Run auditd logic +- name: "Run auditd logic" when: update_audit_template tags: - always ansible.builtin.import_tasks: file: auditd.yml -- name: Run post remediation tasks +- name: "Run post remediation tasks" tags: - post_tasks - always ansible.builtin.import_tasks: file: post.yml -- name: Run post_remediation audit +- name: "Run post_remediation audit" when: - run_audit ansible.builtin.import_tasks: file: post_remediation_audit.yml -- name: Show Audit Summary +- name: "Show Audit Summary" when: run_audit ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" -- name: If Warnings found Output count and control IDs affected +- name: "If Warnings found Output count and control IDs affected" when: warn_count != 0 tags: - always diff --git a/tasks/prelim.yml b/tasks/prelim.yml index bd8bf48..96e9657 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -3,7 +3,7 @@ # Preliminary tasks that should always be run # List users in order to look files inside each home directory -- name: PRELIM | Include audit specific variables +- name: "PRELIM | Include audit specific variables" when: - run_audit or audit_only - setup_audit @@ -13,7 +13,7 @@ ansible.builtin.include_vars: file: audit.yml -- name: PRELIM | Include pre-remediation audit tasks +- name: "PRELIM | Include pre-remediation audit tasks" when: - run_audit or audit_only - setup_audit @@ -45,47 +45,26 @@ changed_when: false register: prelim_interactive_uids -- name: "PRELIM | capture /etc/password variables" +- name: "PRELIM | AUDIT | Capture /etc/password variables" ansible.builtin.include_tasks: file: parse_etc_password.yml tags: - always -- name: "PRELIM | List users accounts" - ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd" - changed_when: false - check_mode: false - register: users - tags: - - level1-server - - level1-workstation - - users - -- name: "PRELIM | Gather accounts with empty password fields" - ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'" - changed_when: false - check_mode: false - register: empty_password_accounts - tags: - - level1-server - - level1-workstation - - passwords - -- name: "PRELIM | Ensure python3-libselinux is installed" +- name: "PRELIM | PATCH | Ensure python3-libselinux is installed" when: - '"python3-libselinux" not in ansible_facts.packages' ansible.builtin.package: name: python3-libselinux state: present -- name: "PRELIM | Section 1.1 | Create list of mount points" +- name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" + tags: + - Always ansible.builtin.set_fact: mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" - tags: - - level1-server - - level1-workstation -- name: "PRELIM | Update to latest gpg keys" +- name: "PRELIM | PATCH | Update to latest gpg keys" when: - rhel9cis_rule_1_2_1_1 - ansible_facts.distribution != 'RedHat' @@ -94,32 +73,32 @@ name: "{{ gpg_key_package }}" state: latest -- name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not | RedHat Only" +- name: "PRELIM | AUDIT | Import gpg keys | RedHat Only" when: - rhel9cis_rule_1_2_1_1 - rhel9cis_force_gpg_key_import - ansible_facts.distribution == 'RedHat' block: - - name: "PRELIM | Check gpg keys are imported will cause 1.2.1.1 to fail if not" + - name: "PRELIM | AUDIT | Import gpg keys | get data" ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' changed_when: false failed_when: false - register: check_gpg_imported + register: prelim_check_gpg_imported - - name: "PRELIM | Check key package matches RedHat" - when: "'not installed' in check_gpg_imported.stdout" + - name: "PRELIM | AUDIT | Import gpg keys | Check Package" + when: "'not installed' in prelim_check_gpg_imported.stdout" ansible.builtin.shell: rpm -qi redhat-release | grep Signature changed_when: false failed_when: false - register: os_gpg_package_valid + register: prelim_os_gpg_package_valid - - name: "PRELIM | Force keys to be imported" + - name: "PRELIM | PATCH | Force keys to be imported" when: - - "'not installed' in check_gpg_imported.stdout" - - "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout" + - "'not installed' in prelim_check_gpg_imported.stdout" + - "'Key ID 199e2f91fd431d51' in prelim_os_gpg_package_valid.stdout" ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release -- name: "PRELIM | if systemd coredump" +- name: "PRELIM | AUDIT | Check systemd coredump" when: - rhel9cis_rule_1_5_4 tags: @@ -129,9 +108,9 @@ - systemd ansible.builtin.stat: path: /etc/systemd/coredump.conf - register: systemd_coredump + register: prelim_systemd_coredump -- name: "PRELIM | Setup crypto-policy" +- name: "PRELIM | PATCH | Setup crypto-policy" when: - rhel9cis_rule_1_6_1 tags: @@ -140,43 +119,43 @@ - rule_1.6.1 - crypto block: - - name: "PRELIM | Install crypto-policies | pkgs present" + - name: "PRELIM | PATCH | Install crypto-policies | pkgs present" ansible.builtin.package: name: - crypto-policies - crypto-policies-scripts state: present - - name: "PRELIM | Gather system-wide crypto-policy" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy" ansible.builtin.shell: 'update-crypto-policies --show' changed_when: false check_mode: false - register: rhel9cis_system_wide_crypto_policy + register: prelim_system_wide_crypto_policy - - name: "PRELIM | Gather system-wide crypto-policy | set fact system policy" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy | set fact system policy" ansible.builtin.set_fact: - current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}" + current_crypto_policy: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[0] }}" - - name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule" - when: "':' in rhel9cis_system_wide_crypto_policy.stdout" + - name: "PRELIM | AUDIT | Gather system-wide crypto-policy module | set fact system policy submodule" + when: "':' in prelim_system_wide_crypto_policy.stdout" ansible.builtin.set_fact: - current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}" + current_crypto_module: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[1] }}" -- name: "PRELIM | Set facts based on boot type" +- name: "PRELIM | AUDIT | Set facts based on boot type" block: - - name: "PRELIM | Check whether machine is UEFI-based" + - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" ansible.builtin.stat: path: /sys/firmware/efi - register: rhel_09_efi_boot + register: prelim_efi_boot - - name: "PRELIM | set legacy boot and grub path | Bios" - when: not rhel_09_efi_boot.stat.exists + - name: "PRELIM | AUDIT | Set legacy boot and grub path | Bios" + when: not prelim_efi_boot.stat.exists ansible.builtin.set_fact: rhel9cis_legacy_boot: true grub2_path: /etc/grub2.cfg - - name: "PRELIM | set grub fact | UEFI" - when: rhel_09_efi_boot.stat.exists + - name: "PRELIM | AUDIT | Set grub fact | UEFI" + when: prelim_efi_boot.stat.exists ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg @@ -193,51 +172,15 @@ changed_when: false failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] - - name: "PRELIM | PATCH | Install Network-Manager | if wireless adpater present" + - name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present" when: - - rhel9cis_install_network_manager - discover_wireless_adapters.rc == 0 - - "'network-manager' not in ansible_facts.packages" + - "'NetworkManager' not in ansible_facts.packages" ansible.builtin.package: - name: network-manager + name: NetworkManager state: present -- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" - ansible.builtin.package: - name: audit - state: present - become: true - when: - - '"auditd" not in ansible_facts.packages' - - rhel9cis_rule_4_1_1_1 - tags: - - level2-server - - level2-workstation - - patch - - rule_4.1.1.1 - - auditd - -- name: "PRELIM | 4.1.4.5 | Audit conf and rules files | list files" - when: - - rhel9cis_rule_4_1_4_5 or - rhel9cis_rule_4_1_4_6 or - rhel9cis_rule_4_1_4_7 - tags: - - level2-server - - level2-workstation - - patch - - auditd - - rule_4.1.4.5 - - rule_4.1.4.6 - - rule_4.1.4.7 - ansible.builtin.find: - path: /etc/audit - file_type: file - recurse: true - patterns: '*.conf,*.rules' - register: auditd_conf_files - -- name: "PRELIM | Section 5.1 | Configure cron" +- name: "PRELIM | PATCH | Install Cronie" when: - rhel9cis_rule_5_1_1 - '"cronie" not in ansible_facts.packages' @@ -251,7 +194,7 @@ state: present # Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config -- name: "PRELIM | Section 5.2 | SSH" +- name: "PRELIM | PATCH | SSH Config file is not exist" when: - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' - "'openssh-server' in ansible_facts.packages" @@ -266,55 +209,94 @@ mode: '0600' state: touch -- name: "PRELIM | 5.3.4 | Find all sudoers files." - when: - - rhel9cis_rule_5_3_4 or - rhel9cis_rule_5_3_5 +- name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" + when: rhel9cis_rule_5_4_2_1 tags: - - rule_5.3.4 - - rule_5.3.5 - ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" - changed_when: false - failed_when: false - check_mode: false - register: rhel9cis_sudoers_files - -- name: "PRELIM | Gather UID 0 accounts other than root" - tags: - - rule_6.2.9 + - rule_5.4.2.1 - level1-server - level1-workstation - users 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: rhel9cis_uid_zero_accounts_except_root + register: prelim_uid_zero_accounts_except_root -- name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def" +- name: "PRELIM | PATCH | Create journald config directory" + when: + - rhel9cis_syslog == 'journald' + - rhel9cis_rule_6_2_1_3 or + rhel9cis_rule_6_2_1_4 + tags: always + ansible.builtin.file: + path: /etc/systemd/journald.conf.d + state: directory + +- name: "PRELIM | PATCH | Configure System Accounting (auditd)" + when: + - '"auditd" not in ansible_facts.packages' + - rhel9cis_rule_6_3_1_1 + tags: + - level2-server + - level2-workstation + - patch + - rule_6.3.1.1 + - auditd + ansible.builtin.package: + name: audit + state: present + become: true + +- name: "PRELIM | AUDIT | Discover audit logfile" + when: + - rhel9cis_rule_6_3_4_1 or + rhel9cis_rule_6_3_4_2 or + rhel9cis_rule_6_3_4_3 or + rhel9cis_rule_6_3_4_4 + tags: always + ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' + changed_when: false + register: prelim_auditd_logfile + +- name: "PRELIM | AUDIT | Audit conf and rules files | list files" + when: + - rhel9cis_rule_6_3_4_5 or + rhel9cis_rule_6_3_4_6 or + rhel9cis_rule_6_3_4_7 + tags: + - level2-server + - level2-workstation + - patch + - auditd + - rule_6.3.4.5 + - rule_6.3.4.6 + - rule_6.3.4.7 + ansible.builtin.find: + path: /etc/audit + file_type: file + recurse: true + patterns: '*.conf,*.rules' + register: prelim_auditd_conf_files + +- name: "PRELIM | AUDIT | Discover Interactive UID MIN and MIN from logins.def" when: rhel9cis_discover_int_uid + tags: always block: - - name: "PRELIM | Capture UID_MIN information from logins.def" + - name: "PRELIM | AUDIT | Capture UID_MIN information from logins.def" ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' changed_when: false - register: uid_min_id + register: prelim_uid_min_id - - name: "PRELIM | Capture UID_MAX information from logins.def" + - name: "PRELIM | AUDIT | Capture UID_MAX information from logins.def" ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}' changed_when: false - register: uid_max_id + register: prelim_uid_max_id - - name: "PRELIM | Capture GID_MIN information from logins.def" - ansible.builtin.shell: grep -w "^GID_MIN" /etc/login.defs | awk '{print $NF}' - changed_when: false - register: gid_min_id - - - name: "PRELIM | set_facts for interactive uid/gid" + - name: "PRELIM | AUDIT | set_facts for interactive uid/gid" ansible.builtin.set_fact: - min_int_uid: "{{ uid_min_id.stdout }}" - max_int_uid: "{{ uid_max_id.stdout }}" - min_int_gid: "{{ gid_min_id.stdout }}" + prelim_min_int_uid: "{{ prelim_uid_min_id.stdout }}" + prelim_max_int_uid: "{{ prelim_uid_max_id.stdout }}" -- name: "PRELIM | Gather the package facts after prelim" +- name: "PRELIM | AUDIT | Gather the package facts after prelim" tags: - always ansible.builtin.package_facts: diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 144adec..db66377 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -10,17 +10,10 @@ - auditd - rule_6.3.4.1 - NIST800-53R5_AU-3 - block: - - name: "6.3.4.1 | AUDIT | Ensure the audit log file directory mode is configured | get current permissions" - ansible.builtin.stat: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - register: auditlog_dir - - - name: "6.3.4.1 | PATCH | Ensure the audit log file directory mode is configured | set" - ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout | dirname }}" - state: directory - mode: 'g-w,o-rwx' + ansible.builtin.file: + path: "{{ prelim_auditd_logfile.stdout | dirname }}" + state: directory + mode: 'g-w,o-rwx' - name: | "6.3.4.2 | PATCH | Ensure audit log files mode is configured" @@ -39,21 +32,11 @@ - rule_6.3.4.2 - rule_6.3.4.3 - NIST800-53R5_AU-3 - block: - - name: "6.3.4.2 | AUDIT | Ensure audit log files mode is configured | discover file" - ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' - changed_when: false - register: audit_discovered_logfile - - - name: | - "6.3.4.2 | PATCH | Ensure audit log files mode is configured" - "6.3.4.3 | PATCH | Ensure audit log files owner is configured" - "6.3.4.4 | PATCH | Ensure audit log files group owner is configured" - ansible.builtin.file: - path: "{{ audit_discovered_logfile.stdout }}" - mode: 'o-x,g-wx,o-rwx' - owner: root - group: root + ansible.builtin.file: + path: "{{ prelim_auditd_logfile.stdout }}" + mode: 'o-x,g-wx,o-rwx' + owner: root + group: root - name: "6.3.4.5 | PATCH | Ensure audit configuration files mode is configured" when: @@ -67,7 +50,7 @@ ansible.builtin.file: path: "{{ item.path }}" mode: 'u-x,g-wx,o-rwx' - loop: "{{ auditd_conf_files.files }}" + loop: "{{ prelim_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -83,7 +66,7 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root - loop: "{{ auditd_conf_files.files | default([]) }}" + loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" @@ -99,7 +82,7 @@ ansible.builtin.file: path: "{{ item.path }}" group: root - loop: "{{ auditd_conf_files.files | default([]) }}" + loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" @@ -114,7 +97,7 @@ - rule_6.3.4.8 - NIST800-53R5_AU-3 ansible.builtin.file: - path: "{{ item.item }}" + path: "{{ item }}" mode: 'go-w' loop: - /sbin/auditctl diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 7517062..4c95687 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -192,6 +192,7 @@ - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" when: - rhel_09_7_1_11_perms_results.stdout_lines is defined + - rhel_09_7_1_11_perms_results.stdout_lines | length > 0 - rhel9cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' @@ -200,7 +201,10 @@ loop: "{{ rhel_09_7_1_11_perms_results.stdout_lines }}" - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable directories add sticky bit" - 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 + ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -o+w ! -perm -1002 2>/dev/null | xargs chmod a+t + failed_when: rhel9cis_set_stickybit.rc not in [ 0, 123 ] + changed_when: rhel9cis_set_stickybit.rc == 0 + register: rhel9cis_set_stickybit - name: "7.1.12 | PATCH | Ensure no files or directories without an owner and a group exist" when: @@ -250,7 +254,7 @@ owner: "{{ rhel9cis_unowned_owner }}" group: "{{ rhel9cis_unowned_group }}" with_items: - - "{{ udiscovered_unowned_files_flatten }}" + - "{{ discovered_unowned_files_flatten }}" - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Warn Count" when: diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 5cfbbc3..47d48f6 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -84,7 +84,7 @@ - name: "7.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 users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join (', ') }}" + msg: "Warning!! The following users have non-existent GIDs (Groups): {{ discovered_passwd_gid_check.stdout_lines | join(', ') }}" - name: "7.2.3 | WARNING | Ensure all groups in /etc/passwd exist in /etc/group | warn_count" when: discovered_passwd_gid_check.stdout | length > 0 @@ -243,7 +243,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | list }}" + loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" @@ -316,31 +316,3 @@ path: '{{ item }}' mode: 'go-w' with_items: "{{ discovered_homedir_dot_files.stdout_lines }}" - -- name: "7.2.4 | PATCH | Ensure shadow group is empty" - when: - - rhel9cis_rule_7_2_4 - tags: - - level1-server - - level1-workstation - - patch - - rule_6.2.4 - - user - vars: - warn_control_id: '7.2.4' - block: - - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" - ansible.builtin.getent: - database: group - split: ':' - key: shadow - - - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" - ansible.builtin.debug: - msg: "Warning!! - You have users in the shadow group" - when: ansible_facts.getent_group.shadow[2] | length > 0 - - - name: "7.2.4 | AUDIT | Ensure shadow group is empty | check users in group" - ansible.builtin.import_tasks: - file: warning_facts.yml - when: ansible_facts.getent_group.shadow[2] | length > 0 From 49fdafc5e03b215d82ae1fbf33270a69c8f37c7a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 12:37:43 +0100 Subject: [PATCH 036/327] fix typo in tag Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.3.x.yml | 4 ++-- tasks/section_1/cis_1.1.2.4.x.yml | 4 ++-- tasks/section_1/cis_1.1.2.5.x.yml | 6 +++--- tasks/section_1/cis_1.1.2.6.x.yml | 6 +++--- tasks/section_1/cis_1.1.2.7.x.yml | 6 +++--- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index cf45245..728b3c9 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -35,8 +35,8 @@ - level1-workstation - patch - mounts - - rule_1_1_2.3.2 - - rule_1_1_2.3.3 + - rule_1.1.2.3.2 + - rule_1.1.2.3.3 - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index a2b0695..d2e4aa8 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -36,8 +36,8 @@ - level1-workstation - patch - mounts - - rule_1_1_2.4.2 - - rule_1_1_2.4.3 + - rule_1.1.2.4.2 + - rule_1.1.2.4.3 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 ansible.posix.mount: diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index 6e630e4..a09d46d 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -39,9 +39,9 @@ - level1-workstation - patch - mounts - - rule_1_1_2.5.2 - - rule_1_1_2.5.3 - - rule_1_1_2.5.4 + - 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 ansible.posix.mount: diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index dea5d85..d6e2c56 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -37,9 +37,9 @@ - level1-workstation - patch - mounts - - rule_1_1_2.6.2 - - rule_1_1_2.6.3 - - rule_1_1_2.6.4 + - 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 ansible.posix.mount: diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 2747e49..4e21461 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -37,9 +37,9 @@ - level1-workstation - patch - mounts - - rule_1_1_2.7.2 - - rule_1_1_2.7.3 - - rule_1_1_2.7.4 + - 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 ansible.posix.mount: From d5b688caac8346083c724e35cb556adf0b738ffb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 7 Aug 2024 14:05:59 +0100 Subject: [PATCH 037/327] Improved logic for crypto policy additions Signed-off-by: Mark Bolwell --- handlers/main.yml | 3 +- tasks/section_1/cis_1.6.x.yml | 61 +++++++++++++++++++++++------------ tasks/section_5/cis_5.1.x.yml | 2 +- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 125586c..2009fa2 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -38,14 +38,13 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}:{{ rhel9cis_crypto_policy_module }}{% endif %}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}" notify: Set Crypto Policy - name: Set Crypto Policy when: prelim_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy ansible.builtin.shell: | update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" - update-crypto-policies notify: - Change_requires_reboot - Restart sshd diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index f941d47..f0798e9 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -55,13 +55,15 @@ owner: root group: root mode: '0640' - notify: - - Update Crypto Policy - - Set Crypto Policy + register: NO_SHA1_TEMPLATE - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SHA1' }}" + changed_when: NO_SHA1_TEMPLATE is defined + notify: + - Update Crypto Policy + - Set Crypto Policy - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits" when: @@ -76,6 +78,9 @@ - rule_1.6.4 - NIST800-53R5_SC-6 block: + + - ansible.builtin.debug: + msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -83,13 +88,15 @@ owner: root group: root mode: '0640' - notify: - - Update Crypto Policy - - Set Crypto Policy + register: NO_WEAKMAC_TEMPLATE - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-WEAKMAC' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-WEAKMAC' }}" + changed_when: NO_WEAKMAC_TEMPLATE is defined + notify: + - Update Crypto Policy + - Set Crypto Policy - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh" when: @@ -104,6 +111,8 @@ - rule_1.6.5 - NIST800-53R5_SC-6 block: + - ansible.builtin.debug: + msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -111,18 +120,20 @@ owner: root group: root mode: '0640' + register: NO_SSHCBC_TEMPLATE + + - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" + ansible.builtin.set_fact: + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHCBC' }}" + changed_when: NO_SSHCBC_TEMPLATE is defined notify: - Update Crypto Policy - Set Crypto Policy - - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" - ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHCBC' }}" - - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh" when: - rhel9cis_rule_1_6_6 - - "'NO-SSHWEAKMAC' not in rhel9cis_crypto_policy_module" + - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" tags: - level1-server - level1-workstation @@ -132,6 +143,8 @@ - rule_1.6.6 - NIST800-53R5_SC-6 block: + - ansible.builtin.debug: + msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 @@ -139,13 +152,15 @@ owner: root group: root mode: '0640' - notify: - - Update Crypto Policy - - Set Crypto Policy + register: NO_SSHWEAKCIPHERS_TEMPLATE - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKCIPHERS' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKCIPHERS' }}" + changed_when: NO_SSHWEAKCIPHERS_TEMPLATE is defined + notify: + - Update Crypto Policy + - Set Crypto Policy - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh" when: @@ -160,6 +175,8 @@ - rule_1.6.7 - NIST800-53R5_SC-6 block: + - ansible.builtin.debug: + msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -167,10 +184,12 @@ owner: root group: root mode: '0640' - notify: - - Update Crypto Policy - - Set Crypto Policy + register: NO_SSHETM_TEMPLATE - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHETM' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHETM' }}" + changed_when: NO_SSHETM_TEMPLATE is defined + notify: + - Update Crypto Policy + - Set Crypto Policy diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 62c3af9..eeb486d 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -161,7 +161,7 @@ - name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules" ansible.builtin.set_fact: - rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}" + rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKMACS' }}" - name: "5.1.7 | PATCH | Ensure sshd access is configured" when: From 9598139f4c7a7d1a46980979bfc7be99cd562dd7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 8 Aug 2024 11:07:16 +0100 Subject: [PATCH 038/327] Add handler Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 41 +++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 7 deletions(-) diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index eeb486d..95addf3 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -251,6 +251,7 @@ regexp: '^ClientAliveInterval' line: "ClientAliveInterval {{ rhel9cis_sshd_clientaliveinterval }}" validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" ansible.builtin.lineinfile: @@ -258,6 +259,7 @@ regexp: '^ClientAliveCountMax' line: "ClientAliveCountMax {{ rhel9cis_sshd_clientalivecountmax }}" validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled" when: @@ -276,6 +278,7 @@ regexp: ^(#|)\s*DisableForwarding line: 'DisableForwarding yes' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" ansible.builtin.lineinfile: @@ -283,6 +286,7 @@ regexp: ^(?i)(#|)\s*X11Forwarding line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled" when: @@ -298,11 +302,22 @@ - NIST800-53R5_CM-6 - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 - ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*GSSAPIAuthentication - line: 'GSSAPIAuthentication no' - validate: sshd -t -f %s + block: + - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" + ansible.builtin.lineinfile: + path: /etc/ssh/sshd_config.d/50-redhat.conf + regexp: ^(?i)(#|)\s*GSSAPIAuthentication + line: GSSAPIAuthentication no + validate: sshd -t -f %s + notify: Restart sshd + + - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config" + ansible.builtin.lineinfile: + path: "{{ rhel9_cis_sshd_config_file }}" + regexp: ^(?i)(#|)\s*GSSAPIAuthentication + line: GSSAPIAuthentication no + validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.12 | PATCH | Ensure sshd HostbasedAuthentication is disabled" when: @@ -323,6 +338,7 @@ regexp: ^(?i)(#|)\s*HostbasedAuthentication line: 'HostbasedAuthentication no' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.13 | PATCH | Ensure sshd IgnoreRhosts is enabled" when: @@ -343,6 +359,7 @@ regexp: ^(?i)(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.14 | PATCH | Ensure sshd LoginGraceTime is set to one minute or less" when: @@ -359,6 +376,7 @@ regexp: ^(?i)(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.15 | PATCH | Ensure sshd LogLevel is appropriate" when: @@ -377,6 +395,7 @@ regexp: ^(?i)(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.16 | PATCH | Ensure sshd MaxAuthTries is set to 4 or less" when: @@ -393,6 +412,7 @@ regexp: '^(#)?MaxAuthTries \d' line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.17 | PATCH | Ensure sshd MaxStartups is configured" when: @@ -413,6 +433,7 @@ regexp: ^(?i)(#|)\s*MaxStartups line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" when: @@ -433,6 +454,7 @@ regexp: ^(?i)(#|)\s*MaxSessions line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.19 | PATCH | Ensure sshd PermitEmptyPasswords is disabled" when: @@ -453,6 +475,7 @@ regexp: ^(?i)(#|)\s*PermitEmptyPasswords line: 'PermitEmptyPasswords no' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled" when: @@ -471,11 +494,13 @@ regexp: ^(?i)(#|)\s*PermitRootLogin line: 'PermitRootLogin no' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | override file" ansible.builtin.file: path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf state: absent + notify: Restart sshd - name: "5.1.21 | PATCH | Ensure sshd PermitUserEnvironment is disabled" when: @@ -493,9 +518,10 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9_cis_sshd_config_file }}" - regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" + regexp: ^(?i)(#|)\s*PermitUserEnvironment line: 'PermitUserEnvironment no' validate: sshd -t -f %s + notify: Restart sshd - name: "5.1.22 | PATCH | Ensure SSH PAM is enabled" when: @@ -513,6 +539,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9_cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxStartupsUsePAM + regexp: ^(?i)(#|)\s*UsePAM line: 'UsePAM yes' validate: sshd -t -f %s + notify: Restart sshd From 565ef207155c825196297978fca8666242cbf78c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 8 Aug 2024 11:08:09 +0100 Subject: [PATCH 039/327] updated authselect logic Signed-off-by: Mark Bolwell --- defaults/main.yml | 36 +++++++++- tasks/main.yml | 23 +++++++ tasks/section_5/cis_5.3.2.x.yml | 111 +++++++++++------------------- tasks/section_5/cis_5.3.3.3.x.yml | 58 +++++++++++----- 4 files changed, 135 insertions(+), 93 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 04f8f71..b836238 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -641,7 +641,7 @@ rhel9cis_chrony_server_minsources: 2 # # Setting both Service and Mask to false will remove the package if exists rhel9cis_autofs_services: false -rhel9cis_autofs_mask: true +rhel9cis_autofs_mask: false rhel9cis_avahi_server: false rhel9cis_avahi_mask: false rhel9cis_dhcp_server: false @@ -860,7 +860,7 @@ rhel9cis_sudoers_exclude_nopasswd_list: ## Control 5.2 - Ensure access to the 'su' command is restricted # This variable determines the name of the group of users that are allowed to use the su command. # CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. -rhel9cis_sugroup: nosugroup +rhel9cis_sugroup: sugroup ## 5.3.x PAM and Authselect # Do not use authselect if: @@ -868,10 +868,30 @@ rhel9cis_sugroup: nosugroup # 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. -rhel9cis_allow_authselect_updates: false +rhel9cis_allow_authselect_updates: true ## rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install + +## PAM AND Authselect + +# To create a new profile (best for greenfield fresh sites not configured) +# This allows creation of a custom profile using an existing one to build from +# will only create if profiel does not already exist +## options true or false +rhel9cis_authselect_custom_profile_create: true +## Controls: +# - 5.3.2.1 - Ensure custom authselect profile is used +# Settings in place now will fail, they are placeholders 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. + +# This variable configures the name of the custom profile to be created and selected. +# To be changed from default - cis_example_profile +rhel9cis_authselect_custom_profile_name: cis_example_profile +# Name of the existing authselect profile to copy - options can be found with +# ```authselect list``` on the host to be configured +rhel9cis_authselect_default_profile_to_copy: "sssd --symlink-meta" + ## Controls # - 5.3.3. - Ensure lockout for failed password attempts is configured # - 5.5.3 - Ensure password reuse is limited @@ -905,7 +925,12 @@ rhel9cis_passwd_minlen_value: 14 # 5.3.3.2.3 - password complex rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # pragma: allowlist secret +# Choose if using minclass or credits options +# Options are: minclass or credits +# ensure only one is selected +rhel9cis_passwd_complex_option: minclass rhel9cis_passwd_minclass: 3 +#rhel9cis_passwd_complex: credits rhel9cis_passwd_dcredit: -1 rhel9cis_passwd_ucredit: -2 rhel9cis_passwd_ocredit: 0 @@ -931,6 +956,11 @@ rhel9cis_passwd_quality_enforce_value: 1 rhel9cis_passwd_quality_enforce_root_file: etc/security/pwquality.conf.d/50-pwroot.conf # pragma: allowlist secret rhel9cis_passwd_quality_enforce_root_value: enforce_for_root # pragma: allowlist secret +# PWhistory +## 5.3.3.3.1 remember history +# rhel9cis_pamd_pwhistory_remember: - is the number of old passwords to remember +rhel9cis_pamd_pwhistory_remember: 24 + # 5.3.3.4.x rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret diff --git a/tasks/main.yml b/tasks/main.yml index 6a28be4..488c765 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -112,6 +112,29 @@ fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" +- name: "PRELIM | AUDIT | Check authselect profile is selected" + when: + - rhel9cis_allow_authselect_updates + tags: + - always + block: + - name: "PRELIM | AUDIT | Check authselect profile name has been updated" + ansible.builtin.assert: + that: rhel9cis_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" + ansible.builtin.shell: authselect current + changed_when: false + failed_when: prelim_authselect_current_config.rc not in [ 0, 1 ] + register: prelim_authselect_current_config + + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.assert: + that: prelim_authselect_current_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: "Ensure root password is set" when: - rhel9cis_rule_5_4_2_4 diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 3f318c9..3bc8ec0 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,19 +14,28 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: - - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - - rhel9cis_authselect_custom_profile_create - - not rhel9cis_5_3_2_1_profile.stat.exists - ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }}" + when: prelim_authselect_current_config.stdout is not defined + ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" args: - creates: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}" + creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" - - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Select profiles" - when: - - "rhel9cis_authselect['custom_profile_name'] not in authselect_running_config.stdout" - - rhel9cis_authselect_custom_profile_select - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force" + - name: "5.3.2.1 | AUDIT | Ensure active authselect profile includes pam modules | get profile features" + ansible.builtin.shell: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" + changed_when: false + register: discovered_authselect_profile_features + + - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Add missing pam modules to config | pwquality" + when: "'with-pwquality' not in discovered_authselect_profile_features.stdout_lines" + ansible.builtin.lineinfile: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^password\s*requisite\s*pam_pwquality.so.* + line: password requisite pam_pwquality.so local_users_only {include if "with-pwquality"} + loop: + - system + - password + + - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Backup and Add pam modules" + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled" when: @@ -45,17 +54,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.2 - notify: Update_authselect + notify: Authselect update block: - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_faillock.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_faillock - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-faillock" + when: rhel9cis_authselect_current_faillock.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: @@ -70,62 +79,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.3 - notify: Update_authselect block: - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" ansible.builtin.shell: authselect current | grep quality changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_quality.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_quality - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-pwquality" - -# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" -# when: -# - rhel9cis_rule_5_3_2_3 -# - rhel9cis_disruption_high -# - rhel9cis_allow_authselect_updates -# tags: -# - level1-server -# - level1-workstation -# - automated -# - patch -# - NIST800-53R5_IA-5 -# - authselect -# - rule_5.3.2.3 -# notify: Update_authselect -# block: -# - name: "5.3.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: rhel9cis_pwquality_enabled.rc not in [ 0, 1 ] -# register: rhel9cis_pwquality_enabled - -# - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | system-auth" -# when: "'system-auth:password' not in rhel9cis_pwquality_enabled.stdout" -# ansible.builtin.lineinfile: -# path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth -# regexp: "{{ item.regexp }}" -# line: "{{ item.line }}" -# backrefs: true -# insertbefore: "{{ item.before | default (omit) }}" -# 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: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | password-auth" -# when: "'password-auth:password' not in rhel9cis_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/{{ rhel9cis_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]' } + when: rhel9cis_authselect_current_quality.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" when: @@ -140,17 +104,17 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.4 - notify: Update_authselect block: - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: rhel9cis_authselect_current.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current + failed_when: rhel9cis_authselect_current_history.rc not in [ 0, 1 ] + register: rhel9cis_authselect_current_history - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: rhel9cis_authselect_current.rc != 0 - ansible.builtin.shell: "authselect enable-feature with-pwhistory" + when: rhel9cis_authselect_current_history.rc != 0 + ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" when: @@ -173,6 +137,9 @@ failed_when: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] register: rhel9cis_authselect_pam_unix + - debug: + msg: "{{ rhel9cis_authselect_pam_unix }}" + - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" when: "'system-auth:password' not in rhel9cis_authselect_pam_unix.stdout" ansible.builtin.lineinfile: @@ -185,6 +152,7 @@ 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' } + notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" when: "'password-auth:password' not in rhel9cis_authselect_pam_unix.stdout" @@ -198,3 +166,4 @@ 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' } + notify: Authselect update diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index ffb1bff..6c04d33 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -16,16 +16,11 @@ changed_when: false failed_when: rhel9_pwhistory_remember.rc not in [0, 1] - - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set" - when: - - rhel9_pwhistory_remember.stdout | length > 0 - - not rhel9cis_allow_authselect_updates + - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set pwhistory file" ansible.builtin.lineinfile: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" - regexp: ^(password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+)(.*)(remember=\d+) - line: '\1\2 remember={{ rhel9cis_pamd_pwhistory_remember }}' - backrefs: true - notify: Pam_auth_update_pwhistory + path: "/etc/security/pwhistory.conf" + regexp: remember\s*=\s*\d* + line: remember = {{ rhel9cis_pamd_pwhistory_remember }} - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files NOT AuthSelect" when: @@ -55,7 +50,6 @@ - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user" when: - rhel9cis_rule_5_3_3_3_2 - - rhel9cis_disruption_high tags: - level1-server - level1-workstation @@ -69,26 +63,45 @@ changed_when: false failed_when: rhel9_pwhistory_enforce_for_root.rc not in [0, 1] - - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure remember is set" + - name: "5.3.3.3.2 | PATCH| Ensure password history is enforced for the root user | Ensure enforce_for_root is set pwhistory file" + ansible.builtin.lineinfile: + path: "/etc/security/pwhistory.conf" + regexp: ^\s*(?#)enforce_for_root + line: enforce_for_root + + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_enforce_for_root.stdout | length > 0 + - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root) line: '\1\2\3 enforce_for_root' backrefs: true - notify: Pam_auth_update_pwhistory + + - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" + when: + - rhel9cis_allow_authselect_updates + - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - rhel9cis_disruption_high + ansible.builtin.replace: + path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" + regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\senforce_for_root(.*$) + replace: \1\2enforce_for_root\3 + loop: + - password + - system + notify: Authselect update - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" when: - rhel9cis_rule_5_3_3_3_3 - - rhel9cis_disruption_high tags: - level1-server - level1-workstation - patch - - rule_5.3.3.3.2 + - rule_5.3.3.3.3 - pam block: - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" @@ -97,20 +110,27 @@ changed_when: false failed_when: rhel9_pwhistory_use_authtok.rc not in [0, 1] - - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure remember is set" + - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Update pwhistory for use_authtok" + ansible.builtin.lineinfile: + path: "/etc/security/pwhistory.conf" + regexp: ^\s*(?#)use_authtok + line: use_authtok + + - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure use_authtok is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_use_authtok.stdout | length > 0 + - rhel9_pwhistory_use_authtok.stdout | length == 0 + - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) - line: '\1\2\3 use_authtok' + line: '\1\2 use_authtok' backrefs: true - notify: Pam_auth_update_pwhistory - name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect" when: - rhel9cis_allow_authselect_updates + - rhel9_pwhistory_use_authtok.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" From 485a85db76227ad7becb027c9fd549890be59d6c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 8 Aug 2024 11:08:22 +0100 Subject: [PATCH 040/327] improved jinja logic Signed-off-by: Mark Bolwell --- .../etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 index 0c12e7a..ecf6e58 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -1,7 +1,11 @@ # CIS Configurations # 5.3.3.2.3 Ensure password complexity is configured +{% if rhel9cis_passwd_complex_option == minclass %} minclass = {{ rhel9cis_passwd_minclass }} +{ %endif %} +{% if rhel9cis_passwd_complex_option == credits %} dcredit = {{rhel9cis_passwd_dcredit }} ucredit = {{ rhel9cis_passwd_ucredit }} ocredit = {{ rhel9cis_passwd_ocredit }} lcredit = {{ rhel9cis_passwd_lcredit }} +{% endif %} From 265423eb0ab2f2974d9a48c85ae1c4e7b2d3fc4b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:13:17 +0100 Subject: [PATCH 041/327] improved tests and updated Signed-off-by: Mark Bolwell --- tasks/main.yml | 8 +- tasks/section_5/cis_5.3.2.x.yml | 4 +- tasks/section_5/cis_5.3.3.4.x.yml | 28 ++++--- tasks/section_5/cis_5.4.1.x.yml | 16 ++-- tasks/section_6/cis_6.1.x.yml | 36 +++++--- tasks/section_6/cis_6.2.2.1.x.yml | 82 ------------------ tasks/section_6/cis_6.2.2.x.yml | 83 +++++++++++++++++++ tasks/section_6/cis_6.2.4.1.yml | 48 +++++------ tasks/section_6/main.yml | 7 +- templates/audit/99_auditd.rules.j2 | 5 +- .../pwquality.conf.d/50-pwcomplexity.conf.j2 | 6 +- 11 files changed, 171 insertions(+), 152 deletions(-) create mode 100644 tasks/section_6/cis_6.2.2.x.yml diff --git a/tasks/main.yml b/tasks/main.yml index 488c765..8e283e0 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -124,14 +124,14 @@ fail_msg: "You still have the default name for your authselect profile" - name: "PRELIM | AUDIT | Check authselect profile is selected" - ansible.builtin.shell: authselect current + ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' changed_when: false - failed_when: prelim_authselect_current_config.rc not in [ 0, 1 ] - register: prelim_authselect_current_config + failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] + register: prelim_authselect_current_profile - name: "PRELIM | AUDIT | Check authselect profile is selected" ansible.builtin.assert: - that: prelim_authselect_current_config is defined + that: prelim_authselect_current_profile is defined success_msg: "Authselect is running and profile is selected" fail_msg: Authselect updates have been selected there are issues with profile selection" diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 3bc8ec0..571cb70 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,7 +14,9 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: prelim_authselect_current_config.stdout is not defined + when: + - rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or + prelim_authselect_current_profile.stdout is not defined ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" args: creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml index 89f39cc..4712373 100644 --- a/tasks/section_5/cis_5.3.3.4.x.yml +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -51,7 +51,7 @@ - rule_5.3.3.4.2 block: - name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" - ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -P -- '\bremember\b' + ansible.builtin.shell: grep -E "password.*pam_unix.so.*remember" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq changed_when: false failed_when: rhel9cis_pam_remember.rc not in [ 0, 1 ] register: rhel9cis_pam_remember @@ -61,9 +61,10 @@ - not rhel9cis_allow_authselect_updates - rhel9cis_pam_remember.stdout | length > 0 ansible.builtin.replace: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" - regexp: remember=\d+ + path: "{{ item }}" + regexp: remember replace: '' + loop: "{{ rhel9cis_pam_remember.stdout_lines }}" - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Remove remember from pam files AuthSelect" when: @@ -90,7 +91,7 @@ - NIST800-53R5_IA-5 block: - name: "5.3.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" - ansible.builtin.shell: grep -PH -- '^\h*password\h+([^#\n\r]+)\h+pam_unix\.so\h+([^#\n\r]+\h+)?("{{ rhel9cis_passwd_hash_algo }}")\b' /etc/pam.d/*-auth + ansible.builtin.shell: grep -E "password.*pam_unix.so.*(sha512|yescrypt)" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq changed_when: false failed_when: rhel9cis_pam_pwhash.rc not in [ 0, 1 ] register: rhel9cis_pam_pwhash @@ -100,17 +101,18 @@ - not rhel9cis_allow_authselect_updates - rhel9cis_pam_remember.stdout | length > 0 ansible.builtin.replace: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwunix_file }}" + path: "{{ item }}" regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)" replace: '{{ rhel9cis_passwd_hash_algo }}' + loop: "{{ rhel9cis_pam_remember.stdout_lines }}" - - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Remove remember from pam files AuthSelect" + - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Add hash algorithm to pam files AuthSelect" when: - rhel9cis_allow_authselect_updates ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)(sha512|yescrypt)(.*$) - line: \1\2 {{ rhel9cis_passwd_hash_algo }}\4 + regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)(sha512|yescrypt)(.*$) + line: \1\2\3\4{{ rhel9cis_passwd_hash_algo }}\6 backrefs: true loop: - password @@ -130,7 +132,7 @@ - NIST800-53R5_IA-5 block: - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" - ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix\.so\b' /etc/pam.d/{password,system}-auth | grep -Pv -- '\buse_authtok\b' + ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix.so\b' /etc/pam.d/{password,system}-auth | grep -Pv -- '\buse_authtok\b' changed_when: false failed_when: rhel9cis_pam_authtok.rc not in [ 0, 1 ] register: rhel9cis_pam_authtok @@ -142,8 +144,8 @@ - rhel9cis_pam_authtok.stdout | length > 0 ansible.builtin.lineinfile: path: "{{ item }}" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)use_authtok(.*$) - line: \1\2 use_authtok\3 + regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$) + line: \1\2\3\4use_authtok \5 backrefs: true loop: "{{ rhel9cis_pam_authtok.stdout_lines }}" @@ -152,8 +154,8 @@ - rhel9cis_allow_authselect_updates ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)use_authtok(.*$) - line: \1\2 use_authtok\3 + regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$) + line: \1\2\3\4use_authtok\5 backrefs: true loop: - password diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 9da1ed0..a5cd8c5 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -19,10 +19,10 @@ ansible.builtin.lineinfile: path: /etc/login.defs regexp: '^PASS_MAX_DAYS' - line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}" + line: "PASS_MAX_DAYS {{ rhel9cis_pass_max_days }}" - name: "5.4.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS" - ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass['max_days'] }} || $5< {{ rhel9cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow" + ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass_max_days }} || $5< {{ rhel9cis_pass_max_days }} || $5 == -1)){print $1}' /etc/shadow" changed_when: false failed_when: false register: discovered_max_days @@ -34,7 +34,7 @@ - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass['max_days'] }}" + password_expire_max: "{{ rhel9cis_pass_max_days }}" loop: "{{ discovered_max_days.stdout_lines }}" - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured" @@ -51,10 +51,10 @@ ansible.builtin.lineinfile: path: /etc/login.defs regexp: '^PASS_MIN_DAYS' - line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}" + line: "PASS_MIN_DAYS {{ rhel9cis_pass_min_days }}" - name: "5.4.1.2 | AUDIT | Ensure minimum password days is configured | Get existing users PASS_MIN_DAYS" - ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass['min_days'] }} {print $1}' /etc/shadow" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass_min_days }} {print $1}' /etc/shadow" changed_when: false failed_when: false register: discovered_min_days @@ -66,7 +66,7 @@ - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass['min_days'] }}" + password_expire_max: "{{ rhel9cis_pass_min_days }}" loop: "{{ discovered_min_days.stdout_lines }}" - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" @@ -83,10 +83,10 @@ ansible.builtin.lineinfile: path: /etc/login.defs regexp: '^PASS_WARN_AGE' - line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}" + line: "PASS_WARN_AGE {{ rhel9cis_pass_warn_age }}" - name: "5.4.1.3 | AUDIT | Ensure password expiration warning days is configured | Get existing users WARN_DAYS" - ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass['warn_age'] }} {print $1}' /etc/shadow" + ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass_warn_age }} {print $1}' /etc/shadow" changed_when: false failed_when: false register: discovered_warn_days diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 5ff643b..95f8064 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -46,16 +46,32 @@ - patch - rule_6.1.2 - NIST800-53R5_AU-2 - ansible.builtin.cron: - name: Run AIDE integrity check - cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}" - user: "{{ rhel9cis_aide_cron['cron_user'] }}" - minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}" - hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}" - day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}" - month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}" - weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}" - job: "{{ rhel9cis_aide_cron['aide_job'] }}" + block: + - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" + when: rhel9cis_aide_scan == "cron" + ansible.builtin.cron: + name: Run AIDE integrity check + cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}" + user: "{{ rhel9cis_aide_cron['cron_user'] }}" + minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}" + hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}" + day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}" + month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}" + weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}" + job: "{{ rhel9cis_aide_cron['aide_job'] }}" + + - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" + when: rhel9cis_aide_scan == "timer" + ansible.builtin.systemd: + name: aidecheck.service + enabled: true + + - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" + when: rhel9cis_aide_scan == "timer" + ansible.builtin.systemd: + name: aidecheck.timer + state: running + enabled: true - name: "6.1.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" when: diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml index 20b148b..00e949b 100644 --- a/tasks/section_6/cis_6.2.2.1.x.yml +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -78,85 +78,3 @@ loop: - systemd-journal-remote.socket - systemd-journal-remote.service - -- name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled" - when: - - rhel9cis_rule_6_2_2_2 - tags: - - level1-server - - level2-workstation - - patch - - journald - - rule_6.2.2.2 - - NIST800-53R5_AU-2 - - NIST800-53R5_AU-6 - - NIST800-53R5_AU-7 - - NIST800-53R5_AU-12 - notify: Restart journald - block: - - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | Add file" - ansible.builtin.template: - src: etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 - dest: /etc/systemd/journald.conf.d/forwardtosyslog.conf - owner: root - group: root - mode: '0640' - - - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | comment out current entries" - ansible.builtin.replace: - path: /etc/systemd/journald.conf - regexp: ^(\s*ForwardToSyslog) - replace: '#\1' - -- name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" - when: - - rhel9cis_rule_6_2_2_3 - tags: - - level1-server - - level1-workstation - - patch - - journald - - rule_6.2.2.3 - - NIST800-53R5_AU-4 - notify: Restart journald - block: - - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | Add file" - ansible.builtin.template: - src: etc/systemd/journald.conf.d/storage.conf.j2 # Added to the same file as 6.2.1.1.4 - dest: /etc/systemd/journald.conf.d/storage.conf - owner: root - group: root - mode: '0640' - - - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" - ansible.builtin.replace: - path: /etc/systemd/journald.conf - regexp: ^(?i)(\s*compress=) - replace: '#\1' - -- name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" - when: - - rhel9cis_rule_6_2_2_4 - tags: - - level1-server - - level1-workstation - - patch - - journald - - rule_6.2.2.4 - - NIST800-53R5_AU-3 - - NIST800-53R5_AU-12 - notify: Restart journald - block: - - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | Add file" - ansible.builtin.template: - src: etc/systemd/journald.conf.d/storage.conf.j2 - dest: /etc/systemd/journald.conf.d/storage.conf - owner: root - group: root - mode: '0640' - - - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" - ansible.builtin.replace: - path: /etc/systemd/journald.conf - regexp: ^(?i)(\s*storage=) - replace: '#\1' diff --git a/tasks/section_6/cis_6.2.2.x.yml b/tasks/section_6/cis_6.2.2.x.yml new file mode 100644 index 0000000..3dd8dab --- /dev/null +++ b/tasks/section_6/cis_6.2.2.x.yml @@ -0,0 +1,83 @@ +--- + +- name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled" + when: + - rhel9cis_rule_6_2_2_2 + tags: + - level1-server + - level2-workstation + - patch + - journald + - rule_6.2.2.2 + - NIST800-53R5_AU-2 + - NIST800-53R5_AU-6 + - NIST800-53R5_AU-7 + - NIST800-53R5_AU-12 + notify: Restart journald + block: + - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/forwardtosyslog.conf.j2 + dest: /etc/systemd/journald.conf.d/forwardtosyslog.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(\s*ForwardToSyslog) + replace: '#\1' + +- name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" + when: + - rhel9cis_rule_6_2_2_3 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.3 + - NIST800-53R5_AU-4 + notify: Restart journald + block: + - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/storage.conf.j2 # Added to the same file as 6.2.1.1.4 + dest: /etc/systemd/journald.conf.d/storage.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(?i)(\s*compress=) + replace: '#\1' + +- name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" + when: + - rhel9cis_rule_6_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - journald + - rule_6.2.2.4 + - NIST800-53R5_AU-3 + - NIST800-53R5_AU-12 + notify: Restart journald + block: + - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | Add file" + ansible.builtin.template: + src: etc/systemd/journald.conf.d/storage.conf.j2 + dest: /etc/systemd/journald.conf.d/storage.conf + owner: root + group: root + mode: '0640' + + - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" + ansible.builtin.replace: + path: /etc/systemd/journald.conf + regexp: ^(?i)(\s*storage=) + replace: '#\1' diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index 68799c8..07ba04b 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -16,47 +16,37 @@ failed_when: false register: discovered_logfiles - - name: "6.2.4.1 | AUDIT | Ensure access to all logfiles has been configured | set_fact" + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" when: - discovered_logfiles.stdout_lines | length > 0 - - discovered_logfiles is defined - ansible.builtin.set_fact: - discovered_logfiles_flattened: "{{ discovered_logfiles.stdout_lines | flatten }}" - - - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" - when: - - discovered_logfiles_flattened is defined - - item == "/var/log/secure" - - item == "/var/log/auth.log" - - item == "/var/log/syslog" - - "'journal' in item" + - ('audit.log' in item or 'journal' in item) or + item == '/var/log/secure' or + item == '/var/log/syslog' or + item == '/var/log/messages' or + item == '/var/log/auth.log' ansible.builtin.file: path: "{{ item }}" mode: 'u-x,g-wx,o-rwx' - loop: "{{ discovered_logfiles_flattened }}" + loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" when: - - discovered_logfiles_flattened is defined - - item == "/var/log/btmp" - - item == "/var/log/utmp" - - item == "/var/log/wtmp" - - item == "/var/log/lastlog" + - discovered_logfiles.stdout_lines | length > 0 + - ('anaconda' in item or 'dnf' in item or 'secure' in item or 'messages' in item or 'hawkey' in item) ansible.builtin.file: path: "{{ item }}" - mode: 'u-x,g-wx,o-rwx' - owner: root - group: root - loop: "{{ discovered_logfiles_flattened }}" + mode: 'u-x,g-x,o-rwx' + loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" when: - - discovered_logfiles_flattened is defined - - "'sssd' in item" - - item == "/var/log/utmp" - - item == "/var/log/wtmp" - - item == "/var/log/lastlog" + - discovered_logfiles.stdout_lines | length > 0 + - ('sssd' in item or 'lastlog' in item) or + item == "/var/log/btmp" or + item == "/var/log/utmp" or + item == "/var/log/wtmp" or + item == "/var/log/lastlog" ansible.builtin.file: path: "{{ item }}" - mode: 'u-x,g-wx,o-rwx' - loop: "{{ discovered_logfiles_flattened }}" + mode: 'ug-x,o-wx' + loop: "{{ discovered_logfiles.stdout_lines }}" diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index c75ebed..a1909dc 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -8,11 +8,16 @@ ansible.builtin.import_tasks: file: cis_6.2.1.x.yml -- name: "SECTION | 6.2.2 | Configure journald" +- name: "SECTION | 6.2.2.1.x | Configure journald-remote" when: rhel9cis_syslog == 'journald' ansible.builtin.import_tasks: file: cis_6.2.2.1.x.yml +- name: "SECTION | 6.2.2.x | Configure journald" + when: rhel9cis_syslog == 'journald' + ansible.builtin.import_tasks: + file: cis_6.2.2.x.yml + - name: "SECTION | 6.2.3 | Configure rsyslog" when: rhel9cis_syslog == 'rsyslog' ansible.builtin.import_tasks: diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 20eb5df..bfb925b 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -46,6 +46,9 @@ -w /etc/gshadow -p wa -k identity -w /etc/shadow -p wa -k identity -w /etc/security/opasswd -p wa -k identity +-w /etc/nsswitch.conf -p wa -k identity +-w /etc/pam.conf -p wa -k identity +-w /etc/pam.d -p wa -k identity {% endif %} {% if rhel9cis_rule_6_3_3_9 %} -a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod @@ -83,7 +86,7 @@ -a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_chng {% endif %} {% if rhel9cis_rule_6_3_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k priv_cmd +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k priv_chng {% endif %} {% if rhel9cis_rule_6_3_3_18 %} -a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k usermod diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 index ecf6e58..6a9855a 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -1,9 +1,9 @@ # CIS Configurations # 5.3.3.2.3 Ensure password complexity is configured -{% if rhel9cis_passwd_complex_option == minclass %} +{% if rhel9cis_passwd_complex_option == 'minclass' %} minclass = {{ rhel9cis_passwd_minclass }} -{ %endif %} -{% if rhel9cis_passwd_complex_option == credits %} +{% endif %} +{% if rhel9cis_passwd_complex_option == 'credits' %} dcredit = {{rhel9cis_passwd_dcredit }} ucredit = {{ rhel9cis_passwd_ucredit }} ocredit = {{ rhel9cis_passwd_ocredit }} From 89345c12f89e69f297a37b6e87fc5c1aec5eb3de Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:13:35 +0100 Subject: [PATCH 042/327] rename snmp var Signed-off-by: Mark Bolwell --- defaults/main.yml | 15 +++++++++------ tasks/section_2/cis_2.1.x.yml | 8 ++++---- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index b836238..95b6184 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -666,8 +666,8 @@ rhel9cis_rpc_server: true rhel9cis_rpc_mask: true rhel9cis_rsync_server: false rhel9cis_rsync_mask: false -rhel9cis_net_snmp_server: false -rhel9cis_net_snmp_mask: false +rhel9cis_snmp_server: false +rhel9cis_snmp_mask: false rhel9cis_telnet_server: false rhel9cis_telnet_mask: false rhel9cis_tftp_server: false @@ -965,19 +965,18 @@ rhel9cis_pamd_pwhistory_remember: 24 rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret ## Section 5.4.1.x: Shadow Password Suite Parameters -rhel9cis_pass: ## Control 5.6.1.1 - Ensure password expiration is 365 days or less # This variable governs after how many days a password expires. # CIS requires a value of 365 or less. - max_days: 365 +rhel9cis_pass_max_days: 365 ## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more # This variable specifies the minimum number of days allowed between changing # passwords. CIS requires a value of at least 1. - min_days: 7 +rhel9cis_pass_min_days: 7 ## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more # This variable governs, how many days before a password expires, the user will be warned. # CIS requires a value of at least 7. - warn_age: 7 +rhel9cis_pass_warn_age: 7 ## Control 5.4.1.x - Ensure inactive password lock is 30 days or less rhel9cis_inactivelock: @@ -1052,6 +1051,10 @@ max_int_uid: 65533 rhel9cis_config_aide: true ## Control 6.1.2 AIDE cron settings + +## How the aide schedule is run either cron or timer +rhel9cis_aide_scan: cron + # These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. # The sub-settings of this variable provide the parameters required to configure # the cron job on the target system. diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index a3df3eb..73e7986 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -461,16 +461,16 @@ block: - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Remove package" when: - - not rhel9cis_net_snmp_server - - not rhel9cis_net_snmp_mask + - not rhel9cis_snmp_server + - not rhel9cis_snmp_mask ansible.builtin.package: name: net-snmp state: absent - name: "2.1.14 | PATCH | Ensure snmp services are not in use | Mask service" when: - - not rhel9cis_net_snmp_server - - rhel9cis_net_snmp_mask + - not rhel9cis_snmp_server + - rhel9cis_snmp_mask notify: Systemd_daemon_reload ansible.builtin.systemd: name: snmpd.service From fd3b9703e34a07e5923e5e211ea6a949a10179b6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:14:56 +0100 Subject: [PATCH 043/327] tidy up and realign Signed-off-by: Mark Bolwell --- defaults/main.yml | 15 - templates/ansible_vars_goss.yml.j2 | 990 ++++++++++++++++++----------- vars/main.yml | 17 + 3 files changed, 642 insertions(+), 380 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 95b6184..32d3fcf 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -4,21 +4,6 @@ # These values may be overriden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: # https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable -## Usage on containerized images -# The role discovers dynamically (in tasks/main.yml) whether it -# is executed on a container image and sets the variable -# system_is_container the true. Otherwise, the default value -# 'false' is left unchanged. -system_is_container: false -# The filename of the existing yml file in role's 'vars/' sub-directory -# to be used for managing the role-behavior when a container was detected: -# (de)activating rules or for other tasks(e.g. disabling Selinux or a specific -# firewall-type). -container_vars_file: is_container.yml -# rhel9cis is left off the front of this var for consistency in testing pipeline -# system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks -system_is_ec2: false - # Run the OS validation check # Supported OSs will not need for this to be changed - see README e.g. CentOS os_check: true diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index f3b8a98..ad44fb3 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -1,116 +1,145 @@ +--- -## This file is managed by Ansible, YOUR CHANGED WILL BE LOST! -## metadata for benchmark -## metadata for Audit benchmark -benchmark_version: '1.0.0' +# Enable logrunning potential resource intensive tests +run_heavy_tests: {{ audit_run_heavy_tests }} -# Set if genuine RHEL (subscription manager check) not for derivatives e.g. CentOS -# If run via script this is discovered and set -host_os_distribution: {{ ansible_facts.distribution | lower }} - -# timeout for each command to run where set - default = 10seconds/10000ms +# Extend default command timeout for longer running tests timeout_ms: {{ audit_cmd_timeout }} -# Taken from LE rhel9-cis +## Switching on/off specific baseline sections +# These variables govern whether the tasks of a particular section are to be executed when running the role. +# E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. +# If you do not want the tasks from that section to get executed you simply set the variable to "false". rhel9cis_section1: {{ rhel9cis_section1 }} rhel9cis_section2: {{ rhel9cis_section2 }} rhel9cis_section3: {{ rhel9cis_section3 }} rhel9cis_section4: {{ rhel9cis_section4 }} rhel9cis_section5: {{ rhel9cis_section5 }} rhel9cis_section6: {{ rhel9cis_section6 }} +rhel9cis_section7: {{ rhel9cis_section7 }} +# This is used for audit purposes to run only specific level use the tags +# e.g. +# - level1-server +# - level2-workstation rhel9cis_level_1: {{ rhel9cis_level_1 }} rhel9cis_level_2: {{ rhel9cis_level_2 }} +## Section 1.6 - Mandatory Access Control +# This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting +# 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. rhel9cis_selinux_disable: {{ rhel9cis_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 - -# True is BIOS based system else set to false -{% if rhel9cis_legacy_boot is defined %} +# This variable is used in a preliminary task, handling grub2 paths either in case of +# UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: {{ rhel9cis_legacy_boot }} -{% endif %} -rhel9cis_set_boot_pass: {{ rhel9cis_set_boot_pass }} +## Benchmark name used by audting control role +# The audit variable found at the base +## metadata for Audit benchmark +benchmark_version: 'v2.0.0' + +benchmark: RHEL9-CIS # 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. # You must enable an entire section in order for the variables below to take effect. -# Section 1 rules -# 1.1.1 Disable unused filesystems + +# Section 1 is Initial setup (FileSystem Configuration, Configure Software Updates, Filesystem Integrity Checking, Secure Boot Settings, +# Additional Process Hardening, Mandatory Access Control, Command Line Warning Banners, and GNOME Display Manager) +# Filesystem kernel modules rhel9cis_rule_1_1_1_1: {{ rhel9cis_rule_1_1_1_1 }} rhel9cis_rule_1_1_1_2: {{ rhel9cis_rule_1_1_1_2 }} -# 1.1.2 Configure /tmp -rhel9cis_rule_1_1_2_1: {{ rhel9cis_rule_1_1_2_1 }} -rhel9cis_rule_1_1_2_2: {{ rhel9cis_rule_1_1_2_2 }} -rhel9cis_rule_1_1_2_3: {{ rhel9cis_rule_1_1_2_3 }} -rhel9cis_rule_1_1_2_4: {{ rhel9cis_rule_1_1_2_4 }} -# 1.1.3 Configure /var -rhel9cis_rule_1_1_3_1: {{ rhel9cis_rule_1_1_3_1 }} -rhel9cis_rule_1_1_3_2: {{ rhel9cis_rule_1_1_3_2 }} -rhel9cis_rule_1_1_3_3: {{ rhel9cis_rule_1_1_3_3 }} -# 1.1.4 Configure /var/tmp -rhel9cis_rule_1_1_4_1: {{ rhel9cis_rule_1_1_4_1 }} -rhel9cis_rule_1_1_4_2: {{ rhel9cis_rule_1_1_4_2 }} -rhel9cis_rule_1_1_4_3: {{ rhel9cis_rule_1_1_4_3 }} -rhel9cis_rule_1_1_4_4: {{ rhel9cis_rule_1_1_4_4 }} -# 1.1.5 Configure /var/log -rhel9cis_rule_1_1_5_1: {{ rhel9cis_rule_1_1_5_1 }} -rhel9cis_rule_1_1_5_2: {{ rhel9cis_rule_1_1_5_2 }} -rhel9cis_rule_1_1_5_3: {{ rhel9cis_rule_1_1_5_3 }} -rhel9cis_rule_1_1_5_4: {{ rhel9cis_rule_1_1_5_4 }} -# 1.1.6 Configure /var/log/audit -rhel9cis_rule_1_1_6_1: {{ rhel9cis_rule_1_1_6_1 }} -rhel9cis_rule_1_1_6_2: {{ rhel9cis_rule_1_1_6_2 }} -rhel9cis_rule_1_1_6_3: {{ rhel9cis_rule_1_1_6_3 }} -rhel9cis_rule_1_1_6_4: {{ rhel9cis_rule_1_1_6_4 }} -# 1.1.7 Configure /home -rhel9cis_rule_1_1_7_1: {{ rhel9cis_rule_1_1_7_1 }} -rhel9cis_rule_1_1_7_2: {{ rhel9cis_rule_1_1_7_2 }} -rhel9cis_rule_1_1_7_3: {{ rhel9cis_rule_1_1_7_3 }} -# 1.1.8 Configure /dev/shm -rhel9cis_rule_1_1_8_1: {{ rhel9cis_rule_1_1_8_1 }} -rhel9cis_rule_1_1_8_2: {{ rhel9cis_rule_1_1_8_2 }} -rhel9cis_rule_1_1_8_3: {{ rhel9cis_rule_1_1_8_3 }} -rhel9cis_rule_1_1_8_4: {{ rhel9cis_rule_1_1_8_4 }} -# 1.9 usb-storage -rhel9cis_rule_1_1_9: {{ rhel9cis_rule_1_1_9 }} -# 1.2 Configure Software Updates -rhel9cis_rule_1_2_1: {{ rhel9cis_rule_1_2_1 }} -rhel9cis_rule_1_2_2: {{ rhel9cis_rule_1_2_2 }} -rhel9cis_rule_1_2_3: {{ rhel9cis_rule_1_2_3 }} -rhel9cis_rule_1_2_4: {{ rhel9cis_rule_1_2_4 }} -# 1.3 Filesystem Integrity Checking -rhel9cis_rule_1_3_1: {{ rhel9cis_rule_1_3_1 }} -rhel9cis_rule_1_3_2: {{ rhel9cis_rule_1_3_2 }} -rhel9cis_rule_1_3_3: {{ rhel9cis_rule_1_3_3 }} -# 1.4 Secure Boot Settings +rhel9cis_rule_1_1_1_3: {{ rhel9cis_rule_1_1_1_3 }} +rhel9cis_rule_1_1_1_4: {{ rhel9cis_rule_1_1_1_4 }} +rhel9cis_rule_1_1_1_5: {{ rhel9cis_rule_1_1_1_5 }} +rhel9cis_rule_1_1_1_6: {{ rhel9cis_rule_1_1_1_6 }} +rhel9cis_rule_1_1_1_7: {{ rhel9cis_rule_1_1_1_7 }} +rhel9cis_rule_1_1_1_8: {{ rhel9cis_rule_1_1_1_8 }} +rhel9cis_rule_1_1_1_9: {{ rhel9cis_rule_1_1_1_9 }} +# Filesystems +# /tmp +rhel9cis_rule_1_1_2_1_1: {{ rhel9cis_rule_1_1_2_1_1 }} +rhel9cis_rule_1_1_2_1_2: {{ rhel9cis_rule_1_1_2_1_2 }} +rhel9cis_rule_1_1_2_1_3: {{ rhel9cis_rule_1_1_2_1_3 }} +rhel9cis_rule_1_1_2_1_4: {{ rhel9cis_rule_1_1_2_1_4 }} +# /dev/shm +rhel9cis_rule_1_1_2_2_1: {{ rhel9cis_rule_1_1_2_2_1 }} +rhel9cis_rule_1_1_2_2_2: {{ rhel9cis_rule_1_1_2_2_2 }} +rhel9cis_rule_1_1_2_2_3: {{ rhel9cis_rule_1_1_2_2_3 }} +rhel9cis_rule_1_1_2_2_4: {{ rhel9cis_rule_1_1_2_2_4 }} +# /home +rhel9cis_rule_1_1_2_3_1: {{ rhel9cis_rule_1_1_2_3_1 }} +rhel9cis_rule_1_1_2_3_2: {{ rhel9cis_rule_1_1_2_3_2 }} +rhel9cis_rule_1_1_2_3_3: {{ rhel9cis_rule_1_1_2_3_3 }} +# /var +rhel9cis_rule_1_1_2_4_1: {{ rhel9cis_rule_1_1_2_4_1 }} +rhel9cis_rule_1_1_2_4_2: {{ rhel9cis_rule_1_1_2_4_2 }} +rhel9cis_rule_1_1_2_4_3: {{ rhel9cis_rule_1_1_2_4_3 }} +# /var/tmp +rhel9cis_rule_1_1_2_5_1: {{ rhel9cis_rule_1_1_2_5_1 }} +rhel9cis_rule_1_1_2_5_2: {{ rhel9cis_rule_1_1_2_5_2 }} +rhel9cis_rule_1_1_2_5_3: {{ rhel9cis_rule_1_1_2_5_3 }} +rhel9cis_rule_1_1_2_5_4: {{ rhel9cis_rule_1_1_2_5_4 }} +# /var/log +rhel9cis_rule_1_1_2_6_1: {{ rhel9cis_rule_1_1_2_6_1 }} +rhel9cis_rule_1_1_2_6_2: {{ rhel9cis_rule_1_1_2_6_2 }} +rhel9cis_rule_1_1_2_6_3: {{ rhel9cis_rule_1_1_2_6_3 }} +rhel9cis_rule_1_1_2_6_4: {{ rhel9cis_rule_1_1_2_6_4 }} +# /var/log/audit +rhel9cis_rule_1_1_2_7_1: {{ rhel9cis_rule_1_1_2_7_1 }} +rhel9cis_rule_1_1_2_7_2: {{ rhel9cis_rule_1_1_2_7_2 }} +rhel9cis_rule_1_1_2_7_3: {{ rhel9cis_rule_1_1_2_7_3 }} +rhel9cis_rule_1_1_2_7_4: {{ rhel9cis_rule_1_1_2_7_4 }} + +# Package Mgmt +# Config Pkg Repos +rhel9cis_rule_1_2_1_1: {{ rhel9cis_rule_1_2_1_1 }} +rhel9cis_rule_1_2_1_2: {{ rhel9cis_rule_1_2_1_2 }} +rhel9cis_rule_1_2_1_3: {{ rhel9cis_rule_1_2_1_3 }} +rhel9cis_rule_1_2_1_4: {{ rhel9cis_rule_1_2_1_4 }} +# Package updates +rhel9cis_rule_1_2_2_1: {{ rhel9cis_rule_1_2_2_1 }} + +# Selinux +rhel9cis_rule_1_3_1_1: {{ rhel9cis_rule_1_3_1_1 }} +rhel9cis_rule_1_3_1_2: {{ rhel9cis_rule_1_3_1_2 }} +rhel9cis_rule_1_3_1_3: {{ rhel9cis_rule_1_3_1_3 }} +rhel9cis_rule_1_3_1_4: {{ rhel9cis_rule_1_3_1_4 }} +rhel9cis_rule_1_3_1_5: {{ rhel9cis_rule_1_3_1_5 }} +rhel9cis_rule_1_3_1_6: {{ rhel9cis_rule_1_3_1_6 }} +rhel9cis_rule_1_3_1_7: {{ rhel9cis_rule_1_3_1_7 }} +rhel9cis_rule_1_3_1_8: {{ rhel9cis_rule_1_3_1_8 }} + +# Bootloader rhel9cis_rule_1_4_1: {{ rhel9cis_rule_1_4_1 }} rhel9cis_rule_1_4_2: {{ rhel9cis_rule_1_4_2 }} -# 1.5 Additional Process Hardening + +# Additional Process Hardening rhel9cis_rule_1_5_1: {{ rhel9cis_rule_1_5_1 }} rhel9cis_rule_1_5_2: {{ rhel9cis_rule_1_5_2 }} rhel9cis_rule_1_5_3: {{ rhel9cis_rule_1_5_3 }} -# 1.6 Mandatory Access Control -rhel9cis_rule_1_6_1_1: {{ rhel9cis_rule_1_6_1_1 }} -rhel9cis_rule_1_6_1_2: {{ rhel9cis_rule_1_6_1_2 }} -rhel9cis_rule_1_6_1_3: {{ rhel9cis_rule_1_6_1_3 }} -rhel9cis_rule_1_6_1_4: {{ rhel9cis_rule_1_6_1_4 }} -rhel9cis_rule_1_6_1_5: {{ rhel9cis_rule_1_6_1_5 }} -rhel9cis_rule_1_6_1_6: {{ rhel9cis_rule_1_6_1_6 }} -rhel9cis_rule_1_6_1_7: {{ rhel9cis_rule_1_6_1_7 }} -rhel9cis_rule_1_6_1_8: {{ rhel9cis_rule_1_6_1_8 }} -# 1.7 Command Line Warning Banners +rhel9cis_rule_1_5_4: {{ rhel9cis_rule_1_5_4 }} + +# Config system wide Crypto +rhel9cis_rule_1_6_1: {{ rhel9cis_rule_1_6_1 }} +rhel9cis_rule_1_6_2: {{ rhel9cis_rule_1_6_2 }} +rhel9cis_rule_1_6_3: {{ rhel9cis_rule_1_6_3 }} +rhel9cis_rule_1_6_4: {{ rhel9cis_rule_1_6_4 }} +rhel9cis_rule_1_6_5: {{ rhel9cis_rule_1_6_5 }} +rhel9cis_rule_1_6_6: {{ rhel9cis_rule_1_6_6 }} +rhel9cis_rule_1_6_7: {{ rhel9cis_rule_1_6_7 }} + +# Command line warning banners rhel9cis_rule_1_7_1: {{ rhel9cis_rule_1_7_1 }} rhel9cis_rule_1_7_2: {{ rhel9cis_rule_1_7_2 }} rhel9cis_rule_1_7_3: {{ rhel9cis_rule_1_7_3 }} rhel9cis_rule_1_7_4: {{ rhel9cis_rule_1_7_4 }} rhel9cis_rule_1_7_5: {{ rhel9cis_rule_1_7_5 }} rhel9cis_rule_1_7_6: {{ rhel9cis_rule_1_7_6 }} -# 1.8 Gnome Display Manager + +# Gnome Display Manager rhel9cis_rule_1_8_1: {{ rhel9cis_rule_1_8_1 }} rhel9cis_rule_1_8_2: {{ rhel9cis_rule_1_8_2 }} rhel9cis_rule_1_8_3: {{ rhel9cis_rule_1_8_3 }} @@ -121,52 +150,68 @@ rhel9cis_rule_1_8_7: {{ rhel9cis_rule_1_8_7 }} rhel9cis_rule_1_8_8: {{ rhel9cis_rule_1_8_8 }} rhel9cis_rule_1_8_9: {{ rhel9cis_rule_1_8_9 }} rhel9cis_rule_1_8_10: {{ rhel9cis_rule_1_8_10 }} -# 1.9 Ensure updates, patches, and additional security software are installed -rhel9cis_rule_1_9: {{ rhel9cis_rule_1_9 }} -# Ensure system-wide crypto policy is not legacy -rhel9cis_rule_1_10: {{ rhel9cis_rule_1_10 }} -# section 2 -# Services -# 2.1 Time Synchronization +# Section 2 rules are controling Services (Special Purpose Services, and service clients) +## Configure Server Services rhel9cis_rule_2_1_1: {{ rhel9cis_rule_2_1_1 }} rhel9cis_rule_2_1_2: {{ rhel9cis_rule_2_1_2 }} -# 2.2 Special Purpose Services +rhel9cis_rule_2_1_3: {{ rhel9cis_rule_2_1_3 }} +rhel9cis_rule_2_1_4: {{ rhel9cis_rule_2_1_4 }} +rhel9cis_rule_2_1_5: {{ rhel9cis_rule_2_1_5 }} +rhel9cis_rule_2_1_6: {{ rhel9cis_rule_2_1_6 }} +rhel9cis_rule_2_1_7: {{ rhel9cis_rule_2_1_7 }} +rhel9cis_rule_2_1_8: {{ rhel9cis_rule_2_1_8 }} +rhel9cis_rule_2_1_9: {{ rhel9cis_rule_2_1_9 }} +rhel9cis_rule_2_1_10: {{ rhel9cis_rule_2_1_10 }} +rhel9cis_rule_2_1_11: {{ rhel9cis_rule_2_1_11 }} +rhel9cis_rule_2_1_12: {{ rhel9cis_rule_2_1_12 }} +rhel9cis_rule_2_1_13: {{ rhel9cis_rule_2_1_13 }} +rhel9cis_rule_2_1_14: {{ rhel9cis_rule_2_1_14 }} +rhel9cis_rule_2_1_15: {{ rhel9cis_rule_2_1_15 }} +rhel9cis_rule_2_1_16: {{ rhel9cis_rule_2_1_16 }} +rhel9cis_rule_2_1_17: {{ rhel9cis_rule_2_1_17 }} +rhel9cis_rule_2_1_18: {{ rhel9cis_rule_2_1_18 }} +rhel9cis_rule_2_1_19: {{ rhel9cis_rule_2_1_19 }} +rhel9cis_rule_2_1_20: {{ rhel9cis_rule_2_1_20 }} +rhel9cis_rule_2_1_21: {{ rhel9cis_rule_2_1_21 }} +rhel9cis_rule_2_1_22: {{ rhel9cis_rule_2_1_22 }} + +## Configure Client Services rhel9cis_rule_2_2_1: {{ rhel9cis_rule_2_2_1 }} rhel9cis_rule_2_2_2: {{ rhel9cis_rule_2_2_2 }} rhel9cis_rule_2_2_3: {{ rhel9cis_rule_2_2_3 }} rhel9cis_rule_2_2_4: {{ rhel9cis_rule_2_2_4 }} rhel9cis_rule_2_2_5: {{ rhel9cis_rule_2_2_5 }} -rhel9cis_rule_2_2_6: {{ rhel9cis_rule_2_2_6 }} -rhel9cis_rule_2_2_7: {{ rhel9cis_rule_2_2_7 }} -rhel9cis_rule_2_2_8: {{ rhel9cis_rule_2_2_8 }} -rhel9cis_rule_2_2_9: {{ rhel9cis_rule_2_2_9 }} -rhel9cis_rule_2_2_10: {{ rhel9cis_rule_2_2_10 }} -rhel9cis_rule_2_2_11: {{ rhel9cis_rule_2_2_11 }} -rhel9cis_rule_2_2_12: {{ rhel9cis_rule_2_2_12 }} -rhel9cis_rule_2_2_13: {{ rhel9cis_rule_2_2_13 }} -rhel9cis_rule_2_2_14: {{ rhel9cis_rule_2_2_14 }} -rhel9cis_rule_2_2_15: {{ rhel9cis_rule_2_2_15 }} -rhel9cis_rule_2_2_16: {{ rhel9cis_rule_2_2_16 }} -rhel9cis_rule_2_2_17: {{ rhel9cis_rule_2_2_17 }} -rhel9cis_rule_2_2_18: {{ rhel9cis_rule_2_2_18 }} -# 2.3 service clients + +## Configure Time Synchronization rhel9cis_rule_2_3_1: {{ rhel9cis_rule_2_3_1 }} rhel9cis_rule_2_3_2: {{ rhel9cis_rule_2_3_2 }} rhel9cis_rule_2_3_3: {{ rhel9cis_rule_2_3_3 }} -rhel9cis_rule_2_3_4: {{ rhel9cis_rule_2_3_4 }} -rhel9cis_rule_2_4: true +## Job Schedulers +### cron +rhel9cis_rule_2_4_1_1: {{ rhel9cis_rule_2_4_1_1 }} +rhel9cis_rule_2_4_1_2: {{ rhel9cis_rule_2_4_1_2 }} +rhel9cis_rule_2_4_1_3: {{ rhel9cis_rule_2_4_1_3 }} +rhel9cis_rule_2_4_1_4: {{ rhel9cis_rule_2_4_1_4 }} +rhel9cis_rule_2_4_1_5: {{ rhel9cis_rule_2_4_1_5 }} +rhel9cis_rule_2_4_1_6: {{ rhel9cis_rule_2_4_1_6 }} +rhel9cis_rule_2_4_1_7: {{ rhel9cis_rule_2_4_1_7 }} +rhel9cis_rule_2_4_1_8: {{ rhel9cis_rule_2_4_1_8 }} +### at +rhel9cis_rule_2_4_2_1: {{ rhel9cis_rule_2_4_2_1 }} -# Section 3 rules -# 3.1 Disable unused network protocols and devices +# Section 3 Network +## Network Devices rhel9cis_rule_3_1_1: {{ rhel9cis_rule_3_1_1 }} rhel9cis_rule_3_1_2: {{ rhel9cis_rule_3_1_2 }} rhel9cis_rule_3_1_3: {{ rhel9cis_rule_3_1_3 }} -# 3.2 Network Parameters (Host Only) +## Network Kernel Modules rhel9cis_rule_3_2_1: {{ rhel9cis_rule_3_2_1 }} rhel9cis_rule_3_2_2: {{ rhel9cis_rule_3_2_2 }} -# 3.3 Network Parameters (Host and Router) +rhel9cis_rule_3_2_3: {{ rhel9cis_rule_3_2_3 }} +rhel9cis_rule_3_2_4: {{ rhel9cis_rule_3_2_4 }} +# Network Kernel Parameters rhel9cis_rule_3_3_1: {{ rhel9cis_rule_3_3_1 }} rhel9cis_rule_3_3_2: {{ rhel9cis_rule_3_3_2 }} rhel9cis_rule_3_3_3: {{ rhel9cis_rule_3_3_3 }} @@ -176,94 +221,24 @@ rhel9cis_rule_3_3_6: {{ rhel9cis_rule_3_3_6 }} rhel9cis_rule_3_3_7: {{ rhel9cis_rule_3_3_7 }} rhel9cis_rule_3_3_8: {{ rhel9cis_rule_3_3_8 }} rhel9cis_rule_3_3_9: {{ rhel9cis_rule_3_3_9 }} -# 3.4.1 Configure firewalld -rhel9cis_rule_3_4_1_1: {{ rhel9cis_rule_3_4_1_1 }} -rhel9cis_rule_3_4_1_2: {{ rhel9cis_rule_3_4_1_2 }} +rhel9cis_rule_3_3_10: {{ rhel9cis_rule_3_3_10 }} +rhel9cis_rule_3_3_11: {{ rhel9cis_rule_3_3_11 }} -# 3.4.1 Configure nftables -rhel9cis_rule_3_4_2_1: {{ rhel9cis_rule_3_4_2_1 }} -rhel9cis_rule_3_4_2_2: {{ rhel9cis_rule_3_4_2_2 }} -rhel9cis_rule_3_4_2_3: {{ rhel9cis_rule_3_4_2_3 }} -rhel9cis_rule_3_4_2_4: {{ rhel9cis_rule_3_4_2_4 }} -rhel9cis_rule_3_4_2_5: {{ rhel9cis_rule_3_4_2_5 }} -rhel9cis_rule_3_4_2_6: {{ rhel9cis_rule_3_4_2_6 }} -rhel9cis_rule_3_4_2_7: {{ rhel9cis_rule_3_4_2_7 }} +# Section 4 Firewalls +## Firewall utility +rhel9cis_rule_4_1_1: {{ rhel9cis_rule_4_1_1 }} +rhel9cis_rule_4_1_2: {{ rhel9cis_rule_4_1_2 }} +## Configure firewalld +rhel9cis_rule_4_2_1: {{ rhel9cis_rule_4_2_1 }} +rhel9cis_rule_4_2_2: {{ rhel9cis_rule_4_2_2 }} +# Configure nftables +rhel9cis_rule_4_3_1: {{ rhel9cis_rule_4_3_1 }} +rhel9cis_rule_4_3_2: {{ rhel9cis_rule_4_3_2 }} +rhel9cis_rule_4_3_3: {{ rhel9cis_rule_4_3_3 }} +rhel9cis_rule_4_3_4: {{ rhel9cis_rule_4_3_4 }} -# Section 4 rules -# 4.1 Configure System Accounting -rhel9cis_rule_4_1_1_1: {{ rhel9cis_rule_4_1_1_1 }} -rhel9cis_rule_4_1_1_2: {{ rhel9cis_rule_4_1_1_2 }} -rhel9cis_rule_4_1_1_3: {{ rhel9cis_rule_4_1_1_3 }} -rhel9cis_rule_4_1_1_4: {{ rhel9cis_rule_4_1_1_4 }} - -# 4.1.2 Configure Data retention -rhel9cis_rule_4_1_2_1: {{ rhel9cis_rule_4_1_2_1 }} -rhel9cis_rule_4_1_2_2: {{ rhel9cis_rule_4_1_2_2 }} -rhel9cis_rule_4_1_2_3: {{ rhel9cis_rule_4_1_2_3 }} - -# 4.1.3 Configure auditd rules -rhel9cis_rule_4_1_3_1: {{ rhel9cis_rule_4_1_3_1 }} -rhel9cis_rule_4_1_3_2: {{ rhel9cis_rule_4_1_3_2 }} -rhel9cis_rule_4_1_3_3: {{ rhel9cis_rule_4_1_3_3 }} -rhel9cis_rule_4_1_3_4: {{ rhel9cis_rule_4_1_3_4 }} -rhel9cis_rule_4_1_3_5: {{ rhel9cis_rule_4_1_3_5 }} -rhel9cis_rule_4_1_3_6: {{ rhel9cis_rule_4_1_3_6 }} -rhel9cis_rule_4_1_3_7: {{ rhel9cis_rule_4_1_3_7 }} -rhel9cis_rule_4_1_3_8: {{ rhel9cis_rule_4_1_3_8 }} -rhel9cis_rule_4_1_3_9: {{ rhel9cis_rule_4_1_3_9 }} -rhel9cis_rule_4_1_3_10: {{ rhel9cis_rule_4_1_3_10 }} -rhel9cis_rule_4_1_3_11: {{ rhel9cis_rule_4_1_3_11 }} -rhel9cis_rule_4_1_3_12: {{ rhel9cis_rule_4_1_3_12 }} -rhel9cis_rule_4_1_3_13: {{ rhel9cis_rule_4_1_3_13 }} -rhel9cis_rule_4_1_3_14: {{ rhel9cis_rule_4_1_3_14 }} -rhel9cis_rule_4_1_3_15: {{ rhel9cis_rule_4_1_3_15 }} -rhel9cis_rule_4_1_3_16: {{ rhel9cis_rule_4_1_3_16 }} -rhel9cis_rule_4_1_3_17: {{ rhel9cis_rule_4_1_3_17 }} -rhel9cis_rule_4_1_3_18: {{ rhel9cis_rule_4_1_3_18 }} -rhel9cis_rule_4_1_3_19: {{ rhel9cis_rule_4_1_3_19 }} -rhel9cis_rule_4_1_3_20: {{ rhel9cis_rule_4_1_3_20 }} -rhel9cis_rule_4_1_3_21: {{ rhel9cis_rule_4_1_3_21 }} - -# 4.1.4 Configure auditd file Access -rhel9cis_rule_4_1_4_1: {{ rhel9cis_rule_4_1_4_1 }} -rhel9cis_rule_4_1_4_2: {{ rhel9cis_rule_4_1_4_2 }} -rhel9cis_rule_4_1_4_3: {{ rhel9cis_rule_4_1_4_3 }} -rhel9cis_rule_4_1_4_4: {{ rhel9cis_rule_4_1_4_4 }} -rhel9cis_rule_4_1_4_5: {{ rhel9cis_rule_4_1_4_5 }} -rhel9cis_rule_4_1_4_6: {{ rhel9cis_rule_4_1_4_6 }} -rhel9cis_rule_4_1_4_7: {{ rhel9cis_rule_4_1_4_7 }} -rhel9cis_rule_4_1_4_8: {{ rhel9cis_rule_4_1_4_8 }} -rhel9cis_rule_4_1_4_9: {{ rhel9cis_rule_4_1_4_9 }} -rhel9cis_rule_4_1_4_10: {{ rhel9cis_rule_4_1_4_10 }} - -# 4.2.1 Configure rsyslog -rhel9cis_rule_4_2_1_1: {{ rhel9cis_rule_4_2_1_1 }} -rhel9cis_rule_4_2_1_2: {{ rhel9cis_rule_4_2_1_2 }} -rhel9cis_rule_4_2_1_3: {{ rhel9cis_rule_4_2_1_3 }} -rhel9cis_rule_4_2_1_4: {{ rhel9cis_rule_4_2_1_4 }} -rhel9cis_rule_4_2_1_5: {{ rhel9cis_rule_4_2_1_5 }} -rhel9cis_rule_4_2_1_6: {{ rhel9cis_rule_4_2_1_6 }} -rhel9cis_rule_4_2_1_7: {{ rhel9cis_rule_4_2_1_7 }} - -# 4.2.2 Configure journald -rhel9cis_rule_4_2_2_1_1: {{ rhel9cis_rule_4_2_2_1_1 }} -rhel9cis_rule_4_2_2_1_2: {{ rhel9cis_rule_4_2_2_1_2 }} -rhel9cis_rule_4_2_2_1_3: {{ rhel9cis_rule_4_2_2_1_3 }} -rhel9cis_rule_4_2_2_1_4: {{ rhel9cis_rule_4_2_2_1_4 }} -rhel9cis_rule_4_2_2_2: {{ rhel9cis_rule_4_2_2_2 }} -rhel9cis_rule_4_2_2_3: {{ rhel9cis_rule_4_2_2_3 }} -rhel9cis_rule_4_2_2_4: {{ rhel9cis_rule_4_2_2_4 }} -rhel9cis_rule_4_2_2_5: {{ rhel9cis_rule_4_2_2_5 }} -rhel9cis_rule_4_2_2_6: {{ rhel9cis_rule_4_2_2_6 }} -rhel9cis_rule_4_2_2_7: {{ rhel9cis_rule_4_2_2_7 }} -rhel9cis_rule_4_2_3: {{ rhel9cis_rule_4_2_3 }} - -# 4.3 Logrotate -rhel9cis_rule_4_3: {{ rhel9cis_rule_4_3 }} - -# Section 5 -# Authentication and Authorization -# 5.1 Configure time-based job schedulers +## Section 5 +## 5.1. Configure SSH Server rhel9cis_rule_5_1_1: {{ rhel9cis_rule_5_1_1 }} rhel9cis_rule_5_1_2: {{ rhel9cis_rule_5_1_2 }} rhel9cis_rule_5_1_3: {{ rhel9cis_rule_5_1_3 }} @@ -273,8 +248,20 @@ rhel9cis_rule_5_1_6: {{ rhel9cis_rule_5_1_6 }} rhel9cis_rule_5_1_7: {{ rhel9cis_rule_5_1_7 }} rhel9cis_rule_5_1_8: {{ rhel9cis_rule_5_1_8 }} rhel9cis_rule_5_1_9: {{ rhel9cis_rule_5_1_9 }} - -# 5.2 Configure SSH Server +rhel9cis_rule_5_1_10: {{ rhel9cis_rule_5_1_10 }} +rhel9cis_rule_5_1_11: {{ rhel9cis_rule_5_1_11 }} +rhel9cis_rule_5_1_12: {{ rhel9cis_rule_5_1_12 }} +rhel9cis_rule_5_1_13: {{ rhel9cis_rule_5_1_13 }} +rhel9cis_rule_5_1_14: {{ rhel9cis_rule_5_1_14 }} +rhel9cis_rule_5_1_15: {{ rhel9cis_rule_5_1_15 }} +rhel9cis_rule_5_1_16: {{ rhel9cis_rule_5_1_16 }} +rhel9cis_rule_5_1_17: {{ rhel9cis_rule_5_1_17 }} +rhel9cis_rule_5_1_18: {{ rhel9cis_rule_5_1_18 }} +rhel9cis_rule_5_1_19: {{ rhel9cis_rule_5_1_19 }} +rhel9cis_rule_5_1_20: {{ rhel9cis_rule_5_1_20 }} +rhel9cis_rule_5_1_21: {{ rhel9cis_rule_5_1_21 }} +rhel9cis_rule_5_1_22: {{ rhel9cis_rule_5_1_22 }} +## 5.2 Configure Privilege Escalation rhel9cis_rule_5_2_1: {{ rhel9cis_rule_5_2_1 }} rhel9cis_rule_5_2_2: {{ rhel9cis_rule_5_2_2 }} rhel9cis_rule_5_2_3: {{ rhel9cis_rule_5_2_3 }} @@ -282,223 +269,496 @@ rhel9cis_rule_5_2_4: {{ rhel9cis_rule_5_2_4 }} rhel9cis_rule_5_2_5: {{ rhel9cis_rule_5_2_5 }} rhel9cis_rule_5_2_6: {{ rhel9cis_rule_5_2_6 }} rhel9cis_rule_5_2_7: {{ rhel9cis_rule_5_2_7 }} -rhel9cis_rule_5_2_8: {{ rhel9cis_rule_5_2_8 }} -rhel9cis_rule_5_2_9: {{ rhel9cis_rule_5_2_9 }} -rhel9cis_rule_5_2_10: {{ rhel9cis_rule_5_2_10 }} -rhel9cis_rule_5_2_11: {{ rhel9cis_rule_5_2_11 }} -rhel9cis_rule_5_2_12: {{ rhel9cis_rule_5_2_12 }} -rhel9cis_rule_5_2_13: {{ rhel9cis_rule_5_2_13 }} -rhel9cis_rule_5_2_14: {{ rhel9cis_rule_5_2_14 }} -rhel9cis_rule_5_2_15: {{ rhel9cis_rule_5_2_15 }} -rhel9cis_rule_5_2_16: {{ rhel9cis_rule_5_2_16 }} -rhel9cis_rule_5_2_17: {{ rhel9cis_rule_5_2_17 }} -rhel9cis_rule_5_2_18: {{ rhel9cis_rule_5_2_18 }} -rhel9cis_rule_5_2_19: {{ rhel9cis_rule_5_2_19 }} -rhel9cis_rule_5_2_20: {{ rhel9cis_rule_5_2_20 }} -# 5.3 Configure privilege escalation -rhel9cis_rule_5_3_1: {{ rhel9cis_rule_5_3_1 }} -rhel9cis_rule_5_3_2: {{ rhel9cis_rule_5_3_2 }} -rhel9cis_rule_5_3_3: {{ rhel9cis_rule_5_3_3 }} -rhel9cis_rule_5_3_4: {{ rhel9cis_rule_5_3_4 }} -rhel9cis_rule_5_3_5: {{ rhel9cis_rule_5_3_5 }} -rhel9cis_rule_5_3_6: {{ rhel9cis_rule_5_3_6 }} -rhel9cis_rule_5_3_7: {{ rhel9cis_rule_5_3_7 }} +# 5.3.1.x Configure PAM software packages +rhel9cis_rule_5_3_1_1: {{ rhel9cis_rule_5_3_1_1 }} +rhel9cis_rule_5_3_1_2: {{ rhel9cis_rule_5_3_1_2 }} +rhel9cis_rule_5_3_1_3: {{ rhel9cis_rule_5_3_1_3 }} +# 5.3.2 Configure authselect +rhel9cis_rule_5_3_2_1: {{ rhel9cis_rule_5_3_2_1 }} +rhel9cis_rule_5_3_2_2: {{ rhel9cis_rule_5_3_2_2 }} +rhel9cis_rule_5_3_2_3: {{ rhel9cis_rule_5_3_2_3 }} +rhel9cis_rule_5_3_2_4: {{ rhel9cis_rule_5_3_2_4 }} +rhel9cis_rule_5_3_2_5: {{ rhel9cis_rule_5_3_2_5 }} +# 5.3.3.1 Configure pam_faillock module +rhel9cis_rule_5_3_3_1_1: {{ rhel9cis_rule_5_3_3_1_1 }} +rhel9cis_rule_5_3_3_1_2: {{ rhel9cis_rule_5_3_3_1_2 }} +rhel9cis_rule_5_3_3_1_3: {{ rhel9cis_rule_5_3_3_1_3 }} +# 5.3.3.2 Configure pam_pwquality module +rhel9cis_rule_5_3_3_2_1: {{ rhel9cis_rule_5_3_3_2_1 }} +rhel9cis_rule_5_3_3_2_2: {{ rhel9cis_rule_5_3_3_2_2 }} +rhel9cis_rule_5_3_3_2_3: {{ rhel9cis_rule_5_3_3_2_3 }} +rhel9cis_rule_5_3_3_2_4: {{ rhel9cis_rule_5_3_3_2_4 }} +rhel9cis_rule_5_3_3_2_5: {{ rhel9cis_rule_5_3_3_2_5 }} +rhel9cis_rule_5_3_3_2_6: {{ rhel9cis_rule_5_3_3_2_6 }} +rhel9cis_rule_5_3_3_2_7: {{ rhel9cis_rule_5_3_3_2_7 }} +rhel9cis_rule_5_3_3_2_8: {{ rhel9cis_rule_5_3_3_2_8 }} +# 5.3.3.3 Configure pam_pwhistory module +# This are added as part of 5.3.2.4 using jinja2 template +rhel9cis_rule_5_3_3_3_1: {{ rhel9cis_rule_5_3_3_3_1 }} +rhel9cis_rule_5_3_3_3_2: {{ rhel9cis_rule_5_3_3_3_2 }} +rhel9cis_rule_5_3_3_3_3: {{ rhel9cis_rule_5_3_3_3_3 }} +# 5.3.3.4 Configure pam_unix module +rhel9cis_rule_5_3_3_4_1: {{ rhel9cis_rule_5_3_3_4_1 }} +rhel9cis_rule_5_3_3_4_2: {{ rhel9cis_rule_5_3_3_4_2 }} +rhel9cis_rule_5_3_3_4_3: {{ rhel9cis_rule_5_3_3_4_3 }} +rhel9cis_rule_5_3_3_4_4: {{ rhel9cis_rule_5_3_3_4_4 }} +# 5.4 User Accounts and Environment +# 5.4.1 Configure shadow password suite parameters +rhel9cis_rule_5_4_1_1: {{ rhel9cis_rule_5_4_1_1 }} +rhel9cis_rule_5_4_1_2: {{ rhel9cis_rule_5_4_1_2 }} +rhel9cis_rule_5_4_1_3: {{ rhel9cis_rule_5_4_1_3 }} +rhel9cis_rule_5_4_1_4: {{ rhel9cis_rule_5_4_1_4 }} +rhel9cis_rule_5_4_1_5: {{ rhel9cis_rule_5_4_1_5 }} +rhel9cis_rule_5_4_1_6: {{ rhel9cis_rule_5_4_1_6 }} +# 5.4.2 Configure root and system accounts and environment +rhel9cis_rule_5_4_2_1: {{ rhel9cis_rule_5_4_2_1 }} +rhel9cis_rule_5_4_2_2: {{ rhel9cis_rule_5_4_2_2 }} +rhel9cis_rule_5_4_2_3: {{ rhel9cis_rule_5_4_2_3 }} +rhel9cis_rule_5_4_2_4: {{ rhel9cis_rule_5_4_2_4 }} +rhel9cis_rule_5_4_2_5: {{ rhel9cis_rule_5_4_2_5 }} +rhel9cis_rule_5_4_2_6: {{ rhel9cis_rule_5_4_2_6 }} +rhel9cis_rule_5_4_2_7: {{ rhel9cis_rule_5_4_2_7 }} +rhel9cis_rule_5_4_2_8: {{ rhel9cis_rule_5_4_2_8 }} +# 5.4.2 Configure user default environment +rhel9cis_rule_5_4_3_1: {{ rhel9cis_rule_5_4_3_1 }} +rhel9cis_rule_5_4_3_2: {{ rhel9cis_rule_5_4_3_2 }} +rhel9cis_rule_5_4_3_3: {{ rhel9cis_rule_5_4_3_3 }} -# 5.4 Configure authselect - -rhel9cis_rule_5_4_1: {{ rhel9cis_rule_5_4_1 }} -rhel9cis_rule_5_4_2: {{ rhel9cis_rule_5_4_2 }} - -# 5.5 Configure PAM -rhel9cis_rule_5_5_1: {{ rhel9cis_rule_5_5_1 }} -rhel9cis_rule_5_5_2: {{ rhel9cis_rule_5_5_2 }} -rhel9cis_rule_5_5_3: {{ rhel9cis_rule_5_5_3 }} -rhel9cis_rule_5_5_4: {{ rhel9cis_rule_5_5_4 }} - -# 5.6 User Accounts and Environment -# 5.6.1 Set Shadow Password Suite Parameters -rhel9cis_rule_5_6_1_1: {{ rhel9cis_rule_5_6_1_1 }} -rhel9cis_rule_5_6_1_2: {{ rhel9cis_rule_5_6_1_2 }} -rhel9cis_rule_5_6_1_3: {{ rhel9cis_rule_5_6_1_3 }} -rhel9cis_rule_5_6_1_4: {{ rhel9cis_rule_5_6_1_4 }} -rhel9cis_rule_5_6_1_5: {{ rhel9cis_rule_5_6_1_5 }} -rhel9cis_rule_5_6_2: {{ rhel9cis_rule_5_6_2 }} -rhel9cis_rule_5_6_3: {{ rhel9cis_rule_5_6_3 }} -rhel9cis_rule_5_6_4: {{ rhel9cis_rule_5_6_4 }} -rhel9cis_rule_5_6_5: {{ rhel9cis_rule_5_6_5 }} -rhel9cis_rule_5_6_6: {{ rhel9cis_rule_5_6_6 }} - -# Section 6 -# 6 System Maintenance -# 6.1 System File Permissions +# Section 6 Logging and Auditing +## 6.1 Configure Integrity Checking rhel9cis_rule_6_1_1: {{ rhel9cis_rule_6_1_1 }} rhel9cis_rule_6_1_2: {{ rhel9cis_rule_6_1_2 }} rhel9cis_rule_6_1_3: {{ rhel9cis_rule_6_1_3 }} -rhel9cis_rule_6_1_4: {{ rhel9cis_rule_6_1_4 }} -rhel9cis_rule_6_1_5: {{ rhel9cis_rule_6_1_5 }} -rhel9cis_rule_6_1_6: {{ rhel9cis_rule_6_1_6 }} -rhel9cis_rule_6_1_7: {{ rhel9cis_rule_6_1_7 }} -rhel9cis_rule_6_1_8: {{ rhel9cis_rule_6_1_8 }} -rhel9cis_rule_6_1_9: {{ rhel9cis_rule_6_1_9 }} -rhel9cis_rule_6_1_10: {{ rhel9cis_rule_6_1_10 }} -rhel9cis_rule_6_1_11: {{ rhel9cis_rule_6_1_11 }} -rhel9cis_rule_6_1_12: {{ rhel9cis_rule_6_1_12 }} -rhel9cis_rule_6_1_13: {{ rhel9cis_rule_6_1_13 }} -rhel9cis_rule_6_1_14: {{ rhel9cis_rule_6_1_14 }} -rhel9cis_rule_6_1_15: {{ rhel9cis_rule_6_1_15 }} +## 6.2.1 Configure systemd-journald service +rhel9cis_rule_6_2_1_1: {{ rhel9cis_rule_6_2_1_1 }} +rhel9cis_rule_6_2_1_2: {{ rhel9cis_rule_6_2_1_2 }} +rhel9cis_rule_6_2_1_3: {{ rhel9cis_rule_6_2_1_3 }} +rhel9cis_rule_6_2_1_4: {{ rhel9cis_rule_6_2_1_4 }} +## 6.2.2.x Configure journald +rhel9cis_rule_6_2_2_1_1: {{ rhel9cis_rule_6_2_2_1_1 }} +rhel9cis_rule_6_2_2_1_2: {{ rhel9cis_rule_6_2_2_1_2 }} +rhel9cis_rule_6_2_2_1_3: {{ rhel9cis_rule_6_2_2_1_3 }} +rhel9cis_rule_6_2_2_1_4: {{ rhel9cis_rule_6_2_2_1_4 }} +rhel9cis_rule_6_2_2_2: {{ rhel9cis_rule_6_2_2_2 }} +rhel9cis_rule_6_2_2_3: {{ rhel9cis_rule_6_2_2_3 }} +rhel9cis_rule_6_2_2_4: {{ rhel9cis_rule_6_2_2_4 }} +## 6.2.3 Configure rsyslog +rhel9cis_rule_6_2_3_1: {{ rhel9cis_rule_6_2_3_1 }} +rhel9cis_rule_6_2_3_2: {{ rhel9cis_rule_6_2_3_2 }} +rhel9cis_rule_6_2_3_3: {{ rhel9cis_rule_6_2_3_3 }} +rhel9cis_rule_6_2_3_4: {{ rhel9cis_rule_6_2_3_4 }} +rhel9cis_rule_6_2_3_5: {{ rhel9cis_rule_6_2_3_5 }} +rhel9cis_rule_6_2_3_6: {{ rhel9cis_rule_6_2_3_6 }} +rhel9cis_rule_6_2_3_7: {{ rhel9cis_rule_6_2_3_7 }} +rhel9cis_rule_6_2_3_8: {{ rhel9cis_rule_6_2_3_8 }} +## 6.2.4 Configure Logfiles +rhel9cis_rule_6_2_4_1: {{ rhel9cis_rule_6_2_4_1 }} +## 6.3 Configure Auditing +## 6.3.1 Configure auditd Service +rhel9cis_rule_6_3_1_1: {{ rhel9cis_rule_6_3_1_1 }} +rhel9cis_rule_6_3_1_2: {{ rhel9cis_rule_6_3_1_2 }} +rhel9cis_rule_6_3_1_3: {{ rhel9cis_rule_6_3_1_3 }} +rhel9cis_rule_6_3_1_4: {{ rhel9cis_rule_6_3_1_4 }} +## 6.3.2 Configure Data Retention +rhel9cis_rule_6_3_2_1: {{ rhel9cis_rule_6_3_2_1 }} +rhel9cis_rule_6_3_2_2: {{ rhel9cis_rule_6_3_2_2 }} +rhel9cis_rule_6_3_2_3: {{ rhel9cis_rule_6_3_2_3 }} +rhel9cis_rule_6_3_2_4: {{ rhel9cis_rule_6_3_2_4 }} +## 6.3.3 Configure auditd Rules +rhel9cis_rule_6_3_3_1: {{ rhel9cis_rule_6_3_3_1 }} +rhel9cis_rule_6_3_3_2: {{ rhel9cis_rule_6_3_3_2 }} +rhel9cis_rule_6_3_3_3: {{ rhel9cis_rule_6_3_3_3 }} +rhel9cis_rule_6_3_3_4: {{ rhel9cis_rule_6_3_3_4 }} +rhel9cis_rule_6_3_3_5: {{ rhel9cis_rule_6_3_3_5 }} +rhel9cis_rule_6_3_3_6: {{ rhel9cis_rule_6_3_3_6 }} +rhel9cis_rule_6_3_3_7: {{ rhel9cis_rule_6_3_3_7 }} +rhel9cis_rule_6_3_3_8: {{ rhel9cis_rule_6_3_3_8 }} +rhel9cis_rule_6_3_3_9: {{ rhel9cis_rule_6_3_3_9 }} +rhel9cis_rule_6_3_3_10: {{ rhel9cis_rule_6_3_3_10 }} +rhel9cis_rule_6_3_3_11: {{ rhel9cis_rule_6_3_3_11 }} +rhel9cis_rule_6_3_3_12: {{ rhel9cis_rule_6_3_3_12 }} +rhel9cis_rule_6_3_3_13: {{ rhel9cis_rule_6_3_3_13 }} +rhel9cis_rule_6_3_3_14: {{ rhel9cis_rule_6_3_3_14 }} +rhel9cis_rule_6_3_3_15: {{ rhel9cis_rule_6_3_3_15 }} +rhel9cis_rule_6_3_3_16: {{ rhel9cis_rule_6_3_3_16 }} +rhel9cis_rule_6_3_3_17: {{ rhel9cis_rule_6_3_3_17 }} +rhel9cis_rule_6_3_3_18: {{ rhel9cis_rule_6_3_3_18 }} +rhel9cis_rule_6_3_3_19: {{ rhel9cis_rule_6_3_3_19 }} +rhel9cis_rule_6_3_3_20: {{ rhel9cis_rule_6_3_3_20 }} +rhel9cis_rule_6_3_3_21: {{ rhel9cis_rule_6_3_3_21 }} +## 6.3.4 Configure auditd File Access +rhel9cis_rule_6_3_4_1: {{ rhel9cis_rule_6_3_4_1 }} +rhel9cis_rule_6_3_4_2: {{ rhel9cis_rule_6_3_4_2 }} +rhel9cis_rule_6_3_4_3: {{ rhel9cis_rule_6_3_4_3 }} +rhel9cis_rule_6_3_4_4: {{ rhel9cis_rule_6_3_4_4 }} +rhel9cis_rule_6_3_4_5: {{ rhel9cis_rule_6_3_4_5 }} +rhel9cis_rule_6_3_4_6: {{ rhel9cis_rule_6_3_4_6 }} +rhel9cis_rule_6_3_4_7: {{ rhel9cis_rule_6_3_4_7 }} +rhel9cis_rule_6_3_4_8: {{ rhel9cis_rule_6_3_4_8 }} +rhel9cis_rule_6_3_4_9: {{ rhel9cis_rule_6_3_4_9 }} +rhel9cis_rule_6_3_4_10: {{ rhel9cis_rule_6_3_4_10 }} -# 6.2 User and Group Settings -rhel9cis_rule_6_2_1: {{ rhel9cis_rule_6_2_1 }} -rhel9cis_rule_6_2_2: {{ rhel9cis_rule_6_2_2 }} -rhel9cis_rule_6_2_3: {{ rhel9cis_rule_6_2_3 }} -rhel9cis_rule_6_2_4: {{ rhel9cis_rule_6_2_4 }} -rhel9cis_rule_6_2_5: {{ rhel9cis_rule_6_2_5 }} -rhel9cis_rule_6_2_6: {{ rhel9cis_rule_6_2_6 }} -rhel9cis_rule_6_2_7: {{ rhel9cis_rule_6_2_7 }} -rhel9cis_rule_6_2_8: {{ rhel9cis_rule_6_2_8 }} -rhel9cis_rule_6_2_9: {{ rhel9cis_rule_6_2_9 }} -rhel9cis_rule_6_2_10: {{ rhel9cis_rule_6_2_10 }} -rhel9cis_rule_6_2_11: {{ rhel9cis_rule_6_2_11 }} -rhel9cis_rule_6_2_12: {{ rhel9cis_rule_6_2_12 }} -rhel9cis_rule_6_2_13: {{ rhel9cis_rule_6_2_13 }} -rhel9cis_rule_6_2_14: {{ rhel9cis_rule_6_2_14 }} -rhel9cis_rule_6_2_15: {{ rhel9cis_rule_6_2_15 }} -rhel9cis_rule_6_2_16: {{ rhel9cis_rule_6_2_16 }} +# Section 7 System Maintenance +## 7.1 System File Permissions +rhel9cis_rule_7_1_1: {{ rhel9cis_rule_7_1_1 }} +rhel9cis_rule_7_1_2: {{ rhel9cis_rule_7_1_2 }} +rhel9cis_rule_7_1_3: {{ rhel9cis_rule_7_1_3 }} +rhel9cis_rule_7_1_4: {{ rhel9cis_rule_7_1_4 }} +rhel9cis_rule_7_1_5: {{ rhel9cis_rule_7_1_5 }} +rhel9cis_rule_7_1_6: {{ rhel9cis_rule_7_1_6 }} +rhel9cis_rule_7_1_7: {{ rhel9cis_rule_7_1_7 }} +rhel9cis_rule_7_1_8: {{ rhel9cis_rule_7_1_8 }} +rhel9cis_rule_7_1_9: {{ rhel9cis_rule_7_1_9 }} +rhel9cis_rule_7_1_10: {{ rhel9cis_rule_7_1_10 }} +rhel9cis_rule_7_1_11: {{ rhel9cis_rule_7_1_11 }} +rhel9cis_rule_7_1_12: {{ rhel9cis_rule_7_1_12 }} +rhel9cis_rule_7_1_13: {{ rhel9cis_rule_7_1_13 }} +## 7.2 Local User and Group Settings +rhel9cis_rule_7_2_1: {{ rhel9cis_rule_7_2_1 }} +rhel9cis_rule_7_2_2: {{ rhel9cis_rule_7_2_2 }} +rhel9cis_rule_7_2_3: {{ rhel9cis_rule_7_2_3 }} +rhel9cis_rule_7_2_4: {{ rhel9cis_rule_7_2_4 }} +rhel9cis_rule_7_2_5: {{ rhel9cis_rule_7_2_5 }} +rhel9cis_rule_7_2_6: {{ rhel9cis_rule_7_2_6 }} +rhel9cis_rule_7_2_7: {{ rhel9cis_rule_7_2_7 }} +rhel9cis_rule_7_2_8: {{ rhel9cis_rule_7_2_8 }} +rhel9cis_rule_7_2_9: {{ rhel9cis_rule_7_2_9 }} -############ +## Section 1 vars -# Section 1 +## Control 1.4.1 +# This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. +rhel9cis_set_boot_pass: {{ rhel9cis_set_boot_pass }} -# AIDE -rhel9cis_config_aide: {{ rhel9cis_config_aide }} - -# Whether or not to run tasks related to auditing/patching the desktop environment -rhel9cis_gui: {{ rhel9cis_gui }} - -# Warning Banner Content (issue, issue.net, motd) +## Controls: +# - 1.7.1 - Ensure message of the day is configured properly +# - 1.7.2 - Ensure local login warning banner is configured properly +# - 1.7.3 - Ensure remote login warning banner is configured properly +# This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). rhel9cis_warning_banner: {{ rhel9cis_warning_banner }} # End Banner -# aide setup via - cron, timer -rhel9_aide_scan: cron +## Control 1.8.x - Settings for GDM +## 1.8 GDM graphical interface +rhel9cis_gui: {{ rhel9cis_gui }} -# 1.8 Gnome Desktop +# This variable specifies the GNOME configuration database file to which configurations are written. +# (See "https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en") +# The default database is 'local'. rhel9cis_dconf_db_name: {{ rhel9cis_dconf_db_name }} -rhel9cis_screensaver_idle_delay: {{ rhel9cis_screensaver_idle_delay }} # Set max value for idle-delay in seconds (between 1 and 900) -rhel9cis_screensaver_lock_delay: {{ rhel9cis_screensaver_lock_delay }} # Set max value for lock-delay in seconds (between 0 and 5) -# Section 2 -## 2.2 Special Purposes -# Set to 'true' if X Windows is needed in your environment -rhel9cis_xwindows_required: false -### Service configuration booleans set true to keep service + +## Section 2. Services + +# Service configuration +# Options are +# Service +# - false - removes package +# - true - leaves package installed +# Mask +# - false - leaves service in current status +# - true - sets service name to masked +# +# Setting both Service and Mask to false will remove the package if exists +rhel9cis_autofs_services: {{ rhel9cis_autofs_services }} +rhel9cis_autofs_mask: {{ rhel9cis_autofs_mask }} rhel9cis_avahi_server: {{ rhel9cis_avahi_server }} -rhel9cis_cups_server: {{ rhel9cis_cups_server }} +rhel9cis_avahi_mask: {{ rhel9cis_avahi_mask }} rhel9cis_dhcp_server: {{ rhel9cis_dhcp_server }} +rhel9cis_dhcp_mask: {{ rhel9cis_dhcp_mask }} rhel9cis_dns_server: {{ rhel9cis_dns_server }} +rhel9cis_dns_mask: {{ rhel9cis_dns_mask }} rhel9cis_dnsmasq_server: {{ rhel9cis_dnsmasq_server }} -rhel9cis_vsftpd_server: {{ rhel9cis_vsftpd_server }} -rhel9cis_tftp_server: {{ rhel9cis_tftp_server }} -rhel9cis_httpd_server: {{ rhel9cis_httpd_server }} -rhel9cis_nginx_server: {{ rhel9cis_nginx_server }} -rhel9cis_dovecot_server: {{ rhel9cis_dovecot_server }} -rhel9cis_imap_server: {{ rhel9cis_imap_server }} +rhel9cis_dnsmasq_mask: {{ rhel9cis_dnsmasq_mask }} rhel9cis_samba_server: {{ rhel9cis_samba_server }} -rhel9cis_squid_server: {{ rhel9cis_squid_server }} +rhel9cis_samba_mask: {{ rhel9cis_samba_mask }} +rhel9cis_ftp_server: {{ rhel9cis_ftp_server }} +rhel9cis_ftp_mask: {{ rhel9cis_ftp_mask }} +rhel9cis_message_server: {{ rhel9cis_message_server }} # This is for messaging dovecot and cyrus-imap +rhel9cis_message_mask: {{ rhel9cis_message_mask }} +rhel9cis_nfs_server: {{ rhel9cis_nfs_server }} +rhel9cis_nfs_mask: {{ rhel9cis_nfs_mask }} +rhel9cis_nis_server: {{ rhel9cis_nis_server }} # set to mask if nis client required +rhel9cis_nis_mask: {{ rhel9cis_nis_mask }} +rhel9cis_print_server: {{ rhel9cis_print_server }} # replaces cups +rhel9cis_print_mask: {{ rhel9cis_print_mask }} +rhel9cis_rpc_server: {{ rhel9cis_rpc_server }} +rhel9cis_rpc_mask: {{ rhel9cis_rpc_mask }} +rhel9cis_rsync_server: {{ rhel9cis_rsync_server }} +rhel9cis_rsync_mask: {{ rhel9cis_rsync_mask }} rhel9cis_snmp_server: {{ rhel9cis_snmp_server }} +rhel9cis_snmp_mask: {{ rhel9cis_snmp_mask }} rhel9cis_telnet_server: {{ rhel9cis_telnet_server }} +rhel9cis_telnet_mask: {{ rhel9cis_telnet_mask }} +rhel9cis_tftp_server: {{ rhel9cis_tftp_server }} +rhel9cis_tftp_mask: {{ rhel9cis_tftp_mask }} +rhel9cis_squid_server: {{ rhel9cis_squid_server }} +rhel9cis_squid_mask: {{ rhel9cis_squid_mask }} +rhel9cis_httpd_server: {{ rhel9cis_httpd_server }} +rhel9cis_httpd_mask: {{ rhel9cis_httpd_mask }} +rhel9cis_nginx_server: {{ rhel9cis_nginx_server }} +rhel9cis_nginx_mask: {{ rhel9cis_nginx_mask }} +rhel9cis_xinetd_server: {{ rhel9cis_xinetd_server }} +rhel9cis_xinetd_mask: {{ rhel9cis_xinetd_mask }} +rhel9cis_xwindow_server: {{ rhel9cis_xwindow_server }} # will remove mask not an option rhel9cis_is_mail_server: {{ rhel9cis_is_mail_server }} -# Note the options -# Packages are used for client services and Server- only remove if you dont use the client service -# -rhel9cis_use_nfs_server: {{ rhel9cis_use_nfs_server }} -rhel9cis_use_nfs_service: {{ rhel9cis_use_nfs_service }} -rhel9cis_use_rpc_server: {{ rhel9cis_use_rpc_server }} -rhel9cis_use_rpc_service: {{ rhel9cis_use_rpc_service }} -rhel9cis_use_rsync_server: {{ rhel9cis_use_rsync_server }} -rhel9cis_use_rsync_service: {{ rhel9cis_use_rsync_service }} +## Section 2.3 Service clients -#### 2.3 Service clients -rhel9cis_telnet_required: {{ rhel9cis_telnet_required }} -rhel9cis_openldap_clients_required: {{ rhel9cis_openldap_clients_required }} -rhel9cis_tftp_client: {{ rhel9cis_tftp_client }} rhel9cis_ftp_client: {{ rhel9cis_ftp_client }} +rhel9cis_openldap_clients_required: {{ rhel9cis_openldap_clients_required }} +rhel9cis_ypbind_required: {{ rhel9cis_ypbind_required }} # Same package as NIS server +rhel9cis_telnet_required: {{ rhel9cis_telnet_required }} +rhel9cis_tftp_client: {{ rhel9cis_tftp_client }} -# Section 3 +## Section 3 vars +## Sysctl +# Service configuration +# Options are +# Service +# - false - removes package +# - true - leaves package installed +# Mask +# - false - leaves service in current status +# - true - sets service name to masked +# +# Setting both Service and Mask to false will remove the package if exists +# +rhel9cis_bluetooth_service: {{ rhel9cis_bluetooth_service }} +rhel9cis_bluetooth_mask: {{ rhel9cis_bluetooth_mask }} -## IPv6 required +## 3.1 IPv6 requirement toggle +# This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: {{ rhel9cis_ipv6_required }} -## 3.2 System network parameters (host only OR host and router) +# 3.3 System network parameters (host only OR host and router) +# This variable governs whether specific CIS rules +# concerned with acceptance and routing of packages are skipped. rhel9cis_is_router: {{ rhel9cis_is_router }} -## Section 3.4 -### Firewall +# Section 4 vars +### Firewall Service to install and configure - Options are: +# 1) either 'firewalld' +# 2) or 'nftables' +#### Some control allow for services to be removed or masked +#### The options are under each heading +#### absent = remove the package +#### masked = leave package if installed and mask the service rhel9cis_firewall: {{ rhel9cis_firewall }} -##### firewalld -rhel9cis_default_zone: {{ rhel9cis_default_zone }} -#### nftables +## Section5 vars -rhel9cis_nft_tables_autonewtable: {{ rhel9cis_nft_tables_autonewtable }} -rhel9cis_nft_tables_tablename: {{ rhel9cis_nft_tables_tablename }} -rhel9cis_nft_tables_autochaincreate: {{ rhel9cis_nft_tables_autochaincreate }} +## Section 5.1 - SSH -# Section 4 +## Controls: +## - 5.1.7 - Ensure SSH access is limited +# This variable, if specified, configures a list of USER name patterns, separated by spaces, to allow SSH +# access for users whose user name matches one of the patterns. This is done +# by setting the value of `AllowUsers` option in `/etc/ssh/sshd_config` file. +# If an USER@HOST format will be used, the specified user will be allowed only on that particular host. +rhel9cis_sshd_allowusers: "{% if ansible_facts.user_id != 'root' %}{{ ansible_facts.user_id }}{% elif ansible_env.SUDO_USER is defined %}{{ ansible_env.SUDO_USER }}{% endif %}" -## Set if host is a logserver -rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }} +# (String) This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access +# for users whose primary group or supplementary group list matches one of the patterns. This is done +# by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. +rhel9cis_sshd_allowgroups: {{ rhel9cis_sshd_allowgroups }} -# Remote logserver settings -rhel9cis_remote_log_host: {{ rhel9cis_remote_log_host }} -rhel9cis_remote_log_port: {{ rhel9cis_remote_log_port }} -rhel9cis_remote_log_protocol: {{ rhel9cis_remote_log_protocol }} -rhel9cis_remote_log_retrycount: {{ rhel9cis_remote_log_retrycount }} -rhel9cis_remote_log_queuesize: {{ rhel9cis_remote_log_queuesize }} +# This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access +# for users whose user name matches one of the patterns. This is done +# by setting the value of `DenyUsers` option in `/etc/ssh/sshd_config` file. +# If an USER@HOST format will be used, the specified user will be restricted only on that particular host. +rhel9cis_sshd_denyusers: {{ rhel9cis_sshd_denyusers }} -## syslog +# This variable, if specified, configures a list of GROUP name patterns, separated by spaces, +# to prevent SSH access for users whose primary group or supplementary group list matches one of the patterns. This is done +# by setting the value of `DenyGroups` option in `/etc/ssh/sshd_config` file. +rhel9cis_sshd_denygroups: {{ rhel9cis_sshd_denygroups }} + +## Control 5.2.x - Ensure sudo log file exists +# By default, sudo logs through syslog(3). However, to specify a custom log file, the +# 'logfile' parameter will be used, setting it with current variable's value. +# This variable defines the path and file name of the sudo log file. +rhel9cis_sudolog_location: {{ rhel9cis_sudolog_location }} + +## Control 5.2.4 +# This will leave NOPASSWD intact for these users +rhel9cis_sudoers_exclude_nopasswd_list: + - ec2-user + - vagrant + +## Control 5.2 - Ensure access to the 'su' command is restricted +# This variable determines the name of the group of users that are allowed to use the su command. +# CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. +rhel9cis_sugroup: {{ rhel9cis_sugroup }} + +# Control 5.3.3.2 +# Choose if using minclass or credits options +# Options are: minclass or credits +# ensure only one is selected +rhel9cis_passwd_complex_option: {{ rhel9cis_passwd_complex_option }} + +## Section 5.4.1.x: Shadow Password Suite Parameters + ## Control 5.4.1.1 - Ensure password expiration is 365 days or less + # This variable governs after how many days a password expires. + # CIS requires a value of 365 or less. +rhel9cis_pass_max_days: 365 + ## Control 5.4.1.2 - Ensure minimum days between password changes is 7 or more + # This variable specifies the minimum number of days allowed between changing + # passwords. CIS requires a value of at least 1. +rhel9cis_pass_min_days: 7 + ## Control 5.4.1.3 - Ensure password expiration warning days is 7 or more + # This variable governs, how many days before a password expires, the user will be warned. + # CIS requires a value of at least 7. +rhel9cis_pass_warn_age: 7 + +## PAM AND Authselect + +# This variable configures the name of the custom profile to be created and selected. +# To be changed from default - cis_example_profile +rhel9cis_authselect_custom_profile_name: {{ rhel9cis_authselect_custom_profile_name }} + +### Controls: +# - 5.6.2 - Ensure system accounts are secured +# - 6.2.10 - Ensure local interactive user home directories exist +# - 6.2.11 - Ensure local interactive users own their home directories +# UID settings for interactive users +# These are discovered via logins.def if set true +rhel9cis_discover_int_uid: {{ rhel9cis_discover_int_uid }} +# This variable sets the minimum number from which to search for UID +# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# been set to `true`. +min_int_uid: 1000 +### Controls: +# - Ensure local interactive user home directories exist +# - Ensure local interactive users own their home directories +# This variable sets the maximum number at which the search stops for UID +# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# been set to `true`. +max_int_uid: 65533 + +## Section6 vars + +## Control 6.1.2 AIDE schedule +# how aide sceduler runs can be one of cron or timer +rhel9cis_aide_scan: {{ rhel9cis_aide_scan }} + +# These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. +# The sub-settings of this variable provide the parameters required to configure +# the cron job on the target system. +# Cron is a time-based job scheduling program in Unix OS, which allows tasks to be scheduled +# and executed automatically at a certain point in time. +rhel9cis_aide_cron: + # This variable represents the user account under which the cron job for AIDE will run. + cron_user: root + # This variable represents the path to the AIDE crontab file. + cron_file: /etc/cron.d/aide_cron + # This variable represents the actual command or script that the cron job + # will execute for running AIDE. + aide_job: '/usr/sbin/aide --check' + # These variables define the schedule for the cron job + # This variable governs the minute of the time of day when the AIDE cronjob is run. + # It must be in the range `0-59`. + aide_minute: 0 + # This variable governs the hour of the time of day when the AIDE cronjob is run. + # It must be in the range `0-23`. + aide_hour: 5 + # This variable governs the day of the month when the AIDE cronjob is run. + # `*` signifies that the job is run on all days; furthermore, specific days + # can be given in the range `1-31`; several days can be concatenated with a comma. + # The specified day(s) can must be in the range `1-31`. + aide_day: '*' + # This variable governs months when the AIDE cronjob is run. + # `*` signifies that the job is run in every month; furthermore, specific months + # can be given in the range `1-12`; several months can be concatenated with commas. + # The specified month(s) can must be in the range `1-12`. + aide_month: '*' + # This variable governs the weekdays, when the AIDE cronjob is run. + # `*` signifies that the job is run on all weekdays; furthermore, specific weekdays + # can be given in the range `0-7` (both `0` and `7` represent Sunday); several weekdays + # can be concatenated with commas. + aide_weekday: '*' +# +## Preferred method of logging +## Whether rsyslog or journald preferred method for local logging +## Control 6.2.3 | Configure rsyslog +## Control 6.2.1 | Configure journald +# This variable governs which logging service should be used, choosing between 'rsyslog'(CIS recommendation) +# or 'journald'(only one is implemented) will trigger the execution of the associated subsection, as the-best +# practices are written wholly independent of each other. rhel9cis_syslog: {{ rhel9cis_syslog }} -# Section 5 -# This will allow use of drop in files when CIS adopts them. -rhel9_cis_sshd_config_file: {{ rhel9_cis_sshd_config_file }} +## Control 6.2.2.x & 6.2.3.x - Ensure rsyslog is not configured to receive logs from a remote client +# This variable expresses whether the system is used as a log server or not. If set to: +# - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. +# - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity +# from local attacks on remote clients) +rhel9cis_system_is_log_server: {{ rhel9cis_system_is_log_server }} -## 5.2.4 Note the following to understand precedence and layout -rhel9cis_sshd_limited: false -rhel9cis_sshd_access: - - AllowUser - - AllowGroup - - DenyUser - - DenyGroup +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable governs if 'rsyslog' service should be automatically configured to forward messages to a +# remote log server. If set to 'false', the configuration of the 'omfwd' plugin, used to provide forwarding +# over UDP or TCP, will not be performed. +rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }} -## 5.3.2 & 5.4.2 Enable automation to select custom profile options, using the settings above -rhel9cis_authselect_custom_profile_select: {{ rhel9cis_authselect_custom_profile_select }} +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value of the 'target' parameter to be configured when enabling +# forwarding syslog messages to a remote log server, thus configuring the actual FQDN/IP address of the +# destination server. For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }}'). +rhel9cis_remote_log_host: {{ rhel9cis_remote_log_host }} -## 5.3.2 Authselect select false if using AD or RHEL ID mgmt -rhel9cis_authselect: - custom_profile_name: {{ rhel9cis_authselect['custom_profile_name'] }} - default_file_to_copy: {{ rhel9cis_authselect['default_file_to_copy'] }} +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value of the 'port' parameter to be configured when enabling +# forwarding syslog messages to a remote log server. The default value for this destination port is 514. +# For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }}'). +rhel9cis_remote_log_port: {{ rhel9cis_remote_log_port }} -## 5.4.1 Enable automation to create custom profile settings, using the setings above -rhel9cis_authselect_custom_profile_create: {{ rhel9cis_authselect_custom_profile_create }} +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the value("TCP"/"UDP") of the 'protocol' parameter to be configured when enabling +# forwarding syslog messages to a remote log server. The default value for the 'omfwd' plug-in is UDP. +# For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }}'). +rhel9cis_remote_log_protocol: {{ rhel9cis_remote_log_protocol }} -# 5.5.1 -## PAM -rhel9cis_pam_password: - minlen: {{ rhel9cis_pam_password['minlen'] }} - minclass: {{ rhel9cis_pam_password['minclass'] }} -rhel9cis_pam_passwd_retry: "3" +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable governs how often an action is retried(value is passed to 'action.resumeRetryCount' parameter) before +# it is considered to have failed(that roughly translates to discarded messages). The default value is 0, but +# when set to "-1"(eternal), this setting would prevent rsyslog from dropping messages when retrying to connect +# if server is not responding. For this value to be reflected in the configuration, the variable which enables the +# automatic configuration of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }}'). +rhel9cis_remote_log_retrycount: {{ rhel9cis_remote_log_retrycount }} -## 5.5.3 choose one of below -rhel9cis_pwhistory_so: "14" -rhel9cis_passwd_remember: "5" +## Control 6.2.3.6 - Ensure rsyslog is configured to send logs to a remote log host +# This variable configures the maximum number of messages that can be hold(value is passed to 'queue.size' parameter). +# For this value to be reflected in the configuration, the variable which enables the automatic configuration +# of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: {{ rhel9cis_remote_log_server }}'). +rhel9cis_remote_log_queuesize: {{ rhel9cis_remote_log_queuesize }} -## 5.6.x login.defs password settings -rhel9cis_pass: - max_days: {{ rhel9cis_pass['max_days'] }} - min_days: {{ rhel9cis_pass['min_days'] }} - warn_age: {{ rhel9cis_pass['warn_age'] }} +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to +# URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port +# number may be specified after a colon (":"), otherwise 19532 will be used by default. +rhel9cis_journal_upload_url: {{ rhel9cis_journal_upload_url }} -## 5.3.7 set sugroup if differs from wheel -rhel9cis_sugroup: {{ rhel9cis_sugroup }} +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the private key file used by the remote journal +# server to authenticate itself to the client. This key is used alongside the server's +# public certificate to establish secure communication. +rhel9cis_journal_upload_serverkeyfile: {{ rhel9cis_journal_upload_serverkeyfile }} + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the public certificate file of the remote journal +# server. This certificate is used to verify the authenticity of the remote server. +rhel9cis_journal_servercertificatefile: {{ rhel9cis_journal_servercertificatefile }} + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to a file containing one or more public certificates +# of certificate authorities (CAs) that the client trusts. These trusted certificates are used +# to validate the authenticity of the remote server's certificate. +rhel9cis_journal_trustedcertificatefile: {{ rhel9cis_journal_trustedcertificatefile }} + +# Section 7 Vars + +# 7.1.12 Ensure no files or directories without an owner and a group exist +rhel9cis_exclude_unowned_search_path: \( ! -path "/run/user/*" -a ! -path "/proc/*" -a ! -path "*/containerd/*" -a ! -path "*/kubelet/pods/*" -a ! -path "*/kubelet/plugins/*" -a ! -path "/sys/fs/cgroup/memory/*" -a ! -path "/var/*/private/*" \) diff --git a/vars/main.yml b/vars/main.yml index bbc105f..49c84ba 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -28,3 +28,20 @@ gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" # This variable governs if the auditd logic should be executed(if value is true). # NOTE: The current default value is likely to be overriden(via 'set_fact') by other further tasks(in sub-section 'Auditd rules'). update_audit_template: false + + +# Defaults +## Usage on containerized images +# The role discovers dynamically (in tasks/main.yml) whether it +# is executed on a container image and sets the variable +# system_is_container the true. Otherwise, the default value +# 'false' is left unchanged. +system_is_container: false +# The filename of the existing yml file in role's 'vars/' sub-directory +# to be used for managing the role-behavior when a container was detected: +# (de)activating rules or for other tasks(e.g. disabling Selinux or a specific +# firewall-type). +container_vars_file: is_container.yml +# rhel9cis is left off the front of this var for consistency in testing pipeline +# system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks +system_is_ec2: false From ccac707ddb500e709656743a0dc4fe4261ef0208 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:29:44 +0100 Subject: [PATCH 044/327] Added missing control Signed-off-by: Mark Bolwell --- defaults/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/defaults/main.yml b/defaults/main.yml index 32d3fcf..ba6ccd3 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -419,6 +419,7 @@ rhel9cis_rule_6_2_3_4: true rhel9cis_rule_6_2_3_5: true rhel9cis_rule_6_2_3_6: true rhel9cis_rule_6_2_3_7: true +rhel9cis_rule_6_2_3_8: true ## 6.2.4 Configure Logfiles rhel9cis_rule_6_2_4_1: true ## 6.3 Configure Auditing From c9cf2c83969c16944f8007f90e74dbd57ca9cdee Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:45:00 +0100 Subject: [PATCH 045/327] updated Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 260cffe..6dae53b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -2,8 +2,8 @@ ##### CI for use by github no need for action to be added ##### Inherited ci: - autofix_prs: false - skip: [detect-aws-credentials, ansible-lint ] + autofix_prs: false + skip: [detect-aws-credentials, ansible-lint ] repos: - repo: https://github.com/pre-commit/pre-commit-hooks @@ -33,14 +33,12 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - args: [ '--baseline', '.config/.secrets.baseline' ] - exclude: .config/.gitleaks-report.json + exclude: templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2:3 - repo: https://github.com/gitleaks/gitleaks rev: v8.18.4 hooks: - id: gitleaks - args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint rev: v24.7.0 From 4fc57c5a1fb2a26229868da1cd85274a21b5a40d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:45:51 +0100 Subject: [PATCH 046/327] updated Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 6dae53b..e53f665 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -33,7 +33,7 @@ repos: rev: v1.5.0 hooks: - id: detect-secrets - exclude: templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2:3 + exclude: templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 - repo: https://github.com/gitleaks/gitleaks rev: v8.18.4 From 671ba154e7a6086d9504935a2dae1cd93a54f7f7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 13:47:38 +0100 Subject: [PATCH 047/327] linting updates Signed-off-by: Mark Bolwell --- .ansible-lint | 30 +-- .config/.gitleaks-report.json | 322 -------------------------------- .config/.secrets.baseline | 119 ------------ .config/requirements.txt | 5 - .yamllint | 44 ++--- collections/requirements.yml | 18 +- defaults/main.yml | 26 ++- tasks/main.yml | 32 ++-- tasks/parse_etc_password.yml | 2 +- tasks/section_1/cis_1.6.x.yml | 28 +-- tasks/section_5/cis_5.3.2.x.yml | 3 - tasks/section_6/cis_6.2.3.x.yml | 2 +- vars/main.yml | 1 - 13 files changed, 86 insertions(+), 546 deletions(-) delete mode 100644 .config/.gitleaks-report.json delete mode 100644 .config/.secrets.baseline delete mode 100644 .config/requirements.txt diff --git a/.ansible-lint b/.ansible-lint index b717f67..3090307 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -3,20 +3,20 @@ parseable: true quiet: true skip_list: - - 'schema' - - 'no-changed-when' - - 'var-spacing' - - 'experimental' - - 'name[play]' - - 'name[casing]' - - 'name[template]' - - 'key-order[task]' - - '204' - - '305' - - '303' - - '403' - - '306' - - '602' - - '208' + - 'schema' + - 'no-changed-when' + - 'var-spacing' + - 'experimental' + - 'name[play]' + - 'name[casing]' + - 'name[template]' + - 'key-order[task]' + - '204' + - '305' + - '303' + - '403' + - '306' + - '602' + - '208' use_default_rules: true verbosity: 0 diff --git a/.config/.gitleaks-report.json b/.config/.gitleaks-report.json deleted file mode 100644 index fbdde5d..0000000 --- a/.config/.gitleaks-report.json +++ /dev/null @@ -1,322 +0,0 @@ -[ - { - "Description": "Generic API Key", - "StartLine": 119, - "EndLine": 119, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\"", - "Secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.853056, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:119" - }, - { - "Description": "Generic API Key", - "StartLine": 127, - "EndLine": 127, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"fe96f7cfa2ab2224e7d015067a6f6cc713f7012e\"", - "Secret": "fe96f7cfa2ab2224e7d015067a6f6cc713f7012e", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.6568441, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:127" - }, - { - "Description": "Generic API Key", - "StartLine": 135, - "EndLine": 135, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"a415ab5cc17c8c093c015ccdb7e552aee7911aa4\"", - "Secret": "a415ab5cc17c8c093c015ccdb7e552aee7911aa4", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.5221736, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:135" - }, - { - "Description": "Generic API Key", - "StartLine": 145, - "EndLine": 145, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"2478fefdceefe2847c3aa36dc731aaad5b3cc2fb\"", - "Secret": "2478fefdceefe2847c3aa36dc731aaad5b3cc2fb", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.6348295, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:145" - }, - { - "Description": "Generic API Key", - "StartLine": 153, - "EndLine": 153, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"64411efd0f0561fe4852c6e414071345c9c6432a\"", - "Secret": "64411efd0f0561fe4852c6e414071345c9c6432a", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.646039, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:153" - }, - { - "Description": "Generic API Key", - "StartLine": 163, - "EndLine": 163, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360\"", - "Secret": "2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "495f942b7d26ee82690dc16eb4f231c587a57687", - "Entropy": 3.8439426, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-26T15:51:17Z", - "Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:163" - }, - { - "Description": "Generic API Key", - "StartLine": 119, - "EndLine": 119, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\"", - "Secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.853056, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:119" - }, - { - "Description": "Generic API Key", - "StartLine": 127, - "EndLine": 127, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"fe96f7cfa2ab2224e7d015067a6f6cc713f7012e\"", - "Secret": "fe96f7cfa2ab2224e7d015067a6f6cc713f7012e", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.6568441, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:127" - }, - { - "Description": "Generic API Key", - "StartLine": 135, - "EndLine": 135, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"a415ab5cc17c8c093c015ccdb7e552aee7911aa4\"", - "Secret": "a415ab5cc17c8c093c015ccdb7e552aee7911aa4", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.5221736, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:135" - }, - { - "Description": "Generic API Key", - "StartLine": 145, - "EndLine": 145, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"2478fefdceefe2847c3aa36dc731aaad5b3cc2fb\"", - "Secret": "2478fefdceefe2847c3aa36dc731aaad5b3cc2fb", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.6348295, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:145" - }, - { - "Description": "Generic API Key", - "StartLine": 153, - "EndLine": 153, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"64411efd0f0561fe4852c6e414071345c9c6432a\"", - "Secret": "64411efd0f0561fe4852c6e414071345c9c6432a", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.646039, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:153" - }, - { - "Description": "Generic API Key", - "StartLine": 163, - "EndLine": 163, - "StartColumn": 18, - "EndColumn": 68, - "Match": "secret\": \"2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360\"", - "Secret": "2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360", - "File": ".secrets.baseline", - "SymlinkFile": "", - "Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389", - "Entropy": 3.8439426, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-07-04T16:08:02Z", - "Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:163" - }, - { - "Description": "Generic API Key", - "StartLine": 3, - "EndLine": 4, - "StartColumn": 9, - "EndColumn": 1, - "Match": "key_pubkey_name: gpg-pubkey-8d8b756f-629e59ec", - "Secret": "gpg-pubkey-8d8b756f-629e59ec", - "File": "vars/OracleLinux.yml", - "SymlinkFile": "", - "Commit": "e04da88df42da0108d489f359513c574fbe5c87a", - "Entropy": 3.96772, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2023-03-06T11:22:08Z", - "Message": "Added OracleLinux support\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "e04da88df42da0108d489f359513c574fbe5c87a:vars/OracleLinux.yml:generic-api-key:3" - }, - { - "Description": "Generic API Key", - "StartLine": 4, - "EndLine": 5, - "StartColumn": 8, - "EndColumn": 1, - "Match": "key_pubkey_name: gpg-pubkey-fd431d51-4ae0493b", - "Secret": "gpg-pubkey-fd431d51-4ae0493b", - "File": "vars/RedHat.yml", - "SymlinkFile": "", - "Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a", - "Entropy": 3.96772, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2022-07-25T10:26:27Z", - "Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/RedHat.yml:generic-api-key:4" - }, - { - "Description": "Generic API Key", - "StartLine": 4, - "EndLine": 5, - "StartColumn": 8, - "EndColumn": 1, - "Match": "key_pubkey_name: gpg-pubkey-b86b3716-61e69f29", - "Secret": "gpg-pubkey-b86b3716-61e69f29", - "File": "vars/AlmaLinux.yml", - "SymlinkFile": "", - "Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a", - "Entropy": 3.824863, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2022-07-25T10:26:27Z", - "Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/AlmaLinux.yml:generic-api-key:4" - }, - { - "Description": "Generic API Key", - "StartLine": 4, - "EndLine": 5, - "StartColumn": 8, - "EndColumn": 1, - "Match": "key_pubkey_name: gpg-pubkey-350d275d-6279464b", - "Secret": "gpg-pubkey-350d275d-6279464b", - "File": "vars/Rocky.yml", - "SymlinkFile": "", - "Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a", - "Entropy": 3.9946804, - "Author": "Mark Bolwell", - "Email": "mark.bollyuk@gmail.com", - "Date": "2022-07-25T10:26:27Z", - "Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e", - "Tags": [], - "RuleID": "generic-api-key", - "Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/Rocky.yml:generic-api-key:4" - } -] diff --git a/.config/.secrets.baseline b/.config/.secrets.baseline deleted file mode 100644 index 7707be7..0000000 --- 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-21T14:11:05Z" -} diff --git a/.config/requirements.txt b/.config/requirements.txt deleted file mode 100644 index 52cb84d..0000000 --- a/.config/requirements.txt +++ /dev/null @@ -1,5 +0,0 @@ -passlib -lxml -xmltodict -jmespath -yamllint diff --git a/.yamllint b/.yamllint index 27d8aee..ec2d1cd 100644 --- a/.yamllint +++ b/.yamllint @@ -9,25 +9,25 @@ ignore: | *molecule.yml rules: - indentation: - # Requiring 4 space indentation - spaces: 2 - # Requiring consistent indentation within a file, either indented or not - indent-sequences: consistent - braces: - max-spaces-inside: 1 - level: error - brackets: - max-spaces-inside: 1 - level: error - empty-lines: - max: 1 - line-length: disable - key-duplicates: enable - new-line-at-end-of-file: enable - new-lines: - type: unix - trailing-spaces: enable - truthy: - allowed-values: ['true', 'false'] - check-keys: true + indentation: + # Requiring 4 space indentation + spaces: 2 + # Requiring consistent indentation within a file, either indented or not + indent-sequences: consistent + braces: + max-spaces-inside: 1 + level: error + brackets: + max-spaces-inside: 1 + level: error + empty-lines: + max: 1 + line-length: disable + key-duplicates: enable + new-line-at-end-of-file: enable + new-lines: + type: unix + trailing-spaces: enable + truthy: + allowed-values: ['true', 'false'] + check-keys: true diff --git a/collections/requirements.yml b/collections/requirements.yml index 8ebc618..810c9af 100644 --- a/collections/requirements.yml +++ b/collections/requirements.yml @@ -1,14 +1,14 @@ --- collections: - - name: community.general - source: https://github.com/ansible-collections/community.general - type: git + - name: community.general + source: https://github.com/ansible-collections/community.general + type: git - - name: community.crypto - source: https://github.com/ansible-collections/community.crypto - type: git + - name: community.crypto + source: https://github.com/ansible-collections/community.crypto + type: git - - name: ansible.posix - source: https://github.com/ansible-collections/ansible.posix - type: git + - name: ansible.posix + source: https://github.com/ansible-collections/ansible.posix + type: git diff --git a/defaults/main.yml b/defaults/main.yml index ba6ccd3..c524a55 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -858,10 +858,9 @@ rhel9cis_allow_authselect_updates: true ## rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install - ## PAM AND Authselect -# To create a new profile (best for greenfield fresh sites not configured) +# To create a new profile (best for greenfield fresh sites not configured) # This allows creation of a custom profile using an existing one to build from # will only create if profiel does not already exist ## options true or false @@ -914,9 +913,9 @@ rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # Choose if using minclass or credits options # Options are: minclass or credits # ensure only one is selected -rhel9cis_passwd_complex_option: minclass +rhel9cis_passwd_complex_option: minclass # pragma: allowlist secret rhel9cis_passwd_minclass: 3 -#rhel9cis_passwd_complex: credits +# rhel9cis_passwd_complex: credits rhel9cis_passwd_dcredit: -1 rhel9cis_passwd_ucredit: -2 rhel9cis_passwd_ocredit: 0 @@ -950,18 +949,17 @@ rhel9cis_pamd_pwhistory_remember: 24 # 5.3.3.4.x rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret -## Section 5.4.1.x: Shadow Password Suite Parameters - ## Control 5.6.1.1 - Ensure password expiration is 365 days or less - # This variable governs after how many days a password expires. - # CIS requires a value of 365 or less. +## Control 5.6.1.1 - Ensure password expiration is 365 days or less +# This variable governs after how many days a password expires. +# CIS requires a value of 365 or less. rhel9cis_pass_max_days: 365 - ## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more - # This variable specifies the minimum number of days allowed between changing - # passwords. CIS requires a value of at least 1. +## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more +# This variable specifies the minimum number of days allowed between changing +# passwords. CIS requires a value of at least 1. rhel9cis_pass_min_days: 7 - ## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more - # This variable governs, how many days before a password expires, the user will be warned. - # CIS requires a value of at least 7. +## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more +# This variable governs, how many days before a password expires, the user will be warned. +# CIS requires a value of at least 7. rhel9cis_pass_warn_age: 7 ## Control 5.4.1.x - Ensure inactive password lock is 30 days or less diff --git a/tasks/main.yml b/tasks/main.yml index 8e283e0..1dd529e 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -114,26 +114,26 @@ - name: "PRELIM | AUDIT | Check authselect profile is selected" when: - - rhel9cis_allow_authselect_updates + - rhel9cis_allow_authselect_updates tags: - - always + - always block: - - name: "PRELIM | AUDIT | Check authselect profile name has been updated" - ansible.builtin.assert: - that: rhel9cis_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 name has been updated" + ansible.builtin.assert: + that: rhel9cis_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" - ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' - changed_when: false - failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] - register: prelim_authselect_current_profile + - name: "PRELIM | AUDIT | Check authselect profile is selected" + ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' + changed_when: false + failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] + register: prelim_authselect_current_profile - - name: "PRELIM | AUDIT | Check authselect profile is selected" - ansible.builtin.assert: - that: prelim_authselect_current_profile 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 authselect profile is selected" + ansible.builtin.assert: + that: prelim_authselect_current_profile 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: "Ensure root password is set" when: diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index e16f8b9..8270b5a 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -17,7 +17,7 @@ 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/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index f0798e9..f497f15 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -55,12 +55,12 @@ owner: root group: root mode: '0640' - register: NO_SHA1_TEMPLATE + register: no_sha1_template - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SHA1' }}" - changed_when: NO_SHA1_TEMPLATE is defined + changed_when: no_sha1_template is defined notify: - Update Crypto Policy - Set Crypto Policy @@ -79,8 +79,6 @@ - NIST800-53R5_SC-6 block: - - ansible.builtin.debug: - msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 @@ -88,12 +86,12 @@ owner: root group: root mode: '0640' - register: NO_WEAKMAC_TEMPLATE + register: no_weakmac_template - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-WEAKMAC' }}" - changed_when: NO_WEAKMAC_TEMPLATE is defined + changed_when: no_weakmac_template is defined notify: - Update Crypto Policy - Set Crypto Policy @@ -111,8 +109,6 @@ - rule_1.6.5 - NIST800-53R5_SC-6 block: - - ansible.builtin.debug: - msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2 @@ -120,12 +116,12 @@ owner: root group: root mode: '0640' - register: NO_SSHCBC_TEMPLATE + register: no_sshcbc_template - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHCBC' }}" - changed_when: NO_SSHCBC_TEMPLATE is defined + changed_when: no_sshcbc_template is defined notify: - Update Crypto Policy - Set Crypto Policy @@ -143,8 +139,6 @@ - rule_1.6.6 - NIST800-53R5_SC-6 block: - - ansible.builtin.debug: - msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 @@ -152,12 +146,12 @@ owner: root group: root mode: '0640' - register: NO_SSHWEAKCIPHERS_TEMPLATE + register: no_sshweakciphers_template - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKCIPHERS' }}" - changed_when: NO_SSHWEAKCIPHERS_TEMPLATE is defined + changed_when: no_sshweakciphers_template is defined notify: - Update Crypto Policy - Set Crypto Policy @@ -175,8 +169,6 @@ - rule_1.6.7 - NIST800-53R5_SC-6 block: - - ansible.builtin.debug: - msg: "{{ rhel9cis_crypto_policy_module }}" - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2 @@ -184,12 +176,12 @@ owner: root group: root mode: '0640' - register: NO_SSHETM_TEMPLATE + register: no_sshetm_template - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHETM' }}" - changed_when: NO_SSHETM_TEMPLATE is defined + changed_when: no_sshetm_template is defined notify: - Update Crypto Policy - Set Crypto Policy diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 571cb70..c9a7559 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -139,9 +139,6 @@ failed_when: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] register: rhel9cis_authselect_pam_unix - - debug: - msg: "{{ rhel9cis_authselect_pam_unix }}" - - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" when: "'system-auth:password' not in rhel9cis_authselect_pam_unix.stdout" ansible.builtin.lineinfile: diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 86cef8a..4274429 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -263,7 +263,7 @@ - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | set rsyslog conf" ansible.builtin.template: src: etc/logrotate.d/rsyslog.conf.j2 - dest: /etc/logrotate.d/rsyslog.conf + dest: /etc/logrotate.d/rsyslog.conf owner: root group: root mode: '0640' diff --git a/vars/main.yml b/vars/main.yml index 49c84ba..ec72d0b 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -29,7 +29,6 @@ gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" # NOTE: The current default value is likely to be overriden(via 'set_fact') by other further tasks(in sub-section 'Auditd rules'). update_audit_template: false - # Defaults ## Usage on containerized images # The role discovers dynamically (in tasks/main.yml) whether it From 22cd20c067de049a75e6647a7909113ff6bd577c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 16:20:14 +0100 Subject: [PATCH 048/327] updated for issue #226 Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.1.4.x.yml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/tasks/section_4/cis_4.1.4.x.yml b/tasks/section_4/cis_4.1.4.x.yml index c42f876..dcf8413 100644 --- a/tasks/section_4/cis_4.1.4.x.yml +++ b/tasks/section_4/cis_4.1.4.x.yml @@ -23,7 +23,7 @@ "4.1.4.3 | PATCH | Ensure only authorized groups are assigned ownership of audit log files" ansible.builtin.file: path: "{{ audit_discovered_logfile.stdout }}" - mode: "{% if auditd_logfile.stat.mode != '0600' %}0640{% endif %}" + mode: 'u-x,g-rw,o-rwx' owner: root group: root when: @@ -50,7 +50,7 @@ ansible.builtin.file: path: "{{ audit_discovered_logfile.stdout | dirname }}" state: directory - mode: '0750' + mode: 'g-w,o-rwx' when: not auditlog_dir.stat.mode is match('07(0|5)0') when: - rhel9cis_rule_4_1_4_4 @@ -64,7 +64,7 @@ - name: "4.1.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" ansible.builtin.file: path: "{{ item.path }}" - mode: "{{ '0600' if item.mode == '0600' else '0640' }}" + mode: 'u-x,g-wx,u-rwx' loop: "{{ auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -126,8 +126,7 @@ - name: "4.1.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required" ansible.builtin.file: path: "{{ item.item }}" - mode: '0750' - + mode: 'go-w' loop: "{{ audit_bins.results }}" loop_control: label: "{{ item.item }}" From 44aa939e130bc4500ac07e68ed131d7687089b13 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 16:23:37 +0100 Subject: [PATCH 049/327] issue #227 resolved thanks @ckbaker10 Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index d58e921..ad5bcb5 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -35,7 +35,7 @@ - audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' register: post_audit_summary changed_when: false From 82119205b1d111326ba5ee65c13e7b9d24131fba Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 17:21:36 +0100 Subject: [PATCH 050/327] issue #224 addressed thanks to @globalpayments-shoebsyed Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.1.4.x.yml | 6 ++++++ tasks/section_4/cis_4.2.3.yml | 2 ++ 2 files changed, 8 insertions(+) diff --git a/tasks/section_4/cis_4.1.4.x.yml b/tasks/section_4/cis_4.1.4.x.yml index dcf8413..2312b03 100644 --- a/tasks/section_4/cis_4.1.4.x.yml +++ b/tasks/section_4/cis_4.1.4.x.yml @@ -65,6 +65,8 @@ ansible.builtin.file: path: "{{ item.path }}" mode: 'u-x,g-wx,u-rwx' + failed_when: rhel9cis_4_1_4_5_file_list.state not in '[ file, absent ]' + register: rhel9cis_4_1_4_5_file_list loop: "{{ auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -81,6 +83,8 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root + failed_when: rhel9cis_4_1_4_6_file_list.state not in '[ file, absent ]' + register: rhel9cis_4_1_4_6_file_list loop: "{{ auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" @@ -97,6 +101,8 @@ ansible.builtin.file: path: "{{ item.path }}" group: root + failed_when: rhel9cis_4_1_4_7_file_list.state not in '[ file, absent ]' + register: rhel9cis_4_1_4_7_file_list loop: "{{ auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" diff --git a/tasks/section_4/cis_4.2.3.yml b/tasks/section_4/cis_4.2.3.yml index 823975a..42bb419 100644 --- a/tasks/section_4/cis_4.2.3.yml +++ b/tasks/section_4/cis_4.2.3.yml @@ -14,6 +14,8 @@ ansible.builtin.file: path: "{{ item.path }}" mode: "{{ '0600' if item.mode == '0600' else '0640' }}" + failed_when: rhel9cis_4_2_3_file_list.state not in '[ file, absent ]' + register: rhel9cis_4_2_3_file_list loop: "{{ logfiles.files }}" loop_control: label: "{{ item.path }}" From 3c08540062fba3c3764a0d8b2f85ee97df9cf25b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 17:21:47 +0100 Subject: [PATCH 051/327] improved 6.1.10 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index ef3d3b3..87c7a1a 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -150,7 +150,7 @@ - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist" block: - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories" - ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser + ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser -not -fstype nfs changed_when: false failed_when: false check_mode: false @@ -162,26 +162,21 @@ - item['device'].startswith('/dev') - not 'bind' in item['options'] - - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | set fact" + - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Flatten no_user_items results for easier use" ansible.builtin.set_fact: - rhel_09_6_1_10_unowned_files_found: true - loop: "{{ rhel_09_6_1_10_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_unowned_files_flatten: "{{ rhel_09_6_1_10_audit.results | map(attribute='stdout_lines') | flatten }}" - name: "6.1.10 | 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_09_6_1_10_audit.stdout_lines }}" - when: rhel_09_6_1_10_unowned_files_found + msg: "Warning!! Missing owner on items in {{ discovered_unowned_files_flatten }}" + when: discovered_unowned_files_flatten | length > 0 - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | warning" ansible.builtin.import_tasks: file: warning_facts.yml vars: warn_control_id: '6.1.10' - when: rhel_09_6_1_10_unowned_files_found + when: discovered_unowned_files_flatten | length > 0 vars: rhel_09_6_1_10_unowned_files_found: false when: From 82c1137b94287abcbd4a1214571896ecf55ffe8b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 9 Aug 2024 17:33:01 +0100 Subject: [PATCH 052/327] updated logic 6.1.11 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 87c7a1a..a0e8dd6 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -177,8 +177,6 @@ vars: warn_control_id: '6.1.10' when: discovered_unowned_files_flatten | length > 0 - vars: - rhel_09_6_1_10_unowned_files_found: false when: - rhel9cis_rule_6_1_10 tags: @@ -204,28 +202,21 @@ - item['device'].startswith('/dev') - not 'bind' in item['options'] - - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | set fact" + - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Flatten no_user_items results for easier use" ansible.builtin.set_fact: - rhel_09_6_1_11_ungrouped_files_found: true - loop: "{{ rhel_09_6_1_11_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_files_flatten: "{{ rhel_09_6_1_11_audit.results | map(attribute='stdout_lines') | flatten }}" - name: "6.1.11 | 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_09_6_1_11_audit.stdout_lines }}" - when: rhel_09_6_1_11_ungrouped_files_found + msg: "Warning!! Missing group on items in {{ discovered_ungrouped_files_flatten }}" + when: discovered_ungrouped_files_flatten | length > 0 - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | warning" ansible.builtin.import_tasks: file: warning_facts.yml vars: warn_control_id: '6.1.11' - when: rhel_09_6_1_11_ungrouped_files_found - vars: - rhel_09_6_1_11_ungrouped_files_found: false + when: discovered_ungrouped_files_flatten | length > 0 when: - rhel9cis_rule_6_1_11 tags: From a0fd194ef449cf6aebdf3c2bed0464f42ee82d30 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 10:47:38 +0100 Subject: [PATCH 053/327] fixed typo on 4.1.4.5 Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.1.4.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_4/cis_4.1.4.x.yml b/tasks/section_4/cis_4.1.4.x.yml index 2312b03..79c0f23 100644 --- a/tasks/section_4/cis_4.1.4.x.yml +++ b/tasks/section_4/cis_4.1.4.x.yml @@ -64,7 +64,7 @@ - name: "4.1.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive" ansible.builtin.file: path: "{{ item.path }}" - mode: 'u-x,g-wx,u-rwx' + mode: 'u-x,g-wx,o-rwx' failed_when: rhel9cis_4_1_4_5_file_list.state not in '[ file, absent ]' register: rhel9cis_4_1_4_5_file_list loop: "{{ auditd_conf_files.files }}" From 8fe700fea79eb7dd429126d8e7567ea9eb7ce69e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 21:38:52 +0100 Subject: [PATCH 054/327] removed jmespath reference Signed-off-by: Mark Bolwell --- .config/requirements.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/.config/requirements.txt b/.config/requirements.txt index 52cb84d..ba7d83b 100644 --- a/.config/requirements.txt +++ b/.config/requirements.txt @@ -1,5 +1,4 @@ passlib lxml xmltodict -jmespath yamllint From 383d2d410cb8ba0c17869679c6fce887221f1507 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 12 Aug 2024 21:39:03 +0100 Subject: [PATCH 055/327] updated to fix output Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 864f5bb..ab5a573 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -22,7 +22,7 @@ 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: From 5f94f60e69a43f0410a628ee1fe329019bc8dd6c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 13 Aug 2024 08:25:10 +0100 Subject: [PATCH 056/327] Updated audit steps and added ARM support Signed-off-by: Mark Bolwell --- tasks/LE_audit_setup.yml | 10 ++++------ tasks/post_remediation_audit.yml | 2 +- tasks/pre_remediation_audit.yml | 2 +- vars/audit.yml | 5 +++-- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index b3964ce..4b407eb 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -3,16 +3,17 @@ - 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 == "aarch64" 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 +21,12 @@ 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/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index a6f9461..8004ed3 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -35,7 +35,7 @@ - audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: "tail -2 /opt/audit_ubuntu2204-CIS-UBUNTU22_1720624848.documentation" + ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' register: post_audit_summary changed_when: false diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 4dc7c49..9a2c2ce 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -105,7 +105,7 @@ - audit_format == "documentation" block: - name: Pre Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' register: pre_audit_summary changed_when: false diff --git a/vars/audit.yml b/vars/audit.yml index 151e9eb..e54deb8 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -26,8 +26,9 @@ post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchma ### Audit binary settings ### audit_bin_version: - release: v0.4.4 - AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' + release: v0.4.8 + AMD64_checksum: 'sha256:85d00b7bba5f175bec95de7dfe1f71f8f25204914aad4c6f03c8457868eb6e2f' + ARM64_checksum: 'sha256:bca8c898bfd35b94c51455ece6193c95e2cd7b2b183ac2047b2d76291e73e47d' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json From e510607fb6a55bec1a41a2c80a5cb3ec36048321 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 13 Aug 2024 11:12:38 +0100 Subject: [PATCH 057/327] updated audit and arm64 audit support Signed-off-by: Mark Bolwell --- tasks/LE_audit_setup.yml | 2 +- vars/audit.yml | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 7ef94b4..08d047d 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -10,7 +10,7 @@ - name: Pre Audit Setup | Set audit package name | ARM64 ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 - when: ansible_facts.machine == "arm64" + when: ansible_facts.machine == "aarch64" - name: Pre Audit Setup | Download audit binary ansible.builtin.get_url: diff --git a/vars/audit.yml b/vars/audit.yml index 9dc666a..e677d8e 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -26,8 +26,9 @@ post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchma ### Audit binary settings ### audit_bin_version: - release: v0.4.4 - AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5' + release: v0.4.8 + AMD64_checksum: 'sha256:85d00b7bba5f175bec95de7dfe1f71f8f25204914aad4c6f03c8457868eb6e2f' + ARM64_checksum: 'sha256:bca8c898bfd35b94c51455ece6193c95e2cd7b2b183ac2047b2d76291e73e47d' audit_bin_path: /usr/local/bin/ audit_bin: "{{ audit_bin_path }}goss" audit_format: json From 2c654ada1bf360b6a3c1ac8435da9d5dcd3c15d9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 15 Aug 2024 17:03:28 +0100 Subject: [PATCH 058/327] improve logic if files absent since find Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.3.4.x.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index db66377..568e5c2 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -50,6 +50,8 @@ ansible.builtin.file: path: "{{ item.path }}" mode: 'u-x,g-wx,o-rwx' + failed_when: rhel9cis_6_3_4_5_file_list.state not in '[ file, absent ]' + register: rhel9cis_6_3_4_5_file_list loop: "{{ prelim_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" From 27ee4a81673e769958e6f58c88b8b8667ce14471 Mon Sep 17 00:00:00 2001 From: Michael Hicks Date: Wed, 14 Aug 2024 20:29:44 -0700 Subject: [PATCH 059/327] added calls to sshd restart handler to fix #230 Signed-off-by: Michael Hicks --- tasks/section_5/cis_5.2.x.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index ac62767..3c34413 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -125,6 +125,7 @@ regexp: "^#LogLevel|^LogLevel" line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_5 tags: @@ -140,6 +141,7 @@ regexp: "^#UsePAM|^UsePAM" line: 'UsePAM yes' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_6 tags: @@ -162,6 +164,7 @@ ansible.builtin.file: path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf state: absent + notify: Restart sshd when: - rhel9cis_rule_5_2_7 tags: @@ -177,6 +180,7 @@ regexp: "^#HostbasedAuthentication|^HostbasedAuthentication" line: 'HostbasedAuthentication no' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_8 tags: @@ -192,6 +196,7 @@ regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" line: 'PermitEmptyPasswords no' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_9 tags: @@ -207,6 +212,7 @@ regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" line: 'PermitUserEnvironment no' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_10 tags: @@ -222,6 +228,7 @@ regexp: "^#IgnoreRhosts|^IgnoreRhosts" line: 'IgnoreRhosts yes' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_11 tags: @@ -240,6 +247,7 @@ regexp: "^#X11Forwarding|^X11Forwarding" line: 'X11Forwarding no' validate: sshd -t -f %s + notify: Restart sshd - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | override" ansible.builtin.lineinfile: @@ -247,6 +255,7 @@ regexp: "^#X11Forwarding|^X11Forwarding" line: 'X11Forwarding no' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_12 tags: @@ -262,6 +271,7 @@ regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" line: 'AllowTcpForwarding no' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_13 tags: @@ -297,6 +307,7 @@ path: "{{ rhel9_cis_sshd_config_file }}" regexp: '^Banner' line: 'Banner /etc/issue.net' + notify: Restart sshd when: - rhel9cis_rule_5_2_15 tags: @@ -312,6 +323,7 @@ regexp: '^(#)?MaxAuthTries \d' line: 'MaxAuthTries 4' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_16 tags: @@ -327,6 +339,7 @@ regexp: "^#MaxStartups|^MaxStartups" line: 'MaxStartups 10:30:60' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_17 tags: @@ -342,6 +355,7 @@ regexp: "^#MaxSessions|^MaxSessions" line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_18 tags: @@ -357,6 +371,7 @@ regexp: "^#LoginGraceTime|^LoginGraceTime" line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}" validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_19 tags: @@ -374,6 +389,7 @@ regexp: '^ClientAliveInterval' line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}" validate: sshd -t -f %s + notify: Restart sshd - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" ansible.builtin.lineinfile: @@ -381,6 +397,7 @@ regexp: '^ClientAliveCountMax' line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}" validate: sshd -t -f %s + notify: Restart sshd when: - rhel9cis_rule_5_2_20 tags: From 86260d8630d4966556cb921ba711f119b233e3ea Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 20 Aug 2024 16:07:10 +0100 Subject: [PATCH 060/327] updated Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 2 +- .github/workflows/main_pipeline_validation.yml | 12 ------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 912b3db..c9328cb 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -27,7 +27,7 @@ jobs: # This will create messages for first time contributers and direct them to the Discord server welcome: - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/first-interaction@main diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index 4a5adc9..ab11c37 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -23,18 +23,6 @@ # 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: - 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 From 6128104385705f77f6850e868fe394089c1c6fa8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 20 Aug 2024 16:07:27 +0100 Subject: [PATCH 061/327] Added greate logfile logic is file changed Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.4.1.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index 07ba04b..dd584e0 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -27,6 +27,8 @@ ansible.builtin.file: path: "{{ item }}" mode: 'u-x,g-wx,o-rwx' + failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' + register: rhel9cis_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" @@ -36,6 +38,8 @@ ansible.builtin.file: path: "{{ item }}" mode: 'u-x,g-x,o-rwx' + failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' + register: rhel9cis_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" @@ -49,4 +53,6 @@ ansible.builtin.file: path: "{{ item }}" mode: 'ug-x,o-wx' + failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' + register: rhel9cis_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" From 11c980ec5f60f30ecb7735a03304f63a98499ed8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 20 Aug 2024 16:51:53 +0100 Subject: [PATCH 062/327] improved logic for files that change state Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.3.4.x.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 568e5c2..5977406 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -68,6 +68,8 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root + failed_when: rhel9cis_6_3_4_6_file_list.state not in '[ file, absent ]' + register: rhel9cis_6_3_4_6_file_list loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" @@ -84,6 +86,8 @@ ansible.builtin.file: path: "{{ item.path }}" group: root + failed_when: rhel9cis_6_3_4_7_file_list.state not in '[ file, absent ]' + register: rhel9cis_6_3_4_7_file_list loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" From e05c2f32411e01cc60b814cb86b330f073fc7e56 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 21 Aug 2024 11:11:10 +0100 Subject: [PATCH 063/327] added fix for #232 thanks to @Arkhenys Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.2.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_4/cis_4.2.1.x.yml b/tasks/section_4/cis_4.2.1.x.yml index 740f820..fd1961f 100644 --- a/tasks/section_4/cis_4.2.1.x.yml +++ b/tasks/section_4/cis_4.2.1.x.yml @@ -123,7 +123,7 @@ local2,local3.* -/var/log/localmessages local4,local5.* -/var/log/localmessages local6,local7.* -/var/log/localmessages - *.emrg :omusrmsg:* + *.emerg :omusrmsg:* insertafter: '#### RULES ####' notify: Restart rsyslog From 75f3ab9e611ebecdd2339bab88f2b3d8ecf6ebd6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 21 Aug 2024 11:12:48 +0100 Subject: [PATCH 064/327] fix typo for emerg rule Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.3.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 4274429..9e42ee2 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -149,7 +149,7 @@ local2,local3.* -/var/log/localmessages local4,local5.* -/var/log/localmessages local6,local7.* -/var/log/localmessages - *.emrg :omusrmsg:* + *.emerg :omusrmsg:* insertafter: '#### RULES ####' notify: Restart rsyslog From b368d8bf7c767fa7556eece953b4d1a5ac9c6639 Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Thu, 22 Aug 2024 09:13:53 +0100 Subject: [PATCH 065/327] Fix link to Changelog.md in README.md Signed-off-by: Mark Goddard --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f8f3680..3260cb0 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ The control found in the `defaults` main also needs to reflect this, as this con CIS release always contains changes, it is highly recommended to review the new references and available variables. This has changed significantly since the ansible-lockdown initial release. This is now compatible with python3 if it is found to be the default interpreter. This does come with prerequisites which configure the system accordingly. -Further details can be seen in the [Changelog](./ChangeLog.md) +Further details can be seen in the [Changelog](./Changelog.md) ## Auditing (new) From c58c4eb4e8492643748257a30109834890f76f57 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Sep 2024 16:04:47 +0100 Subject: [PATCH 066/327] fixed 5.2.4 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.2.x.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index 6bb0608..f129956 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -57,21 +57,21 @@ - rule_5.2.4 - NIST800-53R5_AC-6 block: - - name: "5.2.4 | AUDIT | Ensure users must provide password for escalation | discover accts with NOPASSWD" + - name: "5.2.4 | AUDIT | Ensure users must provide password for escalation | Discover accts with NOPASSWD" ansible.builtin.shell: grep -Ei '(nopasswd)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1 become: true changed_when: false failed_when: false - register: rhel9cis_5_2_4_nopasswd + register: discovered_nopasswd_sudoers - - name: "5.2.4 | PATCH | Ensure users must provide password for escalation" - when: rhel9cis_5_2_4_nopasswd.std | length > 0 + - name: "5.2.4 | PATCH | Ensure users must provide password for escalation | Remove nopasswd for accounts not excluded" + when: discovered_nopasswd_sudoers.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: '^((?!#|{% for name in rhel9cis_sudoers_exclude_nopasswd_list %}{{ name }}{% if not loop.last -%}|{%- endif -%}{% endfor %}).*)NOPASSWD(.*)' replace: '\1PASSWD\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_5_2_4_nopasswd.stdout_lines }}" + loop: "{{ discovered_nopasswd_sudoers.stdout_lines }}" - name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" when: From 14d038e8eb5b81127585c22335f180e52286c577 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 5 Sep 2024 17:36:07 +0100 Subject: [PATCH 067/327] renamed variables Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.2.x.yml | 4 +-- tasks/section_2/cis_2.4.x.yml | 8 ++--- tasks/section_3/cis_3.1.x.yml | 8 ++--- tasks/section_4/cis_4.2.x.yml | 4 +-- tasks/section_4/cis_4.3.x.yml | 56 +++++++++++++++---------------- tasks/section_5/cis_5.1.x.yml | 8 ++--- tasks/section_5/cis_5.2.x.yml | 10 +++--- tasks/section_5/cis_5.3.2.x.yml | 18 +++++----- tasks/section_5/cis_5.3.3.4.x.yml | 34 +++++++++---------- tasks/section_5/cis_5.4.1.x.yml | 24 ++++++------- tasks/section_6/cis_6.2.4.1.yml | 12 +++---- tasks/section_6/cis_6.3.1.x.yml | 22 ++++++------ tasks/section_6/cis_6.3.4.x.yml | 12 +++---- tasks/section_7/cis_7.1.x.yml | 6 ++-- 14 files changed, 113 insertions(+), 113 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index f93a1d4..eb82773 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -17,10 +17,10 @@ - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" ansible.builtin.shell: mount -l | grep -w /dev/shm changed_when: false - register: rhel9cis_1_8_1_1_mount_check + register: discovered_dev_shm_mount_check - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" - when: rhel9cis_1_8_1_1_mount_check.rc == 1 + when: discovered_dev_shm_mount_check.rc == 1 block: - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" ansible.builtin.debug: diff --git a/tasks/section_2/cis_2.4.x.yml b/tasks/section_2/cis_2.4.x.yml index 072fa0b..16ed0e9 100644 --- a/tasks/section_2/cis_2.4.x.yml +++ b/tasks/section_2/cis_2.4.x.yml @@ -141,12 +141,12 @@ - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Check if cron.allow exists" ansible.builtin.stat: path: "/etc/cron.allow" - register: rhel9cis_2_4_1_8_cron_allow_state + register: discovered_cron_allow_state - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Ensure cron.allow is restricted to authorized users" ansible.builtin.file: path: /etc/cron.allow - state: '{{ "file" if rhel9cis_2_4_1_8_cron_allow_state.stat.exists else "touch" }}' + state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' owner: root group: root mode: u-x,g-wx,o-rwx @@ -171,12 +171,12 @@ - name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists" ansible.builtin.stat: path: "/etc/at.allow" - register: rhel9cis_rule_2_4_2_1_at_allow_state + register: discovered_at_allow_state - name: "2.4.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 rhel9cis_rule_2_4_2_1_at_allow_state.stat.exists else "touch" }}' + state: '{{ "file" if discovered_at_allow_state.stat.exists else "touch" }}' owner: root group: root mode: u-x,g-wx,o-rwx diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 5c76ab6..98e3a93 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -44,15 +44,15 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_3_1_2_wifi_status + register: discovered_wifi_status - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed" when: - "'network-manager' in ansible_facts.packages" - - "'enabled' in rhel9cis_3_1_2_wifi_status.stdout" + - "'enabled' in discovered_wifi_status.stdout" ansible.builtin.shell: nmcli radio all off - changed_when: rhel9cis_3_1_2_nmcli_radio_off.rc == 0 - register: rhel9cis_3_1_2_nmcli_radio_off + changed_when: discovered_nmcli_radio_off.rc == 0 + register: discovered_nmcli_radio_off - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed" when: "'network-manager' not in ansible_facts.packages" diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml index 01fd1eb..0fca4cc 100644 --- a/tasks/section_4/cis_4.2.x.yml +++ b/tasks/section_4/cis_4.2.x.yml @@ -16,13 +16,13 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_4_2_5_servicesport + register: discovered_services_and_ports - name: "4.2.1 | 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" - - "{{ rhel9cis_4_2_5_servicesport.stdout_lines }}" + - "{{ discovered_services_and_ports.stdout_lines }}" - name: "4.2.2 | PATCH | Ensure firewalld loopback traffic is configured | firewalld" when: diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 09e8979..06e27c0 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -15,30 +15,30 @@ ansible.builtin.shell: nft list ruleset | grep 'hook input' changed_when: false failed_when: false - register: rhel9cis_4_3_1_input_chains + register: discovered_nftables_input_chains - name: "4.3.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: rhel9cis_4_3_1_forward_chains + register: discovered_nftables_forward_chains - name: "4.3.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: rhel9cis_4_3_1_output_chains + register: discovered_nftables_output_chains - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Display chains for review" when: not rhel9cis_nft_tables_autochaincreate ansible.builtin.debug: msg: - "Below are the current INPUT chains" - - "{{ rhel9cis_4_3_1_input_chains.stdout_lines }}" + - "{{ discovered_nftables_input_chains.stdout_lines }}" - "Below are the current FORWARD chains" - - "{{ rhel9cis_4_3_1_forward_chains.stdout_lines }}" + - "{{ discovered_nftables_forward_chains.stdout_lines }}" - "Below are teh current OUTPUT chains" - - "{{ rhel9cis_4_3_1_output_chains.stdout_lines }}" + - "{{ discovered_nftables_output_chains.stdout_lines }}" - name: "4.3.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" when: rhel9cis_nft_tables_autochaincreate @@ -64,36 +64,36 @@ 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: rhel9cis_4_3_2_inconnectionrule + register: discovered_nftables_inconnectionrule - name: "4.3.2| 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: rhel9cis_4_3_2_outconnectionrule + register: discovered_nftables_outconnectionrule - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" - when: '"ip protocol tcp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" - when: '"ip protocol udp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + when: '"ip protocol udp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" - when: '"ip protocol icmp ct state established accept" not in rhel9cis_4_3_2_inconnectionrule.stdout' + when: '"ip protocol icmp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" - when: '"ip protocol tcp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + when: '"ip protocol tcp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" - when: '"ip protocol udp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + when: '"ip protocol udp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" - when: '"ip protocol icmp ct state established,related,new accept" not in rhel9cis_4_3_2_outconnectionrule.stdout' + when: '"ip protocol icmp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy" @@ -111,40 +111,40 @@ ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false - register: rhel9cis_4_3_3_inputpolicy + register: discovered_nftables_inputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false - register: rhel9cis_4_3_3_forwardpolicy + register: discovered_nftables_forwardpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false - register: rhel9cis_4_3_3_outputpolicy + register: discovered_nftables_outputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false - register: rhel9cis_4_3_3_sshallowcheck + register: discovered_nftables_sshallowcheck - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" - when: '"tcp dport ssh accept" not in rhel9cis_4_3_3_sshallowcheck.stdout' + when: '"tcp dport ssh accept" not in discovered_nftables_sshallowcheck.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" - when: '"type filter hook input priority 0; policy drop;" not in rhel9cis_4_3_3_inputpolicy.stdout' + when: '"type filter hook input priority 0; policy drop;" not in discovered_nftables_inputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; } - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" - when: '"type filter hook forward priority 0; policy drop;" not in rhel9cis_4_3_3_forwardpolicy.stdout' + when: '"type filter hook forward priority 0; policy drop;" not in discovered_nftables_forwardpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; } - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" - when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_4_3_3_outputpolicy.stdout' + when: '"type filter hook output priority 0; policy drop;" not in discovered_nftables_outputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured" @@ -162,28 +162,28 @@ ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false - register: rhel9cis_4_3_4_iiflo + register: discovered_nftables_iiflo - name: "4.3.4 | AUDIT | Ensure nftables 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: rhel9cis_4_3_4_ipsaddr + register: discovered_nftables_ipsaddr - name: "4.3.4 | AUDIT | Ensure nftables 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: rhel9cis_4_3_4_ip6saddr + register: discovered_nftables_ip6saddr - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule | nftables" - when: '"iif \"lo\" accept" not in rhel9cis_4_3_4_iiflo.stdout' + when: '"iif \"lo\" accept" not in discovered_nftables_iiflo.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule | nftables" - when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel9cis_4_3_4_ipsaddr.stdout' + when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_nftables_ipsaddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule | nftables" - when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_4_3_4_ip6saddr.stdout' + when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_nftables_ip6saddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 95addf3..b68ae3a 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -37,7 +37,7 @@ patterns: 'ssh_host_*_key' recurse: true file_type: any - register: rhel9cis_5_1_2_ssh_private_host_key + register: discovered_ssh_private_host_key - name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys" ansible.builtin.file: @@ -45,7 +45,7 @@ owner: root group: root mode: 'u-x,go-rwx' - loop: "{{ rhel9cis_5_1_2_ssh_private_host_key.files }}" + loop: "{{ discovered_ssh_private_host_key.files }}" loop_control: label: "{{ item.path }}" @@ -67,7 +67,7 @@ patterns: 'ssh_host_*_key.pub' recurse: true file_type: any - register: rhel9cis_5_1_3_ssh_public_host_key + register: discovered_ssh_public_host_key - name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys" ansible.builtin.file: @@ -75,7 +75,7 @@ owner: root group: root mode: 'u-x,go-wx' - loop: "{{ rhel9cis_5_1_3_ssh_public_host_key.files }}" + loop: "{{ discovered_ssh_public_host_key.files }}" loop_control: label: "{{ item.path }}" diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index f129956..2e46de4 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -114,24 +114,24 @@ ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort changed_when: false failed_when: false - register: rhel9cis_5_2_6_timeout_files + register: discovered_sudo_timeout_files - name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results" + when: discovered_sudo_timeout_files.stdout | length == 0 ansible.builtin.lineinfile: path: /etc/sudoers regexp: 'Defaults timestamp_timeout=' line: "Defaults timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}" validate: '/usr/sbin/visudo -cf %s' - when: rhel9cis_5_2_6_timeout_files.stdout | length == 0 - name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results" + when: discovered_sudo_timeout_files.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: 'timestamp_timeout=(\d+)' replace: "timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}" validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_5_2_6_timeout_files.stdout_lines }}" - when: rhel9cis_5_2_6_timeout_files.stdout | length > 0 + loop: "{{ discovered_sudo_timeout_files.stdout_lines }}" - name: "5.2.7 | PATCH | Ensure access to the su command is restricted" when: @@ -149,7 +149,7 @@ ansible.builtin.group: name: "{{ rhel9cis_sugroup }}" state: present - register: rhel9cis_5_2_7_sugroup + register: discovered_sugroup - name: "5.2.7 | PATCH | Ensure access to the su command is restricted | remove users from group" ansible.builtin.lineinfile: diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index c9a7559..3996edc 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -61,11 +61,11 @@ - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" ansible.builtin.shell: authselect current | grep faillock changed_when: false - failed_when: rhel9cis_authselect_current_faillock.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current_faillock + failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] + register: discovered_authselect_current_faillock - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" - when: rhel9cis_authselect_current_faillock.rc != 0 + when: discovered_authselect_current_faillock.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" @@ -85,11 +85,11 @@ - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" ansible.builtin.shell: authselect current | grep quality changed_when: false - failed_when: rhel9cis_authselect_current_quality.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current_quality + failed_when: discovered_authselect_current_quality.rc not in [ 0, 1 ] + register: discovered_authselect_current_quality - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" - when: rhel9cis_authselect_current_quality.rc != 0 + when: discovered_authselect_current_quality.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" notify: Authselect update @@ -110,11 +110,11 @@ - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" ansible.builtin.shell: authselect current | grep pwhistory changed_when: false - failed_when: rhel9cis_authselect_current_history.rc not in [ 0, 1 ] - register: rhel9cis_authselect_current_history + failed_when: discovered_authselect_current_history.rc not in [ 0, 1 ] + register: discovered_authselect_current_history - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" - when: rhel9cis_authselect_current_history.rc != 0 + when: discovered_authselect_current_history.rc != 0 ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" notify: Authselect update diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml index 4712373..a1e5768 100644 --- a/tasks/section_5/cis_5.3.3.4.x.yml +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -14,18 +14,18 @@ - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state" ansible.builtin.shell: grep -E "pam_unix.so.*nullok" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq changed_when: false - failed_when: rhel9cis_pam_nullok.rc not in [ 0, 1 ] - register: rhel9cis_pam_nullok + failed_when: discovered_pam_nullok.rc not in [ 0, 1 ] + register: discovered_pam_nullok - name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | Ensure nullok removed" when: - - rhel9cis_pam_nullok.stdout | length > 0 + - discovered_pam_nullok.stdout | length > 0 - not rhel9cis_allow_authselect_updates ansible.builtin.replace: path: "{{ item }}" regexp: nullok replace: '' - loop: "{{ rhel9cis_pam_nullok.stdout_lines }}" + loop: "{{ discovered_pam_nullok.stdout_lines }}" - name: "5.3.3.4.1 | PATCH | Ensure password number of changed characters is configured | Remove nullok from pam files AuthSelect" when: @@ -53,18 +53,18 @@ - name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state" ansible.builtin.shell: grep -E "password.*pam_unix.so.*remember" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq changed_when: false - failed_when: rhel9cis_pam_remember.rc not in [ 0, 1 ] - register: rhel9cis_pam_remember + failed_when: discovered_pam_remember.rc not in [ 0, 1 ] + register: discovered_pam_remember - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Ensure remember removed" when: - not rhel9cis_allow_authselect_updates - - rhel9cis_pam_remember.stdout | length > 0 + - discovered_pam_remember.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: remember replace: '' - loop: "{{ rhel9cis_pam_remember.stdout_lines }}" + loop: "{{ discovered_pam_remember.stdout_lines }}" - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Remove remember from pam files AuthSelect" when: @@ -93,18 +93,18 @@ - name: "5.3.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state" ansible.builtin.shell: grep -E "password.*pam_unix.so.*(sha512|yescrypt)" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq changed_when: false - failed_when: rhel9cis_pam_pwhash.rc not in [ 0, 1 ] - register: rhel9cis_pam_pwhash + failed_when: discovered_pam_pwhash.rc not in [ 0, 1 ] + register: discovered_pam_pwhash - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Ensure hash algorithm set" when: - not rhel9cis_allow_authselect_updates - - rhel9cis_pam_remember.stdout | length > 0 + - discovered_pam_remember.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)" replace: '{{ rhel9cis_passwd_hash_algo }}' - loop: "{{ rhel9cis_pam_remember.stdout_lines }}" + loop: "{{ discovered_pam_remember.stdout_lines }}" - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Add hash algorithm to pam files AuthSelect" when: @@ -134,20 +134,20 @@ - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state" ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix.so\b' /etc/pam.d/{password,system}-auth | grep -Pv -- '\buse_authtok\b' changed_when: false - failed_when: rhel9cis_pam_authtok.rc not in [ 0, 1 ] - register: rhel9cis_pam_authtok + failed_when: discovered_pam_authtok.rc not in [ 0, 1 ] + register: discovered_pam_authtok - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files" when: - not rhel9cis_allow_authselect_updates - - rhel9cis_pam_authtok is defined - - rhel9cis_pam_authtok.stdout | length > 0 + - discovered_pam_authtok is defined + - discovered_pam_authtok.stdout | length > 0 ansible.builtin.lineinfile: path: "{{ item }}" regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$) line: \1\2\3\4use_authtok \5 backrefs: true - loop: "{{ rhel9cis_pam_authtok.stdout_lines }}" + loop: "{{ discovered_pam_authtok.stdout_lines }}" - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | Add use_authtok pam files AuthSelect" when: diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index a5cd8c5..9e92e86 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -129,22 +129,22 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_5_4_1_5_inactive_settings + register: discovered_passwdlck_inactive_settings - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting" ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} - when: rhel9cis_5_4_1_5_inactive_settings.stdout | length == 0 + when: discovered_passwdlck_inactive_settings.stdout | length == 0 - name: "5.4.1.5 | 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: rhel9cis_5_4_1_5_user_list + register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" when: item in prelim_interactive_usernames.stdout ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" - loop: "{{ rhel9cis_5_4_1_5_user_list.stdout_lines }}" + loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past" when: @@ -162,32 +162,32 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_5_4_1_6_currentut + register: discovered_passwdlck_currentunixtime - name: "5.4.1.6 | 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>{{ rhel9cis_5_4_1_6_currentut.stdout }})print$1}'" + ansible.builtin.shell: "cat /etc/shadow | awk -F: '{if($3>{{ discovered_passwdlck_currentunixtime.stdout }})print$1}'" changed_when: false failed_when: false check_mode: false - register: rhel9cis_5_4_1_6_user_list + register: discovered_passwdlck_user_future - name: "5.4.1.6 | 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: {{ rhel9cis_5_4_1_6_user_list.stdout_lines }}" + msg: "Warning!! The following accounts have the last PW change date in the future: {{ discovered_passwdlck_user_future.stdout_lines }}" when: - - rhel9cis_5_4_1_6_user_list.stdout | length > 0 + - discovered_passwdlck_user_future.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count" ansible.builtin.import_tasks: file: warning_facts.yml when: - - rhel9cis_5_4_1_6_user_list.stdout | length > 0 + - discovered_passwdlck_user_future.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix - name: "5.4.1.6 | 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: - - rhel9cis_5_4_1_5_user_list.stdout | length > 0 + - discovered_passwdlck_user_future.stdout | length > 0 - rhel9cis_futurepwchgdate_autofix - loop: "{{ rhel9cis_5_4_1_6_user_list.stdout_lines }}" + loop: "{{ discovered_passwdlck_user_future.stdout_lines }}" diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index dd584e0..8111ef4 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -27,8 +27,8 @@ ansible.builtin.file: path: "{{ item }}" mode: 'u-x,g-wx,o-rwx' - failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' - register: rhel9cis_logfile_list + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" @@ -38,8 +38,8 @@ ansible.builtin.file: path: "{{ item }}" mode: 'u-x,g-x,o-rwx' - failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' - register: rhel9cis_logfile_list + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" @@ -53,6 +53,6 @@ ansible.builtin.file: path: "{{ item }}" mode: 'ug-x,o-wx' - failed_when: rhel9cis_logfile_list.state not in '[ file, absent ]' - register: rhel9cis_logfile_list + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" diff --git a/tasks/section_6/cis_6.3.1.x.yml b/tasks/section_6/cis_6.3.1.x.yml index b25ab69..3039f2c 100644 --- a/tasks/section_6/cis_6.3.1.x.yml +++ b/tasks/section_6/cis_6.3.1.x.yml @@ -42,13 +42,13 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_6_3_1_2_grubby_curr_value_audit_linux + register: discovered_grubby_curr_value_audit_linux - name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby update, if needed" when: - - rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout == '' or - '0' in rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout or - 'off' in rhel9cis_6_3_1_2_grubby_curr_value_audit_linux.stdout|lower + - discovered_grubby_curr_value_audit_linux.stdout == '' or + '0' in discovered_grubby_curr_value_audit_linux.stdout or + 'off' in discovered_grubby_curr_value_audit_linux.stdout|lower ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1" - name: "6.3.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" @@ -71,25 +71,25 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux + register: discovered_grubby_curr_value_backlog_linux - name: "6.3.1.3 | AUDIT | Check to see if limits are set" when: - - rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux is not defined or - rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux.stdout_lines == [] + - discovered_grubby_curr_value_backlog_linux is not defined or + discovered_grubby_curr_value_backlog_linux.stdout_lines == [] ansible.builtin.set_fact: - rhel9cis_6_3_1_3_reset_backlog_limits: true + discovered_reset_backlog_limits: true - name: "6.3.1.3 | AUDIT | Check to see if any limits are too low" when: - (item | int < rhel9cis_audit_back_log_limit) ansible.builtin.set_fact: - rhel9cis_6_3_1_3_reset_backlog_limits: true - loop: "{{ rhel9cis_6_3_1_3_grubby_curr_value_backlog_linux.stdout_lines }}" + discovered_reset_backlog_limits: true + loop: "{{ discovered_grubby_curr_value_backlog_linux.stdout_lines }}" - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" when: - - rhel9cis_6_3_1_3_reset_backlog_limits is defined + - discovered_reset_backlog_limits is defined ansible.builtin.shell: cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 5977406..c89af87 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -50,8 +50,8 @@ ansible.builtin.file: path: "{{ item.path }}" mode: 'u-x,g-wx,o-rwx' - failed_when: rhel9cis_6_3_4_5_file_list.state not in '[ file, absent ]' - register: rhel9cis_6_3_4_5_file_list + failed_when: discovered_audit_conf_file_list.state not in '[ file, absent ]' + register: discovered_audit_conf_file_list loop: "{{ prelim_auditd_conf_files.files }}" loop_control: label: "{{ item.path }}" @@ -68,8 +68,8 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root - failed_when: rhel9cis_6_3_4_6_file_list.state not in '[ file, absent ]' - register: rhel9cis_6_3_4_6_file_list + failed_when: discovered_audit_conf_file_list.state not in '[ file, absent ]' + register: discovered_audit_conf_file_list loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" @@ -86,8 +86,8 @@ ansible.builtin.file: path: "{{ item.path }}" group: root - failed_when: rhel9cis_6_3_4_7_file_list.state not in '[ file, absent ]' - register: rhel9cis_6_3_4_7_file_list + failed_when: discovered_audit_conf_file_list.state not in '[ file, absent ]' + register: discovered_audit_conf_file_list loop: "{{ prelim_auditd_conf_files.files | default([]) }}" loop_control: label: "{{ item.path }}" diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 4c95687..0fe5fe7 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -202,9 +202,9 @@ - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable directories add sticky bit" ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -o+w ! -perm -1002 2>/dev/null | xargs chmod a+t - failed_when: rhel9cis_set_stickybit.rc not in [ 0, 123 ] - changed_when: rhel9cis_set_stickybit.rc == 0 - register: rhel9cis_set_stickybit + failed_when: discovered_set_stickybit.rc not in [ 0, 123 ] + changed_when: discovered_set_stickybit.rc == 0 + register: discovered_set_stickybit - name: "7.1.12 | PATCH | Ensure no files or directories without an owner and a group exist" when: From 2d2f2817330d3788dff46d9bfa61d25a941ec0d1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 6 Sep 2024 14:32:48 +0100 Subject: [PATCH 068/327] made ssh_config file tage always Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0db27d3..d88a338 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -251,9 +251,7 @@ - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' - "'openssh-server' in ansible_facts.packages" tags: - - ssh - - level1_server - - level1_workstation + - always - name: "PRELIM | 5.3.4 | Find all sudoers files." ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'" From 3cdd2a0368755bd93be5b9e8d2f4db3052f1174f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 6 Sep 2024 14:40:52 +0100 Subject: [PATCH 069/327] updated var naming from rhel9_cis to rhel9cis Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- tasks/prelim.yml | 4 +-- tasks/section_5/cis_5.2.x.yml | 40 +++++++++++++++--------------- templates/ansible_vars_goss.yml.j2 | 2 +- 4 files changed, 24 insertions(+), 24 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 117933e..622af55 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -962,7 +962,7 @@ rhel9cis_logrotate: "daily" # This value, containing the absolute filepath of the produced 'sshd' config file, allows usage of # drop-in files('/etc/ssh/ssh_config.d/{ssh_drop_in_name}.conf', supported by RHEL9) when CIS adopts them. # Otherwise, the default value is '/etc/ssh/ssh_config'. -rhel9_cis_sshd_config_file: /etc/ssh/sshd_config +rhel9cis_sshd_config_file: /etc/ssh/sshd_config ## Controls: ## - 5.2.4 - Ensure SSH access is limited diff --git a/tasks/prelim.yml b/tasks/prelim.yml index d88a338..1db6db5 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -242,13 +242,13 @@ # Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config - name: "PRELIM | Section 5.2 | SSH" ansible.builtin.file: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" owner: root group: root mode: '0600' state: touch when: - - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' + - rhel9cis_sshd_config_file != '/etc/ssh/sshd_config' - "'openssh-server' in ansible_facts.packages" tags: - always diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index 3c34413..d6c6bf9 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -77,7 +77,7 @@ block: - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^AllowUsers" line: "AllowUsers {{ rhel9cis_sshd['allowusers'] }}" validate: sshd -t -f %s @@ -86,7 +86,7 @@ - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^AllowGroups" line: "AllowGroups {{ rhel9cis_sshd['allowgroups'] }}" validate: sshd -t -f %s @@ -95,7 +95,7 @@ - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^DenyUsers" line: "DenyUsers {{ rhel9cis_sshd['denyusers'] }}" validate: sshd -t -f %s @@ -104,7 +104,7 @@ - name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^DenyGroups" line: "DenyGroups {{ rhel9cis_sshd['denygroups'] }}" validate: sshd -t -f %s @@ -121,7 +121,7 @@ - name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#LogLevel|^LogLevel" line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' validate: sshd -t -f %s @@ -137,7 +137,7 @@ - name: "5.2.6 | PATCH | Ensure SSH PAM is enabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#UsePAM|^UsePAM" line: 'UsePAM yes' validate: sshd -t -f %s @@ -155,7 +155,7 @@ block: - name: "5.2.7 | PATCH | Ensure SSH root login is disabled | config file" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#PermitRootLogin|^PermitRootLogin" line: 'PermitRootLogin no' validate: sshd -t -f %s @@ -176,7 +176,7 @@ - name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#HostbasedAuthentication|^HostbasedAuthentication" line: 'HostbasedAuthentication no' validate: sshd -t -f %s @@ -192,7 +192,7 @@ - name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords" line: 'PermitEmptyPasswords no' validate: sshd -t -f %s @@ -208,7 +208,7 @@ - name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#PermitUserEnvironment|^PermitUserEnvironment" line: 'PermitUserEnvironment no' validate: sshd -t -f %s @@ -224,7 +224,7 @@ - name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#IgnoreRhosts|^IgnoreRhosts" line: 'IgnoreRhosts yes' validate: sshd -t -f %s @@ -243,7 +243,7 @@ - name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | config file" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#X11Forwarding|^X11Forwarding" line: 'X11Forwarding no' validate: sshd -t -f %s @@ -267,7 +267,7 @@ - name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#AllowTcpForwarding|^AllowTcpForwarding" line: 'AllowTcpForwarding no' validate: sshd -t -f %s @@ -304,7 +304,7 @@ - name: "5.2.15 | PATCH | Ensure SSH warning banner is configured" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^Banner' line: 'Banner /etc/issue.net' notify: Restart sshd @@ -319,7 +319,7 @@ - name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^(#)?MaxAuthTries \d' line: 'MaxAuthTries 4' validate: sshd -t -f %s @@ -335,7 +335,7 @@ - name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#MaxStartups|^MaxStartups" line: 'MaxStartups 10:30:60' validate: sshd -t -f %s @@ -351,7 +351,7 @@ - name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#MaxSessions|^MaxSessions" line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s @@ -367,7 +367,7 @@ - name: "5.2.19 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^#LoginGraceTime|^LoginGraceTime" line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}" validate: sshd -t -f %s @@ -385,7 +385,7 @@ block: - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^ClientAliveInterval' line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}" validate: sshd -t -f %s @@ -393,7 +393,7 @@ - name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^ClientAliveCountMax' line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}" validate: sshd -t -f %s diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index f3b8a98..e639bef 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -462,7 +462,7 @@ rhel9cis_syslog: {{ rhel9cis_syslog }} # Section 5 # This will allow use of drop in files when CIS adopts them. -rhel9_cis_sshd_config_file: {{ rhel9_cis_sshd_config_file }} +rhel9_cis_sshd_config_file: {{ rhel9cis_sshd_config_file }} ## 5.2.4 Note the following to understand precedence and layout rhel9cis_sshd_limited: false From 7c4c3f9e4d2ed97749142a8a6d97d352ddccd514 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 6 Sep 2024 14:49:41 +0100 Subject: [PATCH 070/327] renamed variable and updated tag Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- tasks/prelim.yml | 6 +++--- tasks/section_5/cis_5.1.x.yml | 40 +++++++++++++++++------------------ 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index c524a55..a246b27 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -750,7 +750,7 @@ rhel9cis_nft_tables_autochaincreate: true # This value, containing the absolute filepath of the produced 'sshd' config file, allows usage of # drop-in files('/etc/ssh/ssh_config.d/{ssh_drop_in_name}.conf', supported by RHEL9) when CIS adopts them. # Otherwise, the default value is '/etc/ssh/ssh_config'. -rhel9_cis_sshd_config_file: /etc/ssh/sshd_config +rhel9cis_sshd_config_file: /etc/ssh/sshd_config ## Controls: ## - 5.1.7 - Ensure SSH access is limited diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 96e9657..78d1771 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -196,14 +196,14 @@ # Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config - name: "PRELIM | PATCH | SSH Config file is not exist" when: - - rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config' + - rhel9cis_sshd_config_file != '/etc/ssh/sshd_config' - "'openssh-server' in ansible_facts.packages" tags: - - ssh + - always - level1_server - level1_workstation ansible.builtin.file: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" owner: root group: root mode: '0600' diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index b68ae3a..31ba7e2 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -178,7 +178,7 @@ - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowusers" when: "rhel9cis_sshd_allowusers | length > 0" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^AllowUsers" line: "AllowUsers {{ rhel9cis_sshd_allowusers }}" validate: sshd -t -f %s @@ -187,7 +187,7 @@ - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowgroups" when: "rhel9cis_sshd_allowgroups | length > 0" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^AllowGroups" line: "AllowGroups {{ rhel9cis_sshd_allowgroups }}" validate: sshd -t -f %s @@ -196,7 +196,7 @@ - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denyusers" when: "rhel9cis_sshd_denyusers | length > 0" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^DenyUsers" line: "DenyUsers {{ rhel9cis_sshd_denyusers }}" validate: sshd -t -f %s @@ -205,7 +205,7 @@ - name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denygroups" when: "rhel9cis_sshd_denygroups | length > 0" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: "^DenyGroups" line: "DenyGroups {{ rhel9cis_sshd_denygroups }}" validate: sshd -t -f %s @@ -226,7 +226,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^Banner' line: 'Banner /etc/issue.net' @@ -247,7 +247,7 @@ block: - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^ClientAliveInterval' line: "ClientAliveInterval {{ rhel9cis_sshd_clientaliveinterval }}" validate: sshd -t -f %s @@ -255,7 +255,7 @@ - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^ClientAliveCountMax' line: "ClientAliveCountMax {{ rhel9cis_sshd_clientalivecountmax }}" validate: sshd -t -f %s @@ -274,7 +274,7 @@ block: - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | config file" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(#|)\s*DisableForwarding line: 'DisableForwarding yes' validate: sshd -t -f %s @@ -313,7 +313,7 @@ - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s @@ -334,7 +334,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*HostbasedAuthentication line: 'HostbasedAuthentication no' validate: sshd -t -f %s @@ -355,7 +355,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' validate: sshd -t -f %s @@ -372,7 +372,7 @@ - rule_5.1.14 - NIST800-53R5_CM-6 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" validate: sshd -t -f %s @@ -391,7 +391,7 @@ - NIST800-53R5_AU-12 - NIST800-53R5_SI-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' validate: sshd -t -f %s @@ -408,7 +408,7 @@ - rule_5.1.16 - NIST800-53R5_AU-3 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: '^(#)?MaxAuthTries \d' line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}' validate: sshd -t -f %s @@ -429,7 +429,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*MaxStartups line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' validate: sshd -t -f %s @@ -450,7 +450,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*MaxSessions line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s @@ -471,7 +471,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*PermitEmptyPasswords line: 'PermitEmptyPasswords no' validate: sshd -t -f %s @@ -490,7 +490,7 @@ block: - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*PermitRootLogin line: 'PermitRootLogin no' validate: sshd -t -f %s @@ -517,7 +517,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*PermitUserEnvironment line: 'PermitUserEnvironment no' validate: sshd -t -f %s @@ -538,7 +538,7 @@ - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 ansible.builtin.lineinfile: - path: "{{ rhel9_cis_sshd_config_file }}" + path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*UsePAM line: 'UsePAM yes' validate: sshd -t -f %s From ab3c9cc8aa0253159fe1c95a7711f7d40ae8be77 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 9 Sep 2024 12:10:38 +0100 Subject: [PATCH 071/327] Updated 4.3.2 Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.3.x.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 06e27c0..60db876 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -66,15 +66,19 @@ failed_when: false register: discovered_nftables_inconnectionrule - - name: "4.3.2| AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" + - name: "4.3.2 | 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: discovered_nftables_outconnectionrule + - name: "4.3.2| AUDIT | Ensure nftables established connections are configured | Create table is doesn't exist" + when: rhel9cis_nft_tables_autonewtable + ansible.builtin.shell: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' - ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + ansible.builtin.shell: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" when: '"ip protocol udp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' From e915a7ae5ddeebf4308c40d7c9644c709f8ed0fa Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 9 Sep 2024 12:36:58 +0100 Subject: [PATCH 072/327] added missing variable Signed-off-by: Mark Bolwell --- defaults/main.yml | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index a246b27..9f64850 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -733,16 +733,21 @@ rhel9cis_firewall: firewalld rhel9cis_default_zone: public ## Controls 4.3.x nftables -# This variable stores the name of the table to be used when configuring nftables(creating chains, configuring loopback -# traffic, established connections, default deny). If 'rhel9cis_nft_tables_autonewtable' is set as true, a new table will -# be created using as name the value stored by this variable. -rhel9cis_nft_tables_tablename: filter -## Ensure nftables base chains exist + +## 4.3.1 Ensure nftables base chains exist # This variable governs if a nftables base chain(entry point for packets from the networking stack) will be automatically # created, if needed. Without a chain, a hook for input, forward, and delete, packets that would flow through those # chains will not be touched by nftables. rhel9cis_nft_tables_autochaincreate: true +## 4.3.2 Create tables if required +rhel9cis_nft_tables_autonewtable: true +# This variable stores the name of the table to be used when configuring nftables(creating chains, configuring loopback +# traffic, established connections, default deny). If 'rhel9cis_nft_tables_autonewtable' is set as true, a new table will +# be created using as name the value stored by this variable. +rhel9cis_nft_tables_tablename: filter + + ## Section5 vars ## Section 5.1 - SSH From 22a19559481ddb7618836141c6e4f4cb8e944438 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 9 Sep 2024 13:59:31 +0100 Subject: [PATCH 073/327] Updated nftables prereqs for table Signed-off-by: Mark Bolwell --- tasks/section_4/cis_4.3.x.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 60db876..4e85deb 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -1,5 +1,15 @@ --- +- name: "OPTIONAL | PATCH | Create Table if doesn't exist and required" + when: + - rhel9cis_nft_tables_autonewtable + - rhel9cis_rule_4_3_1 + - rhel9cis_rule_4_3_2 + - rhel9cis_rule_4_3_3 + - rhel9cis_rule_4_3_4 + tags: always + ansible.builtin.shell: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + - name: "4.3.1 | PATCH | Ensure nftables base chains exist" when: - rhel9cis_rule_4_3_1 @@ -72,10 +82,6 @@ failed_when: false register: discovered_nftables_outconnectionrule - - name: "4.3.2| AUDIT | Ensure nftables established connections are configured | Create table is doesn't exist" - when: rhel9cis_nft_tables_autonewtable - ansible.builtin.shell: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" - - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.shell: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept From 37e13df44a52174654d320abd5970e05f2e2116a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 9 Sep 2024 14:01:21 +0100 Subject: [PATCH 074/327] lint Signed-off-by: Mark Bolwell --- defaults/main.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9f64850..56f07c5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -747,7 +747,6 @@ rhel9cis_nft_tables_autonewtable: true # be created using as name the value stored by this variable. rhel9cis_nft_tables_tablename: filter - ## Section5 vars ## Section 5.1 - SSH From 078c091232b7997444e24e2b83a599e1263073c7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 12 Sep 2024 14:39:19 +0100 Subject: [PATCH 075/327] removed unneccesary vars Signed-off-by: Mark Bolwell --- defaults/main.yml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 622af55..0b24c57 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -49,15 +49,10 @@ rhel9cis_selinux_disable: false # UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: false -## Python Binary -## This is used for python3 Installations where python2 OS modules are used in ansible -python2_bin: /bin/python2.7 - ## Benchmark name used by audting control role # The audit variable found at the base ## metadata for Audit benchmark benchmark_version: 'v1.0.0' - benchmark: RHEL9-CIS # Whether to skip the system reboot before audit From 9d8cef3c30c1c69aa8efcbd7e9f6b400e5a138a6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Sep 2024 17:48:44 +0000 Subject: [PATCH 076/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.18.4 → v8.19.2](https://github.com/gitleaks/gitleaks/compare/v8.18.4...v8.19.2) - [github.com/ansible-community/ansible-lint: v24.7.0 → v24.9.0](https://github.com/ansible-community/ansible-lint/compare/v24.7.0...v24.9.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 260cffe..f009319 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,13 +37,13 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.4 + rev: v8.19.2 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.7.0 + rev: v24.9.0 hooks: - id: ansible-lint name: Ansible-lint From b12b5dcf5004b14af5ebca9bff583f7b5e05e27a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Sep 2024 12:38:49 +0100 Subject: [PATCH 077/327] Added gui discovery and updated comments Signed-off-by: Mark Bolwell --- defaults/main.yml | 10 ++++------ tasks/prelim.yml | 7 +++++++ 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 0b24c57..5b1b81c 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -521,6 +521,10 @@ rhel9cis_selinux_pol: targeted rhel9cis_selinux_enforce: enforcing # Whether or not to run tasks related to auditing/patching the desktop environment +## Control 1.8.1-10 +# This variable governs whether rules dealing with GUI specific packages(and/or their settings) +# Discovered value can be overridden to true is required +rhel9stig_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" ## Section 2. Services @@ -562,12 +566,6 @@ rhel9cis_chrony_server_minsources: 2 # Set the respective variable to true to keep the service, # otherwise the service is stopped and disabled -## Control 1.8.10-10, 2.2.1 -# This variable governs whether rules dealing with GUI specific packages(and/or their settings) should -# be executed either to: -# - secure GDM, if GUI is needed('rhel9cis_gui: true') -# - or remove GDM and X-Windows-system, if no GUI is needed('rhel9cis_gui: false') -rhel9cis_gui: false ## Control 2.2.2 - Ensure Avahi Server is not installed # This variable, when set to false, will specify that Avahi Server packages should be uninstalled. rhel9cis_avahi_server: false diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1db6db5..13afd85 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -190,6 +190,13 @@ - rhel9cis_force_gpg_key_import - ansible_facts.distribution == 'RedHat' +- name: "PRELIM | Discover Gnome Desktop Environment" + ansible.builtin.stat: + path: /usr/share/gnome/gnome-version.xml + register: prelim_gnome_present + tags: + - always + - name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)" ansible.builtin.package: name: audit From 810d0e639f6ed100b6f5ebc163f00ddb04a3601d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 23 Sep 2024 09:33:57 +0100 Subject: [PATCH 078/327] updated typo for gui default Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 5b1b81c..e3dc9b5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -524,7 +524,7 @@ rhel9cis_selinux_enforce: enforcing ## Control 1.8.1-10 # This variable governs whether rules dealing with GUI specific packages(and/or their settings) # Discovered value can be overridden to true is required -rhel9stig_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" +rhel9cis_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" ## Section 2. Services From 93f136f5263ad18e61e93acb8b64dcbcc99e9de8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Sep 2024 17:49:02 +0000 Subject: [PATCH 079/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.9.0 → v24.9.2](https://github.com/ansible-community/ansible-lint/compare/v24.9.0...v24.9.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f009319..51202b8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.9.0 + rev: v24.9.2 hooks: - id: ansible-lint name: Ansible-lint From 506433ee46eb23bc4f080152397bdbf84be4521b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Sep 2024 17:52:58 +0000 Subject: [PATCH 080/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.19.2 → v8.19.3](https://github.com/gitleaks/gitleaks/compare/v8.19.2...v8.19.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 51202b8..f4fb400 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.19.2 + rev: v8.19.3 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From 0f94ed9637c884acddcdf2aeab18be196899bb0e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Oct 2024 18:26:50 +0000 Subject: [PATCH 081/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/pre-commit/pre-commit-hooks: v4.6.0 → v5.0.0](https://github.com/pre-commit/pre-commit-hooks/compare/v4.6.0...v5.0.0) - [github.com/gitleaks/gitleaks: v8.19.3 → v8.20.0](https://github.com/gitleaks/gitleaks/compare/v8.19.3...v8.20.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f4fb400..cf8c7b9 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.6.0 + rev: v5.0.0 hooks: # Safety - id: detect-aws-credentials @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.19.3 + rev: v8.20.0 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From 41bc1e2aa07e6ec3d8c98ea1d497d6aa6668faa5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:59:52 +0000 Subject: [PATCH 082/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.20.0 → v8.20.1](https://github.com/gitleaks/gitleaks/compare/v8.20.0...v8.20.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cf8c7b9..bedf1b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.20.0 + rev: v8.20.1 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From ef00aa00b30cbdb4df508fa98e197eebcd39be12 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Oct 2024 17:54:56 +0000 Subject: [PATCH 083/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.20.1 → v8.21.1](https://github.com/gitleaks/gitleaks/compare/v8.20.1...v8.21.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index bedf1b3..8f6c2b3 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.20.1 + rev: v8.21.1 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From 68921be0b2aad58462ec31f0457453d8af356d09 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 22 Oct 2024 10:38:26 +0100 Subject: [PATCH 084/327] updated for gui discovery and dconf install Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- tasks/prelim.yml | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9f64850..7fee3af 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -569,7 +569,7 @@ rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and ## Control 1.8.x - Settings for GDM ## 1.8 GDM graphical interface -rhel9cis_gui: false +rhel9cis_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" # This variable specifies the GNOME configuration database file to which configurations are written. # (See "https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en") # The default database is 'local'. diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 78d1771..1ec5ace 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -159,6 +159,22 @@ ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg +- name: "PRELIM | Discover Gnome Desktop Environment" + tags: + - always + ansible.builtin.stat: + path: /usr/share/gnome/gnome-version.xml + register: prelim_gnome_present + +- name: "PRELIM | Install dconf if gui installed" + when: + - rhel9cis_gui + tags: + - always + ansible.builtin.package: + name: dconf + state: present + - name: "PRELIM | AUDIT | Wireless adapter pre-requisites" when: - rhel9cis_rule_3_1_2 From aee4c2a25ebcb19205c7803236997153efc0c8bd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 28 Oct 2024 18:01:21 +0000 Subject: [PATCH 085/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.21.1 → v8.21.2](https://github.com/gitleaks/gitleaks/compare/v8.21.1...v8.21.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 8f6c2b3..300b2e2 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -37,7 +37,7 @@ repos: exclude: .config/.gitleaks-report.json - repo: https://github.com/gitleaks/gitleaks - rev: v8.21.1 + rev: v8.21.2 hooks: - id: gitleaks args: ['--baseline-path', '.config/.gitleaks-report.json'] From 988c42f8aacd2dcfbb4360bcda78522a9974d333 Mon Sep 17 00:00:00 2001 From: yinggs Date: Wed, 30 Oct 2024 17:48:51 +0800 Subject: [PATCH 086/327] Added selectattr filter to fix #249 Signed-off-by: yinggs --- tasks/section_6/cis_6.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index a0e8dd6..a89c16c 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -164,7 +164,7 @@ - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Flatten no_user_items results for easier use" ansible.builtin.set_fact: - discovered_unowned_files_flatten: "{{ rhel_09_6_1_10_audit.results | map(attribute='stdout_lines') | flatten }}" + discovered_unowned_files_flatten: "{{ rhel_09_6_1_10_audit.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}" - name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Displaying any unowned files or directories" ansible.builtin.debug: @@ -204,7 +204,7 @@ - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Flatten no_user_items results for easier use" ansible.builtin.set_fact: - discovered_ungrouped_files_flatten: "{{ rhel_09_6_1_11_audit.results | map(attribute='stdout_lines') | flatten }}" + discovered_ungrouped_files_flatten: "{{ rhel_09_6_1_11_audit.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}" - name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Displaying all ungrouped files or directories" ansible.builtin.debug: From 13ab9d54408f5f300ee7dbadb046206ff32d1c5d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 14:10:10 +0000 Subject: [PATCH 087/327] updated logic on 7.12 and 7.13 thansk to @yinggs Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 0fe5fe7..8d0a730 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -233,7 +233,7 @@ - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Flatten no_user_items results for easier use" ansible.builtin.set_fact: - discovered_unowned_files_flatten: "{{ discovered_unowned_files.results | map(attribute='stdout_lines') | flatten }}" + discovered_unowned_files_flatten: "{{ discovered_unowned_files.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}" - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Alert on unowned files and directories" when: @@ -295,7 +295,7 @@ - name: "7.1.13 | AUDIT | Audit SUID executables | Flatten suid_executables results for easier use" ansible.builtin.set_fact: - discovered_suid_sgid_files_flatten: "{{ discovered_suid_sgid_files.results | map(attribute='stdout_lines') | flatten }}" + discovered_suid_sgid_files_flatten: "{{ discovered_suid_sgid_files.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}" - name: "7.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist" when: From 272ac4efb42fd773f83cc5cc52916e8c93877065 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 16:57:27 +0000 Subject: [PATCH 088/327] updated to enable greater idempotence on filemounts Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.7.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.1.7.x.yml b/tasks/section_1/cis_1.1.7.x.yml index d113361..a123426 100644 --- a/tasks/section_1/cis_1.1.7.x.yml +++ b/tasks/section_1/cis_1.1.7.x.yml @@ -32,7 +32,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_7_3 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_7_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_7_3) %},nosuid{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" From efd86bf8052d0f8d0c12c344d20170a8e2aac1d8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 17:01:46 +0000 Subject: [PATCH 089/327] updated for first interaction step Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 912b3db..c9328cb 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -27,7 +27,7 @@ jobs: # This will create messages for first time contributers and direct them to the Discord server welcome: - runs-on: self-hosted + runs-on: ubuntu-latest steps: - uses: actions/first-interaction@main From b7963f7c11ede7e6d83157aace3ec4a7df9f4f66 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 17:11:38 +0000 Subject: [PATCH 090/327] updated idempotency thanks to feedback from @Thulium-Drake Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.3.x.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 728b3c9..c7920cd 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -24,8 +24,8 @@ file: warning_facts.yml - 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" + "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: - item.mount == "/home" - rhel9cis_rule_1_1_2_3_2 or @@ -45,7 +45,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3_3 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_3_3) %},nosuid{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" From fa13b06b1f915179c71616c525196bde54bd740a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 17:15:33 +0000 Subject: [PATCH 091/327] lint updates Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1ec5ace..28292fb 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -161,19 +161,19 @@ - name: "PRELIM | Discover Gnome Desktop Environment" tags: - - always + - always ansible.builtin.stat: - path: /usr/share/gnome/gnome-version.xml + path: /usr/share/gnome/gnome-version.xml register: prelim_gnome_present - name: "PRELIM | Install dconf if gui installed" when: - - rhel9cis_gui + - rhel9cis_gui tags: - - always + - always ansible.builtin.package: - name: dconf - state: present + name: dconf + state: present - name: "PRELIM | AUDIT | Wireless adapter pre-requisites" when: From 879d9c9a1b17e7f18d8cc402785d2ef9bb5e50b6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Nov 2024 18:39:01 +0000 Subject: [PATCH 092/327] lint and var renaming Signed-off-by: Mark Bolwell --- handlers/main.yml | 4 ++-- tasks/auditd.yml | 14 +++++++------- tasks/main.yml | 16 ++++++++-------- tasks/post.yml | 1 - tasks/pre_remediation_audit.yml | 4 ++-- tasks/section_1/cis_1.2.1.x.yml | 22 +++++++++++----------- tasks/section_1/cis_1.3.1.x.yml | 9 ++++----- tasks/section_1/cis_1.6.x.yml | 20 ++++++++++---------- tasks/section_5/cis_5.2.x.yml | 6 +++--- tasks/section_5/cis_5.3.1.x.yml | 4 ++-- tasks/section_5/cis_5.3.2.x.yml | 8 ++++---- tasks/section_5/cis_5.3.3.3.x.yml | 20 ++++++++++---------- tasks/section_6/cis_6.1.x.yml | 4 ++-- tasks/section_6/cis_6.2.1.x.yml | 16 ++++++++-------- tasks/section_6/cis_6.2.3.x.yml | 10 +++++----- tasks/section_6/cis_6.3.3.x.yml | 2 +- tasks/section_7/cis_7.1.x.yml | 8 ++++---- templates/audit/99_auditd.rules.j2 | 2 +- 18 files changed, 84 insertions(+), 86 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 2009fa2..27e4a56 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -98,11 +98,11 @@ - 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 when: - - auditd_immutable_check.stdout == '1' + - discovered_auditd_immutable_check.stdout == '1' ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" notify: Change_requires_reboot diff --git a/tasks/auditd.yml b/tasks/auditd.yml index ac5b8f8..502497c 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -3,7 +3,7 @@ - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: path: /etc/audit/rules.d/99_auditd.rules - register: rhel9cis_auditd_file + register: discovered_auditd_rules_file - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | setup file ansible.builtin.template: @@ -12,8 +12,8 @@ owner: root group: root mode: '0640' - diff: "{{ rhel9cis_auditd_file.stat.exists }}" # Only run diff if not a new file - register: rhel9cis_auditd_template_updated + diff: "{{ discovered_auditd_rules_file.stat.exists }}" # Only run diff if not a new file + register: discovered_auditd_rules_template_updated notify: - Auditd immutable check - Audit immutable fact @@ -21,8 +21,8 @@ - name: POST | AUDITD | Add Warning count for changes to template file | Warn Count # noqa no-handler when: - - rhel9cis_auditd_template_updated.changed - - rhel9cis_auditd_file.stat.exists + - discovered_auditd_rules_template_updated.changed + - discovered_auditd_rules_file.stat.exists ansible.builtin.import_tasks: file: warning_facts.yml vars: @@ -31,7 +31,7 @@ - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: path: /etc/audit/rules.d/98_auditd_exceptions.rules - register: rhel9cis_auditd_exception_file + register: discovered_auditd_exception_file - name: POST | Set up auditd user logging exceptions | setup file when: @@ -43,5 +43,5 @@ owner: root group: root mode: '0640' - diff: "{{ rhel9cis_auditd_exception_file.stat.exists }}" + diff: "{{ discovered_auditd_exception_file.stat.exists }}" notify: Restart auditd diff --git a/tasks/main.yml b/tasks/main.yml index 1dd529e..4598f85 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -86,29 +86,29 @@ changed_when: false failed_when: false check_mode: false - register: rhel9cis_ansible_user_password_set + register: prelim_ansible_user_password_set - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" - when: rhel9cis_ansible_user_password_set.stdout == "not found" + when: prelim_ansible_user_password_set.stdout == "not found" ansible.builtin.debug: msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." - name: "Check local account" when: - - rhel9cis_ansible_user_password_set.stdout != "not found" + - prelim_ansible_user_password_set.stdout != "not found" block: - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" ansible.builtin.assert: that: - - rhel9cis_ansible_user_password_set.stdout | length != 0 - - rhel9cis_ansible_user_password_set.stdout != "!!" + - prelim_ansible_user_password_set.stdout | length != 0 + - prelim_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" - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" ansible.builtin.assert: that: - - not rhel9cis_ansible_user_password_set.stdout.startswith("!") + - not prelim_ansible_user_password_set.stdout.startswith("!") fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" @@ -149,11 +149,11 @@ - name: "Ensure root password is set" ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" changed_when: false - register: root_passwd_set + register: prelim_root_passwd_set - name: "Ensure root password is set" ansible.builtin.assert: - that: root_passwd_set.rc == 0 + that: prelim_root_passwd_set.rc == 0 fail_msg: "You have rule 5.4.2.4 enabled this requires that you have a root password set" success_msg: "You have a root password set" diff --git a/tasks/post.yml b/tasks/post.yml index b3909bf..198d9c0 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -18,7 +18,6 @@ owner: root group: root mode: '0600' - register: sysctl_updated notify: Reload sysctl loop: - 60-kernel_sysctl.conf diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 9a2c2ce..3a3304c 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -60,11 +60,11 @@ - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: path: "{{ audit_bin }}" - register: goss_available + register: discovered_goss_available - name: Pre Audit Setup | If audit ensure goss is available when: - - not goss_available.stat.exists + - not discovered_goss_available.stat.exists ansible.builtin.assert: msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}" diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index c6ee203..d5ea30f 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -18,19 +18,19 @@ ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" changed_when: false failed_when: false - register: os_installed_pub_keys + register: discovered_os_installed_pub_keys - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' changed_when: false failed_when: false - register: os_gpg_key_check - when: os_installed_pub_keys.rc == 0 + register: discovered_os_gpg_key_check + when: discovered_os_installed_pub_keys.rc == 0 - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" when: - - os_installed_pub_keys.rc == 1 or - os_gpg_key_check.rc == 1 + - discovered_os_installed_pub_keys.rc == 1 or + discovered_os_gpg_key_check.rc == 1 ansible.builtin.fail: msg: Installed GPG Keys do not meet expected values or expected keys are not installed @@ -48,14 +48,14 @@ ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" - register: yum_repos + register: discovered_yum_repos - name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" ansible.builtin.replace: name: "{{ item.path }}" regexp: "^gpgcheck=0" replace: "gpgcheck=1" - loop: "{{ yum_repos.files }}" + loop: "{{ discovered_yum_repos.files }}" loop_control: label: "{{ item.path }}" @@ -82,14 +82,14 @@ ansible.builtin.find: paths: /etc/yum.repos.d patterns: "*.repo" - register: repo_files + register: discovered_repo_files - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" ansible.builtin.replace: path: "{{ item.path }}" regexp: '^repo_gpgcheck( |)=( |)0' replace: repo_gpgcheck=1 - loop: "{{ repo_files.files }}" + loop: "{{ discovered_repo_files.files }}" loop_control: label: "{{ item.path }}" @@ -110,14 +110,14 @@ ansible.builtin.shell: dnf repolist changed_when: false failed_when: false - register: dnf_configured + register: discovered_dnf_configured check_mode: false - name: "1.2.1.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.1.4 | AUDIT | Ensure package manager repositories are configured | Warn Count" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 197e474..f3f67f8 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -34,7 +34,6 @@ loop: - selinux=0 - enforcing=0 - register: selinux_grub_patch ignore_errors: true # noqa ignore-errors notify: Grub2cfg @@ -108,17 +107,17 @@ block: - name: "1.3.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_3_1_6_unconf_services + register: discovered_unconf_services failed_when: false changed_when: false - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services" - when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + when: discovered_unconf_services.stdout | length > 0 ansible.builtin.debug: - msg: "Warning!! You have unconfined services: {{ rhelcis_1_3_1_6_unconf_services.stdout_lines }}" + msg: "Warning!! You have unconfined services: {{ discovered_unconf_services.stdout_lines }}" - name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | warning count" - when: rhelcis_1_3_1_6_unconf_services.stdout | length > 0 + when: discovered_unconf_services.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index f497f15..5d9441e 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -55,12 +55,12 @@ owner: root group: root mode: '0640' - register: no_sha1_template + register: discovered_no_sha1_template - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SHA1' }}" - changed_when: no_sha1_template is defined + changed_when: discovered_no_sha1_template is changed # noqa: no-handler notify: - Update Crypto Policy - Set Crypto Policy @@ -86,12 +86,12 @@ owner: root group: root mode: '0640' - register: no_weakmac_template + register: discovered_no_weakmac_template - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-WEAKMAC' }}" - changed_when: no_weakmac_template is defined + changed_when: discovered_no_weakmac_template is changed # noqa: no-handler notify: - Update Crypto Policy - Set Crypto Policy @@ -116,12 +116,12 @@ owner: root group: root mode: '0640' - register: no_sshcbc_template + register: discovered_no_sshcbc_template - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHCBC' }}" - changed_when: no_sshcbc_template is defined + changed_when: discovered_no_sshcbc_template is changed # noqa: no-handler notify: - Update Crypto Policy - Set Crypto Policy @@ -146,12 +146,12 @@ owner: root group: root mode: '0640' - register: no_sshweakciphers_template + register: discovered_no_sshweakciphers_template - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKCIPHERS' }}" - changed_when: no_sshweakciphers_template is defined + changed_when: discovered_no_sshweakciphers_template is changed # noqa: no-handler notify: - Update Crypto Policy - Set Crypto Policy @@ -176,12 +176,12 @@ owner: root group: root mode: '0640' - register: no_sshetm_template + register: discovered_no_sshetm_template - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" ansible.builtin.set_fact: rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHETM' }}" - changed_when: no_sshetm_template is defined + changed_when: discovered_no_sshetm_template is changed # noqa: no-handler notify: - Update Crypto Policy - Set Crypto Policy diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index 2e46de4..87fe46e 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -89,16 +89,16 @@ become: true changed_when: false failed_when: false - register: rhel9cis_5_2_4_authenticate + register: discovered_priv_reauth - name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" - when: rhel9cis_5_2_4_authenticate.stdout | length > 0 + when: discovered_priv_reauth.stdout | length > 0 ansible.builtin.replace: path: "{{ item }}" regexp: '^([^#].*)!authenticate(.*)' replace: '\1authenticate\2' validate: '/usr/sbin/visudo -cf %s' - loop: "{{ rhel9cis_5_2_4_authenticate.stdout_lines }}" + loop: "{{ discovered_priv_reauth.stdout_lines }}" - name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly" when: diff --git a/tasks/section_5/cis_5.3.1.x.yml b/tasks/section_5/cis_5.3.1.x.yml index b8a5576..ce5ae8a 100644 --- a/tasks/section_5/cis_5.3.1.x.yml +++ b/tasks/section_5/cis_5.3.1.x.yml @@ -32,10 +32,10 @@ ansible.builtin.package: name: authselect state: latest - register: rhel9cis_authselect_update + register: discovered_authselect_updated - name: "5.3.1.2 | AUDIT | Ensure latest version of authselect is installed | Patch" - when: rhel9cis_authselect_update.changed # noqa no-handler + when: discovered_authselect_updated.changed # noqa no-handler ansible.builtin.set_fact: authselect_update: OK diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 3996edc..18e9cfd 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -136,11 +136,11 @@ 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: rhel9cis_authselect_pam_unix.rc not in [ 0, 1 ] - register: rhel9cis_authselect_pam_unix + failed_when: discovered_discovered_authselect_pam_unix.rc not in [ 0, 1 ] + register: discovered_discovered_authselect_pam_unix - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" - when: "'system-auth:password' not in rhel9cis_authselect_pam_unix.stdout" + when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth regexp: "{{ item.regexp }}" @@ -154,7 +154,7 @@ notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth" - when: "'password-auth:password' not in rhel9cis_authselect_pam_unix.stdout" + when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout" ansible.builtin.lineinfile: path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth line: "{{ item.line }}" diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index 6c04d33..21a03ee 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -12,9 +12,9 @@ block: - name: "5.3.3.3.1 | AUDIT | Ensure password history remember is configured | Check existing files" ansible.builtin.shell: grep -Psi -- '^\h*password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+([^#\n\r]+\s+)?remember=\d+\b' /etc/pam.d/password-auth /etc/pam.d/system-auth - register: rhel9_pwhistory_remember changed_when: false - failed_when: rhel9_pwhistory_remember.rc not in [0, 1] + failed_when: discovered_pwhistory_remember.rc not in [0, 1] + register: discovered_pwhistory_remember - name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set pwhistory file" ansible.builtin.lineinfile: @@ -59,9 +59,9 @@ block: - name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files" ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/{system,password}-auth - register: rhel9_pwhistory_enforce_for_root + register: discovered_pwhistory_enforce_for_root changed_when: false - failed_when: rhel9_pwhistory_enforce_for_root.rc not in [0, 1] + failed_when: discovered_pwhistory_enforce_for_root.rc not in [0, 1] - name: "5.3.3.3.2 | PATCH| Ensure password history is enforced for the root user | Ensure enforce_for_root is set pwhistory file" ansible.builtin.lineinfile: @@ -72,7 +72,7 @@ - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - discovered_pwhistory_enforce_for_root.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" @@ -83,7 +83,7 @@ - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" when: - rhel9cis_allow_authselect_updates - - rhel9_pwhistory_enforce_for_root.stdout | length == 0 + - discovered_pwhistory_enforce_for_root.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" @@ -106,9 +106,9 @@ block: - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{system,password}-auth - register: rhel9_pwhistory_use_authtok + register: discovered_pwhistory_use_authtok changed_when: false - failed_when: rhel9_pwhistory_use_authtok.rc not in [0, 1] + failed_when: discovered_pwhistory_use_authtok.rc not in [0, 1] - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Update pwhistory for use_authtok" ansible.builtin.lineinfile: @@ -119,7 +119,7 @@ - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure use_authtok is set" when: - not rhel9cis_allow_authselect_updates - - rhel9_pwhistory_use_authtok.stdout | length == 0 + - discovered_pwhistory_use_authtok.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" @@ -130,7 +130,7 @@ - name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect" when: - rhel9cis_allow_authselect_updates - - rhel9_pwhistory_use_authtok.stdout | length == 0 + - discovered_pwhistory_use_authtok.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 95f8064..898444f 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -16,10 +16,10 @@ ansible.builtin.package: name: aide state: present - register: aide_installed + register: discovered_aide_installed - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - when: aide_installed.changed # noqa: no-handler + when: discovered_aide_installed.changed # noqa: no-handler block: - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" ansible.builtin.shell: /usr/sbin/aide --init diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 603e471..1a2a8aa 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -32,26 +32,26 @@ - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Check for override file" ansible.builtin.stat: path: /etc/tmpfiles.d/systemd.conf - register: tmpfile_override + register: discovered_tmpfile_override - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | If override file check for journal" - when: tmpfile_override.stat.exists + when: discovered_tmpfile_override.stat.exists ansible.builtin.shell: grep -E 'z /var/log/journal/%m/system.journal \d*' /usr/lib/tmpfiles.d/systemd.conf - register: journald_fileperms_override + register: discovered_journald_fileperms_override changed_when: false - failed_when: journald_fileperms_override.rc not in [ 0, 1 ] + failed_when: discovered_journald_fileperms_override.rc not in [ 0, 1 ] - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found" when: - - tmpfile_override.stat.exists - - journald_fileperms_override.stdout | length > 0 + - discovered_tmpfile_override.stat.exists + - discovered_journald_fileperms_override.stdout | length > 0 ansible.builtin.debug: msg: "Warning!! - tmpfiles override found /usr/lib/tmpfiles.d/systemd.conf affecting journald files please confirm matches site policy" - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found" when: - - tmpfile_override.stat.exists - - journald_fileperms_override.stdout | length > 0 + - discovered_tmpfile_override.stat.exists + - discovered_journald_fileperms_override.stdout | length > 0 ansible.builtin.import_tasks: file: warning_facts.yml vars: diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 9e42ee2..5af5fcd 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -89,13 +89,13 @@ changed_when: false failed_when: false check_mode: false - register: rhel_09_6_2_3_5_audit + register: discovered_configured_rsyslog - name: "6.2.3.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_09_4_2_1_5_audit.stdout_lines }}" + - "{{ discovered_configured_rsyslog.stdout_lines }}" - name: "6.2.3.5 | PATCH | Ensure logging is configured | mail.* log setting" when: rhel9cis_rsyslog_ansiblemanaged @@ -193,10 +193,10 @@ # target can be IP or FQDN *.* action(type="omfwd" target="{{ rhel9cis_remote_log_host }}" port="{{ rhel9cis_remote_log_port }}" protocol="{{ rhel9cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel9cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel9cis_remote_log_queuesize }}") insertafter: EOF - register: result failed_when: - - result is failed - - result.rc != 257 + - discovered_rsyslog_remote_host is failed + - discovered_rsyslog_remote_host.rc != 257 + register: discovered_rsyslog_remote_host notify: Restart rsyslog - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" diff --git a/tasks/section_6/cis_6.3.3.x.yml b/tasks/section_6/cis_6.3.3.x.yml index 7e7e479..d279259 100644 --- a/tasks/section_6/cis_6.3.3.x.yml +++ b/tasks/section_6/cis_6.3.3.x.yml @@ -88,7 +88,7 @@ changed_when: false failed_when: false check_mode: false - register: priv_procs + register: discovered_priv_procs - name: "6.3.3.6 | PATCH | Ensure use of privileged commands is collected" ansible.builtin.set_fact: diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 8d0a730..232b224 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -187,18 +187,18 @@ 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_09_7_1_11_perms_results + register: discovered_world_writable - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)" when: - - rhel_09_7_1_11_perms_results.stdout_lines is defined - - rhel_09_7_1_11_perms_results.stdout_lines | length > 0 + - discovered_world_writable.stdout_lines is defined + - discovered_world_writable.stdout_lines | length > 0 - rhel9cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' mode: o-w state: touch - loop: "{{ rhel_09_7_1_11_perms_results.stdout_lines }}" + loop: "{{ discovered_world_writable.stdout_lines }}" - name: "7.1.11 | PATCH | Ensure no world writable files exist | Adjust world-writable directories add sticky bit" ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -o+w ! -perm -1002 2>/dev/null | xargs chmod a+t diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index bfb925b..bf2d191 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -30,7 +30,7 @@ -w /etc/sysconfig/network-scripts -p wa -k system-locale {% endif %} {% if rhel9cis_rule_6_3_3_6 %} -{% for proc in priv_procs.stdout_lines -%} +{% for proc in discovered_priv_procs.stdout_lines -%} -a always,exit -F path={{ proc }} -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k privileged {% endfor %} {% endif %} From bb631b10dbe470e3679715640e15de83b3ec62e8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 15:43:44 +0000 Subject: [PATCH 093/327] improved idempotence on mount point options Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.x.yml | 2 +- tasks/section_1/cis_1.1.3.x.yml | 4 +--- tasks/section_1/cis_1.1.4.x.yml | 2 +- tasks/section_1/cis_1.1.5.x.yml | 2 +- tasks/section_1/cis_1.1.6.x.yml | 2 +- tasks/section_1/cis_1.1.8.x.yml | 2 +- 6 files changed, 6 insertions(+), 8 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.x.yml b/tasks/section_1/cis_1.1.2.x.yml index 10d6d2d..861e679 100644 --- a/tasks/section_1/cis_1.1.2.x.yml +++ b/tasks/section_1/cis_1.1.2.x.yml @@ -32,7 +32,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_2_4 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_4) %},nosuid{% endif %}" notify: Remount tmp loop: "{{ ansible_facts.mounts }}" loop_control: diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml index 3a64a06..423b15c 100644 --- a/tasks/section_1/cis_1.1.3.x.yml +++ b/tasks/section_1/cis_1.1.3.x.yml @@ -31,9 +31,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_3_3 %}nosuid{% endif %} - loop: "{{ ansible_facts.mounts }}" - loop_control: + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_3_3) %},nosuid" label: "{{ item.device }}" notify: Change_requires_reboot when: diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml index 713dba6..4487e9b 100644 --- a/tasks/section_1/cis_1.1.4.x.yml +++ b/tasks/section_1/cis_1.1.4.x.yml @@ -33,7 +33,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_4_4 %}nodev{% endif %} + opts: "{{ item.options }}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_4_2) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_4_3) %},nosuid{% endif %}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_4_4) %},nodev{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.5.x.yml b/tasks/section_1/cis_1.1.5.x.yml index ac8b827..8c4732f 100644 --- a/tasks/section_1/cis_1.1.5.x.yml +++ b/tasks/section_1/cis_1.1.5.x.yml @@ -33,7 +33,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_5_4 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_5_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_5_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_5_4) %},nosuid{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.6.x.yml b/tasks/section_1/cis_1.1.6.x.yml index 5a7c8f4..709a206 100644 --- a/tasks/section_1/cis_1.1.6.x.yml +++ b/tasks/section_1/cis_1.1.6.x.yml @@ -32,7 +32,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_6_4 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_6_2) %},noexec{% endif %}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_6_3) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_6_4) %},nosuid{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml index 6a50de8..506c1a6 100644 --- a/tasks/section_1/cis_1.1.8.x.yml +++ b/tasks/section_1/cis_1.1.8.x.yml @@ -40,7 +40,7 @@ src: tmpfs fstype: tmpfs state: mounted - opts: defaults,{% if rhel9cis_rule_1_1_8_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_4 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_8_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_8_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_8_4) %},nosuid{% endif %}" notify: Change_requires_reboot when: - rhel9cis_rule_1_1_8_2 or From 1c1a39c58b5e7b2ea129c15aad4cdda1d4fdc963 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 15:46:17 +0000 Subject: [PATCH 094/327] improved gpg regex Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index fc0bf27..babf869 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -44,7 +44,7 @@ - name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" ansible.builtin.replace: name: "{{ item.path }}" - regexp: "^gpgcheck=0" + regexp: ^gpgcheck\s*=\s*0 replace: "gpgcheck=1" loop: "{{ yum_repos.files }}" loop_control: @@ -104,7 +104,7 @@ - name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" ansible.builtin.replace: path: "{{ item.path }}" - regexp: '^repo_gpgcheck( |)=( |)0' + regexp: ^repo_gpgcheck\s*=\s*0 replace: repo_gpgcheck=1 loop: "{{ repo_files.files }}" loop_control: From fbf16ec54dc9664b9380fe887ca2c37eb859fa96 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 15:59:07 +0000 Subject: [PATCH 095/327] readded lines removed in error Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.3.x.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml index 423b15c..e6d0705 100644 --- a/tasks/section_1/cis_1.1.3.x.yml +++ b/tasks/section_1/cis_1.1.3.x.yml @@ -31,7 +31,9 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_3_3) %},nosuid" + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_3_3) %},nosuid{% endif %}" + loop: "{{ ansible_facts.mounts }}" + loop_control: label: "{{ item.device }}" notify: Change_requires_reboot when: From d6c9e426855bac16047a75ae72238816279c1e2b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 16:00:01 +0000 Subject: [PATCH 096/327] reverted back to original Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.8.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.1.8.x.yml b/tasks/section_1/cis_1.1.8.x.yml index 506c1a6..6a50de8 100644 --- a/tasks/section_1/cis_1.1.8.x.yml +++ b/tasks/section_1/cis_1.1.8.x.yml @@ -40,7 +40,7 @@ src: tmpfs fstype: tmpfs state: mounted - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_8_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_8_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_8_4) %},nosuid{% endif %}" + opts: defaults,{% if rhel9cis_rule_1_1_8_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_4 %}nosuid{% endif %} notify: Change_requires_reboot when: - rhel9cis_rule_1_1_8_2 or From 3df7334cda626f842efa80a370257b349f04e961 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 16:04:14 +0000 Subject: [PATCH 097/327] improved mount idempotence Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.1.x.yml | 2 +- tasks/section_1/cis_1.1.2.4.x.yml | 2 +- tasks/section_1/cis_1.1.2.5.x.yml | 2 +- tasks/section_1/cis_1.1.2.6.x.yml | 2 +- tasks/section_1/cis_1.1.2.7.x.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index d64c3a7..5683cde 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -33,7 +33,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_1_4 %}noexec{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_1_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_1_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_1_4) %},noexec{% endif %}" notify: Remount tmp loop: "{{ ansible_facts.mounts }}" loop_control: diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index d2e4aa8..0aa4fa2 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -45,7 +45,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_4_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_4_3 %}nosuid{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_4_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_4_2) %},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 index a09d46d..449bc8b 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -49,7 +49,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_5_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_5_4 %}noexec{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_5_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_5_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_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 index d6e2c56..c45da55 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -47,7 +47,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_6_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_6_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_6_4 %}noexec{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_6_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_6_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_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 index 4e21461..4a8f67c 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -47,7 +47,7 @@ src: "{{ item.device }}" fstype: "{{ item.fstype }}" state: present - opts: defaults,{% if rhel9cis_rule_1_1_2_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_7_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_7_4 %}noexec{% endif %} + opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_7_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_7_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_7_4) %},noexec{% endif %}" loop: "{{ ansible_facts.mounts }}" loop_control: label: "{{ item.device }}" From 44b712fdf90f4941d369fdb3ec8b4a72a495c616 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 16:06:29 +0000 Subject: [PATCH 098/327] improved gpg regex Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.2.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index d5ea30f..dca12b0 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -53,7 +53,7 @@ - name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos" ansible.builtin.replace: name: "{{ item.path }}" - regexp: "^gpgcheck=0" + regexp: ^gpgcheck\s*=\s*0 replace: "gpgcheck=1" loop: "{{ discovered_yum_repos.files }}" loop_control: @@ -87,7 +87,7 @@ - name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files" ansible.builtin.replace: path: "{{ item.path }}" - regexp: '^repo_gpgcheck( |)=( |)0' + regexp: ^repo_gpgcheck\s*=s*0 replace: repo_gpgcheck=1 loop: "{{ discovered_repo_files.files }}" loop_control: From 28a35960d7acb7e6c69cdaa9c90fe3663d00ba97 Mon Sep 17 00:00:00 2001 From: Jeffrey van Pelt Date: Mon, 11 Nov 2024 17:38:04 +0100 Subject: [PATCH 099/327] Added a means to allow system users to have a shell Signed-off-by: Jeffrey van Pelt --- defaults/main.yml | 5 +++++ tasks/section_5/cis_5.6.x.yml | 1 + 2 files changed, 6 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index e3dc9b5..0cc7a2b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1137,6 +1137,11 @@ rhel9cis_force_user_mindays: false # This can break current connecting user access rhel9cis_force_user_warnage: false +## Control 5.6.2 - Ensure system accounts are secured | Set nologin +# The system users on this list are allowed to have a shell (e.g. applications +# that require a shell to function) +rhel9cis_system_users_shell: [] + ## Control 5.6.3 - Ensure default user shell timeout is 900 seconds or less # Session timeout setting file (TMOUT setting can be set in multiple files) # Timeout value is in seconds. (60 seconds * 10 = 600) diff --git a/tasks/section_5/cis_5.6.x.yml b/tasks/section_5/cis_5.6.x.yml index 5271388..11bed39 100644 --- a/tasks/section_5/cis_5.6.x.yml +++ b/tasks/section_5/cis_5.6.x.yml @@ -13,6 +13,7 @@ - item.id != "shutdown" - item.id != "halt" - item.id != "nfsnobody" + - item.id not in rhel9cis_system_users_shell - item.uid < min_int_uid | int - item.shell != "/bin/false" - item.shell != "/usr/sbin/nologin" From f02a9d442fe74762cba84891de0f393090dfe9a2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 11 Nov 2024 17:35:12 +0000 Subject: [PATCH 100/327] added system account enhancement 5.4.2.7 thanks to @Thulium-Drake Signed-off-by: Mark Bolwell --- defaults/main.yml | 5 +++++ tasks/section_5/cis_5.4.2.x.yml | 1 + 2 files changed, 6 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index 4e07349..e210596 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -992,6 +992,11 @@ rhel9cis_futurepwchgdate_autofix: true # 5.4.2.x rhel9cis_root_umask: '0027' # 0027 or more restrictive +## Control 5.4.2.7 - Ensure system accounts are secured | Set nologin +# The system users on this list are allowed to have a shell (e.g. applications +# that require a shell to function) +rhel9cis_system_users_shell: [] + ## Control 5.4.3.2 - Configuring user shell timeout # This dictionary is related to ensuring the rule about user shell timeout # This variable represents the amount of seconds a command or process is allowed to diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 4d75928..2cf378c 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -199,6 +199,7 @@ when: - rhel9cis_rule_5_4_2_7 - "item.id not in prelim_interactive_usernames.stdout" + - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high tags: From c4b489fe4c0cd109a574ed734c5d63cccc1c536f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 12 Nov 2024 15:45:20 +0000 Subject: [PATCH 101/327] fixed filename thanks to @levaillx Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.8.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index ce35a48..36f6052 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -131,7 +131,7 @@ - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" ansible.builtin.template: src: etc/dconf/db/00-screensaver_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver_lock" owner: root group: root mode: '0644' From 9614fa9a9a45bd4e9490cd74c28d519eb45ffe73 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 12 Nov 2024 16:00:53 +0000 Subject: [PATCH 102/327] fixed filename thanks to @levaillx Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.8.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index 427eb79..84121b7 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -140,7 +140,7 @@ - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" ansible.builtin.template: src: etc/dconf/db/00-screensaver_lock.j2 - dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" + dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver_lock" owner: root group: root mode: '0644' From 1166b8b9c5962b67e15a631e93a2541b18d684c3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 18 Nov 2024 17:38:04 +0000 Subject: [PATCH 103/327] updated typos Signed-off-by: Mark Bolwell --- README.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3260cb0..86ebd36 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Refer to [Contributing Guide](./CONTRIBUTING.rst) 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. +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 RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. 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. @@ -128,11 +128,9 @@ os_check: false **Technical Dependencies:** - Python3 -- Ansible 2.10+ +- Ansible 2.12+ - python-def (should be included in RHEL 9) - libselinux-python -- pip packages - - jmespath - collections found in collections/requirements.yml pre-commit is available if installed on your host for pull request testing. From f591dc2507c2e4e68ecd5e319214bf5324ffa811 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Nov 2024 17:55:23 +0000 Subject: [PATCH 104/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.9.2 → v24.10.0](https://github.com/ansible-community/ansible-lint/compare/v24.9.2...v24.10.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 300b2e2..1c69745 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.9.2 + rev: v24.10.0 hooks: - id: ansible-lint name: Ansible-lint From fef3554ddecdb81c00232940c45c5659b7febb75 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 18 Nov 2024 18:00:08 +0000 Subject: [PATCH 105/327] updated readme Signed-off-by: Mark Bolwell --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 985dec7..7258e1e 100644 --- a/README.md +++ b/README.md @@ -53,7 +53,7 @@ Refer to [Contributing Guide](./CONTRIBUTING.rst) 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. +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 RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. 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. @@ -128,7 +128,7 @@ os_check: false **Technical Dependencies:** - Python3 -- Ansible 2.10+ +- Ansible 2.12+ - python-def (should be included in RHEL 9) - libselinux-python - pip packages From 576475d851de7a2ce1dd6ebb3c6b2f0d4af3056f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 19 Nov 2024 14:03:46 +0000 Subject: [PATCH 106/327] removed skip_ansible_lint tag Signed-off-by: Mark Bolwell --- handlers/main.yml | 4 ---- tasks/section_1/cis_1.1.3.x.yml | 1 - tasks/section_1/cis_1.1.4.x.yml | 1 - tasks/section_1/cis_1.1.5.x.yml | 2 -- tasks/section_1/cis_1.1.6.x.yml | 1 - tasks/section_1/cis_1.1.7.x.yml | 2 -- tasks/section_1/cis_1.1.8.x.yml | 1 - tasks/section_1/cis_1.2.x.yml | 1 - tasks/section_1/cis_1.9.yml | 2 -- 9 files changed, 15 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index dd97fec..c302106 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -57,8 +57,6 @@ - name: Grub2cfg ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" ignore_errors: true # noqa ignore-errors - tags: - - skip_ansible_lint - name: Restart rsyslog ansible.builtin.systemd: @@ -102,8 +100,6 @@ - name: Restart auditd ansible.builtin.shell: service auditd restart - tags: - - skip_ansible_lint - name: Change_requires_reboot ansible.builtin.set_fact: diff --git a/tasks/section_1/cis_1.1.3.x.yml b/tasks/section_1/cis_1.1.3.x.yml index e6d0705..d219b39 100644 --- a/tasks/section_1/cis_1.1.3.x.yml +++ b/tasks/section_1/cis_1.1.3.x.yml @@ -45,6 +45,5 @@ - level1-workstation - patch - mounts - - skip_ansible_lint - rule_1.1.3.2 - rule_1.1.3.3 diff --git a/tasks/section_1/cis_1.1.4.x.yml b/tasks/section_1/cis_1.1.4.x.yml index 4487e9b..d04ac02 100644 --- a/tasks/section_1/cis_1.1.4.x.yml +++ b/tasks/section_1/cis_1.1.4.x.yml @@ -48,7 +48,6 @@ - level1-workstation - 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 index 8c4732f..af4e230 100644 --- a/tasks/section_1/cis_1.1.5.x.yml +++ b/tasks/section_1/cis_1.1.5.x.yml @@ -22,7 +22,6 @@ - audit - mounts - rule_1.1.5.1 - - skip_ansible_lint - name: | "1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition" @@ -48,7 +47,6 @@ - level1-workstation - 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 index 709a206..d20e83d 100644 --- a/tasks/section_1/cis_1.1.6.x.yml +++ b/tasks/section_1/cis_1.1.6.x.yml @@ -47,7 +47,6 @@ - level1-workstation - 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 index a123426..d081811 100644 --- a/tasks/section_1/cis_1.1.7.x.yml +++ b/tasks/section_1/cis_1.1.7.x.yml @@ -22,7 +22,6 @@ - audit - mounts - rule_1.1.7.1 - - skip_ansible_lint - name: | "1.1.7.2 | PATCH | Ensure nodev option set on /home partition @@ -48,4 +47,3 @@ - mounts - rule_1.1.7.2 - rule_1.1.7.3 - - 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 index 6a50de8..5ebf666 100644 --- a/tasks/section_1/cis_1.1.8.x.yml +++ b/tasks/section_1/cis_1.1.8.x.yml @@ -29,7 +29,6 @@ - audit - mounts - rule_1.1.8.1 - - skip_ansible_lint - name: | "1.1.8.2 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option diff --git a/tasks/section_1/cis_1.2.x.yml b/tasks/section_1/cis_1.2.x.yml index babf869..3c57e41 100644 --- a/tasks/section_1/cis_1.2.x.yml +++ b/tasks/section_1/cis_1.2.x.yml @@ -85,7 +85,6 @@ - manual - audit - rule_1.2.3 - - skip_ansible_lint - name: "1.2.4 | AUDIT | Ensure repo_gpgcheck is globally activated" block: diff --git a/tasks/section_1/cis_1.9.yml b/tasks/section_1/cis_1.9.yml index e226948..39f0cd9 100644 --- a/tasks/section_1/cis_1.9.yml +++ b/tasks/section_1/cis_1.9.yml @@ -7,10 +7,8 @@ notify: Change_requires_reboot when: - rhel9cis_rule_1_9 - - not system_is_ec2 tags: - level1-server - level1-workstation - patch - rule_1.9 - - skip_ansible_lint From 12432ee7480c7588be68776b2b15ef42f5e1b488 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 11:18:33 +0000 Subject: [PATCH 107/327] updated 1.5.2 regexp as per #262 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.5.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 3f80647..d0cb983 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -18,7 +18,7 @@ - name: "1.5.2 | PATCH | Ensure core dump backtraces are disabled" ansible.builtin.lineinfile: path: /etc/systemd/coredump.conf - regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' + regexp: '^ProcessSizeMax\s*=\s*.*[1-9].*' line: 'ProcessSizeMax=0' when: - rhel9cis_rule_1_5_2 From 8aef8f7121600b8e34463fa1d245986668f779df Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 11:19:21 +0000 Subject: [PATCH 108/327] updated Copyright line Signed-off-by: Mark Bolwell --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index f6d2b57..7e51eb7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases +Copyright (c) 2025 Mindpoint Group - A Tyto Athene Company / Ansible Lockdown Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 33969e2a8a962720023609f655b95f272728d901 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 11:31:42 +0000 Subject: [PATCH 109/327] Updated company naming Signed-off-by: Mark Bolwell --- templates/audit/98_auditd_exception.rules.j2 | 2 +- templates/audit/99_auditd.rules.j2 | 2 +- templates/etc/cron.d/aide.cron.j2 | 2 +- templates/etc/dconf/db/00-automount_lock.j2 | 2 +- templates/etc/dconf/db/00-autorun_lock.j2 | 2 +- templates/etc/dconf/db/00-media-automount.j2 | 2 +- templates/etc/dconf/db/00-media-autorun.j2 | 2 +- templates/etc/dconf/db/00-screensaver.j2 | 2 +- templates/etc/dconf/db/00-screensaver_lock.j2 | 2 +- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 0f4a4f9..70ebd03 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 6f7c388..0d75c33 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### 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 diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index db93323..4c1af92 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,7 @@ # Run AIDE integrity check ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index efebeac..0e55b5a 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index 4506f4f..cf9ed5d 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 78ad883..640538c 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [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 index 81bdfea..382469c 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [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 index acfeaee..a747336 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index d6c5d70..5988316 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index c7ae76e..901e9e0 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [org/gnome/login-screen] banner-message-enable=true From 0a5c35cd6983cd1344c875faf38ef028940a672a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 20 Nov 2024 12:00:14 +0000 Subject: [PATCH 110/327] updated to latest layout Signed-off-by: Mark Bolwell --- README.md | 131 +++++++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 60 deletions(-) diff --git a/README.md b/README.md index 7258e1e..0a4b4ff 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant -### Based on [ CIS RedHat Enterprise Linux 9 Benchmark v2.0.0 ](https://www.cisecurity.org/cis-benchmarks/) +### Based on [CIS RedHat Enterprise Linux 9 Benchmark v2.0.0](https://www.cisecurity.org/cis-benchmarks/) --- @@ -32,65 +32,82 @@ --- -## Looking for support? - -[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_RH9_cis) - -[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_RH9_cis) - ### Community Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users. -### Contributing - -Issues and Pull requests are welcome please ensure that all commits are signed-off-by and gpg-signed. -Refer to [Contributing Guide](./CONTRIBUTING.rst) - --- ## Caution(s) 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 RHEL9-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 RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. -To use the release version, please point to the `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?? --- ## Matching a security Level for CIS -It is possible to only run level 1 or level 2 controls for CIS. +It is possible to to only run level 1 or level 2 controls for CIS. This is managed using tags: -- level1-server -- level1-workstation -- level2-server -- level2-workstation +- level1_server +- level1_workstation +- level2_server +- level2_workstation -The control found in the `defaults` main also needs to reflect this, as this control is the testing that takes place if you are using the audit component. +The control found in defaults main also need to reflect this as this control the testing thet takes place if you are using the audit component. ## Coming from a previous release -CIS release always contains changes, it is highly recommended to review the new references and available variables. This has changed significantly since the ansible-lockdown initial release. -This is now compatible with python3 if it is found to be the default interpreter. This does come with prerequisites which configure the system accordingly. +CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. +This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. Further details can be seen in the [Changelog](./ChangeLog.md) ## Auditing (new) -This can be turned on or off within the `defaults/main.yml` file with the variables `setup_audit` and `run_audit`. The value is `false` by default. Please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role. +This can be turned on or off within the defaults/main.yml file with the variable run_audit. The value is false by default, please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role. This is a much quicker, very lightweight, checking (where possible) config compliance and live/running settings. -A new form of auditing has been developed by using a small (12MB) go binary called [goss](https://github.com/goss-org/goss) along with the relevant configurations to check without the need for infrastructure or other tooling. -This audit will not only check the config has the correct setting but aims to capture if it is running with that configuration also try to remove [false positives](https://www.mindpointgroup.com/blog/is-compliance-scanning-still-relevant/) in the process. +A new form of auditing has been developed, by using a small (12MB) go binary called [goss](https://github.com/goss-org/goss) along with the relevant configurations to check. Without the need for infrastructure or other tooling. +This audit will not only check the config has the correct setting but aims to capture if it is running with that configuration also trying to remove [false positives](https://www.mindpointgroup.com/blog/is-compliance-scanning-still-relevant/) in the process. Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit). +## Example Audit Summary + +This is based on a vagrant image with selections enabled. e.g. No Gui or firewall. +Note: More tests are run during audit as we check config and running state. + +```txt + +ok: [default] => { + "msg": [ + "The pre remediation results are: ['Total Duration: 5.454s', 'Count: 338, Failed: 47, Skipped: 5'].", + "The post remediation results are: ['Total Duration: 5.007s', 'Count: 338, Failed: 46, Skipped: 5'].", + "Full breakdown can be found in /var/tmp", + "" + ] +} + +PLAY RECAP ******************************************************************************************************************************************* +default : ok=270 changed=23 unreachable=0 failed=0 skipped=140 rescued=0 ignored=0 +``` + ## Documentation - [Read The Docs](https://ansible-lockdown.readthedocs.io/en/latest/) @@ -101,19 +118,6 @@ Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit). ## Requirements -RHEL 9 -Almalinux 9 -Rocky 9 -OracleLinux 9 - -- 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.) - -CentOS stream - while this will generally work it is not supported and requires the following variable setting - -```sh -os_check: false -``` - **General:** - Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible @@ -123,23 +127,22 @@ os_check: false - [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) - [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html) - Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup. -- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consiquences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. +- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. **Technical Dependencies:** -- Python3 -- Ansible 2.12+ -- python-def (should be included in RHEL 9) -- libselinux-python -- pip packages - - jmespath -- collections found in collections/requirements.yml +RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported. -pre-commit is available if installed on your host for pull request testing. +- 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.8 +- Ansible 2.12+ +- python-def +- libselinux-python ## Role Variables -This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done by overriding the required varaibles as found in defaults/main.yml file. e.g. using inventory, group_vars, extra_vars +This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main.yml file or with extra vars within the project, job, workflow, etc. ## Tags @@ -169,10 +172,7 @@ We encourage you (the community) to contribute to this role. Please read the rul ## Known Issues -CIS 1.2.4 - repo_gpgcheck is not carried out for RedHat hosts as the default repos do not have this function. This also affect EPEL(not covered by var). - - Rocky and Alma not affected. -Variable used to unset. -rhel9cis_rhel_default_repo: true # to be set to false if using repo that does have this ability +Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow gpgcheck(rule_1.2.1.2) or repo_gpgcheck (rule_1.2.1.3) this will cause issues during the playbook unless or a workaround is found. ## Pipeline Testing @@ -180,21 +180,32 @@ uses: - ansible-core 2.12 - ansible collections - pulls in the latest version based on requirements file -- Runs the audit using the devel branch -- Runs the pre-commit setup on the PR to ensure everything is in place as expected. +- runs the audit using the devel branch - This is an automated test that occurs on pull requests into devel ## Local Testing -- Ansible +Molecule can be used to work on this role and test in distinct _scenarios_. - - ansible-base 2.10.17 - python 3.8 - - ansible-core 2.13.4 - python 3.10 - - ansible-core 2.15.1 - python 3.11 +### examples + +```bash +molecule test -s default +molecule converge -s wsl -- --check +molecule verify -s localhost +``` + +local testing uses: + +- ansible 2.13.3 +- molecule 4.0.1 +- molecule-docker 2.0.0 +- molecule-podman 2.0.2 +- molecule-vagrant 1.0.0 +- molecule-azure 0.5.0 ## Added Extras -- makefile - this is there purely for testing and initial setup purposes. - [pre-commit](https://pre-commit.com) can be tested and can be run from within the directory ```sh From 888df3778dafae1cddd966cf3b53fbd3f859f33e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 07:57:11 +0000 Subject: [PATCH 111/327] improve 1.5.3 test Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.5.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 1184603..3767a58 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -50,7 +50,7 @@ - NIST800-53R5_CM-6b ansible.builtin.lineinfile: path: /etc/systemd/coredump.conf - regexp: '^ProcessSizeMax\s*=\s*.*[1-9]$' + regexp: '(?#)^ProcessSizeMax\s*=\s*.*[1-9].*$' line: 'ProcessSizeMax=0' - name: "1.5.4 | PATCH | Ensure core dump storage is disabled" From 9f829accd06c44413fd5d11d4ee26acc639259c4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 08:01:16 +0000 Subject: [PATCH 112/327] improvement to Warning Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.1.x.yml | 2 +- tasks/section_1/cis_1.1.2.2.x.yml | 2 +- tasks/section_1/cis_1.1.2.3.x.yml | 2 +- tasks/section_1/cis_1.1.2.4.x.yml | 2 +- tasks/section_1/cis_1.1.2.5.x.yml | 2 +- tasks/section_1/cis_1.1.2.6.x.yml | 2 +- tasks/section_1/cis_1.1.2.7.x.yml | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 5683cde..04402ab 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -17,7 +17,7 @@ block: - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index eb82773..f360a21 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -24,7 +24,7 @@ block: - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.2.1 | AUDIT | Ensure separate partition exists for /home | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index c7920cd..8894013 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -17,7 +17,7 @@ block: - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 0aa4fa2..328ec8b 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -17,7 +17,7 @@ block: - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index 449bc8b..dbb7b97 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -18,7 +18,7 @@ block: - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index c45da55..c38240c 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -17,7 +17,7 @@ block: - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" ansible.builtin.import_tasks: diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 4a8f67c..526e46b 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -17,7 +17,7 @@ block: - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent" ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + msg: "Warning!! {{ required_mount }} doesn't exist. Please investigate this manual task" - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" ansible.builtin.import_tasks: From 6ed7c7e420b06fb0a5af9c862c64091ac11aa72a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 08:03:33 +0000 Subject: [PATCH 113/327] tidy up layout Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.1.x.yml | 48 +++++++++++---------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index fb0f119..e67edd9 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -1,8 +1,7 @@ --- - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available" - when: - - rhel9cis_rule_1_1_1_1 + when: rhel9cis_rule_1_1_1_1 tags: - level1-server - level1-workstation @@ -35,8 +34,7 @@ state: absent - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available" - when: - - rhel9cis_rule_1_1_1_2 + when: rhel9cis_rule_1_1_1_2 tags: - level1-server - level1-workstation @@ -62,15 +60,13 @@ mode: '0600' - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: freevxfs state: absent - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available" - when: - - rhel9cis_rule_1_1_1_3 + when: rhel9cis_rule_1_1_1_3 tags: - level1-server - level1-workstation @@ -96,15 +92,13 @@ mode: '0600' - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs" - when: - - not system_is_container + 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: - - rhel9cis_rule_1_1_1_4 + when: rhel9cis_rule_1_1_1_4 tags: - level1-server - level1-workstation @@ -130,15 +124,13 @@ mode: '0600' - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus" - when: - - not system_is_container + 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: - - rhel9cis_rule_1_1_1_5 + when: rhel9cis_rule_1_1_1_5 tags: - level1-server - level1-workstation @@ -164,15 +156,13 @@ mode: '0600' - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2" - when: - - not system_is_container + 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: - - rhel9cis_rule_1_1_1_6 + when: rhel9cis_rule_1_1_1_6 tags: - level2-server - level2-workstation @@ -198,15 +188,13 @@ mode: '0600' - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: squashfs state: absent - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available" - when: - - rhel9cis_rule_1_1_1_7 + when: rhel9cis_rule_1_1_1_7 tags: - level2-server - level2-workstation @@ -232,15 +220,13 @@ mode: '0600' - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: udf state: absent - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available" - when: - - rhel9cis_rule_1_1_1_8 + when: rhel9cis_rule_1_1_1_8 tags: - level1-server - level2-workstation @@ -266,15 +252,13 @@ mode: '0600' - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb" - when: - - not system_is_container + when: not system_is_container community.general.modprobe: name: usb-storage state: absent - name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available" - when: - - rhel9cis_rule_1_1_1_9 + when: rhel9cis_rule_1_1_1_9 tags: - level1-server - level1-workstation From 1b694832bb584a6126beab487b45e84fa0a0f114 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 11:37:12 +0000 Subject: [PATCH 114/327] updated lint standards Signed-off-by: Mark Bolwell --- .ansible-lint | 17 ++--------------- .yamllint | 22 ++++++++++++++-------- 2 files changed, 16 insertions(+), 23 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index 3090307..3b7c373 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -3,20 +3,7 @@ parseable: true quiet: true skip_list: - - 'schema' - - 'no-changed-when' - - 'var-spacing' - - 'experimental' - - 'name[play]' - - 'name[casing]' - - 'name[template]' - - 'key-order[task]' - - '204' - - '305' - - '303' - - '403' - - '306' - - '602' - - '208' + - 'package-latest' + - 'risky-shell-pipe' use_default_rules: true verbosity: 0 diff --git a/.yamllint b/.yamllint index ec2d1cd..9c0a13b 100644 --- a/.yamllint +++ b/.yamllint @@ -1,32 +1,38 @@ --- extends: default - +locale: en_US.UTF-8 ignore: | tests/ molecule/ .github/ .gitlab-ci.yml *molecule.yml - rules: - indentation: - # Requiring 4 space indentation - spaces: 2 - # Requiring consistent indentation within a file, either indented or not - indent-sequences: consistent braces: max-spaces-inside: 1 level: error brackets: max-spaces-inside: 1 level: error + comments: + ignore-shebangs: true + min-spaces-from-content: 1 # prettier compatibility + comments-indentation: enabled empty-lines: max: 1 - line-length: disable + indentation: + # Requiring 2 space indentation + spaces: 2 + # Requiring consistent indentation within a file, either indented or not + indent-sequences: consistent key-duplicates: enable + line-length: disable new-line-at-end-of-file: enable new-lines: type: unix + octal-values: + forbid-implicit-octal: true # yamllint defaults to false + forbid-explicit-octal: true trailing-spaces: enable truthy: allowed-values: ['true', 'false'] From 2de8a39cdcfc44d770b169c642cbfcb8fbbdd287 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 4 Dec 2024 11:45:13 +0000 Subject: [PATCH 115/327] updated yamllint, company naming, linting and spacing Signed-off-by: Mark Bolwell --- .yamllint | 2 +- LICENSE | 2 +- handlers/main.yml | 26 +++--- tasks/LE_audit_setup.yml | 5 +- tasks/audit_only.yml | 11 +-- tasks/check_prereqs.yml | 3 +- tasks/main.yml | 50 ++++------- tasks/parse_etc_password.yml | 10 +-- tasks/post.yml | 26 ++---- tasks/post_remediation_audit.yml | 10 +-- tasks/pre_remediation_audit.yml | 55 +++++------- tasks/prelim.yml | 40 ++++----- tasks/section_1/cis_1.1.1.x.yml | 38 ++++----- tasks/section_1/cis_1.1.2.1.x.yml | 2 +- tasks/section_1/cis_1.1.2.2.x.yml | 5 +- tasks/section_1/cis_1.2.1.x.yml | 16 ++-- tasks/section_1/cis_1.3.1.x.yml | 9 +- tasks/section_1/cis_1.4.x.yml | 9 +- tasks/section_1/cis_1.5.x.yml | 9 +- tasks/section_1/cis_1.6.x.yml | 16 ++-- tasks/section_1/cis_1.7.x.yml | 30 +++---- tasks/section_1/cis_1.8.x.yml | 30 +++---- tasks/section_2/cis_2.1.x.yml | 84 +++++-------------- tasks/section_2/cis_2.2.x.yml | 5 -- tasks/section_2/cis_2.3.x.yml | 4 +- tasks/section_2/cis_2.4.x.yml | 45 ++++------ tasks/section_3/cis_3.1.x.yml | 7 +- tasks/section_3/cis_3.2.x.yml | 24 +++--- tasks/section_3/cis_3.3.x.yml | 24 ++---- tasks/section_4/cis_4.1.x.yml | 5 +- tasks/section_4/cis_4.2.x.yml | 6 +- tasks/section_4/cis_4.3.x.yml | 33 +++++--- tasks/section_5/cis_5.1.x.yml | 65 +++++--------- tasks/section_5/cis_5.2.x.yml | 21 ++--- tasks/section_5/cis_5.3.2.x.yml | 35 ++++---- tasks/section_5/cis_5.3.3.1.x.yml | 10 +-- tasks/section_5/cis_5.3.3.2.x.yml | 38 ++++----- tasks/section_5/cis_5.3.3.3.x.yml | 9 +- tasks/section_5/cis_5.3.3.4.x.yml | 12 +-- tasks/section_5/cis_5.4.1.x.yml | 42 +++++----- tasks/section_5/cis_5.4.2.x.yml | 19 ++--- tasks/section_5/cis_5.4.3.x.yml | 11 +-- tasks/section_6/cis_6.1.x.yml | 12 +-- tasks/section_6/cis_6.2.1.x.yml | 16 ++-- tasks/section_6/cis_6.2.2.x.yml | 15 ++-- tasks/section_6/cis_6.2.3.x.yml | 20 ++--- tasks/section_6/cis_6.2.4.1.yml | 3 +- tasks/section_6/cis_6.3.1.x.yml | 22 ++--- tasks/section_6/cis_6.3.2.x.yml | 12 +-- tasks/section_6/cis_6.3.3.x.yml | 66 +++++---------- tasks/section_6/cis_6.3.4.x.yml | 21 ++--- tasks/section_7/cis_7.1.x.yml | 14 ++-- tasks/section_7/cis_7.2.x.yml | 2 +- tasks/warning_facts.yml | 3 +- templates/audit/98_auditd_exception.rules.j2 | 2 +- templates/audit/99_auditd.rules.j2 | 2 +- templates/etc/cron.d/aide.cron.j2 | 2 +- templates/etc/dconf/db/00-automount_lock.j2 | 2 +- templates/etc/dconf/db/00-autorun_lock.j2 | 2 +- templates/etc/dconf/db/00-media-automount.j2 | 2 +- templates/etc/dconf/db/00-media-autorun.j2 | 2 +- templates/etc/dconf/db/00-screensaver.j2 | 2 +- templates/etc/dconf/db/00-screensaver_lock.j2 | 2 +- .../etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- templates/fs_with_cves.sh | 5 +- vars/audit.yml | 2 +- 66 files changed, 461 insertions(+), 675 deletions(-) diff --git a/.yamllint b/.yamllint index 9c0a13b..4cf7047 100644 --- a/.yamllint +++ b/.yamllint @@ -17,7 +17,7 @@ rules: comments: ignore-shebangs: true min-spaces-from-content: 1 # prettier compatibility - comments-indentation: enabled + comments-indentation: enable empty-lines: max: 1 indentation: diff --git a/LICENSE b/LICENSE index f6d2b57..7e51eb7 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases +Copyright (c) 2025 Mindpoint Group - A Tyto Athene Company / Ansible Lockdown Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/handlers/main.yml b/handlers/main.yml index 27e4a56..f6a2806 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -2,7 +2,8 @@ # handlers file for RHEL9-CIS - name: Reload sysctl - ansible.builtin.shell: sysctl --system + ansible.builtin.command: sysctl --system + changed_when: true - name: Sysctl flush ipv4 route table when: @@ -43,8 +44,8 @@ - name: Set Crypto Policy when: prelim_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + ansible.builtin.command: update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + changed_when: true notify: - Change_requires_reboot - Restart sshd @@ -65,11 +66,13 @@ state: restarted - name: Reload dconf - ansible.builtin.shell: dconf update + ansible.builtin.command: dconf update + changed_when: true - name: Grub2cfg - ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" + ansible.builtin.command: "grub2-mkconfig -o /boot/grub2/grub.cfg" ignore_errors: true # noqa ignore-errors + changed_when: true - name: Restart rsyslog ansible.builtin.systemd: @@ -91,24 +94,25 @@ daemon-reload: true - name: Authselect update - ansible.builtin.shell: authselect apply-changes + ansible.builtin.command: authselect apply-changes + changed_when: true ## Auditd tasks note order for handlers to run - name: Auditd immutable check - ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules + ansible.builtin.command: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules changed_when: false register: discovered_auditd_immutable_check - name: Audit immutable fact - when: - - discovered_auditd_immutable_check.stdout == '1' + when: discovered_auditd_immutable_check.stdout == '1' ansible.builtin.debug: msg: "Reboot required for auditd to apply new rules as immutable set" notify: Change_requires_reboot -- name: Restart auditd - ansible.builtin.shell: service auditd restart +- name: Restart auditd # noqa command-instead-of-module + ansible.builtin.command: service auditd restart + changed_when: true - name: Change_requires_reboot ansible.builtin.set_fact: diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 4b407eb..7c2243f 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -1,5 +1,4 @@ --- - - name: Pre Audit Setup | Set audit package name block: - name: Pre Audit Setup | Set audit package name | 64bit @@ -20,13 +19,13 @@ owner: root group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: '0555' + mode: "0555" - 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' + mode: "0555" owner: root group: root diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index b7dad08..c3d9596 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,9 +1,8 @@ --- - - name: Audit_Only | Create local Directories for hosts when: fetch_audit_files ansible.builtin.file: - mode: '0755' + mode: "0755" path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" recurse: true state: directory @@ -15,16 +14,14 @@ ansible.builtin.fetch: dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" flat: true - mode: '0644' + mode: "0644" src: "{{ pre_audit_outfile }}" - name: Audit_only | Show Audit Summary - when: - - audit_only + when: audit_only ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" - name: Audit_only | Stop Playbook Audit Only selected - when: - - audit_only + when: audit_only ansible.builtin.meta: end_play diff --git a/tasks/check_prereqs.yml b/tasks/check_prereqs.yml index 159b72f..b9bf2af 100644 --- a/tasks/check_prereqs.yml +++ b/tasks/check_prereqs.yml @@ -1,8 +1,7 @@ --- - name: "PREREQ | If required install libselinux package to manage file changes." - when: - - '"libselinux-python3" not in ansible_facts.packages' + when: '"libselinux-python3" not in ansible_facts.packages' ansible.builtin.package: name: libselinux-python3 state: present diff --git a/tasks/main.yml b/tasks/main.yml index 4598f85..2ea223c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -2,22 +2,19 @@ # tasks file for RHEL9-CIS - name: "Check OS version and family" + when: os_check + tags: always ansible.builtin.assert: that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==') 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_facts.distribution_major_version }}" - when: - - os_check - tags: - - always - 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: "Setup rules if container" when: @@ -36,8 +33,7 @@ file: "{{ container_vars_file }}" - name: "Output if discovered is a container" - when: - - system_is_container + when: system_is_container ansible.builtin.debug: msg: system has been discovered as a container @@ -51,8 +47,7 @@ when: - rhel9cis_set_boot_pass - rhel9cis_rule_1_4_1 - tags: - - always + tags: always ansible.builtin.assert: that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly" @@ -81,23 +76,22 @@ vars: sudo_password_rule: rhel9cis_rule_5_2_4 # pragma: allowlist secret block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" + - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" # noqa name[template] ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" changed_when: false failed_when: false check_mode: false register: prelim_ansible_user_password_set - - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" + - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" # noqa name[template] when: prelim_ansible_user_password_set.stdout == "not found" ansible.builtin.debug: msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." - name: "Check local account" - when: - - prelim_ansible_user_password_set.stdout != "not found" + when: prelim_ansible_user_password_set.stdout != "not found" block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" + - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" # noqa name[template] ansible.builtin.assert: that: - prelim_ansible_user_password_set.stdout | length != 0 @@ -105,7 +99,7 @@ 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" - - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" + - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: that: - not prelim_ansible_user_password_set.stdout.startswith("!") @@ -113,10 +107,8 @@ success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" - name: "PRELIM | AUDIT | Check authselect profile is selected" - when: - - rhel9cis_allow_authselect_updates - tags: - - always + when: rhel9cis_allow_authselect_updates + tags: always block: - name: "PRELIM | AUDIT | Check authselect profile name has been updated" ansible.builtin.assert: @@ -136,8 +128,7 @@ fail_msg: Authselect updates have been selected there are issues with profile selection" - name: "Ensure root password is set" - when: - - rhel9cis_rule_5_4_2_4 + when: rhel9cis_rule_5_4_2_4 tags: - level1-server - level1-workstation @@ -158,14 +149,12 @@ success_msg: "You have a root password set" - name: "Gather the package facts" - tags: - - always + tags: always ansible.builtin.package_facts: manager: auto - name: "Include OS specific variables" - tags: - - always + tags: always ansible.builtin.include_vars: file: "{{ ansible_facts.distribution }}.yml" @@ -213,8 +202,7 @@ - name: "Run auditd logic" when: update_audit_template - tags: - - always + tags: always ansible.builtin.import_tasks: file: auditd.yml @@ -226,8 +214,7 @@ file: post.yml - name: "Run post_remediation audit" - when: - - run_audit + when: run_audit ansible.builtin.import_tasks: file: post_remediation_audit.yml @@ -238,7 +225,6 @@ - name: "If Warnings found Output count and control IDs affected" when: warn_count != 0 - tags: - - always + 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 8270b5a..102acef 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -1,19 +1,17 @@ --- - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - tags: - - always + tags: always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.shell: cat /etc/passwd + ansible.builtin.command: cat /etc/passwd changed_when: false check_mode: false - register: rhel9cis_passwd_file_audit + register: prelim_passwd_file_audit - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" ansible.builtin.set_fact: - rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" + rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) diff --git a/tasks/post.yml b/tasks/post.yml index 198d9c0..b6efdfe 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -1,9 +1,7 @@ --- -# Post tasks - name: POST | Gather the package facts after remediation - tags: - - always + tags: always ansible.builtin.package_facts: manager: auto @@ -17,7 +15,7 @@ dest: "/etc/sysctl.d/{{ item }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' notify: Reload sysctl loop: - 60-kernel_sysctl.conf @@ -29,28 +27,22 @@ ansible.builtin.meta: flush_handlers - name: POST | reboot system if changes require it and not skipped - tags: - - always + when: change_requires_reboot + tags: always + vars: + warn_control_id: Reboot_required block: - name: POST | Reboot system if changes require it and not skipped + when: not skip_reboot ansible.builtin.reboot: - when: - - change_requires_reboot - - not skip_reboot - name: POST | Warning a reboot required but skip option set + when: 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: true - when: - - change_requires_reboot - - skip_reboot - name: "POST | Warning a reboot required but skip option set | warning count" + when: skip_reboot ansible.builtin.import_tasks: file: warning_facts.yml - when: - - change_requires_reboot - - skip_reboot - vars: - warn_control_id: Reboot_required diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 8004ed3..294d45a 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,7 +1,7 @@ --- -- name: Post Audit | Run post_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" +- name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] + ansible.builtin.command: "{{ 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 }}" @@ -18,8 +18,7 @@ - "{{ pre_audit_outfile }}" - name: Post Audit | Capture audit data if json format - when: - - audit_format == "json" + when: audit_format == "json" block: - name: Post Audit | Capture audit data if json format ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4 @@ -31,8 +30,7 @@ post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format - when: - - audit_format == "documentation" + when: audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 3a3304c..c6a531a 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,22 +1,18 @@ --- - - name: Pre Audit Setup | Setup the LE audit - when: - - setup_audit - tags: - - setup_audit + when: setup_audit + tags: setup_audit ansible.builtin.include_tasks: file: LE_audit_setup.yml -- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists +- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists # noqa name[template] ansible.builtin.file: path: "{{ audit_conf_dir }}" state: directory - mode: '0755' + mode: "0755" - name: Pre Audit Setup | If using git for content set up - when: - - audit_content == 'git' + when: audit_content == 'git' block: - name: Pre Audit Setup | Install git ansible.builtin.package: @@ -30,32 +26,28 @@ version: "{{ audit_git_version }}" - name: Pre Audit Setup | Copy to audit content files to server - when: - - audit_content == 'copy' + when: audit_content == 'copy' ansible.builtin.copy: src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server - when: - - audit_content == 'archive' + when: audit_content == 'archive' ansible.builtin.unarchive: src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url - when: - - audit_content == 'get_url' + when: audit_content == 'get_url' 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', [] ) }}" + 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: - - run_audit + when: run_audit block: - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: @@ -63,24 +55,22 @@ register: discovered_goss_available - name: Pre Audit Setup | If audit ensure goss is available - when: - - not discovered_goss_available.stat.exists + when: not discovered_goss_available.stat.exists ansible.builtin.assert: 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 + when: run_audit tags: - goss_template - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" - mode: '0600' + mode: "0600" -- name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" +- name: Pre Audit | Run pre_remediation {{ benchmark }} audit # noqa name[template] + ansible.builtin.command: "{{ 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 }}" @@ -88,33 +78,30 @@ AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format - when: - - audit_format == "json" + when: audit_format == "json" block: - 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 + register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format - when: - - audit_format == "documentation" + when: audit_format == "documentation" block: - 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 + register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only - when: - - audit_only + when: audit_only ansible.builtin.import_tasks: file: audit_only.yml diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 28292fb..1e67bb3 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -17,50 +17,43 @@ when: - run_audit or audit_only - setup_audit - tags: - - run_audit + tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml - name: "PRELIM | AUDIT | Interactive Users" - tags: - - always + 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: prelim_interactive_usernames - name: "PRELIM | AUDIT | Interactive User accounts home directories" - tags: - - always + 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: prelim_interactive_users_home - name: "PRELIM | AUDIT | Interactive UIDs" - tags: - - always + 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: prelim_interactive_uids - name: "PRELIM | AUDIT | Capture /etc/password variables" + tags: always ansible.builtin.include_tasks: file: parse_etc_password.yml - tags: - - always - name: "PRELIM | PATCH | Ensure python3-libselinux is installed" - when: - - '"python3-libselinux" not in ansible_facts.packages' + when: '"python3-libselinux" not in ansible_facts.packages' ansible.builtin.package: name: python3-libselinux state: present - name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" - tags: - - Always + tags: always ansible.builtin.set_fact: mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" @@ -80,27 +73,27 @@ - ansible_facts.distribution == 'RedHat' block: - name: "PRELIM | AUDIT | Import gpg keys | get data" - ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' + ansible.builtin.command: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' # noqa command-instead-of-module changed_when: false failed_when: false register: prelim_check_gpg_imported - - name: "PRELIM | AUDIT | Import gpg keys | Check Package" + - name: "PRELIM | AUDIT | Import gpg keys | Check Package" # noqa command-instead-of-module when: "'not installed' in prelim_check_gpg_imported.stdout" ansible.builtin.shell: rpm -qi redhat-release | grep Signature changed_when: false failed_when: false register: prelim_os_gpg_package_valid - - name: "PRELIM | PATCH | Force keys to be imported" + - name: "PRELIM | PATCH | Force keys to be imported" # noqa command-instead-of-module when: - "'not installed' in prelim_check_gpg_imported.stdout" - "'Key ID 199e2f91fd431d51' in prelim_os_gpg_package_valid.stdout" - ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + ansible.builtin.command: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + changed_when: false - name: "PRELIM | AUDIT | Check systemd coredump" - when: - - rhel9cis_rule_1_5_4 + when: rhel9cis_rule_1_5_4 tags: - level1-server - level1-workstation @@ -127,7 +120,7 @@ state: present - name: "PRELIM | AUDIT | Gather system-wide crypto-policy" - ansible.builtin.shell: 'update-crypto-policies --show' + ansible.builtin.command: 'update-crypto-policies --show' changed_when: false check_mode: false register: prelim_system_wide_crypto_policy @@ -183,7 +176,7 @@ - always block: - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" - ansible.builtin.shell: find /sys/class/net/*/ -type d -name wireless + ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] @@ -222,7 +215,7 @@ path: "{{ rhel9cis_sshd_config_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' state: touch - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" @@ -246,6 +239,7 @@ ansible.builtin.file: path: /etc/systemd/journald.conf.d state: directory + mode: 'go-w' - name: "PRELIM | PATCH | Configure System Accounting (auditd)" when: diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index e67edd9..579fb1b 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -16,7 +16,7 @@ regexp: "^(#)?install cramfs(\\s|$)" line: "install cramfs /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -24,7 +24,7 @@ regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs" when: @@ -49,7 +49,7 @@ regexp: "^(#)?install freevxfs(\\s|$)" line: "install freevxfs /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -57,7 +57,7 @@ regexp: "^(#)?blacklist freevxfs(\\s|$)" line: "blacklist freevxfs" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs" when: not system_is_container @@ -81,7 +81,7 @@ regexp: "^(#)?install hfs(\\s|$)" line: "install hfs /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -89,7 +89,7 @@ regexp: "^(#)?blacklist hfs(\\s|$)" line: "blacklist hfs" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs" when: not system_is_container @@ -113,7 +113,7 @@ regexp: "^(#)?install hfsplus(\\s|$)" line: "install hfsplus /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -121,7 +121,7 @@ regexp: "^(#)?blacklist hfsplus(\\s|$)" line: "blacklist hfsplus" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus" when: not system_is_container @@ -145,7 +145,7 @@ regexp: "^(#)?install jffs2(\\s|$)" line: "install jffs2 /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -153,7 +153,7 @@ regexp: "^(#)?blacklist jffs2(\\s|$)" line: "blacklist jffs2" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2" when: not system_is_container @@ -177,7 +177,7 @@ regexp: "^(#)?install squashfs(\\s|$)" line: "install squashfs /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -185,7 +185,7 @@ regexp: "^(#)?blacklist squashfs(\\s|$)" line: "blacklist squashfs" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs" when: not system_is_container @@ -209,7 +209,7 @@ regexp: "^(#)?install udf(\\s|$)" line: "install udf /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -217,7 +217,7 @@ regexp: "^(#)?blacklist udf(\\s|$)" line: "blacklist udf" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf" when: not system_is_container @@ -241,7 +241,7 @@ regexp: "^(#)?install usb-storage(\\s|$)" line: "install usb-storage /bin/true" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | blacklist" ansible.builtin.lineinfile: @@ -249,7 +249,7 @@ regexp: "^(#)?blacklist usb-storage(\\s|$)" line: "blacklist usb-storage" create: true - mode: '0600' + mode: 'go-rwx' - name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb" when: not system_is_container @@ -273,10 +273,10 @@ dest: /var/fs_with_cves.sh owner: root group: root - mode: '0744' + mode: 'u+x,go-wx' - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Run discovery script" - ansible.builtin.shell: /var/fs_with_cves.sh + ansible.builtin.command: /var/fs_with_cves.sh changed_when: false failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ] register: discovered_fs_modules_loaded @@ -286,7 +286,7 @@ ansible.builtin.debug: msg: | "Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task - {{ discovered_fs_modules_loaded.stdout_lines}}" + {{ discovered_fs_modules_loaded.stdout_lines }}" - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" when: discovered_fs_modules_loaded.stdout | length > 0 diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 04402ab..4457624 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -84,5 +84,5 @@ dest: /etc/systemd/system/tmp.mount owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Systemd restart tmp.mount diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index f360a21..6f0df56 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -2,8 +2,7 @@ # Skips if mount is absent - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" - when: - - rhel9cis_rule_1_1_2_2_1 + when: rhel9cis_rule_1_1_2_2_1 tags: - level1-server - level1-workstation @@ -14,7 +13,7 @@ vars: warn_control_id: '1.1.2.2.1' block: - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" # noqa command-instead-of-module ansible.builtin.shell: mount -l | grep -w /dev/shm changed_when: false register: discovered_dev_shm_mount_check diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index dca12b0..28cd7cd 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -14,18 +14,18 @@ - rule_1.2.1.1 - NIST800-53R5_SI-2 block: - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" # noqa command-instead-of-module ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" changed_when: false failed_when: false register: discovered_os_installed_pub_keys - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" # noqa command-instead-of-module + when: discovered_os_installed_pub_keys.rc == 0 ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' changed_when: false failed_when: false register: discovered_os_gpg_key_check - when: discovered_os_installed_pub_keys.rc == 0 - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" when: @@ -35,8 +35,7 @@ msg: Installed GPG Keys do not meet expected values or expected keys are not installed - name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated" - when: - - rhel9cis_rule_1_2_1_2 + when: rhel9cis_rule_1_2_1_2 tags: - level1-server - level1-workstation @@ -94,8 +93,7 @@ label: "{{ item.path }}" - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured" - when: - - rhel9cis_rule_1_2_1_4 + when: rhel9cis_rule_1_2_1_4 tags: - level1-server - level1-workstation @@ -107,11 +105,11 @@ warn_control_id: '1.2.1.4' block: - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Get repo list" - ansible.builtin.shell: dnf repolist + ansible.builtin.command: dnf repolist changed_when: false failed_when: false - register: discovered_dnf_configured check_mode: false + register: discovered_dnf_configured - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Display repo list" ansible.builtin.debug: diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index f3f67f8..198ae7b 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -122,8 +122,7 @@ file: warning_facts.yml - name: "1.3.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed" - when: - - rhel9cis_rule_1_3_1_7 + when: rhel9cis_rule_1_3_1_7 tags: - level1-server - level1-workstation @@ -136,9 +135,6 @@ state: absent - name: "1.3.1.8 | PATCH | Ensure SETroubleshoot is not installed" - ansible.builtin.package: - name: setroubleshoot - state: absent when: - rhel9cis_rule_1_3_1_8 - "'setroubleshoot' in ansible_facts.packages" @@ -149,3 +145,6 @@ - rule_1.3.1.8 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + ansible.builtin.package: + name: setroubleshoot + state: absent diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 747faa8..d422f14 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -16,12 +16,11 @@ content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy owner: root group: root - mode: '0600' + mode: 'go-rwx' notify: Grub2cfg - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" - when: - - rhel9cis_rule_1_4_2 + when: rhel9cis_rule_1_4_2 tags: - level1-server - level1-workstation @@ -41,5 +40,5 @@ access_time: preserve loop: - { path: 'grub.cfg', mode: '0700' } - - { path: 'grubenv', mode: '0600' } - - { path: 'user.cfg', mode: '0600' } + - { path: 'grubenv', mode: 'go-rwx' } + - { path: 'user.cfg', mode: 'go-rwx' } diff --git a/tasks/section_1/cis_1.5.x.yml b/tasks/section_1/cis_1.5.x.yml index 3767a58..992785b 100644 --- a/tasks/section_1/cis_1.5.x.yml +++ b/tasks/section_1/cis_1.5.x.yml @@ -1,8 +1,7 @@ --- - name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled" - when: - - rhel9cis_rule_1_5_1 + when: rhel9cis_rule_1_5_1 tags: - level1-server - level1-workstation @@ -21,8 +20,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" - name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted" - when: - - rhel9cis_rule_1_5_2 + when: rhel9cis_rule_1_5_2 tags: - level1-server - level1-workstation @@ -39,8 +37,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf" - name: "1.5.3 | PATCH | Ensure core dump backtraces are disabled" - when: - - rhel9cis_rule_1_5_3 + when: rhel9cis_rule_1_5_3 tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 5d9441e..c418324 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -1,8 +1,7 @@ --- - name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" - when: - - rhel9cis_rule_1_6_1 + when: rhel9cis_rule_1_6_1 tags: - level1-server - level1-workstation @@ -18,8 +17,7 @@ - Set Crypto Policy - name: "1.6.2 | PATCH | Ensure system wide crypto policy is not set in sshd configuration" - when: - - rhel9cis_rule_1_6_2 + when: rhel9cis_rule_1_6_2 tags: - level1-server - level1-workstation @@ -54,7 +52,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' register: discovered_no_sha1_template - name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules" @@ -85,7 +83,7 @@ dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' register: discovered_no_weakmac_template - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules" @@ -115,7 +113,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' register: discovered_no_sshcbc_template - name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules" @@ -145,7 +143,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' register: discovered_no_sshweakciphers_template - name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules" @@ -175,7 +173,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SSHETM.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' register: discovered_no_sshetm_template - name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules" diff --git a/tasks/section_1/cis_1.7.x.yml b/tasks/section_1/cis_1.7.x.yml index c7484cd..7f45476 100644 --- a/tasks/section_1/cis_1.7.x.yml +++ b/tasks/section_1/cis_1.7.x.yml @@ -1,8 +1,7 @@ --- - name: "1.7.1 | PATCH | Ensure message of the day is configured properly" - when: - - rhel9cis_rule_1_7_1 + when: rhel9cis_rule_1_7_1 tags: - level1-server - level1-workstation @@ -17,11 +16,10 @@ dest: /etc/motd owner: root group: root - mode: u-x,go-wx + mode: 'u-x,go-wx' - name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly" - when: - - rhel9cis_rule_1_7_2 + when: rhel9cis_rule_1_7_2 tags: - level1-server - level1-workstation @@ -35,11 +33,10 @@ dest: /etc/issue owner: root group: root - mode: '0644' + mode: 'go-wx' - name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly" - when: - - rhel9cis_rule_1_7_3 + when: rhel9cis_rule_1_7_3 tags: - level1-server - level1-workstation @@ -54,11 +51,10 @@ dest: /etc/issue.net owner: root group: root - mode: '0644' + mode: 'go-wx' - name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured" - when: - - rhel9cis_rule_1_7_4 + when: rhel9cis_rule_1_7_4 tags: - level1-server - level1-workstation @@ -71,11 +67,10 @@ path: /etc/motd owner: root group: root - mode: '0644' + mode: 'go-wx' - name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured" - when: - - rhel9cis_rule_1_7_5 + when: rhel9cis_rule_1_7_5 tags: - level1-server - level1-workstation @@ -88,11 +83,10 @@ path: /etc/issue owner: root group: root - mode: '0644' + mode: 'go-wx' - name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured" - when: - - rhel9cis_rule_1_7_6 + when: rhel9cis_rule_1_7_6 tags: - level1-server - level1-workstation @@ -105,4 +99,4 @@ path: /etc/issue.net owner: root group: root - mode: '0644' + mode: 'go-wx' diff --git a/tasks/section_1/cis_1.8.x.yml b/tasks/section_1/cis_1.8.x.yml index 427eb79..c38b75c 100644 --- a/tasks/section_1/cis_1.8.x.yml +++ b/tasks/section_1/cis_1.8.x.yml @@ -35,7 +35,7 @@ create: true owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf loop: - { regexp: 'user-db', line: 'user-db:user' } @@ -48,7 +48,7 @@ dest: /etc/dconf/db/gdm.d/01-banner-message owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled" @@ -68,7 +68,7 @@ create: true owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf loop: - { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' } @@ -96,7 +96,7 @@ create: true owner: root group: root - mode: '0644' + mode: 'go-wx' loop: - { regexp: '^user-db', line: 'user-db:user' } - { regexp: '^system-db', line: 'system-db:local' } @@ -106,7 +106,7 @@ path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" owner: root group: root - mode: '0755' + mode: 'go-w' state: directory - name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file" @@ -115,7 +115,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-screensaver" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden" @@ -134,7 +134,7 @@ path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" owner: root group: root - mode: '0755' + mode: 'go-w' state: directory - name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file" @@ -143,7 +143,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled" @@ -161,7 +161,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden" @@ -180,7 +180,7 @@ path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" owner: root group: root - mode: '0755' + mode: 'go-w' state: directory - name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file" @@ -189,7 +189,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled" @@ -208,7 +208,7 @@ path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d" owner: root group: root - mode: '0755' + mode: 'go-w' state: directory - name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file" @@ -217,7 +217,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden" @@ -236,7 +236,7 @@ path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks" owner: root group: root - mode: '0755' + mode: 'go-w' state: directory - name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile" @@ -245,7 +245,7 @@ dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock" owner: root group: root - mode: '0644' + mode: 'go-wx' notify: Reload dconf - name: "1.8.10 | PATCH | Ensure XDMCP is not enabled" diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 73e7986..fb0351f 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -33,9 +33,8 @@ masked: true - name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use" - when: - - rhel9cis_rule_2_1_2 - - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" + when: rhel9cis_rule_2_1_2 + tags: - level1-server - level2-workstation @@ -70,9 +69,7 @@ - avahi-daemon.service - name: "2.1.3 | PATCH | Ensure dhcp server services are not in use" - when: - - "'dhcp-server' in ansible_facts.packages" - - rhel9cis_rule_2_1_3 + when: rhel9cis_rule_2_1_3 tags: - level1-server - level1-workstation @@ -105,9 +102,7 @@ - dhcpd6.service - name: "2.1.4 | PATCH | Ensure dns server services are not in use" - when: - - "'bind' in ansible_facts.packages" - - rhel9cis_rule_2_1_4 + when: rhel9cis_rule_2_1_4 tags: - level1-server - level1-workstation @@ -137,9 +132,7 @@ masked: true - name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use" - when: - - "'dnsmasq' in ansible_facts.packages" - - rhel9cis_rule_2_1_5 + when: rhel9cis_rule_2_1_5 tags: - level1-server - level1-workstation @@ -169,9 +162,7 @@ masked: true - name: "2.1.6 | PATCH | Ensure samba file server services are not in use" - when: - - "'samba' in ansible_facts.packages" - - rhel9cis_rule_2_1_6 + when: rhel9cis_rule_2_1_6 tags: - level1-server - level1-workstation @@ -202,9 +193,7 @@ masked: true - name: "2.1.7 | PATCH | Ensure ftp server services are not in use" - when: - - "'ftp' in ansible_facts.packages" - - rhel9cis_rule_2_1_7 + when: rhel9cis_rule_2_1_7 tags: - level1-server - level1-workstation @@ -235,9 +224,7 @@ masked: true - name: "2.1.8 | PATCH | Ensure message access server services are not in use" - when: - - "'dovecot' in ansible_facts.packages or 'cyrus-imapd' in ansible_facts.packages" - - rhel9cis_rule_2_1_8 + when: rhel9cis_rule_2_1_8 tags: - level1-server - level1-workstation @@ -275,9 +262,7 @@ - "cyrus-imapd.service" - name: "2.1.9 | PATCH | Ensure network file system services are not in use" - when: - - "'nfs-utils' in ansible_facts.packages" - - rhel9cis_rule_2_1_9 + when: rhel9cis_rule_2_1_9 tags: - level1-server - level1-workstation @@ -309,9 +294,7 @@ masked: true - name: "2.1.10 | PATCH | Ensure nis server services are not in use" - when: - - "'ypserv' in ansible_facts.packages" - - rhel9cis_rule_2_1_10 + when: rhel9cis_rule_2_1_10 tags: - level1-server - level1-workstation @@ -341,9 +324,7 @@ masked: true - name: "2.1.11 | PATCH | Ensure print server services are not in use" - when: - - "'cups' in ansible_facts.packages" - - rhel9cis_rule_2_1_11 + when: rhel9cis_rule_2_1_11 tags: - level1-server - automated @@ -375,9 +356,7 @@ - "cups.service" - name: "2.1.12 | PATCH | Ensure rpcbind services are not in use" - when: - - "'rpcbind' in ansible_facts.packages" - - rhel9cis_rule_2_1_12 + when: rhel9cis_rule_2_1_12 tags: - level1-server - level1-workstation @@ -411,9 +390,7 @@ - rpcbind.socket - name: "2.1.13 | PATCH | Ensure rsync services are not in use" - when: - - "'rsync-daemon' in ansible_facts.packages" - - rhel9cis_rule_2_1_13 + when: rhel9cis_rule_2_1_13 tags: - level1-server - level1-workstation @@ -447,9 +424,7 @@ - 'rsyncd.service' - name: "2.1.14 | PATCH | Ensure snmp services are not in use" - when: - - "'net-snmp' in ansible_facts.packages" - - rhel9cis_rule_2_1_14 + when: rhel9cis_rule_2_1_14 tags: - level1-server - level1-workstation @@ -479,9 +454,7 @@ masked: true - name: "2.1.15 | PATCH | Ensure telnet server services are not in use" - when: - - "'telnet-server' in ansible_facts.packages" - - rhel9cis_rule_2_1_15 + when: rhel9cis_rule_2_1_15 tags: - level1-server - level1-workstation @@ -512,9 +485,7 @@ masked: true - name: "2.1.16 | PATCH | Ensure tftp server services are not in use" - when: - - "'tftp-server' in ansible_facts.packages" - - rhel9cis_rule_2_1_16 + when: rhel9cis_rule_2_1_16 tags: - level1-server - level1-workstation @@ -547,9 +518,7 @@ - 'tftp.service' - name: "2.1.17 | PATCH | Ensure web proxy server services are not in use" - when: - - "'squid' in ansible_facts.packages" - - rhel9cis_rule_2_117 + when: rhel9cis_rule_2_1_17 tags: - level1-server - level1-workstation @@ -580,8 +549,7 @@ masked: true - name: "2.1.18 | PATCH | Ensure web server services are not in use" - when: - - rhel9cis_rule_2_1_18 + when: rhel9cis_rule_2_1_18 tags: - level1-server - level1-workstation @@ -597,7 +565,6 @@ when: - not rhel9cis_httpd_server - not rhel9cis_httpd_mask - - "'httpd' in ansible_facts.packages" ansible.builtin.package: name: httpd state: absent @@ -606,7 +573,6 @@ when: - not rhel9cis_nginx_server - not rhel9cis_nginx_mask - - "'nginx' in ansible_facts.packages" ansible.builtin.package: name: nginx state: absent @@ -615,7 +581,6 @@ when: - not rhel9cis_httpd_server - rhel9cis_httpd_mask - - "'httpd' in ansible_facts.packages" notify: Systemd_daemon_reload ansible.builtin.systemd: name: httpd.service @@ -627,7 +592,6 @@ when: - not rhel9cis_nginx_server - rhel9cis_nginx_mask - - "'nginx' in ansible_facts.packages" notify: Systemd_daemon_reload ansible.builtin.systemd: name: ngnix.service @@ -636,9 +600,7 @@ masked: true - name: "2.1.19 | PATCH | Ensure xinetd services are not in use" - when: - - "'xinetd' in ansible_facts.packages" - - rhel9cis_rule_2_1_19 + when: rhel9cis_rule_2_1_19 tags: - level1-server - level1-workstation @@ -670,7 +632,6 @@ - name: "2.1.20 | PATCH | Ensure X window server services are not in use" when: - not rhel9cis_xwindow_server - - "'xorg-x11-server-common' in ansible_facts.packages" - rhel9cis_rule_2_1_20 tags: - level1-server @@ -704,8 +665,7 @@ line: "inet_interfaces = loopback-only" - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface" - when: - - rhel9cis_rule_2_1_22 + when: rhel9cis_rule_2_1_22 tags: - level1-server - level1-workstation @@ -717,8 +677,8 @@ vars: warn_control_id: '2.1.22' block: - - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" - ansible.builtin.shell: systemctl list-units --type=service + - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" # noqa command-instead-of-module + ansible.builtin.command: systemctl list-units --type=service changed_when: false failed_when: discovered_running_services.rc not in [ 0, 1 ] check_mode: false diff --git a/tasks/section_2/cis_2.2.x.yml b/tasks/section_2/cis_2.2.x.yml index cdd03b8..0e019e7 100644 --- a/tasks/section_2/cis_2.2.x.yml +++ b/tasks/section_2/cis_2.2.x.yml @@ -3,7 +3,6 @@ - name: "2.2.1 | PATCH | Ensure ftp client is not installed" when: - not rhel9cis_ftp_client - - "'ftp' in ansible_facts.packages" - rhel9cis_rule_2_2_1 tags: - level1-server @@ -20,7 +19,6 @@ - name: "2.2.2 | PATCH | Ensure ldap client is not installed" when: - not rhel9cis_openldap_clients_required - - "'openldap-clients' in ansible_facts.packages" - rhel9cis_rule_2_2_2 tags: - level2-server @@ -37,7 +35,6 @@ - name: "2.2.3 | PATCH | Ensure nis client is not installed" when: - not rhel9cis_ypbind_required - - "'ypbind' in ansible_facts.packages" - rhel9cis_rule_2_2_3 tags: - level1-server @@ -54,7 +51,6 @@ - name: "2.2.4 | PATCH | Ensure telnet client is not installed" when: - not rhel9cis_telnet_required - - "'telnet' in ansible_facts.packages" - rhel9cis_rule_2_2_4 tags: - level1-server @@ -71,7 +67,6 @@ - name: "2.2.5 | PATCH | Ensure TFTP client is not installed" when: - not rhel9cis_tftp_client - - "'tftp' in ansible_facts.packages" - rhel9cis_rule_2_2_5 tags: - level1-server diff --git a/tasks/section_2/cis_2.3.x.yml b/tasks/section_2/cis_2.3.x.yml index dacd624..b84a84b 100644 --- a/tasks/section_2/cis_2.3.x.yml +++ b/tasks/section_2/cis_2.3.x.yml @@ -31,7 +31,7 @@ dest: /etc/chrony.conf owner: root group: root - mode: '0644' + mode: 'go-wx' - name: "2.3.3 | PATCH | Ensure chrony is not run as the root user" when: @@ -48,4 +48,4 @@ line: OPTIONS="\1 -u chrony" create: true backrefs: true - mode: '0644' + mode: 'go-wx' diff --git a/tasks/section_2/cis_2.4.x.yml b/tasks/section_2/cis_2.4.x.yml index 16ed0e9..c4b6b8b 100644 --- a/tasks/section_2/cis_2.4.x.yml +++ b/tasks/section_2/cis_2.4.x.yml @@ -1,8 +1,7 @@ --- - name: "2.4.1.1 | PATCH | Ensure cron daemon is enabled" - when: - - rhel9cis_rule_2_4_1_1 + when: rhel9cis_rule_2_4_1_1 tags: - level1-server - level1-workstation @@ -19,8 +18,7 @@ enabled: true - name: "2.4.1.2 | PATCH | Ensure permissions on /etc/crontab are configured" - when: - - rhel9cis_rule_2_4_1_2 + when: rhel9cis_rule_2_4_1_2 tags: - level1-server - level1-workstation @@ -33,11 +31,10 @@ path: /etc/crontab owner: root group: root - mode: og-rwx + mode: 'og-rwx' - name: "2.4.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured" - when: - - rhel9cis_rule_2_4_1_3 + when: rhel9cis_rule_2_4_1_3 tags: - level1-server - level1-workstation @@ -51,11 +48,10 @@ state: directory owner: root group: root - mode: og-rwx + mode: 'og-rwx' - name: "2.4.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured" - when: - - rhel9cis_rule_2_4_1_4 + when: rhel9cis_rule_2_4_1_4 tags: - level1-server - level1-workstation @@ -67,11 +63,10 @@ state: directory owner: root group: root - mode: og-rwx + mode: 'og-rwx' - name: "2.4.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured" - when: - - rhel9cis_rule_2_4_1_5 + when: rhel9cis_rule_2_4_1_5 tags: - level1-server - level1-workstation @@ -84,11 +79,10 @@ state: directory owner: root group: root - mode: og-rwx + mode: 'og-rwx' - name: "2.4.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured" - when: - - rhel9cis_rule_2_4_1_6 + when: rhel9cis_rule_2_4_1_6 tags: - level1-server - level1-workstation @@ -101,11 +95,10 @@ state: directory owner: root group: root - mode: og-rwx + mode: 'og-rwx' - name: "2.4.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured" - when: - - rhel9cis_rule_2_4_1_7 + when: rhel9cis_rule_2_4_1_7 tags: - level1-server - level1-workstation @@ -119,11 +112,10 @@ state: directory owner: root group: root - mode: '0700' + mode: 'og-rwx' - name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users" - when: - - rhel9cis_rule_2_4_1_8 + when: rhel9cis_rule_2_4_1_8 tags: - level1-server - level1-workstation @@ -146,14 +138,13 @@ - name: "2.4.1.8 | PATCH | Ensure crontab 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" }}' + state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' owner: root group: root - mode: u-x,g-wx,o-rwx + mode: 'u-x,g-wx,o-rwx' - name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users" - when: - - rhel9cis_rule_2_4_2_1 + when: rhel9cis_rule_2_4_2_1 tags: - level1-server - level1-workstation @@ -179,4 +170,4 @@ state: '{{ "file" if discovered_at_allow_state.stat.exists else "touch" }}' owner: root group: root - mode: u-x,g-wx,o-rwx + mode: 'u-x,g-wx,o-rwx' diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 98e3a93..e8934d4 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -40,7 +40,7 @@ block: - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" when: "'network-manager' in ansible_facts.packages" - ansible.builtin.shell: nmcli radio wifi + ansible.builtin.command: nmcli radio wifi changed_when: false failed_when: false check_mode: false @@ -50,7 +50,7 @@ when: - "'network-manager' in ansible_facts.packages" - "'enabled' in discovered_wifi_status.stdout" - ansible.builtin.shell: nmcli radio all off + ansible.builtin.command: nmcli radio all off changed_when: discovered_nmcli_radio_off.rc == 0 register: discovered_nmcli_radio_off @@ -65,8 +65,7 @@ file: warning_facts.yml - name: "3.1.3 | PATCH | Ensure bluetooth services are not in use" - when: - - rhel9cis_rule_3_1_3 + when: rhel9cis_rule_3_1_3 tags: - level1-server - level2-workstation diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index bc210ae..4903070 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -1,8 +1,7 @@ --- - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available" - when: - - rhel9cis_rule_3_2_1 + when: rhel9cis_rule_3_2_1 tags: - level2-server - level2-workstation @@ -18,6 +17,7 @@ regexp: '^(#)?install dccp(\\s|$)' line: "{{ item }}" create: true + mode: 'go-wx' loop: - install dccp /bin/true - blacklist dccp @@ -28,11 +28,10 @@ regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: '0600' + mode: 'go-wx' - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" - when: - - rhel9cis_rule_3_2_2 + when: rhel9cis_rule_3_2_2 tags: - level2-server - level2-workstation @@ -48,6 +47,7 @@ regexp: '^(#)?install tipc(\\s|$)' line: "{{ item }}" create: true + mode: 'go-wx' loop: - install tipc /bin/true - blacklist tipc @@ -58,11 +58,10 @@ regexp: "^(#)?blacklist tipc(\\s|$)" line: "blacklist tipc" create: true - mode: '0600' + mode: 'go-wx' - name: "3.2.3 | PATCH | Ensure rds kernel module is not available" - when: - - rhel9cis_rule_3_2_3 + when: rhel9cis_rule_3_2_3 tags: - level2-server - level2-workstation @@ -78,6 +77,7 @@ regexp: '^(#)?install rds(\\s|$)' line: "{{ item }}" create: true + mode: 'go-wx' loop: - install rds /bin/true - blacklist rds @@ -88,11 +88,10 @@ regexp: "^(#)?blacklist rds(\\s|$)" line: "blacklist rds" create: true - mode: '0600' + mode: 'go-wx' - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" - when: - - rhel9cis_rule_3_2_4 + when: rhel9cis_rule_3_2_4 tags: - level2-server - level2-workstation @@ -108,6 +107,7 @@ regexp: '^(#)?install sctp(\\s|$)' line: "{{ item }}" create: true + mode: 'go-wx' loop: - install sctp /bin/true - blacklist sctp @@ -118,4 +118,4 @@ regexp: "^(#)?blacklist sctp(\\s|$)" line: "blacklist sctp" create: true - mode: '0600' + mode: 'go-wx' diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 2f73979..123928e 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -61,8 +61,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored" - when: - - rhel9cis_rule_3_3_3 + when: rhel9cis_rule_3_3_3 tags: - level1-server - level1-workstation @@ -85,8 +84,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored" - when: - - rhel9cis_rule_3_3_4 + when: rhel9cis_rule_3_3_4 tags: - level1-server - level1-workstation @@ -109,8 +107,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted" - when: - - rhel9cis_rule_3_3_5 + when: rhel9cis_rule_3_3_5 tags: - level1-server - level1-workstation @@ -144,8 +141,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted" - when: - - rhel9cis_rule_3_3_6 + when: rhel9cis_rule_3_3_6 tags: - level1-server - level1-workstation @@ -179,8 +175,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled" - when: - - rhel9cis_rule_3_3_7 + when: rhel9cis_rule_3_3_7 tags: - level1-server - level1-workstation @@ -203,8 +198,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - name: "3.3.8 | PATCH | Ensure source routed packets are not accepted" - when: - - rhel9cis_rule_3_3_8 + when: rhel9cis_rule_3_3_8 tags: - level1-server - level1-workstation @@ -237,8 +231,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf" - name: "3.3.9 | PATCH | Ensure suspicious packets are logged" - when: - - rhel9cis_rule_3_3_9 + when: rhel9cis_rule_3_3_9 tags: - level1-server - level1-workstation @@ -257,8 +250,7 @@ msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" - name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled" - when: - - rhel9cis_rule_3_3_10 + when: rhel9cis_rule_3_3_10 tags: - level1-server - level1-workstation diff --git a/tasks/section_4/cis_4.1.x.yml b/tasks/section_4/cis_4.1.x.yml index f0a6636..ab61c81 100644 --- a/tasks/section_4/cis_4.1.x.yml +++ b/tasks/section_4/cis_4.1.x.yml @@ -17,8 +17,7 @@ state: present - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use" - when: - - rhel9cis_rule_4_1_2 + when: rhel9cis_rule_4_1_2 tags: - level1-server - level1-workstation @@ -52,7 +51,7 @@ name: "{{ rhel9cis_firewall }}" state: installed - - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" # noqa name[template] ansible.builtin.systemd: name: "{{ rhel9cis_firewall }}" enabled: true diff --git a/tasks/section_4/cis_4.2.x.yml b/tasks/section_4/cis_4.2.x.yml index 0fca4cc..6e8eb3c 100644 --- a/tasks/section_4/cis_4.2.x.yml +++ b/tasks/section_4/cis_4.2.x.yml @@ -1,8 +1,7 @@ --- - name: "4.2.1 | AUDIT | Ensure firewalld drops unnecessary services and ports" - when: - - rhel9cis_rule_4_2_1 + when: rhel9cis_rule_4_2_1 tags: - level1-server - level1-workstation @@ -25,8 +24,7 @@ - "{{ discovered_services_and_ports.stdout_lines }}" - name: "4.2.2 | PATCH | Ensure firewalld loopback traffic is configured | firewalld" - when: - - rhel9cis_rule_4_2_2 + when: rhel9cis_rule_4_2_2 tags: - level1-server - level1-workstation diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 4e85deb..450ef3b 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -8,11 +8,11 @@ - rhel9cis_rule_4_3_3 - rhel9cis_rule_4_3_4 tags: always - ansible.builtin.shell: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + ansible.builtin.command: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + changed_when: true - name: "4.3.1 | PATCH | Ensure nftables base chains exist" - when: - - rhel9cis_rule_4_3_1 + when: rhel9cis_rule_4_3_1 tags: - level1-server - level1-workstation @@ -52,7 +52,8 @@ - name: "4.3.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" when: rhel9cis_nft_tables_autochaincreate - ansible.builtin.shell: "{{ item }}" + ansible.builtin.command: "{{ item }}" + changed_when: true failed_when: false loop: - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } @@ -60,8 +61,7 @@ - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; } - name: "4.3.2 | PATCH | Ensure nftables established connections are configured" - when: - - rhel9cis_rule_4_3_2 + when: rhel9cis_rule_4_3_2 tags: - level1-server - level1-workstation @@ -84,31 +84,36 @@ - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' - ansible.builtin.shell: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" when: '"ip protocol udp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" when: '"ip protocol icmp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" when: '"ip protocol tcp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" when: '"ip protocol udp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" when: '"ip protocol icmp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy" - when: - - rhel9cis_rule_4_3_3 + when: rhel9cis_rule_4_3_3 tags: - level1-server - level1-workstation @@ -144,22 +149,25 @@ - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" when: '"tcp dport ssh accept" not in discovered_nftables_sshallowcheck.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" when: '"type filter hook input priority 0; policy drop;" not in discovered_nftables_inputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; } + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" when: '"type filter hook forward priority 0; policy drop;" not in discovered_nftables_forwardpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; } + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" when: '"type filter hook output priority 0; policy drop;" not in discovered_nftables_outputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured" - when: - - rhel9cis_rule_4_3_4 + when: rhel9cis_rule_4_3_4 tags: - level1-server - level1-workstation @@ -189,11 +197,14 @@ - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule | nftables" when: '"iif \"lo\" accept" not in discovered_nftables_iiflo.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule | nftables" when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_nftables_ipsaddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule | nftables" when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_nftables_ip6saddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop + changed_when: true diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 31ba7e2..296ebf9 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -1,8 +1,7 @@ --- - name: "5.1.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured" - when: - - rhel9cis_rule_5_1_1 + when: rhel9cis_rule_5_1_1 tags: - level1-server - level1-workstation @@ -16,11 +15,10 @@ path: "/etc/ssh/sshd_config" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured" - when: - - rhel9cis_rule_5_1_2 + when: rhel9cis_rule_5_1_2 tags: - level1-server - level1-workstation @@ -50,8 +48,7 @@ label: "{{ item.path }}" - name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured" - when: - - rhel9cis_rule_5_1_3 + when: rhel9cis_rule_5_1_3 tags: - level1-server - level1-workstation @@ -98,7 +95,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' notify: - Update Crypto Policy - Set Crypto Policy @@ -126,7 +123,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' notify: - Update Crypto Policy - Set Crypto Policy @@ -154,7 +151,7 @@ dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' notify: - Update Crypto Policy - Set Crypto Policy @@ -164,8 +161,7 @@ rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKMACS' }}" - name: "5.1.7 | PATCH | Ensure sshd access is configured" - when: - - rhel9cis_rule_5_1_7 + when: rhel9cis_rule_5_1_7 tags: - level1-server - level1-workstation @@ -212,8 +208,7 @@ notify: Restart sshd - name: "5.1.8 | PATCH | Ensure sshd Banner is configured" - when: - - rhel9cis_rule_5_1_8 + when: rhel9cis_rule_5_1_8 tags: - level1-server - level1-workstation @@ -231,8 +226,7 @@ line: 'Banner /etc/issue.net' - name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured" - when: - - rhel9cis_rule_5_1_9 + when: rhel9cis_rule_5_1_9 tags: - level1-server - level1-workstation @@ -262,8 +256,7 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled" - when: - - rhel9cis_rule_5_1_10 + when: rhel9cis_rule_5_1_10 tags: - level2-server - level1-workstation @@ -289,8 +282,7 @@ notify: Restart sshd - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled" - when: - - rhel9cis_rule_5_1_11 + when: rhel9cis_rule_5_1_11 tags: - level1-server - level1-workstation @@ -320,8 +312,7 @@ notify: Restart sshd - name: "5.1.12 | PATCH | Ensure sshd HostbasedAuthentication is disabled" - when: - - rhel9cis_rule_5_1_12 + when: rhel9cis_rule_5_1_12 tags: - level1-server - level1-workstation @@ -341,8 +332,7 @@ notify: Restart sshd - name: "5.1.13 | PATCH | Ensure sshd IgnoreRhosts is enabled" - when: - - rhel9cis_rule_5_1_13 + when: rhel9cis_rule_5_1_13 tags: - level1-server - level1-workstation @@ -362,8 +352,7 @@ notify: Restart sshd - name: "5.1.14 | PATCH | Ensure sshd LoginGraceTime is set to one minute or less" - when: - - rhel9cis_rule_5_1_14 + when: rhel9cis_rule_5_1_14 tags: - level1-server - level1-workstation @@ -379,8 +368,7 @@ notify: Restart sshd - name: "5.1.15 | PATCH | Ensure sshd LogLevel is appropriate" - when: - - rhel9cis_rule_5_1_15 + when: rhel9cis_rule_5_1_15 tags: - level1-server - level1-workstation @@ -398,8 +386,7 @@ notify: Restart sshd - name: "5.1.16 | PATCH | Ensure sshd MaxAuthTries is set to 4 or less" - when: - - rhel9cis_rule_5_1_16 + when: rhel9cis_rule_5_1_16 tags: - level1-server - level1-workstation @@ -415,8 +402,7 @@ notify: Restart sshd - name: "5.1.17 | PATCH | Ensure sshd MaxStartups is configured" - when: - - rhel9cis_rule_5_1_17 + when: rhel9cis_rule_5_1_17 tags: - level1-server - level1-workstation @@ -436,8 +422,7 @@ notify: Restart sshd - name: "5.1.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less" - when: - - rhel9cis_rule_5_1_18 + when: rhel9cis_rule_5_1_18 tags: - level1-server - level1-workstation @@ -457,8 +442,7 @@ notify: Restart sshd - name: "5.1.19 | PATCH | Ensure sshd PermitEmptyPasswords is disabled" - when: - - rhel9cis_rule_5_1_19 + when: rhel9cis_rule_5_1_19 tags: - level1-server - level1-workstation @@ -478,8 +462,7 @@ notify: Restart sshd - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled" - when: - - rhel9cis_rule_5_1_20 + when: rhel9cis_rule_5_1_20 tags: - level1-server - level1-workstation @@ -503,8 +486,7 @@ notify: Restart sshd - name: "5.1.21 | PATCH | Ensure sshd PermitUserEnvironment is disabled" - when: - - rhel9cis_rule_5_1_21 + when: rhel9cis_rule_5_1_21 tags: - level1-server - level1-workstation @@ -524,8 +506,7 @@ notify: Restart sshd - name: "5.1.22 | PATCH | Ensure SSH PAM is enabled" - when: - - rhel9cis_rule_5_1_22 + when: rhel9cis_rule_5_1_22 tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.2.x.yml b/tasks/section_5/cis_5.2.x.yml index 87fe46e..3d57dbf 100644 --- a/tasks/section_5/cis_5.2.x.yml +++ b/tasks/section_5/cis_5.2.x.yml @@ -1,8 +1,7 @@ --- - name: "5.2.1 | PATCH | Ensure sudo is installed" - when: - - rhel9cis_rule_5_2_1 + when: rhel9cis_rule_5_2_1 tags: - level1-server - level1-workstation @@ -15,8 +14,7 @@ state: present - name: "5.2.2 | PATCH | Ensure sudo commands use pty" - when: - - rhel9cis_rule_5_2_2 + when: rhel9cis_rule_5_2_2 tags: - level1-server - level1-workstation @@ -30,8 +28,7 @@ validate: '/usr/sbin/visudo -cf %s' - name: "5.2.3 | PATCH | Ensure sudo log file exists" - when: - - rhel9cis_rule_5_2_3 + when: rhel9cis_rule_5_2_3 tags: - level1-server - level1-workstation @@ -47,8 +44,7 @@ validate: '/usr/sbin/visudo -cf %s' - name: "5.2.4 | PATCH | Ensure users must provide password for escalation" - when: - - rhel9cis_rule_5_2_4 + when: rhel9cis_rule_5_2_4 tags: - level2-server - level2-workstation @@ -74,8 +70,7 @@ loop: "{{ discovered_nopasswd_sudoers.stdout_lines }}" - name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally" - when: - - rhel9cis_rule_5_2_5 + when: rhel9cis_rule_5_2_5 tags: - level1-server - level1-workstation @@ -101,8 +96,7 @@ loop: "{{ discovered_priv_reauth.stdout_lines }}" - name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly" - when: - - rhel9cis_rule_5_2_6 + when: rhel9cis_rule_5_2_6 tags: - level1-server - level1-workstation @@ -134,8 +128,7 @@ loop: "{{ discovered_sudo_timeout_files.stdout_lines }}" - name: "5.2.7 | PATCH | Ensure access to the su command is restricted" - when: - - rhel9cis_rule_5_2_7 + when: rhel9cis_rule_5_2_7 tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 18e9cfd..7923d50 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -17,12 +17,13 @@ when: - rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or prelim_authselect_current_profile.stdout is not defined - ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" + ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" + changed_when: true args: creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" - name: "5.3.2.1 | AUDIT | Ensure active authselect profile includes pam modules | get profile features" - ansible.builtin.shell: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" + ansible.builtin.command: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" changed_when: false register: discovered_authselect_profile_features @@ -37,7 +38,8 @@ - password - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Backup and Add pam modules" - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" + changed_when: true - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled" when: @@ -64,9 +66,11 @@ failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] register: discovered_authselect_current_faillock - - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" # noqa syntax-check[specific]" when: discovered_authselect_current_faillock.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true + notify: Authselect update - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: @@ -90,7 +94,8 @@ - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" when: discovered_authselect_current_quality.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true notify: Authselect update - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" @@ -115,7 +120,8 @@ - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" when: discovered_authselect_current_history.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" @@ -133,8 +139,7 @@ - rule_5.3.2.5 block: - name: "5.3.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 + ansible.builtin.command: grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false failed_when: discovered_discovered_authselect_pam_unix.rc not in [ 0, 1 ] register: discovered_discovered_authselect_pam_unix @@ -142,12 +147,12 @@ - name: "5.3.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: - path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth + path: /etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/system-auth regexp: "{{ item.regexp }}" line: "{{ item.line }}" backrefs: true - insertafter: "{{ item.after | default (omit) }}" - insertbefore: "{{ item.before | default (omit) }}" + insertafter: "{{ item.after | default(omit) }}" + insertbefore: "{{ item.before | default(omit) }}" 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' } @@ -156,12 +161,12 @@ - name: "5.3.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: - path: /etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth + path: /etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/password-auth line: "{{ item.line }}" regexp: "{{ item.regexp }}" backrefs: true - insertafter: "{{ item.after | default (omit) }}" - insertbefore: "{{ item.before | default (omit) }}" + insertafter: "{{ item.after | default(omit) }}" + insertbefore: "{{ item.before | default(omit) }}" 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_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 8206074..f7bfb64 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -1,8 +1,7 @@ --- - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured" - when: - - rhel9cis_rule_5_3_3_1_1 + when: rhel9cis_rule_5_3_3_1_1 tags: - level1-server - level1-workstation @@ -44,8 +43,7 @@ notify: Authselect update - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured" - when: - - rhel9cis_rule_5_3_3_1_2 + when: rhel9cis_rule_5_3_3_1_2 tags: - level1-server - level1-workstation @@ -87,8 +85,7 @@ notify: Authselect update - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" - when: - - rhel9cis_rule_5_3_3_1_3 + when: rhel9cis_rule_5_3_3_1_3 tags: - level1-server - level1-workstation @@ -104,6 +101,7 @@ line: "{{ rhel9cis_pamroot_lock_option }}" insertafter: '^# end of pam-auth-update config' create: true + mode: 'go-rwx' - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files NOT AuthSelect" when: diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index 9317326..920ed88 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -1,8 +1,7 @@ --- - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured" - when: - - rhel9cis_rule_5_3_3_2_1 + when: rhel9cis_rule_5_3_3_2_1 tags: - level1-server - level1-workstation @@ -30,7 +29,7 @@ dest: "/{{ rhel9cis_passwd_difok_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from pam files Not AuthSelect" when: @@ -58,8 +57,7 @@ notify: Authselect update - name: "5.3.3.2.2 | PATCH | Ensure password length is configured" - when: - - rhel9cis_rule_5_3_3_2_2 + when: rhel9cis_rule_5_3_3_2_2 tags: - level1-server - level1-workstation @@ -87,7 +85,7 @@ dest: "/{{ rhel9cis_passwd_minlen_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from pam files NOT AuthSelect" when: @@ -115,8 +113,7 @@ notify: Authselect update - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured" - when: - - rhel9cis_rule_5_3_3_2_3 + when: rhel9cis_rule_5_3_3_2_3 tags: - level1-server - level1-workstation @@ -144,7 +141,7 @@ dest: "/{{ rhel9cis_passwd_complex_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove complexity from pam files NOT AuthSelect" when: @@ -172,8 +169,7 @@ notify: Authselect update - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured" - when: - - rhel9cis_rule_5_3_3_2_4 + when: rhel9cis_rule_5_3_3_2_4 tags: - level1-server - level1-workstation @@ -183,8 +179,7 @@ - pam block: - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file" - when: - - item != rhel9cis_passwd_maxrepeat_file + when: item != rhel9cis_passwd_maxrepeat_file ansible.builtin.replace: path: "{{ item }}" regexp: 'maxrepeat\s*=\s*\d+\b' @@ -200,7 +195,7 @@ dest: "/{{ rhel9cis_passwd_maxrepeat_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat from pam files NOT AuthSelect" when: @@ -228,8 +223,7 @@ notify: Authselect update - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is is configured" - when: - - rhel9cis_rule_5_3_3_2_5 + when: rhel9cis_rule_5_3_3_2_5 tags: - level1-server - level1-workstation @@ -257,7 +251,7 @@ dest: "/{{ rhel9cis_passwd_maxsequence_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence from pam files NOT AuthSelect" when: @@ -285,8 +279,7 @@ notify: Authselect update - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled" - when: - - rhel9cis_rule_5_3_3_2_6 + when: rhel9cis_rule_5_3_3_2_6 tags: - level1-server - level1-workstation @@ -313,7 +306,7 @@ dest: "/{{ rhel9cis_passwd_dictcheck_file }}" owner: root group: root - mode: '0600' + mode: 'go-rwx' - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck from pam files NOT AuthSelect" when: @@ -342,8 +335,7 @@ notify: Authselect update - name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user" - when: - - rhel9cis_rule_5_3_3_2_7 + when: rhel9cis_rule_5_3_3_2_7 tags: - level1-server - level1-workstation @@ -356,4 +348,4 @@ dest: "/{{ rhel9cis_passwd_quality_enforce_root_file }}" owner: root group: root - mode: '0600' + mode: 'o-rwx' diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index 21a03ee..ca5a5dc 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -1,8 +1,7 @@ --- - name: "5.3.3.3.1 | PATCH | Ensure password history remember is configured" - when: - - rhel9cis_rule_5_3_3_3_1 + when: rhel9cis_rule_5_3_3_3_1 tags: - level1-server - level1-workstation @@ -48,8 +47,7 @@ notify: Authselect update - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user" - when: - - rhel9cis_rule_5_3_3_3_2 + when: rhel9cis_rule_5_3_3_3_2 tags: - level1-server - level1-workstation @@ -95,8 +93,7 @@ notify: Authselect update - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" - when: - - rhel9cis_rule_5_3_3_3_3 + when: rhel9cis_rule_5_3_3_3_3 tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.3.3.4.x.yml b/tasks/section_5/cis_5.3.3.4.x.yml index a1e5768..ddca97a 100644 --- a/tasks/section_5/cis_5.3.3.4.x.yml +++ b/tasks/section_5/cis_5.3.3.4.x.yml @@ -28,8 +28,7 @@ loop: "{{ discovered_pam_nullok.stdout_lines }}" - name: "5.3.3.4.1 | PATCH | Ensure password number of changed characters is configured | Remove nullok from pam files AuthSelect" - when: - - rhel9cis_allow_authselect_updates + when: rhel9cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\snullok(.*$) @@ -67,8 +66,7 @@ loop: "{{ discovered_pam_remember.stdout_lines }}" - name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Remove remember from pam files AuthSelect" - when: - - rhel9cis_allow_authselect_updates + when: rhel9cis_allow_authselect_updates ansible.builtin.replace: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\sremember\s*=\s*=\d*(.*$) @@ -107,8 +105,7 @@ loop: "{{ discovered_pam_remember.stdout_lines }}" - name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Add hash algorithm to pam files AuthSelect" - when: - - rhel9cis_allow_authselect_updates + when: rhel9cis_allow_authselect_updates ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)(sha512|yescrypt)(.*$) @@ -150,8 +147,7 @@ loop: "{{ discovered_pam_authtok.stdout_lines }}" - name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | Add use_authtok pam files AuthSelect" - when: - - rhel9cis_allow_authselect_updates + when: rhel9cis_allow_authselect_updates ansible.builtin.lineinfile: path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$) diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 9e92e86..2363590 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -1,8 +1,7 @@ --- - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less" - when: - - rhel9cis_rule_5_4_1_1 + when: rhel9cis_rule_5_4_1_1 tags: - level1-server - level1-workstation @@ -38,8 +37,7 @@ loop: "{{ discovered_max_days.stdout_lines }}" - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured" - when: - - rhel9cis_rule_5_4_1_2 + when: rhel9cis_rule_5_4_1_2 tags: - level1-server - level1-workstation @@ -70,8 +68,7 @@ loop: "{{ discovered_min_days.stdout_lines }}" - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" - when: - - rhel9cis_rule_5_4_1_3 + when: rhel9cis_rule_5_4_1_3 tags: - level1-server - level1-workstation @@ -96,12 +93,12 @@ - discovered_warn_days.stdout_lines | length > 0 - item in prelim_interactive_usernames.stdout - rhel9cis_force_user_warnage - ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + changed_when: true loop: "{{ discovered_warn_days.stdout_lines }}" - name: "5.4.1.4 | PATCH | Ensure strong password hashing algorithm is configured" - when: - - rhel9cis_rule_5_4_1_4 + when: rhel9cis_rule_5_4_1_4 tags: - level1-server - level1-workstation @@ -115,8 +112,7 @@ line: 'ENCRYPT_METHOD {{ rhel9cis_passwd_hash_algo | upper }}' - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured" - when: - - rhel9cis_rule_5_4_1_5 + when: rhel9cis_rule_5_4_1_5 tags: - level1-server - level1-workstation @@ -132,23 +128,24 @@ register: discovered_passwdlck_inactive_settings - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting" - ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} + ansible.builtin.command: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} + changed_when: true when: discovered_passwdlck_inactive_settings.stdout | length == 0 - name: "5.4.1.5 | 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" + ansible.builtin.command: "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: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" when: item in prelim_interactive_usernames.stdout - ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" + ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" + changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past" - when: - - rhel9cis_rule_5_4_1_6 + when: rhel9cis_rule_5_4_1_6 tags: - level1-server - level1-workstation @@ -172,22 +169,23 @@ register: discovered_passwdlck_user_future - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" + when: + - discovered_passwdlck_user_future.stdout | length > 0 + - not rhel9cis_futurepwchgdate_autofix ansible.builtin.debug: msg: "Warning!! The following accounts have the last PW change date in the future: {{ discovered_passwdlck_user_future.stdout_lines }}" - when: - - discovered_passwdlck_user_future.stdout | length > 0 - - not rhel9cis_futurepwchgdate_autofix - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml when: - discovered_passwdlck_user_future.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix + ansible.builtin.import_tasks: + file: warning_facts.yml - name: "5.4.1.6 | 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: - discovered_passwdlck_user_future.stdout | length > 0 - rhel9cis_futurepwchgdate_autofix + ansible.builtin.command: passwd --expire {{ item }} + changed_when: true loop: "{{ discovered_passwdlck_user_future.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 2cf378c..0153820 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -17,7 +17,7 @@ - NIST800-53R5_CM-6 - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 - ansible.builtin.shell: passwd -l {{ item }} + ansible.builtin.command: passwd -l {{ item }} changed_when: false failed_when: false loop: "{{ prelim_uid_zero_accounts_except_root.stdout_lines }}" @@ -56,8 +56,7 @@ loop: "{{ discovered_gid0_members.stdout_lines }}" - name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group" - when: - - rhel9cis_rule_5_4_2_3 + when: rhel9cis_rule_5_4_2_3 tags: - level1-server - level1-workstation @@ -96,8 +95,7 @@ warn_control_id: '5.4.2.3' - name: "5.4.2.4 | PATCH | Ensure root account access is controlled " - when: - - rhel9cis_rule_5_4_2_4 + when: rhel9cis_rule_5_4_2_4 tags: - level1-server - level1-workstation @@ -108,8 +106,7 @@ msg: "This is set as an assert in tasks/main" - name: "5.4.2.5 | PATCH | Ensure root PATH Integrity" - when: - - rhel9cis_rule_5_4_2_5 + when: rhel9cis_rule_5_4_2_5 tags: - level1-server - level1-workstation @@ -172,15 +169,14 @@ state: directory owner: root group: root - mode: '0755' + mode: 'go-w' follow: false loop: "{{ discovered_root_path_perms.results }}" loop_control: label: "{{ item }}" - name: "5.4.2.6 | PATCH | Ensure root user umask is configured" - when: - - rhel9cis_rule_5_4_2_6 + when: rhel9cis_rule_5_4_2_6 tags: - level1-server - level1-workstation @@ -194,6 +190,9 @@ regexp: \s*umask line: "umask {{ rhel9cis_root_umask }}" create: true + owner: root + group: root + mode: 'go-rwx' - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: diff --git a/tasks/section_5/cis_5.4.3.x.yml b/tasks/section_5/cis_5.4.3.x.yml index 7816938..109b6a5 100644 --- a/tasks/section_5/cis_5.4.3.x.yml +++ b/tasks/section_5/cis_5.4.3.x.yml @@ -1,8 +1,7 @@ --- - name: "5.4.3.1 | PATCH | Ensure nologin is not listed in /etc/shells" - when: - - rhel9cis_rule_5_4_3_1 + when: rhel9cis_rule_5_4_3_1 tags: - level2-server - level2-workstation @@ -20,8 +19,7 @@ replace: "" - name: "5.4.3.2 | PATCH | Ensure default user shell timeout is configured" - when: - - rhel9cis_rule_5_4_3_2 + when: rhel9cis_rule_5_4_3_2 tags: - level1-server - level1-workstation @@ -33,7 +31,7 @@ state: "{{ item.state }}" marker: "# {mark} - CIS benchmark - Ansible-lockdown" create: true - mode: '0644' + mode: 'go-wx' block: | TMOUT={{ rhel9cis_shell_session_timeout }} readonly TMOUT @@ -43,8 +41,7 @@ - { path: /etc/profile, state: "{{ (rhel9cis_shell_session_file == '/etc/profile') | ternary('present', 'absent') }}" } - name: "5.4.3.3 | PATCH | Ensure default user umask is configured" - when: - - rhel9cis_rule_5_4_3_3 + when: rhel9cis_rule_5_4_3_3 tags: - level1-server - level1-workstation diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 898444f..5896695 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -19,10 +19,11 @@ register: discovered_aide_installed - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - when: discovered_aide_installed.changed # noqa: no-handler + when: discovered_aide_installed.changed # noqa no-handler block: - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - ansible.builtin.shell: /usr/sbin/aide --init + ansible.builtin.command: /usr/sbin/aide --init + changed_when: true - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB | Wait for file before continuing" ansible.builtin.wait_for: @@ -33,6 +34,7 @@ src: /var/lib/aide/aide.db.new.gz dest: /var/lib/aide/aide.db.gz remote_src: true + mode: 'go-wx' - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: @@ -62,15 +64,15 @@ - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd: + ansible.builtin.systemd_service: name: aidecheck.service enabled: true - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd: + ansible.builtin.systemd_service: name: aidecheck.timer - state: running + state: started enabled: true - name: "6.1.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 1a2a8aa..3afa31c 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -1,8 +1,7 @@ --- - name: "6.2.1.1 | PATCH | Ensure journald service is enabled and active" - when: - - rhel9cis_rule_6_2_1_1 + when: rhel9cis_rule_6_2_1_1 tags: - level1-server - level1-workstation @@ -15,8 +14,7 @@ state: started - name: "6.2.1.2 | PATCH | Ensure journald log file access is configured" - when: - - rhel9cis_rule_6_2_1_2 + when: rhel9cis_rule_6_2_1_2 tags: - level1-server - level1-workstation @@ -27,7 +25,7 @@ - name: "6.2.1.2 | PATCH | Ensure journald log file access is configured | Default file permissions" ansible.builtin.file: path: /usr/lib/tmpfiles.d/systemd.conf - mode: '0640' + mode: 'g-wx,o-rwx' - name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Check for override file" ansible.builtin.stat: @@ -58,8 +56,7 @@ warn_control_id: '6.2.1.2' - name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured" - when: - - rhel9cis_rule_6_2_1_3 + when: rhel9cis_rule_6_2_1_3 tags: - level1-server - level1-workstation @@ -74,7 +71,7 @@ dest: /etc/systemd/journald.conf.d/rotation.conf owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' - name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured | comment out current entries" ansible.builtin.replace: @@ -89,8 +86,7 @@ - '^(\s*MaxFileSec\s*=.*)' - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use" - when: - - rhel9cis_rule_6_2_1_4 + when: rhel9cis_rule_6_2_1_4 tags: - level1-server - level1-workstation diff --git a/tasks/section_6/cis_6.2.2.x.yml b/tasks/section_6/cis_6.2.2.x.yml index 3dd8dab..a57efe2 100644 --- a/tasks/section_6/cis_6.2.2.x.yml +++ b/tasks/section_6/cis_6.2.2.x.yml @@ -1,8 +1,7 @@ --- - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled" - when: - - rhel9cis_rule_6_2_2_2 + when: rhel9cis_rule_6_2_2_2 tags: - level1-server - level2-workstation @@ -21,7 +20,7 @@ dest: /etc/systemd/journald.conf.d/forwardtosyslog.conf owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' - name: "6.2.2.2 | PATCH | Ensure journald ForwardToSyslog is disabled | comment out current entries" ansible.builtin.replace: @@ -30,8 +29,7 @@ replace: '#\1' - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured" - when: - - rhel9cis_rule_6_2_2_3 + when: rhel9cis_rule_6_2_2_3 tags: - level1-server - level1-workstation @@ -47,7 +45,7 @@ dest: /etc/systemd/journald.conf.d/storage.conf owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" ansible.builtin.replace: @@ -56,8 +54,7 @@ replace: '#\1' - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" - when: - - rhel9cis_rule_6_2_2_4 + when: rhel9cis_rule_6_2_2_4 tags: - level1-server - level1-workstation @@ -74,7 +71,7 @@ dest: /etc/systemd/journald.conf.d/storage.conf owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" ansible.builtin.replace: diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 5af5fcd..9333697 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -18,8 +18,7 @@ state: present - name: "6.2.3.2 | PATCH | Ensure rsyslog Service is enabled and active" - when: - - rhel9cis_rule_6_2_3_2 + when: rhel9cis_rule_6_2_3_2 tags: - level1-server - level1-workstation @@ -35,8 +34,7 @@ state: started - name: "6.2.3.3 | PATCH | Ensure journald is configured to send logs to rsyslog" - when: - - rhel9cis_rule_6_2_3_3 + when: rhel9cis_rule_6_2_3_3 tags: - level1-server - level1-workstation @@ -54,8 +52,7 @@ notify: Restart rsyslog - name: "6.2.3.4 | PATCH | Ensure rsyslog log file creation mode is configured" - when: - - rhel9cis_rule_6_2_3_4 + when: rhel9cis_rule_6_2_3_4 tags: - level1-server - level1-workstation @@ -72,8 +69,7 @@ notify: Restart rsyslog - name: "6.2.3.5 | PATCH | Ensure logging is configured" - when: - - rhel9cis_rule_6_2_3_5 + when: rhel9cis_rule_6_2_3_5 tags: - level1-server - level1-workstation @@ -200,8 +196,7 @@ notify: Restart rsyslog - name: "6.2.3.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client" - when: - - rhel9cis_rule_6_2_3_7 + when: rhel9cis_rule_6_2_3_7 tags: - level1-server - level1-workstation @@ -238,8 +233,7 @@ - 'InputTCPServerRun' - name: "6.2.3.8 | PATCH | Ensure rsyslog logrotate is configured" - when: - - rhel9cis_rule_6_2_3_8 + when: rhel9cis_rule_6_2_3_8 tags: - level1-server - level1-workstation @@ -266,4 +260,4 @@ dest: /etc/logrotate.d/rsyslog.conf owner: root group: root - mode: '0640' + mode: 'g-wx,o-rwx' diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index 8111ef4..814c46c 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -1,8 +1,7 @@ --- - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured" - when: - - rhel9cis_rule_6_2_4_1 + when: rhel9cis_rule_6_2_4_1 tags: - level1-server - level1-workstation diff --git a/tasks/section_6/cis_6.3.1.x.yml b/tasks/section_6/cis_6.3.1.x.yml index 3039f2c..b27ba99 100644 --- a/tasks/section_6/cis_6.3.1.x.yml +++ b/tasks/section_6/cis_6.3.1.x.yml @@ -27,8 +27,7 @@ state: present - name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" - when: - - rhel9cis_rule_6_3_1_2 + when: rhel9cis_rule_6_3_1_2 tags: - level2-server - level2-workstation @@ -49,11 +48,11 @@ - discovered_grubby_curr_value_audit_linux.stdout == '' or '0' in discovered_grubby_curr_value_audit_linux.stdout or 'off' in discovered_grubby_curr_value_audit_linux.stdout|lower - ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1" + ansible.builtin.command: grubby --update-kernel=ALL --args="audit=1" + changed_when: true - name: "6.3.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" - when: - - rhel9cis_rule_6_3_1_3 + when: rhel9cis_rule_6_3_1_3 tags: - level2-server - level2-workstation @@ -81,21 +80,18 @@ discovered_reset_backlog_limits: true - name: "6.3.1.3 | AUDIT | Check to see if any limits are too low" - when: - - (item | int < rhel9cis_audit_back_log_limit) + when: (item | int < rhel9cis_audit_back_log_limit) ansible.builtin.set_fact: discovered_reset_backlog_limits: true loop: "{{ discovered_grubby_curr_value_backlog_linux.stdout_lines }}" - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" - when: - - discovered_reset_backlog_limits is defined - ansible.builtin.shell: - cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' + when: discovered_reset_backlog_limits is defined + ansible.builtin.command: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' + changed_when: true - name: "6.3.1.4 | PATCH | Ensure auditd service is enabled and active" - when: - - rhel9cis_rule_6_3_1_4 + when: rhel9cis_rule_6_3_1_4 tags: - level2-server - level2-workstation diff --git a/tasks/section_6/cis_6.3.2.x.yml b/tasks/section_6/cis_6.3.2.x.yml index 08a5365..dc0804f 100644 --- a/tasks/section_6/cis_6.3.2.x.yml +++ b/tasks/section_6/cis_6.3.2.x.yml @@ -1,8 +1,7 @@ --- - name: "6.3.2.1 | PATCH | Ensure audit log storage size is configured" - when: - - rhel9cis_rule_6_3_2_1 + when: rhel9cis_rule_6_3_2_1 tags: - level2-server - level2-workstation @@ -17,8 +16,7 @@ notify: Restart auditd - name: "6.3.2.2 | PATCH | Ensure audit logs are not automatically deleted" - when: - - rhel9cis_rule_6_3_2_2 + when: rhel9cis_rule_6_3_2_2 tags: - level2-server - level2-workstation @@ -33,8 +31,7 @@ notify: Restart auditd - name: "6.3.2.3 | PATCH | Ensure system is disabled when audit logs are full" - when: - - rhel9cis_rule_6_3_2_3 + when: rhel9cis_rule_6_3_2_3 tags: - level2-server - level2-workstation @@ -55,8 +52,7 @@ - { regexp: '^disk_error_action', line: 'disk_error_action = {{ rhel9cis_auditd_disk_error_action }}' } - name: "6.3.2.4 | PATCH | Ensure system warns when audit logs are low on space" - when: - - rhel9cis_rule_6_3_2_4 + when: rhel9cis_rule_6_3_2_4 tags: - level2-server - level2-workstation diff --git a/tasks/section_6/cis_6.3.3.x.yml b/tasks/section_6/cis_6.3.3.x.yml index d279259..5ff73f9 100644 --- a/tasks/section_6/cis_6.3.3.x.yml +++ b/tasks/section_6/cis_6.3.3.x.yml @@ -2,8 +2,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected" - when: - - rhel9cis_rule_6_3_3_1 + when: rhel9cis_rule_6_3_3_1 tags: - level2-server - level2-workstation @@ -16,8 +15,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.2 | PATCH | Ensure actions as another user are always logged" - when: - - rhel9cis_rule_6_3_3_2 + when: rhel9cis_rule_6_3_3_2 tags: - level2-server - level2-workstation @@ -30,8 +28,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.3 | PATCH | Ensure events that modify the sudo log file are collected" - when: - - rhel9cis_rule_6_3_3_3 + when: rhel9cis_rule_6_3_3_3 tags: - level2-server - level2-workstation @@ -43,8 +40,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.4 | PATCH | Ensure events that modify date and time information are collected" - when: - - rhel9cis_rule_6_3_3_4 + when: rhel9cis_rule_6_3_3_4 tags: - level2-server - level2-workstation @@ -58,8 +54,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.5 | PATCH | Ensure events that modify the system's network environment are collected" - when: - - rhel9cis_rule_6_3_3_5 + when: rhel9cis_rule_6_3_3_5 tags: - level2-server - level2-workstation @@ -73,8 +68,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.6 | PATCH | Ensure use of privileged commands is collected" - when: - - rhel9cis_rule_6_3_3_6 + when: rhel9cis_rule_6_3_3_6 tags: - level2-server - level2-workstation @@ -97,8 +91,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.7 | PATCH | Ensure unsuccessful file access attempts are collected" - when: - - rhel9cis_rule_6_3_3_7 + when: rhel9cis_rule_6_3_3_7 tags: - level2-server - level2-workstation @@ -111,8 +104,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.8 | PATCH | Ensure events that modify user/group information are collected" - when: - - rhel9cis_rule_6_3_3_8 + when: rhel9cis_rule_6_3_3_8 tags: - level2-server - level2-workstation @@ -125,8 +117,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.9 | PATCH | Ensure discretionary access control permission modification events are collected" - when: - - rhel9cis_rule_6_3_3_9 + when: rhel9cis_rule_6_3_3_9 tags: - level2-server - level2-workstation @@ -140,8 +131,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.10 | PATCH | Ensure successful file system mounts are collected" - when: - - rhel9cis_rule_6_3_3_10 + when: rhel9cis_rule_6_3_3_10 tags: - level2-server - level2-workstation @@ -154,8 +144,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.11 | PATCH | Ensure session initiation information is collected" - when: - - rhel9cis_rule_6_3_3_11 + when: rhel9cis_rule_6_3_3_11 tags: - level2-server - level2-workstation @@ -168,8 +157,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.12 | PATCH | Ensure login and logout events are collected" - when: - - rhel9cis_rule_6_3_3_12 + when: rhel9cis_rule_6_3_3_12 tags: - level2-server - level2-workstation @@ -182,8 +170,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.13 | PATCH | Ensure file deletion events by users are collected" - when: - - rhel9cis_rule_6_3_3_13 + when: rhel9cis_rule_6_3_3_13 tags: - level2-server - level2-workstation @@ -197,8 +184,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected" - when: - - rhel9cis_rule_6_3_3_14 + when: rhel9cis_rule_6_3_3_14 tags: - level2-server - level2-workstation @@ -212,8 +198,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded" - when: - - rhel9cis_rule_6_3_3_15 + when: rhel9cis_rule_6_3_3_15 tags: - level2-server - level2- workstation @@ -228,8 +213,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded" - when: - - rhel9cis_rule_6_3_3_16 + when: rhel9cis_rule_6_3_3_16 tags: - level2-server - level2-workstation @@ -244,8 +228,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded" - when: - - rhel9cis_rule_6_3_3_17 + when: rhel9cis_rule_6_3_3_17 tags: - level2-server - level2-workstation @@ -260,8 +243,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded" - when: - - rhel9cis_rule_6_3_3_18 + when: rhel9cis_rule_6_3_3_18 tags: - level2-server - level2-workstation @@ -276,8 +258,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.19 | PATCH | Ensure kernel module loading and unloading and modification is collected" - when: - - rhel9cis_rule_6_3_3_19 + when: rhel9cis_rule_6_3_3_19 tags: - level2-server - level2-workstation @@ -291,8 +272,7 @@ # All changes selected are managed by the POST audit and handlers to update - name: "6.3.3.20 | PATCH | Ensure the audit configuration is immutable" - when: - - rhel9cis_rule_6_3_3_20 + when: rhel9cis_rule_6_3_3_20 tags: - level2-server - level2-workstation @@ -306,8 +286,7 @@ update_audit_template: true - name: "6.3.3.21 | AUDIT | Ensure the running and on disk configuration is the same" - when: - - rhel9cis_rule_6_3_3_21 + when: rhel9cis_rule_6_3_3_21 tags: - level2-server - level2-workstation @@ -321,8 +300,7 @@ - "Please run augenrules --load if you suspect there is a configuration that is not active" - name: Auditd | 6.3.3.x | Auditd controls updated - when: - - update_audit_template + 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 diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index c89af87..806a1ec 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -1,8 +1,7 @@ --- - name: "6.3.4.1 | PATCH | Ensure the audit log file directory mode is configured" - when: - - rhel9cis_rule_6_3_4_1 + when: rhel9cis_rule_6_3_4_1 tags: - level2-server - level2-workstation @@ -39,8 +38,7 @@ group: root - name: "6.3.4.5 | PATCH | Ensure audit configuration files mode is configured" - when: - - rhel9cis_rule_6_3_4_5 + when: rhel9cis_rule_6_3_4_5 tags: - level2-server - level2-workstation @@ -57,8 +55,7 @@ label: "{{ item.path }}" - name: "6.3.4.6 | PATCH | Ensure audit configuration files owner is configured" - when: - - rhel9cis_rule_6_3_4_6 + when: rhel9cis_rule_6_3_4_6 tags: - level2-server - level2-workstation @@ -75,8 +72,7 @@ label: "{{ item.path }}" - name: "6.3.4.7 | PATCH | Ensure audit configuration files group owner is configured" - when: - - rhel9cis_rule_6_3_4_7 + when: rhel9cis_rule_6_3_4_7 tags: - level2-server - level2-workstation @@ -93,8 +89,7 @@ label: "{{ item.path }}" - name: "6.3.4.8 | PATCH | Ensure audit tools mode is configured" - when: - - rhel9cis_rule_6_3_4_8 + when: rhel9cis_rule_6_3_4_8 tags: - level2-server - level2-workstation @@ -114,8 +109,7 @@ - /sbin/augenrules - name: "6.3.4.9 | PATCH | Ensure audit tools owner is configured" - when: - - rhel9cis_rule_6_3_4_9 + when: rhel9cis_rule_6_3_4_9 tags: - level2-server - level2-workstation @@ -135,8 +129,7 @@ - /sbin/augenrules - name: "6.3.4.10 | PATCH | Ensure audit tools group owner is configured" - when: - - rhel9cis_rule_6_3_4_10 + when: rhel9cis_rule_6_3_4_10 tags: - level2-server - level2-workstation diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 232b224..83c83a0 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -83,7 +83,7 @@ path: /etc/shadow owner: root group: root - mode: '0000' + mode: 'ugo-rwx' - name: "7.1.6 | PATCH | Ensure permissions on /etc/shadow- are configured" when: @@ -100,7 +100,7 @@ path: /etc/shadow- owner: root group: root - mode: '0000' + mode: 'ugo-rwx' - name: "7.1.7 | PATCH | Ensure permissions on /etc/gshadow are configured" when: @@ -117,7 +117,7 @@ path: /etc/gshadow owner: root group: root - mode: '0000' + mode: 'ugo-rwx' - name: "7.1.8 | PATCH | Ensure permissions on /etc/gshadow- are configured" when: @@ -134,7 +134,7 @@ path: /etc/gshadow- owner: root group: root - mode: '0000' + mode: 'ugo-rwx' - name: "7.1.9 | PATCH | Ensure permissions on /etc/shells are configured" when: @@ -196,7 +196,7 @@ - rhel9cis_no_world_write_adjust ansible.builtin.file: path: '{{ item }}' - mode: o-w + mode: 'o-w' state: touch loop: "{{ discovered_world_writable.stdout_lines }}" @@ -221,7 +221,7 @@ warn_control_id: '7.1.12' block: - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Get list files or directories" - ansible.builtin.shell: find {{ rhel9cis_exclude_unowned_search_path }} {{ item.mount }} -xdev \( -nouser -o -nogroup \) -not -fstype nfs + ansible.builtin.command: find {{ rhel9cis_exclude_unowned_search_path }} {{ item.mount }} -xdev \( -nouser -o -nogroup \) -not -fstype nfs changed_when: false failed_when: false check_mode: false @@ -283,7 +283,7 @@ warn_control_id: '7.1.13' block: - name: "7.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find SUID and SGID" - ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm \( -02000 or -04000 \) -not -fstype nfs + ansible.builtin.command: find {{ item.mount }} -xdev -type f -perm \( -02000 or -04000 \) -not -fstype nfs changed_when: false failed_when: false check_mode: false diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 47d48f6..28c7fc6 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -237,7 +237,7 @@ - users - rule_7.2.8 block: - - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Create dir if absent" + - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Create dir if absent" # noqa risky-file-permissions ansible.builtin.file: path: "{{ item.dir }}" state: directory diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 98cd4b6..b70a836 100644 --- a/tasks/warning_facts.yml +++ b/tasks/warning_facts.yml @@ -1,5 +1,4 @@ --- - # This task is used to create variables used in giving a warning summary for manual tasks # that need attention # @@ -14,7 +13,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 }} | AUDIT | Set fact for manual task warning." # noqa name[template] ansible.builtin.set_fact: warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" warn_count: "{{ warn_count | int + 1 }}" diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 0f4a4f9..70ebd03 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index bf2d191..e977e4e 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### 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 diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index db93323..4c1af92 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,7 @@ # Run AIDE integrity check ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index efebeac..0e55b5a 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index 4506f4f..cf9ed5d 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 78ad883..640538c 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [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 index 81bdfea..382469c 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [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 index acfeaee..a747336 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index d6c5d70..5988316 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index c7ae76e..901e9e0 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company [org/gnome/login-screen] banner-message-enable=true diff --git a/templates/fs_with_cves.sh b/templates/fs_with_cves.sh index 89ba49b..a6d937c 100644 --- a/templates/fs_with_cves.sh +++ b/templates/fs_with_cves.sh @@ -1,11 +1,8 @@ -{% raw %} -#! /usr/bin/env bash +{% raw %}#! /usr/bin/env bash # Based on original Script provided by CIS # CVEs correct at time of creation - April2024 -#! /usr/bin/env bash - { a_output=(); a_output2=(); a_modprope_config=(); a_excluded=(); a_available_modules=() a_ignore=("xfs" "vfat" "ext2" "ext3" "ext4") diff --git a/vars/audit.yml b/vars/audit.yml index e54deb8..1dc1cf1 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -35,7 +35,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results}} + 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 }} From 95cf8b94925ce868dd2ad6a96fd1c4f3883a223f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 10:09:46 +0000 Subject: [PATCH 116/327] updated auditd handlers for restart Signed-off-by: Mark Bolwell --- handlers/main.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 27e4a56..d7f49d9 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -107,8 +107,15 @@ msg: "Reboot required for auditd to apply new rules as immutable set" notify: Change_requires_reboot -- name: Restart auditd - ansible.builtin.shell: service auditd restart +- name: Stop auditd process + ansible.builtin.shell: systemctl kill auditd + listen: Restart auditd + +- name: Start auditd process + ansible.builtin.systemd_service: + name: auditd + state: started + listen: Restart auditd - name: Change_requires_reboot ansible.builtin.set_fact: From 0a8d8abf1e8a041cfa47501f1dff3d4490f86279 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 10:10:09 +0000 Subject: [PATCH 117/327] Changed warning if auditd template updated Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 502497c..7022e2c 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -26,7 +26,7 @@ ansible.builtin.import_tasks: file: warning_facts.yml vars: - warn_control_id: 'Auditd template updated, see diff output for details' + warn_control_id: 'Auditd template updated, validate as expected' - name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file ansible.builtin.stat: From a6ce1ef1bf9a492d4ee61b9a57c6413ca430069a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 10:18:09 +0000 Subject: [PATCH 118/327] updated auditd restart handler Signed-off-by: Mark Bolwell --- handlers/main.yml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index c302106..31e784d 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -98,8 +98,15 @@ when: - auditd_immutable_check.stdout == '1' -- name: Restart auditd - ansible.builtin.shell: service auditd restart +- name: Stop auditd process + ansible.builtin.shell: systemctl kill auditd + listen: Restart auditd + +- name: Start auditd process + ansible.builtin.systemd_service: + name: auditd + state: started + listen: Restart auditd - name: Change_requires_reboot ansible.builtin.set_fact: From 088cd51931f2b07d8d655903615cbb0292523cfd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 10:18:25 +0000 Subject: [PATCH 119/327] Updated auditd template changed warning Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 62f2794..82ee5de 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -23,7 +23,7 @@ ansible.builtin.import_tasks: file: warning_facts.yml vars: - warn_control_id: 'Auditd template updated, see diff output for details' + warn_control_id: 'Auditd template updated, validate as expected' when: - rhel9cis_auditd_template_updated.changed - rhel9cis_auditd_file.stat.exists From 7a780a4702e358aa13d8dfdbb2f08d00bd67d769 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 10:29:50 +0000 Subject: [PATCH 120/327] updated for lint Signed-off-by: Mark Bolwell --- handlers/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 31e784d..cea6940 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -104,8 +104,8 @@ - name: Start auditd process ansible.builtin.systemd_service: - name: auditd - state: started + name: auditd + state: started listen: Restart auditd - name: Change_requires_reboot From f3ef69d54c397a72960161b85481eb176008135b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 16:43:27 +0000 Subject: [PATCH 121/327] updated lint files Signed-off-by: Mark Bolwell --- .ansible-lint | 17 ++--------------- .pre-commit-config.yaml | 18 ++++++++++++------ .yamllint | 21 +++++++++++++-------- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/.ansible-lint b/.ansible-lint index 3090307..3b7c373 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -3,20 +3,7 @@ parseable: true quiet: true skip_list: - - 'schema' - - 'no-changed-when' - - 'var-spacing' - - 'experimental' - - 'name[play]' - - 'name[casing]' - - 'name[template]' - - 'key-order[task]' - - '204' - - '305' - - '303' - - '403' - - '306' - - '602' - - '208' + - 'package-latest' + - 'risky-shell-pipe' use_default_rules: true verbosity: 0 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e53f665..acdd896 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,16 +7,21 @@ ci: repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.6.0 + rev: v5.0.0 hooks: # Safety - id: detect-aws-credentials + name: Detect AWS Credentials - id: detect-private-key + name: Detect Private Keys # git checks - id: check-merge-conflict + name: Check for merge conflicts - id: check-added-large-files + name: Check for Large files - id: check-case-conflict + name: Check case conflict # General checks - id: trailing-whitespace @@ -27,21 +32,21 @@ repos: types: [text] args: [--markdown-linebreak-ext=md] - id: end-of-file-fixer + name: Ensure line at end of file # Scan for passwords - repo: https://github.com/Yelp/detect-secrets rev: v1.5.0 hooks: - id: detect-secrets - exclude: templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 - repo: https://github.com/gitleaks/gitleaks - rev: v8.18.4 + rev: v8.21.2 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.7.0 + rev: v24.10.0 hooks: - id: ansible-lint name: Ansible-lint @@ -52,14 +57,15 @@ repos: # https://github.com/ansible/ansible-lint/issues/611 pass_filenames: false always_run: true - additional_dependencies: + # additional_dependencies: # https://github.com/pre-commit/pre-commit/issues/1526 # If you want to use specific version of ansible-core or ansible, feel # free to override `additional_dependencies` in your own hook config # file. - - ansible-core>=2.10.1 + # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git rev: v1.35.1 # or higher tag hooks: - id: yamllint + name: Check YAML Lint diff --git a/.yamllint b/.yamllint index ec2d1cd..fa7b697 100644 --- a/.yamllint +++ b/.yamllint @@ -1,32 +1,37 @@ --- extends: default - ignore: | tests/ molecule/ .github/ .gitlab-ci.yml *molecule.yml - rules: - indentation: - # Requiring 4 space indentation - spaces: 2 - # Requiring consistent indentation within a file, either indented or not - indent-sequences: consistent braces: max-spaces-inside: 1 level: error brackets: max-spaces-inside: 1 level: error + comments: + ignore-shebangs: true + min-spaces-from-content: 1 # prettier compatibility + comments-indentation: enable empty-lines: max: 1 - line-length: disable + indentation: + # Requiring 2 space indentation + spaces: 2 + # Requiring consistent indentation within a file, either indented or not + indent-sequences: consistent key-duplicates: enable + line-length: disable new-line-at-end-of-file: enable new-lines: type: unix + octal-values: + forbid-implicit-octal: true # yamllint defaults to false + forbid-explicit-octal: true trailing-spaces: enable truthy: allowed-values: ['true', 'false'] From b4afeab63878df54cc1447f9898d3ddc9e75252a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 16:44:14 +0000 Subject: [PATCH 122/327] updated title Signed-off-by: Mark Bolwell --- LICENSE | 2 +- templates/audit/98_auditd_exception.rules.j2 | 2 +- templates/audit/99_auditd.rules.j2 | 2 +- templates/etc/cron.d/aide.cron.j2 | 2 +- templates/etc/dconf/db/00-automount_lock.j2 | 2 +- templates/etc/dconf/db/00-autorun_lock.j2 | 2 +- templates/etc/dconf/db/00-media-automount.j2 | 2 +- templates/etc/dconf/db/00-media-autorun.j2 | 2 +- templates/etc/dconf/db/00-screensaver.j2 | 2 +- templates/etc/dconf/db/00-screensaver_lock.j2 | 2 +- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/LICENSE b/LICENSE index f6d2b57..bb487ce 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases +2025 Mindpoint Group - A Tyto Athene Company / Ansible Lockdown Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/templates/audit/98_auditd_exception.rules.j2 b/templates/audit/98_auditd_exception.rules.j2 index 0f4a4f9..82f6555 100644 --- a/templates/audit/98_auditd_exception.rules.j2 +++ b/templates/audit/98_auditd_exception.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### YOUR CHANGES WILL BE LOST! # This file contains users whose actions are not logged by auditd diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index bf2d191..6d69976 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### 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 diff --git a/templates/etc/cron.d/aide.cron.j2 b/templates/etc/cron.d/aide.cron.j2 index db93323..f9324da 100644 --- a/templates/etc/cron.d/aide.cron.j2 +++ b/templates/etc/cron.d/aide.cron.j2 @@ -1,7 +1,7 @@ # Run AIDE integrity check ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown ### YOUR CHANGES WILL BE LOST! # CIS 1.3.2 diff --git a/templates/etc/dconf/db/00-automount_lock.j2 b/templates/etc/dconf/db/00-automount_lock.j2 index efebeac..45989d0 100644 --- a/templates/etc/dconf/db/00-automount_lock.j2 +++ b/templates/etc/dconf/db/00-automount_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop media-handling automount setting /org/gnome/desktop/media-handling/automount diff --git a/templates/etc/dconf/db/00-autorun_lock.j2 b/templates/etc/dconf/db/00-autorun_lock.j2 index 4506f4f..60265c4 100644 --- a/templates/etc/dconf/db/00-autorun_lock.j2 +++ b/templates/etc/dconf/db/00-autorun_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop media-handling settings /org/gnome/desktop/media-handling/autorun-never diff --git a/templates/etc/dconf/db/00-media-automount.j2 b/templates/etc/dconf/db/00-media-automount.j2 index 78ad883..96c122f 100644 --- a/templates/etc/dconf/db/00-media-automount.j2 +++ b/templates/etc/dconf/db/00-media-automount.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [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 index 81bdfea..0e371af 100644 --- a/templates/etc/dconf/db/00-media-autorun.j2 +++ b/templates/etc/dconf/db/00-media-autorun.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [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 index acfeaee..95237fb 100644 --- a/templates/etc/dconf/db/00-screensaver.j2 +++ b/templates/etc/dconf/db/00-screensaver.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Specify the dconf path [org/gnome/desktop/session] diff --git a/templates/etc/dconf/db/00-screensaver_lock.j2 b/templates/etc/dconf/db/00-screensaver_lock.j2 index d6c5d70..1b99027 100644 --- a/templates/etc/dconf/db/00-screensaver_lock.j2 +++ b/templates/etc/dconf/db/00-screensaver_lock.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown # Lock desktop screensaver idle-delay setting /org/gnome/desktop/session/idle-delay diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index c7ae76e..da31670 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -1,6 +1,6 @@ ## Ansible controlled file # Added as part of ansible-lockdown CIS baseline -# provided by MindPointGroup LLC +# provided by Mindpoint Group - A Tyto Athene Company / Ansible Lockdown [org/gnome/login-screen] banner-message-enable=true From 2827c752ac821b01eab3836caeed00be839c85ac Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 16:45:49 +0000 Subject: [PATCH 123/327] aide variablizing Signed-off-by: Mark Bolwell --- defaults/main.yml | 13 ++++++++++-- tasks/section_6/cis_6.1.x.yml | 37 ++++++++++++++++++++++++++++++----- vars/main.yml | 12 ++++++++++++ 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index e210596..32bb5af 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1034,8 +1034,7 @@ min_int_uid: 1000 max_int_uid: 65533 ## Section6 vars - -## Control 6.1.1 - allow aide to be configured +## Control 6.1.x - allow aide to be configured # AIDE is a file integrity checking tool, similar in nature to Tripwire. # While it cannot prevent intrusions, it can detect unauthorized changes # to configuration files by alerting when the files are changed. Review @@ -1043,6 +1042,16 @@ max_int_uid: 65533 # By setting this variable to `true`, all of the settings related to AIDE will be applied! rhel9cis_config_aide: true +# If DB file older than below will automatically rebuild DB +# e.g. options:1w = 1 week, 1d = 1day 1h = 1 hour +rhel9cis_aide_db_file_age: 1w + +# If aide already setup this forces a new DB to be created +rhel9cis_aide_db_recreate: false + +# allows to change db file, not config need to be adjusted too +rhel9cis_aide_db_file: /var/lib/aide/aide.db + ## Control 6.1.2 AIDE cron settings ## How the aide schedule is run either cron or timer diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 898444f..950ca5e 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -12,17 +12,44 @@ - rule_6.1.1 - NIST800-53R5_AU-2 block: + block: - name: "6.1.1 | PATCH | Ensure AIDE is installed" + when: + - "'aide' not in ansible_facts.packages or + 'aide-common' not in ansible_facts.packages" ansible.builtin.package: - name: aide + name: ['aide', 'aide-common'] state: present - register: discovered_aide_installed + update_cache: true + register: discovered_aide_pkg_added - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - when: discovered_aide_installed.changed # noqa: no-handler + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Recapture packages" + when: discovered_aide_pkg_added.skipped is not defined + ansible.builtin.package_facts: + manager: auto + + - name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check file exists" + ansible.builtin.stat: + path: "{{ rhel9cis_aide_db_file }}" + register: discovered_aide_db_file + + - name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check current db file age" + when: discovered_aide_db_file.stat.exists + ansible.builtin.find: + path: "{{ rhel9cis_aide_db_file | dirname }}" + pattern: "{{ rhel9cis_aide_db_file | basename }}" + age: "{{ rhel9cis_aide_db_file_age }}" + register: discovered_aide_db_age + + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Configure AIDE" + when: + - not ansible_check_mode + - not discovered_aide_db_file.stat.exists or + (discovered_aide_db_age.files | length > 0) or + rhel9cis_aide_db_recreate block: - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" - ansible.builtin.shell: /usr/sbin/aide --init + ansible.builtin.shell: "{{ aide_initiate_command }}" - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB | Wait for file before continuing" ansible.builtin.wait_for: diff --git a/vars/main.yml b/vars/main.yml index ec72d0b..679c5b9 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -44,3 +44,15 @@ container_vars_file: is_container.yml # rhel9cis is left off the front of this var for consistency in testing pipeline # system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks system_is_ec2: false + +# Aide initiate command for new DB creation +aide_initiate_command: aideinit -y -f + +# Audit vars +audit_bins: + - /sbin/auditctl + - /sbin/aureport + - /sbin/ausearch + - /sbin/autrace + - /sbin/auditd + - /sbin/augenrules From c5278da4e5a382438bd94575c94332c3e1e0c593 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 16:46:08 +0000 Subject: [PATCH 124/327] audit binaries variables Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.3.4.x.yml | 24 +++--------------------- 1 file changed, 3 insertions(+), 21 deletions(-) diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index c89af87..d55b4e8 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -105,13 +105,7 @@ ansible.builtin.file: path: "{{ item }}" mode: 'go-w' - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" - name: "6.3.4.9 | PATCH | Ensure audit tools owner is configured" when: @@ -126,13 +120,7 @@ path: "{{ item }}" owner: root group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" - name: "6.3.4.10 | PATCH | Ensure audit tools group owner is configured" when: @@ -147,10 +135,4 @@ ansible.builtin.file: path: "{{ item }}" group: root - loop: - - /sbin/auditctl - - /sbin/aureport - - /sbin/ausearch - - /sbin/autrace - - /sbin/auditd - - /sbin/augenrules + loop: "{{ audit_bins }}" From a3f8d4fe1fc4276735d967b8526e36efb3eee7f2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 16:46:17 +0000 Subject: [PATCH 125/327] layout update Signed-off-by: Mark Bolwell --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 985dec7..7551cc9 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ ## Configure a RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant -### Based on [ CIS RedHat Enterprise Linux 9 Benchmark v2.0.0 ](https://www.cisecurity.org/cis-benchmarks/) +### Based on [CIS RedHat Enterprise Linux 9 Benchmark v2.0.0](https://www.cisecurity.org/cis-benchmarks/) --- From bab28dda4518be1d8bcfdec8d49e26e1a312eacf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 17:28:49 +0000 Subject: [PATCH 126/327] Added further aide variable Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 10 +++------- vars/main.yml | 6 +++++- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 950ca5e..f889cd4 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -12,13 +12,9 @@ - rule_6.1.1 - NIST800-53R5_AU-2 block: - block: - name: "6.1.1 | PATCH | Ensure AIDE is installed" - when: - - "'aide' not in ansible_facts.packages or - 'aide-common' not in ansible_facts.packages" ansible.builtin.package: - name: ['aide', 'aide-common'] + name: "{{ aide_packages }}" state: present update_cache: true register: discovered_aide_pkg_added @@ -48,10 +44,10 @@ (discovered_aide_db_age.files | length > 0) or rhel9cis_aide_db_recreate block: - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB" + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB" ansible.builtin.shell: "{{ aide_initiate_command }}" - - name: "6.1.1 | PATCH | Ensure AIDE is installed| Build AIDE DB | Wait for file before continuing" + - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB | Wait for file before continuing" ansible.builtin.wait_for: path: /var/lib/aide/aide.db.new.gz diff --git a/vars/main.yml b/vars/main.yml index 679c5b9..93439ad 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -45,8 +45,12 @@ container_vars_file: is_container.yml # system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks system_is_ec2: false +# Aide Packages + +aide_packages: + - aide # Aide initiate command for new DB creation -aide_initiate_command: aideinit -y -f +aide_initiate_command: /usr/sbin/aide --init # Audit vars audit_bins: From fd97459b6a7b9c194406880e6b07af5065fad464 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 17:29:27 +0000 Subject: [PATCH 127/327] Updated mountpoints controls Signed-off-by: Mark Bolwell --- defaults/main.yml | 5 + handlers/main.yml | 148 +++++++++++++++++++++++++++++- tasks/prelim.yml | 29 +++++- tasks/section_1/cis_1.1.2.1.x.yml | 118 ++++++++++++++++-------- tasks/section_1/cis_1.1.2.2.x.yml | 96 +++++++++++++------ tasks/section_1/cis_1.1.2.3.x.yml | 82 +++++++++++------ tasks/section_1/cis_1.1.2.4.x.yml | 77 ++++++++++------ tasks/section_1/cis_1.1.2.5.x.yml | 97 ++++++++++++++------ tasks/section_1/cis_1.1.2.6.x.yml | 95 +++++++++++++------ tasks/section_1/cis_1.1.2.7.x.yml | 95 +++++++++++++------ 10 files changed, 628 insertions(+), 214 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 32bb5af..816eb11 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -495,6 +495,11 @@ rhel9cis_rule_7_2_9: true ## Section 1 vars +## Ability to enabe debug on mounts to assist in troubleshooting +# Mount point changes are set based upon facts created in Prelim +# these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. +rhel9cis_debug_mount_data: false + ## Control 1.1.2 # If set to `true`, rule will be implemented using the `tmp.mount` systemd-service, # otherwise fstab configuration will be used. diff --git a/handlers/main.yml b/handlers/main.yml index d7f49d9..96cc86e 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -1,6 +1,149 @@ --- # handlers file for RHEL9-CIS +- name: "Adding options for /tmp" + when: not rhel9cis_tmp_svc + vars: + mount_point: '/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /tmp" + +- name: "Remounting /tmp" + vars: + mount_point: '/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /tmp" + +- name: "Remounting /tmp systemd" + vars: + mount_point: '/tmp' + ansible.builtin.systemd: + name: tmp.mount + state: restarted + daemon_reload: true + listen: "Remount /tmp" + +- name: "Adding options for /dev/shm" + vars: + mount_point: '/dev/shm' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /dev/shm" + +- name: "Remounting /dev/shm" + vars: + mount_point: '/dev/shm' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /dev/shm" + +- name: "Adding options for /home" + vars: + mount_point: '/home' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /home" + +- name: "Remounting /home" + vars: + mount_point: '/home' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /home" + +- name: "Adding options for /var" + vars: + mount_point: '/var' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var" + +- name: "Remounting /var" + vars: + mount_point: '/var' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var" + +- name: "Adding options for /var/tmp" + vars: + mount_point: '/var/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/tmp" + +- name: "Remounting /var/tmp" + vars: + mount_point: '/var/tmp' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/tmp" + +- name: "Adding options for /var/log" + vars: + mount_point: '/var/log' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/log" + +- name: "Remounting /var/log" + vars: + mount_point: '/var/log' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/log" + +- name: "Adding options for /var/log/audit" + vars: + mount_point: '/var/log/audit' + ansible.posix.mount: + path: "{{ mount_point }}" + src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + state: present + fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + listen: "Remount /var/log/audit" + +- name: "Remounting /var/log/audit" + vars: + mount_point: '/var/log/audit' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + listen: "Remount /var/log/audit" + - name: Reload sysctl ansible.builtin.shell: sysctl --system @@ -31,11 +174,6 @@ masked: false state: reloaded -- name: Remount tmp - ansible.posix.mount: - path: /tmp - state: remounted - - name: Update Crypto Policy ansible.builtin.set_fact: rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}" diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 28292fb..36c70c8 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -58,12 +58,35 @@ name: python3-libselinux state: present -- name: "PRELIM | AUDIT | Section 1.1 | Create list of mount points" - tags: - - Always +- name: PRELIM | AUDIT | Section 1.1 | Create list of mount points + tags: always ansible.builtin.set_fact: mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" +- name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options + tags: always + block: + - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - call mount # noqa command-instead-of-module + ansible.builtin.shell: | + mount | awk '{print $1, $3, $5, $6}' + changed_when: false + register: mount_output + + - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact + ansible.builtin.set_fact: + mount_point_fs_and_options: >- + {%- set mount_point_fs_and_options = {} -%} + {%- for line in mount_output.stdout_lines -%} + {%- set fields = line.split() -%} + {%- set _ = mount_point_fs_and_options.update({fields[1]: {'src': fields[0], 'fs_type': fields[2], 'original_options': fields[3][1:-1].split(','), 'options': fields[3][1:-1].split(',')}}) -%} + {%- endfor -%} + {{ mount_point_fs_and_options }} + + - name: "PRELIM | AUDIT | Debug of mount variables to assist in troubleshooting" + when: rhel9cis_debug_mount_data + ansible.builtin.debug: + msg: "{{ mount_point_fs_and_options }}" + - name: "PRELIM | PATCH | Update to latest gpg keys" when: - rhel9cis_rule_1_2_1_1 diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 5683cde..a2adce0 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -12,62 +12,104 @@ - rule_1.1.2.1.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.1.1' - required_mount: '/tmp' + 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 }} doesn't exist. This is a manual task" + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_tmp_mount.rc not in [ 0, 1 ] + register: discovered_tmp_mount - - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition | Present" + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Absent" + when: discovered_tmp_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Present" + when: discovered_tmp_mount is undefined 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" - ansible.posix.mount: - name: /tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_1_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_1_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_1_4) %},noexec{% endif %}" - notify: Remount tmp - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" +- name: "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" when: - - item.mount == "/tmp" + - mount_point_fs_and_options[mount_point] is defined + - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_2 - not rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_1_2 or - rhel9cis_rule_1_1_2_1_3 or - rhel9cis_rule_1_1_2_1_4 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.1.2 - - rule_1.1.2.1.3 - - rule_1.1.2.1.4 - - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_3 + - not rhel9cis_tmp_svc + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - rhel9cis_rule_1_1_2_1_4 + - not rhel9cis_tmp_svc + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.1.4 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when # 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 noexec option set on /tmp partition" - "1.1.2.1.4 | PATCH | Ensure nosuid option set on /tmp partition" + "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 noexec option set on /tmp partition + 1.1.2.1.4 | PATCH | Ensure nosuid option set on /tmp partition" when: - rhel9cis_tmp_svc - - rhel9cis_rule_1_1_2_1_1 or - rhel9cis_rule_1_1_2_1_2 or - rhel9cis_rule_1_1_2_1_3 or - rhel9cis_rule_1_1_2_1_4 + - rhel9cis_rule_1_1_2_1_1 or rhel9cis_rule_1_1_2_1_2 or rhel9cis_rule_1_1_2_1_3 or rhel9cis_rule_1_1_2_1_4 tags: - level1-server - level1-workstation @@ -79,10 +121,12 @@ - rule_1.1.2.1.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 + vars: + mount_point: "/tmp" 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 + mode: "go-wx" + notify: *mount_option_notify diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index eb82773..a2af00d 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -1,9 +1,9 @@ --- -# Skips if mount is absent -- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" +- name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition" when: - rhel9cis_rule_1_1_2_2_1 + - required_mount not in mount_names tags: - level1-server - level1-workstation @@ -12,46 +12,84 @@ - rule_1.1.2.2.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.2.1' + warn_control_id: "1.1.2.2.1" + required_mount: "/dev/shm" block: - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists" - ansible.builtin.shell: mount -l | grep -w /dev/shm + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" changed_when: false - register: discovered_dev_shm_mount_check + failed_when: discovered_dev_shm_mount.rc not in [ 0, 1 ] + register: discovered_dev_shm_mount - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition" - when: discovered_dev_shm_mount_check.rc == 1 - block: - - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - - name: "1.1.2.2.1 | AUDIT | Ensure separate partition exists for /home | Present" - ansible.builtin.import_tasks: - file: warning_facts.yml + - name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Present" + when: discovered_dev_shm_mount 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" +- name: "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition" when: - - rhel9cis_rule_1_1_2_2_2 or - rhel9cis_rule_1_1_2_2_3 or - rhel9cis_rule_1_1_2_2_4 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.2.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/dev/shm" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.2.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/dev/shm" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_2_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.2.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /dev/shm - src: tmpfs - fstype: tmpfs - state: mounted - opts: defaults,{% if rhel9cis_rule_1_1_2_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_2_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_2_4 %}noexec{% endif %} - notify: Change_requires_reboot + vars: + mount_point: "/dev/shm" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index c7920cd..224bf38 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -1,52 +1,74 @@ --- - -- name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home" +- name: "1.1.2.3.1 | PATCH | Ensure /home is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_3_1 + - required_mount not in mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.3.1 + - rule_1.1.2.3.1 - NIST800-53R5_CM-7 vars: - warn_control_id: '1.1.2.3.1' - required_mount: '/home' + 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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_home_mount.rc not in [ 0, 1 ] + register: discovered_home_mount - - name: "1.1.2.3.1 | AUDIT | Ensure separate partition exists for /home | Present" + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" + when: discovered_dev_shm_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml -- 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" +- name: "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition" when: - - item.mount == "/home" - - rhel9cis_rule_1_1_2_3_2 or - rhel9cis_rule_1_1_2_3_3 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_3_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.3.2 - - rule_1.1.2.3.3 - - NIST800-53R5_CM-7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /home - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_3_3) %},nosuid{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/home" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_3_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts + - rule_1.1.2.3.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/home" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 0aa4fa2..3a3aabf 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -1,52 +1,75 @@ --- -- name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var" +- name: "1.1.2.4.1 | PATCH | Ensure /var is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_4_1 + - required_mount not in mount_names tags: - - level2-server - - level2-workstation - - patch + - level1-server + - level1-workstation + - audit - mounts - - rule_1_1_2.4.1 + - rule_1.1.2.4.1 - NIST800-53R5_CM-7 vars: warn_control_id: '1.1.2.4.1' required_mount: '/var' block: - - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_mount.rc not in [ 0, 1 ] + register: discovered_var_mount - - name: "1.1.2.4.1 | AUDIT | Ensure separate partition exists for /var | Present" + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" + when: discovered_dev_shm_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" + when: discovered_dev_shm_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml -# 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" +- name: "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" when: - - item.mount == "/var" - - rhel9cis_rule_1_1_2_4_2 or - rhel9cis_rule_1_1_2_4_3 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_4_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.4.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_4_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.4.3 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_4_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_4_2) %},nosuid{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index 449bc8b..2706d4b 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -1,56 +1,95 @@ --- -# Skips if mount is absent -- name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp" +- name: "1.1.2.5.1 | PATCH | Ensure /var/tmp is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_5_1 + - required_mount not in mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.5.1 + - rule_1.1.2.5.1 - NIST800-53R5_CM-7 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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_tmp_mount.rc not in [ 0, 1 ] + register: discovered_var_tmp_mount - - name: "1.1.2.5.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present" + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Absent" + when: discovered_var_tmp_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Present" + when: discovered_var_tmp_mount is undefined 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" +- name: "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition" when: - - item.mount == "/var/tmp" - - rhel9cis_rule_1_1_2_5_2 or - rhel9cis_rule_1_1_2_5_3 or - rhel9cis_rule_1_1_2_5_4 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.5.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/tmp" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.5.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/tmp" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_5_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.5.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/tmp - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_5_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_5_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_5_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/tmp" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index c45da55..77da285 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -1,54 +1,95 @@ --- -- name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log" +- name: "1/.1 | PATCH | Ensure /var/log is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_6_1 + - required_mount not in mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.6.1 + - 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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_log_mount.rc not in [ 0, 1 ] + register: discovered_var_log_mount - - name: "1.1.2.6.1 | AUDIT | Ensure separate partition exists for /var/log | Present" + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Absent" + when: discovered_var_log_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Present" + when: discovered_var_log_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml -- 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" +- name: "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition" when: - - item.mount == "/var/log" - - rhel9cis_rule_1_1_2_6_2 or - rhel9cis_rule_1_1_2_6_3 or - rhel9cis_rule_1_1_2_6_4 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.6.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.6.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_6_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.6.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/log - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_6_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_6_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_6_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/log" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 4a8f67c..93bcb23 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -1,54 +1,95 @@ --- -- name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit" +- name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition" when: - - required_mount not in mount_names - rhel9cis_rule_1_1_2_7_1 + - required_mount not in mount_names tags: - - level2-server - - level2-workstation + - level1-server + - level1-workstation - audit - mounts - - rule_1_1_2.7.1 + - 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 | Absent" - ansible.builtin.debug: - msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task" + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | check for mount" + ansible.builtin.command: findmnt -kn "{{ required_mount }}" + changed_when: false + failed_when: discovered_var_log_audit_mount.rc not in [ 0, 1 ] + register: discovered_var_log_audit_mount - - name: "1.1.2.7.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present" + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Absent" + when: discovered_var_log_audit_mount is undefined + ansible.builtin.debug: + msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" + + - name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Present" + when: discovered_var_log_audit_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml -- 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" +- name: "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" when: - - item.mount == "/var/log/audit" - - rhel9cis_rule_1_1_2_7_2 or - rhel9cis_rule_1_1_2_7_3 or - rhel9cis_rule_1_1_2_7_4 + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_2 tags: - level1-server - level1-workstation - patch - mounts - rule_1.1.2.7.2 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log/audit" + required_option: nodev + notify: &mount_option_notify + - "Remount {{ mount_point }}" + ansible.builtin.set_fact: &mount_option_set_fact + mount_point_fs_and_options: | + {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + changed_when: &mount_option_changed_when + - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + +- name: "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_3 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.7.3 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 + vars: + mount_point: "/var/log/audit" + required_option: nosuid + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when + +- name: "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" + when: + - mount_point_fs_and_options[mount_point] is defined + - rhel9cis_rule_1_1_2_7_4 + tags: + - level1-server + - level1-workstation + - patch + - mounts - rule_1.1.2.7.4 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 - ansible.posix.mount: - name: /var/log/audit - src: "{{ item.device }}" - fstype: "{{ item.fstype }}" - state: present - opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_7_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_7_3) %},nosuid{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_7_4) %},noexec{% endif %}" - loop: "{{ ansible_facts.mounts }}" - loop_control: - label: "{{ item.device }}" - notify: Change_requires_reboot + vars: + mount_point: "/var/log/audit" + required_option: noexec + notify: *mount_option_notify + ansible.builtin.set_fact: + <<: *mount_option_set_fact + changed_when: *mount_option_changed_when From 7875e1f6b50199d068d1b81ac58291e0344da4eb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 10 Dec 2024 17:29:40 +0000 Subject: [PATCH 128/327] udpated output 1.1.1.9 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.1.x.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index fb0f119..bd56bde 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -300,9 +300,7 @@ - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning" when: discovered_fs_modules_loaded.stdout | length > 0 ansible.builtin.debug: - msg: | - "Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task - {{ discovered_fs_modules_loaded.stdout_lines}}" + msg: "{{ ['Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task'] + discovered_fs_modules_loaded.stdout_lines }}" - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning" when: discovered_fs_modules_loaded.stdout | length > 0 From d850fc58750627349736d911132eb42856731b1b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 10:09:31 +0000 Subject: [PATCH 129/327] Updated mountpoint vars correctly Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 16 ++++++++-------- tasks/section_1/cis_1.1.2.1.x.yml | 20 ++++++++++---------- tasks/section_1/cis_1.1.2.2.x.yml | 14 +++++++------- tasks/section_1/cis_1.1.2.3.x.yml | 12 ++++++------ tasks/section_1/cis_1.1.2.4.x.yml | 12 ++++++------ tasks/section_1/cis_1.1.2.5.x.yml | 14 +++++++------- tasks/section_1/cis_1.1.2.6.x.yml | 14 +++++++------- tasks/section_1/cis_1.1.2.7.x.yml | 14 +++++++------- 8 files changed, 58 insertions(+), 58 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 36c70c8..7896d58 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -61,7 +61,7 @@ - name: PRELIM | AUDIT | Section 1.1 | Create list of mount points tags: always ansible.builtin.set_fact: - mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" + prelim_mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}" - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options tags: always @@ -70,22 +70,22 @@ ansible.builtin.shell: | mount | awk '{print $1, $3, $5, $6}' changed_when: false - register: mount_output + register: prelim_mount_output - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact ansible.builtin.set_fact: - mount_point_fs_and_options: >- - {%- set mount_point_fs_and_options = {} -%} - {%- for line in mount_output.stdout_lines -%} + prelim_mount_point_fs_and_options: >- + {%- set prelim_mount_point_fs_and_options = {} -%} + {%- for line in prelim_mount_output.stdout_lines -%} {%- set fields = line.split() -%} - {%- set _ = mount_point_fs_and_options.update({fields[1]: {'src': fields[0], 'fs_type': fields[2], 'original_options': fields[3][1:-1].split(','), 'options': fields[3][1:-1].split(',')}}) -%} + {%- set _ = prelim_mount_point_fs_and_options.update({fields[1]: {'src': fields[0], 'fs_type': fields[2], 'original_options': fields[3][1:-1].split(','), 'options': fields[3][1:-1].split(',')}}) -%} {%- endfor -%} - {{ mount_point_fs_and_options }} + {{ prelim_mount_point_fs_and_options }} - name: "PRELIM | AUDIT | Debug of mount variables to assist in troubleshooting" when: rhel9cis_debug_mount_data ansible.builtin.debug: - msg: "{{ mount_point_fs_and_options }}" + msg: "{{ prelim_mount_point_fs_and_options }}" - name: "PRELIM | PATCH | Update to latest gpg keys" when: diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index a2adce0..355c32b 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -2,7 +2,7 @@ - name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition" when: - - required_mount not in mount_names + - required_mount not in prelim_mount_names - rhel9cis_rule_1_1_2_1_1 tags: - level1-server @@ -34,8 +34,8 @@ # via fstab - name: "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined - - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" - rhel9cis_rule_1_1_2_1_2 - not rhel9cis_tmp_svc tags: @@ -52,15 +52,15 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined - - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" - rhel9cis_rule_1_1_2_1_3 - not rhel9cis_tmp_svc tags: @@ -81,8 +81,8 @@ - name: "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined - - not mount_point_fs_and_options[mount_point]['src'] == "tmpfs" + - prelim_mount_point_fs_and_options[mount_point] is defined + - not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs" - rhel9cis_rule_1_1_2_1_4 - not rhel9cis_tmp_svc tags: diff --git a/tasks/section_1/cis_1.1.2.2.x.yml b/tasks/section_1/cis_1.1.2.2.x.yml index a2af00d..57e92eb 100644 --- a/tasks/section_1/cis_1.1.2.2.x.yml +++ b/tasks/section_1/cis_1.1.2.2.x.yml @@ -3,7 +3,7 @@ - name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition" when: - rhel9cis_rule_1_1_2_2_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -33,7 +33,7 @@ - name: "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_2_2 tags: - level1-server @@ -49,14 +49,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_2_3 tags: - level1-server @@ -76,7 +76,7 @@ - name: "1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_2_4 tags: - level1-server diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 224bf38..998d1ba 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -2,7 +2,7 @@ - name: "1.1.2.3.1 | PATCH | Ensure /home is a separate partition" when: - rhel9cis_rule_1_1_2_3_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -32,7 +32,7 @@ - name: "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_3_2 tags: - level1-server @@ -48,14 +48,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_3_3 tags: - level1-server diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index 3a3aabf..e0afd4e 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -3,7 +3,7 @@ - name: "1.1.2.4.1 | PATCH | Ensure /var is a separate partition" when: - rhel9cis_rule_1_1_2_4_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -33,7 +33,7 @@ - name: "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_4_2 tags: - level1-server @@ -49,14 +49,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_4_3 tags: - level1-server diff --git a/tasks/section_1/cis_1.1.2.5.x.yml b/tasks/section_1/cis_1.1.2.5.x.yml index 2706d4b..180d016 100644 --- a/tasks/section_1/cis_1.1.2.5.x.yml +++ b/tasks/section_1/cis_1.1.2.5.x.yml @@ -3,7 +3,7 @@ - name: "1.1.2.5.1 | PATCH | Ensure /var/tmp is a separate partition" when: - rhel9cis_rule_1_1_2_5_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -33,7 +33,7 @@ - name: "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_5_2 tags: - level1-server @@ -49,14 +49,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_5_3 tags: - level1-server @@ -76,7 +76,7 @@ - name: "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_5_4 tags: - level1-server diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index 77da285..765de3d 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -3,7 +3,7 @@ - name: "1/.1 | PATCH | Ensure /var/log is a separate partition" when: - rhel9cis_rule_1_1_2_6_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -33,7 +33,7 @@ - name: "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_6_2 tags: - level1-server @@ -49,14 +49,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_6_3 tags: - level1-server @@ -76,7 +76,7 @@ - name: "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_6_4 tags: - level1-server diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 93bcb23..2dc5939 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -3,7 +3,7 @@ - name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition" when: - rhel9cis_rule_1_1_2_7_1 - - required_mount not in mount_names + - required_mount not in prelim_mount_names tags: - level1-server - level1-workstation @@ -33,7 +33,7 @@ - name: "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_7_2 tags: - level1-server @@ -49,14 +49,14 @@ notify: &mount_option_notify - "Remount {{ mount_point }}" ansible.builtin.set_fact: &mount_option_set_fact - mount_point_fs_and_options: | - {{ mount_point_fs_and_options | combine({mount_point: {'options': (mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} + prelim_mount_point_fs_and_options: | + {{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }} changed_when: &mount_option_changed_when - - required_option not in mount_point_fs_and_options[mount_point]['original_options'] + - required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options'] - name: "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_7_3 tags: - level1-server @@ -76,7 +76,7 @@ - name: "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition" when: - - mount_point_fs_and_options[mount_point] is defined + - prelim_mount_point_fs_and_options[mount_point] is defined - rhel9cis_rule_1_1_2_7_4 tags: - level1-server From 834fa7a5eeeb9a815e9693b7c0bfac2ef36fe3f9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 10:22:33 +0000 Subject: [PATCH 130/327] Added comment on set_fact for mountpoints Signed-off-by: Mark Bolwell --- handlers/main.yml | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 96cc86e..c122eaa 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -7,10 +7,10 @@ mount_point: '/tmp' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /tmp" - name: "Remounting /tmp" @@ -35,10 +35,10 @@ mount_point: '/dev/shm' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /dev/shm" - name: "Remounting /dev/shm" @@ -54,10 +54,10 @@ mount_point: '/home' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /home" - name: "Remounting /home" @@ -73,10 +73,10 @@ mount_point: '/var' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /var" - name: "Remounting /var" @@ -92,10 +92,10 @@ mount_point: '/var/tmp' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /var/tmp" - name: "Remounting /var/tmp" @@ -111,10 +111,10 @@ mount_point: '/var/log' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /var/log" - name: "Remounting /var/log" @@ -130,10 +130,10 @@ mount_point: '/var/log/audit' ansible.posix.mount: path: "{{ mount_point }}" - src: "{{ mount_point_fs_and_options[mount_point]['src'] }}" + src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}" state: present - fstype: "{{ mount_point_fs_and_options[mount_point]['fs_type'] }}" - opts: "{{ mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" + fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}" + opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}" listen: "Remount /var/log/audit" - name: "Remounting /var/log/audit" From 3545620db8afe57bdc0ef85ccf746292a94a8f2a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 10:22:44 +0000 Subject: [PATCH 131/327] udpated variable Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 7896d58..4664879 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -72,7 +72,7 @@ changed_when: false register: prelim_mount_output - - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact + - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact # This is inherited and used in mountpoints tasks ansible.builtin.set_fact: prelim_mount_point_fs_and_options: >- {%- set prelim_mount_point_fs_and_options = {} -%} From 69e01b84f3fed923138b512654ceed7251a68250 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 11:20:00 +0000 Subject: [PATCH 132/327] Updated files to std Signed-off-by: Mark Bolwell --- tasks/LE_audit_setup.yml | 6 ++-- tasks/audit_only.yml | 10 +++--- tasks/post_remediation_audit.yml | 18 +++++----- tasks/pre_remediation_audit.yml | 58 +++++++++++++------------------- 4 files changed, 38 insertions(+), 54 deletions(-) diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index 4b407eb..52fc8bd 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -8,7 +8,7 @@ audit_pkg_arch_name: AMD64 - name: Pre Audit Setup | Set audit package name | ARM64 - when: ansible_facts.machine == "aarch64" + when: ansible_facts.machine == "arm64" ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 @@ -20,13 +20,13 @@ owner: root group: root checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}" - mode: '0555' + mode: 'u+x,go-w' - 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 + mode: 'u+x,go-w' diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index b7dad08..008d358 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -3,7 +3,7 @@ - name: Audit_Only | Create local Directories for hosts when: fetch_audit_files ansible.builtin.file: - mode: '0755' + mode: 'u+x,go-w' path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" recurse: true state: directory @@ -15,16 +15,14 @@ ansible.builtin.fetch: dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" flat: true - mode: '0644' + mode: 'go-wx' src: "{{ pre_audit_outfile }}" - name: Audit_only | Show Audit Summary - when: - - audit_only + when: audit_only ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" - name: Audit_only | Stop Playbook Audit Only selected - when: - - audit_only + when: audit_only ansible.builtin.meta: end_play diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 8004ed3..54d5785 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 }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" +- name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] + ansible.builtin.command: "{{ 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_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' @@ -18,26 +18,24 @@ - "{{ pre_audit_outfile }}" - name: Post Audit | Capture audit data if json format - when: - - audit_format == "json" + when: audit_format == "json" block: - 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 + register: post_audit_summary - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: post_audit_results: "{{ post_audit_summary.stdout }}" - name: Post Audit | Capture audit data if documentation format - when: - - audit_format == "documentation" + when: audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' - register: post_audit_summary + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + register: post_audit_summary - name: Post Audit | Set Fact for audit summary ansible.builtin.set_fact: diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 3a3304c..91cc9b7 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,22 +1,19 @@ --- - name: Pre Audit Setup | Setup the LE audit - when: - - setup_audit - tags: - - setup_audit + when: setup_audit + tags: setup_audit ansible.builtin.include_tasks: file: LE_audit_setup.yml -- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists +- name: Pre Audit Setup | Ensure existence of {{ audit_conf_dir }} # noqa name[template] ansible.builtin.file: path: "{{ audit_conf_dir }}" + mode: 'go-w' state: directory - mode: '0755' - name: Pre Audit Setup | If using git for content set up - when: - - audit_content == 'git' + when: audit_content == 'git' block: - name: Pre Audit Setup | Install git ansible.builtin.package: @@ -30,57 +27,51 @@ version: "{{ audit_git_version }}" - name: Pre Audit Setup | Copy to audit content files to server - when: - - audit_content == 'copy' + when: audit_content == 'copy' ansible.builtin.copy: src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" mode: preserve - name: Pre Audit Setup | Unarchive audit content files on server - when: - - audit_content == 'archive' + when: audit_content == 'archive' ansible.builtin.unarchive: src: "{{ audit_conf_source }}" dest: "{{ audit_conf_dest }}" - name: Pre Audit Setup | Get audit content from url - when: - - audit_content == 'get_url' + when: audit_content == 'get_url' 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', [] ) }}" + 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: - - run_audit + when: run_audit block: - name: Pre Audit Setup | Check for goss file ansible.builtin.stat: path: "{{ audit_bin }}" - register: discovered_goss_available + register: prelim_goss_available - name: Pre Audit Setup | If audit ensure goss is available - when: - - not discovered_goss_available.stat.exists + when: not prelim_goss_available.stat.exists ansible.builtin.assert: 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 + when: run_audit tags: - goss_template - run_audit ansible.builtin.template: src: ansible_vars_goss.yml.j2 dest: "{{ audit_vars_path }}" - mode: '0600' + mode: 'go-rwx' -- name: Pre Audit | Run pre_remediation {{ benchmark }} audit - ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" +- name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] + ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" @@ -88,33 +79,30 @@ AUDIT_FILE: goss.yml - name: Pre Audit | Capture audit data if json format - when: - - audit_format == "json" + when: audit_format == "json" block: - 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 + register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Pre Audit | Capture audit data if documentation format - when: - - audit_format == "documentation" + when: audit_format == "documentation" block: - name: Pre Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' - register: pre_audit_summary + ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary ansible.builtin.set_fact: pre_audit_results: "{{ pre_audit_summary.stdout }}" - name: Audit_Only | Run Audit Only - when: - - audit_only + when: audit_only ansible.builtin.import_tasks: file: audit_only.yml From fcf9eb674f5c1908e0373264709db1643408d4ea Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 11:20:19 +0000 Subject: [PATCH 133/327] lint and best practise Signed-off-by: Mark Bolwell --- handlers/main.yml | 21 ++++++++++++------- tasks/main.yml | 8 +++---- tasks/parse_etc_password.yml | 2 +- tasks/post.yml | 17 ++++++--------- tasks/prelim.yml | 11 ++++++---- .../pwquality.conf.d/50-pwcomplexity.conf.j2 | 4 ++-- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index c122eaa..91181a1 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -145,7 +145,8 @@ listen: "Remount /var/log/audit" - name: Reload sysctl - ansible.builtin.shell: sysctl --system + ansible.builtin.command: sysctl --system + changed_when: true - name: Sysctl flush ipv4 route table when: @@ -181,8 +182,8 @@ - name: Set Crypto Policy when: prelim_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy - ansible.builtin.shell: | - update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + ansible.builtin.command: update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}" + changed_when: true notify: - Change_requires_reboot - Restart sshd @@ -203,10 +204,12 @@ state: restarted - name: Reload dconf - ansible.builtin.shell: dconf update + ansible.builtin.command: dconf update + changed_when: true - name: Grub2cfg - ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg" + ansible.builtin.command: "grub2-mkconfig -o /boot/grub2/grub.cfg" + changed_when: true ignore_errors: true # noqa ignore-errors - name: Restart rsyslog @@ -229,12 +232,13 @@ daemon-reload: true - name: Authselect update - ansible.builtin.shell: authselect apply-changes + ansible.builtin.command: authselect apply-changes + changed_when: true ## Auditd tasks note order for handlers to run - name: Auditd immutable check - ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules + ansible.builtin.command: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules changed_when: false register: discovered_auditd_immutable_check @@ -246,7 +250,8 @@ notify: Change_requires_reboot - name: Stop auditd process - ansible.builtin.shell: systemctl kill auditd + ansible.builtin.command: systemctl kill auditd + changed_when: true listen: Restart auditd - name: Start auditd process diff --git a/tasks/main.yml b/tasks/main.yml index 4598f85..4cb6869 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -81,14 +81,14 @@ vars: sudo_password_rule: rhel9cis_rule_5_2_4 # pragma: allowlist secret block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" + - name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" # noqa name[template] ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'" changed_when: false failed_when: false check_mode: false register: prelim_ansible_user_password_set - - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" + - name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" # noqa name[template] when: prelim_ansible_user_password_set.stdout == "not found" ansible.builtin.debug: msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks." @@ -97,7 +97,7 @@ when: - prelim_ansible_user_password_set.stdout != "not found" block: - - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" + - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" # noqa name[template] ansible.builtin.assert: that: - prelim_ansible_user_password_set.stdout | length != 0 @@ -105,7 +105,7 @@ 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" - - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" + - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: that: - not prelim_ansible_user_password_set.stdout.startswith("!") diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 8270b5a..49941bf 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -5,7 +5,7 @@ - always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.shell: cat /etc/passwd + ansible.builtin.command: cat /etc/passwd changed_when: false check_mode: false register: rhel9cis_passwd_file_audit diff --git a/tasks/post.yml b/tasks/post.yml index 198d9c0..4308727 100644 --- a/tasks/post.yml +++ b/tasks/post.yml @@ -29,28 +29,23 @@ ansible.builtin.meta: flush_handlers - name: POST | reboot system if changes require it and not skipped + when: change_requires_reboot tags: - always + vars: + warn_control_id: Reboot_required block: - name: POST | Reboot system if changes require it and not skipped + when: not skip_reboot ansible.builtin.reboot: - when: - - change_requires_reboot - - not skip_reboot - name: POST | Warning a reboot required but skip option set + when: 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: true - when: - - change_requires_reboot - - skip_reboot - name: "POST | Warning a reboot required but skip option set | warning count" + when: skip_reboot ansible.builtin.import_tasks: file: warning_facts.yml - when: - - change_requires_reboot - - skip_reboot - vars: - warn_control_id: Reboot_required diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 4664879..efa13d5 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -103,14 +103,14 @@ - ansible_facts.distribution == 'RedHat' block: - name: "PRELIM | AUDIT | Import gpg keys | get data" - ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' + ansible.builtin.command: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' # noqa command-instead-of-module changed_when: false failed_when: false register: prelim_check_gpg_imported - name: "PRELIM | AUDIT | Import gpg keys | Check Package" when: "'not installed' in prelim_check_gpg_imported.stdout" - ansible.builtin.shell: rpm -qi redhat-release | grep Signature + ansible.builtin.shell: rpm -qi redhat-release | grep Signature # noqa command-instead-of-module changed_when: false failed_when: false register: prelim_os_gpg_package_valid @@ -119,7 +119,9 @@ when: - "'not installed' in prelim_check_gpg_imported.stdout" - "'Key ID 199e2f91fd431d51' in prelim_os_gpg_package_valid.stdout" - ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + ansible.builtin.rpm_key: + key: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release + state: present - name: "PRELIM | AUDIT | Check systemd coredump" when: @@ -150,7 +152,7 @@ state: present - name: "PRELIM | AUDIT | Gather system-wide crypto-policy" - ansible.builtin.shell: 'update-crypto-policies --show' + ansible.builtin.command: 'update-crypto-policies --show' changed_when: false check_mode: false register: prelim_system_wide_crypto_policy @@ -269,6 +271,7 @@ ansible.builtin.file: path: /etc/systemd/journald.conf.d state: directory + mode: 'u+x,g-w,o-rwx' - name: "PRELIM | PATCH | Configure System Accounting (auditd)" when: diff --git a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 index 6a9855a..c223c84 100644 --- a/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 +++ b/templates/etc/security/pwquality.conf.d/50-pwcomplexity.conf.j2 @@ -1,9 +1,9 @@ # CIS Configurations # 5.3.3.2.3 Ensure password complexity is configured -{% if rhel9cis_passwd_complex_option == 'minclass' %} +{% if rhel9cis_passwd_complex_option == 'minclass' %} # pragma: allowlist secret minclass = {{ rhel9cis_passwd_minclass }} {% endif %} -{% if rhel9cis_passwd_complex_option == 'credits' %} +{% if rhel9cis_passwd_complex_option == 'credits' %} # pragma: allowlist secret dcredit = {{rhel9cis_passwd_dcredit }} ucredit = {{ rhel9cis_passwd_ucredit }} ocredit = {{ rhel9cis_passwd_ocredit }} From 88ac5c3d65f0481b8fe1c266c57525e3c1a3c3ff Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 11:49:02 +0000 Subject: [PATCH 134/327] Lint updates Signed-off-by: Mark Bolwell --- {templates => files}/fs_with_cves.sh | 5 +-- tasks/section_1/cis_1.1.1.x.yml | 6 +-- tasks/section_1/cis_1.2.1.x.yml | 8 ++-- tasks/section_2/cis_2.1.x.yml | 2 +- tasks/section_2/cis_2.4.x.yml | 2 +- tasks/section_3/cis_3.1.x.yml | 4 +- tasks/section_3/cis_3.2.x.yml | 12 ++++-- tasks/section_4/cis_4.1.x.yml | 2 +- tasks/section_4/cis_4.3.x.yml | 62 +++++++++++++++++++--------- tasks/section_5/cis_5.3.2.x.yml | 36 +++++++++------- tasks/section_5/cis_5.3.3.1.x.yml | 1 + tasks/section_5/cis_5.4.1.x.yml | 28 ++++++++----- tasks/section_5/cis_5.4.2.x.yml | 3 +- tasks/section_6/cis_6.1.x.yml | 10 +++-- tasks/section_6/cis_6.3.1.x.yml | 18 ++++---- tasks/section_7/cis_7.1.x.yml | 4 +- tasks/section_7/cis_7.2.x.yml | 4 +- tasks/warning_facts.yml | 2 +- vars/audit.yml | 2 +- 19 files changed, 127 insertions(+), 84 deletions(-) rename {templates => files}/fs_with_cves.sh (98%) diff --git a/templates/fs_with_cves.sh b/files/fs_with_cves.sh similarity index 98% rename from templates/fs_with_cves.sh rename to files/fs_with_cves.sh index 89ba49b..a6d937c 100644 --- a/templates/fs_with_cves.sh +++ b/files/fs_with_cves.sh @@ -1,11 +1,8 @@ -{% raw %} -#! /usr/bin/env bash +{% raw %}#! /usr/bin/env bash # Based on original Script provided by CIS # CVEs correct at time of creation - April2024 -#! /usr/bin/env bash - { a_output=(); a_output2=(); a_modprope_config=(); a_excluded=(); a_available_modules=() a_ignore=("xfs" "vfat" "ext2" "ext3" "ext4") diff --git a/tasks/section_1/cis_1.1.1.x.yml b/tasks/section_1/cis_1.1.1.x.yml index bd56bde..02a387e 100644 --- a/tasks/section_1/cis_1.1.1.x.yml +++ b/tasks/section_1/cis_1.1.1.x.yml @@ -284,15 +284,15 @@ warn_control_id: '1.1.1.9' block: - name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available | Add discovery script" - ansible.builtin.template: + ansible.builtin.copy: src: fs_with_cves.sh dest: /var/fs_with_cves.sh owner: root group: root - mode: '0744' + mode: 'u+x,go-wx' - name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Run discovery script" - ansible.builtin.shell: /var/fs_with_cves.sh + ansible.builtin.command: /var/fs_with_cves.sh changed_when: false failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ] register: discovered_fs_modules_loaded diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index dca12b0..454fd95 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -15,13 +15,15 @@ - NIST800-53R5_SI-2 block: - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" - ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + ansible.builtin.shell: | + "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" changed_when: false failed_when: false register: discovered_os_installed_pub_keys - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys" - ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' + ansible.builtin.shell: | + 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"' changed_when: false failed_when: false register: discovered_os_gpg_key_check @@ -107,7 +109,7 @@ warn_control_id: '1.2.1.4' block: - name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Get repo list" - ansible.builtin.shell: dnf repolist + ansible.builtin.command: dnf repolist changed_when: false failed_when: false register: discovered_dnf_configured diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 73e7986..bf6a81d 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -718,7 +718,7 @@ warn_control_id: '2.1.22' block: - name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services" - ansible.builtin.shell: systemctl list-units --type=service + ansible.builtin.command: systemctl list-units --type=service # noqa command-instead-of-module changed_when: false failed_when: discovered_running_services.rc not in [ 0, 1 ] check_mode: false diff --git a/tasks/section_2/cis_2.4.x.yml b/tasks/section_2/cis_2.4.x.yml index 16ed0e9..3789aae 100644 --- a/tasks/section_2/cis_2.4.x.yml +++ b/tasks/section_2/cis_2.4.x.yml @@ -146,7 +146,7 @@ - name: "2.4.1.8 | PATCH | Ensure crontab 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" }}' + state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}' owner: root group: root mode: u-x,g-wx,o-rwx diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 98e3a93..84d8784 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -40,7 +40,7 @@ block: - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" when: "'network-manager' in ansible_facts.packages" - ansible.builtin.shell: nmcli radio wifi + ansible.builtin.command: nmcli radio wifi changed_when: false failed_when: false check_mode: false @@ -50,7 +50,7 @@ when: - "'network-manager' in ansible_facts.packages" - "'enabled' in discovered_wifi_status.stdout" - ansible.builtin.shell: nmcli radio all off + ansible.builtin.command: nmcli radio all off changed_when: discovered_nmcli_radio_off.rc == 0 register: discovered_nmcli_radio_off diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index bc210ae..4413d59 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -18,6 +18,7 @@ regexp: '^(#)?install dccp(\\s|$)' line: "{{ item }}" create: true + mode: 'u-x,go-rwx' loop: - install dccp /bin/true - blacklist dccp @@ -28,7 +29,7 @@ regexp: "^(#)?blacklist cramfs(\\s|$)" line: "blacklist cramfs" create: true - mode: '0600' + mode: 'u-x,go-rwx' - name: "3.2.2 | PATCH | Ensure tipc kernel module is not available" when: @@ -48,6 +49,7 @@ regexp: '^(#)?install tipc(\\s|$)' line: "{{ item }}" create: true + mode: 'u-x,go-rwx' loop: - install tipc /bin/true - blacklist tipc @@ -58,7 +60,7 @@ regexp: "^(#)?blacklist tipc(\\s|$)" line: "blacklist tipc" create: true - mode: '0600' + mode: 'u-x,go-rwx' - name: "3.2.3 | PATCH | Ensure rds kernel module is not available" when: @@ -78,6 +80,7 @@ regexp: '^(#)?install rds(\\s|$)' line: "{{ item }}" create: true + mode: 'u-x,go-rwx' loop: - install rds /bin/true - blacklist rds @@ -88,7 +91,7 @@ regexp: "^(#)?blacklist rds(\\s|$)" line: "blacklist rds" create: true - mode: '0600' + mode: 'u-x,go-rwx' - name: "3.2.4 | PATCH | Ensure sctp kernel module is not available" when: @@ -108,6 +111,7 @@ regexp: '^(#)?install sctp(\\s|$)' line: "{{ item }}" create: true + mode: 'u-x,go-rwx' loop: - install sctp /bin/true - blacklist sctp @@ -118,4 +122,4 @@ regexp: "^(#)?blacklist sctp(\\s|$)" line: "blacklist sctp" create: true - mode: '0600' + mode: 'u-x,go-rwx' diff --git a/tasks/section_4/cis_4.1.x.yml b/tasks/section_4/cis_4.1.x.yml index f0a6636..06cffbd 100644 --- a/tasks/section_4/cis_4.1.x.yml +++ b/tasks/section_4/cis_4.1.x.yml @@ -52,7 +52,7 @@ name: "{{ rhel9cis_firewall }}" state: installed - - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" + - name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" # noqa name[template] ansible.builtin.systemd: name: "{{ rhel9cis_firewall }}" enabled: true diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 4e85deb..9cab1b4 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -8,7 +8,8 @@ - rhel9cis_rule_4_3_3 - rhel9cis_rule_4_3_4 tags: always - ansible.builtin.shell: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + ansible.builtin.command: "nft add table inet {{ rhel9cis_nft_tables_tablename }}" + changed_when: true - name: "4.3.1 | PATCH | Ensure nftables base chains exist" when: @@ -22,19 +23,22 @@ - NIST800-55_CA-9 block: - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT" - ansible.builtin.shell: nft list ruleset | grep 'hook input' + ansible.builtin.shell: | + nft list ruleset | grep 'hook input' changed_when: false failed_when: false register: discovered_nftables_input_chains - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD" - ansible.builtin.shell: nft list ruleset | grep 'hook forward' + ansible.builtin.shell: | + nft list ruleset | grep 'hook forward' changed_when: false failed_when: false register: discovered_nftables_forward_chains - name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT" - ansible.builtin.shell: nft list ruleset | grep 'hook output' + ansible.builtin.shell: | + nft list ruleset | grep 'hook output' changed_when: false failed_when: false register: discovered_nftables_output_chains @@ -52,7 +56,8 @@ - name: "4.3.1 | PATCH | Ensure nftables base chains exist | Create chains if needed" when: rhel9cis_nft_tables_autochaincreate - ansible.builtin.shell: "{{ item }}" + ansible.builtin.command: "{{ item }}" + changed_when: true failed_when: false loop: - nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; } @@ -71,44 +76,50 @@ - NIST800-55_CA-9 block: - name: "4.3.2 | 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' + 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: discovered_nftables_inconnectionrule - name: "4.3.2 | 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' + ansible.builtin.command: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' changed_when: false failed_when: false register: discovered_nftables_outconnectionrule - name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy" when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' - ansible.builtin.shell: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy" when: '"ip protocol udp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy" when: '"ip protocol icmp ct state established accept" not in discovered_nftables_inconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy" when: '"ip protocol tcp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy" when: '"ip protocol udp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept + changed_when: true - name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy" when: '"ip protocol icmp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy" - when: - - rhel9cis_rule_4_3_3 + when: rhel9cis_rule_4_3_3 tags: - level1-server - level1-workstation @@ -118,25 +129,29 @@ - NIST800-55_CA-9 block: - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input' failed_when: false changed_when: false register: discovered_nftables_inputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward' failed_when: false changed_when: false register: discovered_nftables_forwardpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output' failed_when: false changed_when: false register: discovered_nftables_outputpolicy - name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow" - ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' + ansible.builtin.shell: | + nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh' failed_when: false changed_when: false register: discovered_nftables_sshallowcheck @@ -144,22 +159,25 @@ - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic" when: '"tcp dport ssh accept" not in discovered_nftables_sshallowcheck.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy" when: '"type filter hook input priority 0; policy drop;" not in discovered_nftables_inputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; } + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy" when: '"type filter hook forward priority 0; policy drop;" not in discovered_nftables_forwardpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; } + changed_when: true - name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy" when: '"type filter hook output priority 0; policy drop;" not in discovered_nftables_outputpolicy.stdout' ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; } + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured" - when: - - rhel9cis_rule_4_3_4 + when: rhel9cis_rule_4_3_4 tags: - level1-server - level1-workstation @@ -169,19 +187,22 @@ - NIST800-55_CA-9 block: - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept' changed_when: false failed_when: false register: discovered_nftables_iiflo - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr' changed_when: false failed_when: false register: discovered_nftables_ipsaddr - name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence | nftables" - ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' + ansible.builtin.shell: | + nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr' changed_when: false failed_when: false register: discovered_nftables_ip6saddr @@ -189,11 +210,14 @@ - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule | nftables" when: '"iif \"lo\" accept" not in discovered_nftables_iiflo.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule | nftables" when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_nftables_ipsaddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop + changed_when: true - name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule | nftables" when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_nftables_ip6saddr.stdout' ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop + changed_when: true diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 18e9cfd..696010f 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -17,12 +17,13 @@ when: - rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or prelim_authselect_current_profile.stdout is not defined - ansible.builtin.shell: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" + ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" + changed_when: false args: creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}" - name: "5.3.2.1 | AUDIT | Ensure active authselect profile includes pam modules | get profile features" - ansible.builtin.shell: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" + ansible.builtin.command: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}" changed_when: false register: discovered_authselect_profile_features @@ -37,7 +38,8 @@ - password - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Backup and Add pam modules" - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}" + changed_when: true - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled" when: @@ -59,14 +61,16 @@ notify: Authselect update block: - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep faillock + ansible.builtin.shell: | + authselect current | grep faillock changed_when: false failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] register: discovered_authselect_current_faillock - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" when: discovered_authselect_current_faillock.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: @@ -83,14 +87,16 @@ - rule_5.3.2.3 block: - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep quality + ansible.builtin.shell: | + authselect current | grep quality changed_when: false failed_when: discovered_authselect_current_quality.rc not in [ 0, 1 ] register: discovered_authselect_current_quality - - name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Add feature if missing" + - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | Add feature if missing" when: discovered_authselect_current_quality.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true notify: Authselect update - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled" @@ -108,14 +114,16 @@ - rule_5.3.2.4 block: - name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config" - ansible.builtin.shell: authselect current | grep pwhistory + ansible.builtin.shell: | + authselect current | grep pwhistory changed_when: false failed_when: discovered_authselect_current_history.rc not in [ 0, 1 ] register: discovered_authselect_current_history - name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature" when: discovered_authselect_current_history.rc != 0 - ansible.builtin.shell: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true notify: Authselect update - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled" @@ -146,8 +154,8 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" backrefs: true - insertafter: "{{ item.after | default (omit) }}" - insertbefore: "{{ item.before | default (omit) }}" + insertafter: "{{ item.after | default(omit) }}" + insertbefore: "{{ item.before | default(omit) }}" 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' } @@ -160,8 +168,8 @@ line: "{{ item.line }}" regexp: "{{ item.regexp }}" backrefs: true - insertafter: "{{ item.after | default (omit) }}" - insertbefore: "{{ item.before | default (omit) }}" + insertafter: "{{ item.after | default(omit) }}" + insertbefore: "{{ item.before | default(omit) }}" 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_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 8206074..d625cac 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -104,6 +104,7 @@ line: "{{ rhel9cis_pamroot_lock_option }}" insertafter: '^# end of pam-auth-update config' create: true + mode: 'u-x,go-wx' - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files NOT AuthSelect" when: diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 9e92e86..732fc5c 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -96,7 +96,8 @@ - discovered_warn_days.stdout_lines | length > 0 - item in prelim_interactive_usernames.stdout - rhel9cis_force_user_warnage - ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + changed_when: true loop: "{{ discovered_warn_days.stdout_lines }}" - name: "5.4.1.4 | PATCH | Ensure strong password hashing algorithm is configured" @@ -125,25 +126,29 @@ - rule_5.4.1.5 block: - name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | Check current settings" - ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= + ansible.builtin.shell: | + useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d= changed_when: false failed_when: false check_mode: false register: discovered_passwdlck_inactive_settings - name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting" - ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} when: discovered_passwdlck_inactive_settings.stdout | length == 0 + ansible.builtin.command: useradd -D -f {{ rhel9cis_inactivelock.lock_days }} + changed_when: true - name: "5.4.1.5 | 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" + 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: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" when: item in prelim_interactive_usernames.stdout - ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" + ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" + changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" - name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past" @@ -172,22 +177,23 @@ register: discovered_passwdlck_user_future - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future" + when: + - discovered_passwdlck_user_future.stdout | length > 0 + - not rhel9cis_futurepwchgdate_autofix ansible.builtin.debug: msg: "Warning!! The following accounts have the last PW change date in the future: {{ discovered_passwdlck_user_future.stdout_lines }}" - when: - - discovered_passwdlck_user_future.stdout | length > 0 - - not rhel9cis_futurepwchgdate_autofix - name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count" - ansible.builtin.import_tasks: - file: warning_facts.yml when: - discovered_passwdlck_user_future.stdout | length > 0 - not rhel9cis_futurepwchgdate_autofix + ansible.builtin.import_tasks: + file: warning_facts.yml - name: "5.4.1.6 | 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 }} + changed_when: true when: - discovered_passwdlck_user_future.stdout | length > 0 - rhel9cis_futurepwchgdate_autofix loop: "{{ discovered_passwdlck_user_future.stdout_lines }}" + ansible.builtin.command: passwd --expire {{ item }} diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 2cf378c..a367f72 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -17,7 +17,7 @@ - NIST800-53R5_CM-6 - NIST800-53R5_CM-7 - NIST800-53R5_IA-5 - ansible.builtin.shell: passwd -l {{ item }} + ansible.builtin.command: passwd -l {{ item }} changed_when: false failed_when: false loop: "{{ prelim_uid_zero_accounts_except_root.stdout_lines }}" @@ -194,6 +194,7 @@ regexp: \s*umask line: "umask {{ rhel9cis_root_umask }}" create: true + mode: 'u+x,go-rwx' - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index f889cd4..c000fe1 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -45,7 +45,8 @@ rhel9cis_aide_db_recreate block: - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB" - ansible.builtin.shell: "{{ aide_initiate_command }}" + ansible.builtin.command: "{{ aide_initiate_command }}" + changed_when: true - name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB | Wait for file before continuing" ansible.builtin.wait_for: @@ -56,6 +57,7 @@ src: /var/lib/aide/aide.db.new.gz dest: /var/lib/aide/aide.db.gz remote_src: true + mode: 'ug-wx,o-rwx' - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: @@ -85,15 +87,15 @@ - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd: + ansible.builtin.systemd_service: name: aidecheck.service enabled: true - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd: + ansible.builtin.systemd_service: name: aidecheck.timer - state: running + state: started enabled: true - name: "6.1.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools" diff --git a/tasks/section_6/cis_6.3.1.x.yml b/tasks/section_6/cis_6.3.1.x.yml index 3039f2c..b054848 100644 --- a/tasks/section_6/cis_6.3.1.x.yml +++ b/tasks/section_6/cis_6.3.1.x.yml @@ -1,8 +1,7 @@ --- - name: "6.3.1.1 | PATCH | Ensure auditd is installed" - when: - - rhel9cis_rule_6_3_1_1 + when: rhel9cis_rule_6_3_1_1 tags: - level2-server - level2-workstation @@ -27,8 +26,7 @@ state: present - name: "6.3.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled" - when: - - rhel9cis_rule_6_3_1_2 + when: rhel9cis_rule_6_3_1_2 tags: - level2-server - level2-workstation @@ -49,7 +47,8 @@ - discovered_grubby_curr_value_audit_linux.stdout == '' or '0' in discovered_grubby_curr_value_audit_linux.stdout or 'off' in discovered_grubby_curr_value_audit_linux.stdout|lower - ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1" + ansible.builtin.command: grubby --update-kernel=ALL --args="audit=1" + changed_when: true - name: "6.3.1.3 | PATCH | Ensure audit_backlog_limit is sufficient" when: @@ -81,17 +80,16 @@ discovered_reset_backlog_limits: true - name: "6.3.1.3 | AUDIT | Check to see if any limits are too low" - when: - - (item | int < rhel9cis_audit_back_log_limit) + when: (item | int < rhel9cis_audit_back_log_limit) ansible.builtin.set_fact: discovered_reset_backlog_limits: true loop: "{{ discovered_grubby_curr_value_backlog_linux.stdout_lines }}" - name: "6.3.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied" - when: - - discovered_reset_backlog_limits is defined - ansible.builtin.shell: + when: discovered_reset_backlog_limits is defined + ansible.builtin.command: cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"' + changed_when: true - name: "6.3.1.4 | PATCH | Ensure auditd service is enabled and active" when: diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 232b224..d70bf5f 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -221,7 +221,7 @@ warn_control_id: '7.1.12' block: - name: "7.1.12 | AUDIT | Ensure no files or directories without an owner and a group exist | Get list files or directories" - ansible.builtin.shell: find {{ rhel9cis_exclude_unowned_search_path }} {{ item.mount }} -xdev \( -nouser -o -nogroup \) -not -fstype nfs + ansible.builtin.command: find {{ rhel9cis_exclude_unowned_search_path }} {{ item.mount }} -xdev \( -nouser -o -nogroup \) -not -fstype nfs changed_when: false failed_when: false check_mode: false @@ -283,7 +283,7 @@ warn_control_id: '7.1.13' block: - name: "7.1.13 | AUDIT | Ensure SUID and SGID files are reviewed | Find SUID and SGID" - ansible.builtin.shell: find {{ item.mount }} -xdev -type f -perm \( -02000 or -04000 \) -not -fstype nfs + ansible.builtin.command: find {{ item.mount }} -xdev -type f -perm \( -02000 or -04000 \) -not -fstype nfs changed_when: false failed_when: false check_mode: false diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 47d48f6..2a33f33 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -237,13 +237,13 @@ - users - rule_7.2.8 block: - - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Create dir if absent" + - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Create dir if absent" # noqa risky-file-permissions ansible.builtin.file: path: "{{ item.dir }}" state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', max_int_uid | int) | list }}" + loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" diff --git a/tasks/warning_facts.yml b/tasks/warning_facts.yml index 98cd4b6..36f61cb 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 }} | AUDIT | Set fact for manual task warning." # noqa name[template] ansible.builtin.set_fact: warn_control_list: "{{ warn_control_list }} [{{ warn_control_id }}]" warn_count: "{{ warn_count | int + 1 }}" diff --git a/vars/audit.yml b/vars/audit.yml index e54deb8..1dc1cf1 100644 --- a/vars/audit.yml +++ b/vars/audit.yml @@ -35,7 +35,7 @@ audit_format: json audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml" audit_results: | - The{% if not audit_only %} pre remediation{% endif %} audit results are: {{ pre_audit_results}} + 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 }} From 67df5b77b2633966caf0af79baf5e8c32be3c6b2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 12:03:54 +0000 Subject: [PATCH 135/327] file updated and moved from templates Signed-off-by: Mark Bolwell --- {files => templates}/fs_with_cves.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {files => templates}/fs_with_cves.sh (100%) diff --git a/files/fs_with_cves.sh b/templates/fs_with_cves.sh similarity index 100% rename from files/fs_with_cves.sh rename to templates/fs_with_cves.sh From 51de8bf7c9931ffc038eb55f5cb70fffa5a693ec Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 12:06:45 +0000 Subject: [PATCH 136/327] update var naming Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 49941bf..337889c 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -8,12 +8,12 @@ ansible.builtin.command: cat /etc/passwd changed_when: false check_mode: false - register: rhel9cis_passwd_file_audit + register: prelim_passwd_file_audit - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" ansible.builtin.set_fact: - rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}" + rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + loop: "{{ prelim_passwd_file_audit.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) From 148165ad4d578e43054b3174ae9277ca640c109e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 12:32:59 +0000 Subject: [PATCH 137/327] tidy up script as copy not template Signed-off-by: Mark Bolwell --- {templates => files}/fs_with_cves.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) rename {templates => files}/fs_with_cves.sh (98%) diff --git a/templates/fs_with_cves.sh b/files/fs_with_cves.sh similarity index 98% rename from templates/fs_with_cves.sh rename to files/fs_with_cves.sh index a6d937c..a2bc1b7 100644 --- a/templates/fs_with_cves.sh +++ b/files/fs_with_cves.sh @@ -1,4 +1,4 @@ -{% raw %}#! /usr/bin/env bash +#! /usr/bin/env bash # Based on original Script provided by CIS # CVEs correct at time of creation - April2024 @@ -54,4 +54,3 @@ #[ "${#a_output[@]}" -gt 0 ] && printf '%s\n' "" "-- Correctly set: --" "${a_output[@]}" "" fi } -{% endraw %} From 8cbf82bbc9e2c2cf7d2b23b7293870be570d0979 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 12:35:48 +0000 Subject: [PATCH 138/327] improve layout 1.2.1.1 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.2.1.x.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tasks/section_1/cis_1.2.1.x.yml b/tasks/section_1/cis_1.2.1.x.yml index 454fd95..960b495 100644 --- a/tasks/section_1/cis_1.2.1.x.yml +++ b/tasks/section_1/cis_1.2.1.x.yml @@ -14,9 +14,8 @@ - rule_1.2.1.1 - NIST800-53R5_SI-2 block: - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys" - ansible.builtin.shell: | - "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | List installed pubkey keys" + ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" # noqa command-instead-of-module changed_when: false failed_when: false register: discovered_os_installed_pub_keys @@ -29,7 +28,7 @@ register: discovered_os_gpg_key_check when: discovered_os_installed_pub_keys.rc == 0 - - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | expected keys fail" + - name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | If expected keys fail" when: - discovered_os_installed_pub_keys.rc == 1 or discovered_os_gpg_key_check.rc == 1 From ae228e3f96ea776627239810e218bfdc8b388eb9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 12:37:40 +0000 Subject: [PATCH 139/327] 5.4.1.5 improvemet Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.1.x.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 732fc5c..72dc50f 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -139,8 +139,7 @@ changed_when: true - name: "5.4.1.5 | 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" + 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: discovered_passwdlck_user_list From 6cc43202c85758e65e7cdd41f660d0a42e90b14a Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 13:11:39 +0000 Subject: [PATCH 140/327] removed empty line Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index fb0351f..eaa0c60 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -34,7 +34,6 @@ - name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use" when: rhel9cis_rule_2_1_2 - tags: - level1-server - level2-workstation From c65e9cabb86dde67aef636be46ea5426f5c89eba Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 11 Dec 2024 13:39:16 +0000 Subject: [PATCH 141/327] updated mode for line 131 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.1.2.1.x.yml b/tasks/section_1/cis_1.1.2.1.x.yml index 355c32b..9cca1ec 100644 --- a/tasks/section_1/cis_1.1.2.1.x.yml +++ b/tasks/section_1/cis_1.1.2.1.x.yml @@ -128,5 +128,5 @@ dest: /etc/systemd/system/tmp.mount owner: root group: root - mode: "go-wx" + mode: 'go-wx' notify: *mount_option_notify From 4799e7830bf35cefeafb3b71173ed86f29af6e40 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 16 Dec 2024 17:53:37 +0000 Subject: [PATCH 142/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v24.10.0 → v24.12.2](https://github.com/ansible-community/ansible-lint/compare/v24.10.0...v24.12.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1c69745..0033657 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -43,7 +43,7 @@ repos: args: ['--baseline-path', '.config/.gitleaks-report.json'] - repo: https://github.com/ansible-community/ansible-lint - rev: v24.10.0 + rev: v24.12.2 hooks: - id: ansible-lint name: Ansible-lint From b6fad79a21b531683a5777b5e0a1f5741b23ea0d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 17 Dec 2024 13:42:38 +0000 Subject: [PATCH 143/327] fixed typo in example Signed-off-by: Mark Bolwell --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0a4b4ff..2b6a5fb 100644 --- a/README.md +++ b/README.md @@ -152,8 +152,8 @@ Below is an example of the tag section from a control within this role. Using th ```sh tags: - - level1-server - - level1-workstation + - level1_server + - level1_workstation - scored - avahi - services From 52c1a41434e24c2a6a7ef3757ea61601e0f9c58f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 18 Dec 2024 08:51:13 +0000 Subject: [PATCH 144/327] fixed aide db name Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 816eb11..3f6202b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1055,7 +1055,7 @@ rhel9cis_aide_db_file_age: 1w rhel9cis_aide_db_recreate: false # allows to change db file, not config need to be adjusted too -rhel9cis_aide_db_file: /var/lib/aide/aide.db +rhel9cis_aide_db_file: /var/lib/aide/aide.db.gz ## Control 6.1.2 AIDE cron settings From 5d7bbe67b0eed4dae89aa09542b682fb25551283 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Dec 2024 15:18:27 +0000 Subject: [PATCH 145/327] fix typo in tags Signed-off-by: Mark Bolwell --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 2b6a5fb..745039d 100644 --- a/README.md +++ b/README.md @@ -63,10 +63,10 @@ This role **will make changes to the system** which may have unintended conseque It is possible to to only run level 1 or level 2 controls for CIS. This is managed using tags: -- level1_server -- level1_workstation -- level2_server -- level2_workstation +- level1-server +- level1-workstation +- level2-server +- level2-workstation The control found in defaults main also need to reflect this as this control the testing thet takes place if you are using the audit component. @@ -152,8 +152,8 @@ Below is an example of the tag section from a control within this role. Using th ```sh tags: - - level1_server - - level1_workstation + - level1-server + - level1-workstation - scored - avahi - services From 3d0cbce21e0e0556f7aeb343362e4c2394f6d55d Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 23 Dec 2024 14:14:46 +0000 Subject: [PATCH 146/327] Updated title for authselect checks Signed-off-by: Mark Bolwell --- tasks/main.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 2ea223c..2e5049c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -106,22 +106,22 @@ fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" -- name: "PRELIM | AUDIT | Check authselect profile is selected" +- name: "Check authselect profile is selected" when: rhel9cis_allow_authselect_updates tags: always block: - - name: "PRELIM | AUDIT | Check authselect profile name has been updated" + - name: "Check authselect profile name has been updated | Ensure name from default is changed" ansible.builtin.assert: that: rhel9cis_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" + - name: "Check authselect profile is selected | Check current profile" ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' changed_when: false failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] register: prelim_authselect_current_profile - - name: "PRELIM | AUDIT | Check authselect profile is selected" + - name: "Check authselect profile is selected | Ensure profile name is set" ansible.builtin.assert: that: prelim_authselect_current_profile is defined success_msg: "Authselect is running and profile is selected" From ecc2e66795349db655a22e5aef84f1f089af6bb2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Dec 2024 17:55:03 +0000 Subject: [PATCH 147/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.21.2 → v8.22.0](https://github.com/gitleaks/gitleaks/compare/v8.21.2...v8.22.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9ebfee3..7fe39ad 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.21.2 + rev: v8.22.0 hooks: - id: gitleaks From 58d6389d8544999c72bc67c6a3bd2904b8d002cc Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 30 Dec 2024 17:34:45 +0000 Subject: [PATCH 148/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.22.0 → v8.22.1](https://github.com/gitleaks/gitleaks/compare/v8.22.0...v8.22.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7fe39ad..4561cf6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.22.0 + rev: v8.22.1 hooks: - id: gitleaks From 88a497b1955d61b1e57771a07b44190639261ebd Mon Sep 17 00:00:00 2001 From: Christopher Papke Date: Tue, 7 Jan 2025 12:57:02 -0800 Subject: [PATCH 149/327] Use shell for grep with shell expansions Signed-off-by: Christopher Papke --- tasks/section_5/cis_5.3.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index eddf5ee..91e7186 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -141,7 +141,7 @@ - rule_5.3.2.5 block: - name: "5.3.2.5 | AUDIT | Ensure pam_unix module is enabled" - ansible.builtin.command: grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth + 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_discovered_authselect_pam_unix.rc not in [ 0, 1 ] register: discovered_discovered_authselect_pam_unix From cc8e32fb2da05191c10fc935eb96c6f9716fa09c Mon Sep 17 00:00:00 2001 From: Christopher Papke Date: Tue, 7 Jan 2025 13:01:24 -0800 Subject: [PATCH 150/327] remove extra discovered_ prefix from variable Signed-off-by: Christopher Papke --- tasks/section_5/cis_5.3.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index eddf5ee..143b3c0 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -143,8 +143,8 @@ - name: "5.3.2.5 | AUDIT | Ensure pam_unix module is enabled" ansible.builtin.command: grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth changed_when: false - failed_when: discovered_discovered_authselect_pam_unix.rc not in [ 0, 1 ] - register: discovered_discovered_authselect_pam_unix + failed_when: discovered_authselect_pam_unix.rc not in [ 0, 1 ] + register: discovered_authselect_pam_unix - name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth" when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout" From 424e5f78eb9230b816c3f357b9b49fc50e0f8f04 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 13 Jan 2025 11:55:27 +0000 Subject: [PATCH 151/327] Added fix for 5.3.2.2 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.2.x.yml | 62 ++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index d80e39a..ef84113 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -45,7 +45,6 @@ when: - rhel9cis_rule_5_3_2_2 - rhel9cis_disruption_high - - rhel9cis_allow_authselect_updates tags: - level1-server - level1-workstation @@ -58,19 +57,58 @@ - NIST800-53R5_IA-5 - authselect - rule_5.3.2.2 - notify: Authselect update block: - - name: "5.3.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_faillock.rc not in [ 0, 1 ] - register: discovered_authselect_current_faillock + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config authselect" + block: + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config authselect" + when: rhel9cis_allow_authselect_updates + ansible.builtin.shell: authselect current | grep faillock + changed_when: false + failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ] + register: discovered_authselect_current_faillock - - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" # noqa syntax-check[specific]" - when: discovered_authselect_current_faillock.rc != 0 - ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" - changed_when: true + - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled | Add feature if missing authselect" # noqa syntax-check[specific]" + when: + - rhel9cis_allow_authselect_updates + - discovered_authselect_current_faillock.rc != 0 + ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}" + changed_when: true + notify: Authselect update + + - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled | Get current config not authselect" + block: + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | not authselect" + when: not rhel9cis_allow_authselect_updates + ansible.builtin.command: grep -E "(auth|account)\s*required\s*pam_faillock.so" /etc/pam.d/{system,password}-auth + changed_when: false + failed_when: false + register: discovered_faillock_not_authselect + + - name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled | Add lines system-auth" + when: not rhel9cis_allow_authselect_updates + ansible.builtin.lineinfile: + path: "/etc/pam.d/system-auth" + regexp: "{{ item.regexp }}" + insertbefore: "{{ item.before | default(omit) }}" + insertafter: "{{ item.after | default(omit) }}" + line: "{{ item.line }}" + loop: + - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } + - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } + - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: account required pam_faillock.so } + + - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add lines password-auth" + when: not rhel9cis_allow_authselect_updates + ansible.builtin.lineinfile: + path: "/etc/pam.d/password-auth" + regexp: "{{ item.regexp }}" + insertbefore: "{{ item.before | default(omit) }}" + insertafter: "{{ item.after | default(omit) }}" + line: "{{ item.line }}" + loop: + - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } + - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } + - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: account required pam_faillock.so } - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: From c0ce0533387039e8f8d599b0ef98723e407daba9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 13 Jan 2025 11:55:41 +0000 Subject: [PATCH 152/327] added origin #272 5.3.3.3.3 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.3.3.x.yml | 52 +++++-------------------------- 1 file changed, 8 insertions(+), 44 deletions(-) diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index ca5a5dc..8fe6036 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -54,43 +54,10 @@ - patch - rule_5.3.3.3.2 - pam - block: - - name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files" - ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/{system,password}-auth - register: discovered_pwhistory_enforce_for_root - changed_when: false - failed_when: discovered_pwhistory_enforce_for_root.rc not in [0, 1] - - - name: "5.3.3.3.2 | PATCH| Ensure password history is enforced for the root user | Ensure enforce_for_root is set pwhistory file" - ansible.builtin.lineinfile: - path: "/etc/security/pwhistory.conf" - regexp: ^\s*(?#)enforce_for_root - line: enforce_for_root - - - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" - when: - - not rhel9cis_allow_authselect_updates - - discovered_pwhistory_enforce_for_root.stdout | length == 0 - - rhel9cis_disruption_high - ansible.builtin.lineinfile: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" - regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root) - line: '\1\2\3 enforce_for_root' - backrefs: true - - - name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set" - when: - - rhel9cis_allow_authselect_updates - - discovered_pwhistory_enforce_for_root.stdout | length == 0 - - rhel9cis_disruption_high - ansible.builtin.replace: - path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth" - regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\senforce_for_root(.*$) - replace: \1\2enforce_for_root\3 - loop: - - password - - system - notify: Authselect update + ansible.builtin.lineinfile: + path: "/etc/security/pwhistory.conf" + regexp: ^\s*(?#)enforce_for_root + line: enforce_for_root - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok" when: rhel9cis_rule_5_3_3_3_3 @@ -107,22 +74,19 @@ changed_when: false failed_when: discovered_pwhistory_use_authtok.rc not in [0, 1] - - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Update pwhistory for use_authtok" - ansible.builtin.lineinfile: - path: "/etc/security/pwhistory.conf" - regexp: ^\s*(?#)use_authtok - line: use_authtok - - name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure use_authtok is set" when: - not rhel9cis_allow_authselect_updates - discovered_pwhistory_use_authtok.stdout | length == 0 - rhel9cis_disruption_high ansible.builtin.lineinfile: - path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}" + path: "{{ item }}" regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) line: '\1\2 use_authtok' backrefs: true + loop: + - /etc/pam.d/password-auth + - /etc/pam.d/system-auth - name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect" when: From 60d4e73bb0c67ab2873ebf50d27fc1ef813b3e1b Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Jan 2025 17:49:55 +0000 Subject: [PATCH 153/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.22.1 → v8.23.0](https://github.com/gitleaks/gitleaks/compare/v8.22.1...v8.23.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4561cf6..4671271 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.22.1 + rev: v8.23.0 hooks: - id: gitleaks From 6f1fce2fc42044a9514baf7b5452a53eb92c5809 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 20 Jan 2025 17:45:13 +0000 Subject: [PATCH 154/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.23.0 → v8.23.1](https://github.com/gitleaks/gitleaks/compare/v8.23.0...v8.23.1) - [github.com/ansible-community/ansible-lint: v24.12.2 → v25.1.0](https://github.com/ansible-community/ansible-lint/compare/v24.12.2...v25.1.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4671271..c80dacd 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.23.0 + rev: v8.23.1 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v24.12.2 + rev: v25.1.0 hooks: - id: ansible-lint name: Ansible-lint From fb73b18596f3d5ad19ee11800e0931bc6defd132 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 22 Jan 2025 08:53:02 +0000 Subject: [PATCH 155/327] Add new pwquality dicovery & title update Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 6602d28..5695843 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -177,14 +177,14 @@ ansible.builtin.set_fact: grub2_path: /etc/grub2-efi.cfg -- name: "PRELIM | Discover Gnome Desktop Environment" +- name: "PRELIM | AUDIT | Discover Gnome Desktop Environment" tags: - always ansible.builtin.stat: path: /usr/share/gnome/gnome-version.xml register: prelim_gnome_present -- name: "PRELIM | Install dconf if gui installed" +- name: "PRELIM | PATCH | Install dconf if gui installed" when: - rhel9cis_gui tags: @@ -243,6 +243,15 @@ mode: 'go-rwx' state: touch +- name: "PRELIM | AUDIT | Capture pam secuirty related files" + tags: always + ansible.builtin.find: + paths: + - /etc/security/pwquality.conf.d/ + - /etc/pam.d/ + patterns: '*-auth,*.conf' + register: prelim_pam_pwquality_confs + - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" when: rhel9cis_rule_5_4_2_1 tags: @@ -326,7 +335,7 @@ changed_when: false register: prelim_uid_max_id - - name: "PRELIM | AUDIT | set_facts for interactive uid/gid" + - name: "PRELIM | AUDIT | Set Fact for interactive uid/gid" ansible.builtin.set_fact: prelim_min_int_uid: "{{ prelim_uid_min_id.stdout }}" prelim_max_int_uid: "{{ prelim_uid_max_id.stdout }}" From 5e176d4dc9bf4ce22c4d532cdbc18501b9433e45 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 22 Jan 2025 08:53:27 +0000 Subject: [PATCH 156/327] Use new prelim task for controls based on #273 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.3.2.x.yml | 42 +++++++++++++------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index 920ed88..702503d 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -18,10 +18,9 @@ path: "{{ item }}" regexp: 'difok\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - /etc/pam.d/*-auth + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists" ansible.builtin.template: @@ -74,10 +73,9 @@ path: "{{ item }}" regexp: 'minlen\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/*-auth' + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists" ansible.builtin.template: @@ -130,10 +128,9 @@ path: "{{ item }}" regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/*-auth' + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists" ansible.builtin.template: @@ -184,10 +181,9 @@ path: "{{ item }}" regexp: 'maxrepeat\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/*-auth' + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists" ansible.builtin.template: @@ -240,10 +236,9 @@ path: "{{ item }}" regexp: 'maxsequence\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/*-auth' + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists" ansible.builtin.template: @@ -295,10 +290,9 @@ path: "{{ item }}" regexp: 'dictcheck\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/*-auth' + loop: + - /etc/security/pwquality.conf + - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists" ansible.builtin.template: From 7d49c0d27c69419189b8b31f930b10ba1aa7d53f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 22 Jan 2025 14:23:31 +0000 Subject: [PATCH 157/327] added fix for #280 thanks to @msachikanta Signed-off-by: Mark Bolwell --- templates/etc/systemd/system/tmp.mount.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/etc/systemd/system/tmp.mount.j2 b/templates/etc/systemd/system/tmp.mount.j2 index 3f689ee..7f64547 100644 --- a/templates/etc/systemd/system/tmp.mount.j2 +++ b/templates/etc/systemd/system/tmp.mount.j2 @@ -23,7 +23,7 @@ After=swap.target What=tmpfs Where=/tmp Type=tmpfs -Options=mode=1777,strictatime,{% if rhel9cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_4 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_3 %}noexec{% endif %} +Options=mode=1777,strictatime,{% if rhel9cis_rule_1_1_2_1_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_1_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_2_1_4 %}noexec{% endif %} # Make 'systemctl enable tmp.mount' work: [Install] From 9f3d8becf03de14eed78d59f13a6d09d8de2e910 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 22 Jan 2025 16:56:51 +0000 Subject: [PATCH 158/327] Improve logic for 5.3.3.2.x controls Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 5 ++-- tasks/section_5/cis_5.3.3.2.x.yml | 48 +++++++++++++++++++------------ 2 files changed, 32 insertions(+), 21 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 5695843..1ec355b 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -243,13 +243,12 @@ mode: 'go-rwx' state: touch -- name: "PRELIM | AUDIT | Capture pam secuirty related files" +- name: "PRELIM | AUDIT | Capture pam security related files" tags: always ansible.builtin.find: paths: - /etc/security/pwquality.conf.d/ - - /etc/pam.d/ - patterns: '*-auth,*.conf' + patterns: '*.conf' register: prelim_pam_pwquality_confs - name: "PRELIM | AUDIT | Gather UID 0 accounts other than root" diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index 702503d..e8e1530 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -14,13 +14,15 @@ when: - item != rhel9cis_passwd_difok_file - rhel9cis_disruption_high - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: 'difok\s*=\s*\d+\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists" ansible.builtin.template: @@ -69,13 +71,15 @@ when: - item != rhel9cis_passwd_minlen_file - rhel9cis_disruption_high - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: 'minlen\s*=\s*\d+\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists" ansible.builtin.template: @@ -124,13 +128,15 @@ when: - item != rhel9cis_passwd_complex_file - rhel9cis_disruption_high - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists" ansible.builtin.template: @@ -177,13 +183,15 @@ block: - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file" when: item != rhel9cis_passwd_maxrepeat_file - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: 'maxrepeat\s*=\s*\d+\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists" ansible.builtin.template: @@ -232,13 +240,15 @@ when: - item != rhel9cis_passwd_maxsequence_file - rhel9cis_disruption_high - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: 'maxsequence\s*=\s*\d+\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists" ansible.builtin.template: @@ -286,13 +296,15 @@ - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck settings from conf files except expected file" when: - item != rhel9cis_passwd_dictcheck_file - ansible.builtin.replace: + ansible.builtin.lineinfile: path: "{{ item }}" regexp: 'dictcheck\s*=\s*\d+\b' - replace: '' + state: absent loop: - /etc/security/pwquality.conf - - "{{ prelim_pam_pwquality_confs.files | default ([]) }}" + - /etc/pam.d/system-auth + - /etc/pam.d/password-auth + - "{{ prelim_pam_pwquality_confs.files | default([]) }}" - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists" ansible.builtin.template: From ee9258a74b37a449187cf96aa155e5c512db6d3e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 27 Jan 2025 17:53:00 +0000 Subject: [PATCH 159/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.23.1 → v8.23.2](https://github.com/gitleaks/gitleaks/compare/v8.23.1...v8.23.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c80dacd..a802c69 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.23.1 + rev: v8.23.2 hooks: - id: gitleaks From d1a6f6d2b854de835b9cf5adcfa0a9fc6696f4ee Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 29 Jan 2025 10:27:20 +0000 Subject: [PATCH 160/327] Updated arm discovery Signed-off-by: Mark Bolwell --- tasks/LE_audit_setup.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/LE_audit_setup.yml b/tasks/LE_audit_setup.yml index c1fd66e..d784dc1 100644 --- a/tasks/LE_audit_setup.yml +++ b/tasks/LE_audit_setup.yml @@ -7,7 +7,7 @@ audit_pkg_arch_name: AMD64 - name: Pre Audit Setup | Set audit package name | ARM64 - when: ansible_facts.machine == "arm64" + when: (ansible_facts.machine == "arm64" or ansible_facts.machine == "aarch64") ansible.builtin.set_fact: audit_pkg_arch_name: ARM64 @@ -24,7 +24,7 @@ - name: Pre Audit Setup | Copy audit binary when: get_audit_binary_method == 'copy' ansible.builtin.copy: - src: "{{ audit_bin_copy_location }}" + src: "{{ audit_bin_copy_location }}/goss-linux-{{ audit_pkg_arch_name }}" dest: "{{ audit_bin }}" owner: root group: root From c178cba7bc68031f460303fe836e74d89e36827c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 29 Jan 2025 13:53:58 +0000 Subject: [PATCH 161/327] Updated comments Signed-off-by: Mark Bolwell --- vars/main.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/vars/main.yml b/vars/main.yml index 93439ad..c1d0fb3 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -24,9 +24,11 @@ warn_count: 0 gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" -## Control 6.3.3.x - Audit template -# This variable governs if the auditd logic should be executed(if value is true). -# NOTE: The current default value is likely to be overriden(via 'set_fact') by other further tasks(in sub-section 'Auditd rules'). +## Controls 6.3.3.x - Audit template +# This variable is set to true by tasks 6.3.3.1 to 6.3.3.20. As a result, the +# audit settings are overwritten with the role's template. In order to exclude +# specific rules, you must set the variable of form `ubtu24cis_rule_6_3_3_x` above +# to `false`. update_audit_template: false # Defaults From ed1a209635b724b76e96143351559252e5c9cb1f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 29 Jan 2025 13:54:13 +0000 Subject: [PATCH 162/327] Updated audit rules for arch Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 19 +++- templates/audit/99_auditd.rules.j2 | 135 ++++++++++++++++++++++++----- 2 files changed, 129 insertions(+), 25 deletions(-) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7022e2c..7b86b94 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -1,17 +1,30 @@ --- -- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file +# Since auditd rules are dependent on syscalls and syscall tables are architecture specific, +# we need to update the auditd rules depending on the architecture of the system. +# This task passed the syscalls table to the auditd template and updates the auditd rules + +- name: "POST | AUDITD | Set supported_syscalls variable" + ansible.builtin.shell: ausyscall --dump | awk '{print $2}' + changed_when: false + failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] + register: discovered_auditd_syscalls + +- name: POST | AUDITD | Apply auditd template will for section 6.3.3 - only required rules will be added | stat file ansible.builtin.stat: path: /etc/audit/rules.d/99_auditd.rules register: discovered_auditd_rules_file -- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | setup file +- name: POST | Apply auditd template for section 6.3.3.x + when: update_audit_template + vars: + supported_syscalls: "{{ discovered_auditd_syscalls.stdout_lines }}" ansible.builtin.template: src: audit/99_auditd.rules.j2 dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: '0640' + mode: 'u-x,go-wx' diff: "{{ discovered_auditd_rules_file.stat.exists }}" # Only run diff if not a new file register: discovered_auditd_rules_template_updated notify: diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index e977e4e..cb12736 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -9,20 +9,40 @@ -w /etc/sudoers.d -p wa -k scope {% endif %} {% if rhel9cis_rule_6_3_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 +{% set syscalls = ["execve"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation +-a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation {% endif %} {% if rhel9cis_rule_6_3_3_3 %} -w {{ rhel9cis_sudolog_location }} -p wa -k sudo_log_file {% endif %} {% if rhel9cis_rule_6_3_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 +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k time-change +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k time-change -w /etc/localtime -p wa -k time-change {% endif %} {% if rhel9cis_rule_6_3_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 +{% set syscalls = ["sethostname","setdomainname"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k 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 @@ -35,10 +55,17 @@ {% endfor %} {% endif %} {% if rhel9cis_rule_6_3_3_7 %} --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b64 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S creat,open,openat,truncate,ftruncate -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +{% set syscalls = ["creat","open","openat","truncate","ftruncate"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access {% endif %} {% if rhel9cis_rule_6_3_3_8 %} -w /etc/group -p wa -k identity @@ -51,16 +78,66 @@ -w /etc/pam.d -p wa -k identity {% endif %} {% if rhel9cis_rule_6_3_3_9 %} --a always,exit -F arch=b64 -S chmod,fchmod,fchmodat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S chown,fchown,lchown,fchownat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S chmod,fchmod,fchmodat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S lchown,fchown,chown,fchownat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b64 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod --a always,exit -F arch=b32 -S setxattr,lsetxattr,fsetxattr,removexattr,lremovexattr,fremovexattr -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=perm_mod +{% set syscalls = ["chmod","fchmod","fchmodat"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +{% set syscalls = ["chown","fchown","lchown","fchownat"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +{% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +{% set syscalls = ["chmod","fchmod","fchmodat"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +{% set syscalls = ["chown","fchown","lchown","fchownat"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +{% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% endif %} {% if rhel9cis_rule_6_3_3_10 %} --a always,exit -F arch=b32 -S mount -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts --a always,exit -F arch=b64 -S mount -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts +{% set syscalls = ["mount"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts +{% endif %} {% endif %} {% if rhel9cis_rule_6_3_3_11 %} -w /var/run/utmp -p wa -k session @@ -72,8 +149,15 @@ -w /var/run/faillock -p wa -k logins {% endif %} {% if rhel9cis_rule_6_3_3_13 %} --a always,exit -F arch=b64 -S rename,unlink,unlinkat,renameat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=delete --a always,exit -F arch=b32 -S rename,unlink,unlinkat,renameat -F auid>={{ prelim_min_int_uid }} -F auid!=unset -F key=delete +{% set syscalls = ["unlink","unlinkat","rename","renameat"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k delete +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k delete {% endif %} {% if rhel9cis_rule_6_3_3_14 %} -w /etc/selinux -p wa -k MAC-policy @@ -92,8 +176,15 @@ -a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k usermod {% endif %} {% if rhel9cis_rule_6_3_3_19 %} --a always,exit -F arch=b64 -S init_module,finit_module,delete_module,create_module,query_module -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules --a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules +-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid=>{{ prelim_min_int_uid }} -F auid!=-1 -k kernel_modules +{% set syscalls = ["init_module","finit_module","delete_module","create_module","query_module"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append( syscall) }} +{% endif %} +{% endfor %} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=-1 -k kernel_modules {% endif %} {% if rhel9cis_rule_6_3_3_20 %} -e 2 From 91699576985e103d8c03d94d4a0b58038da010b8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 29 Jan 2025 14:22:24 +0000 Subject: [PATCH 163/327] Updated template Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 1 - 1 file changed, 1 deletion(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index cb12736..c162bc0 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -138,7 +138,6 @@ -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts {% endif %} -{% endif %} {% if rhel9cis_rule_6_3_3_11 %} -w /var/run/utmp -p wa -k session -w /var/log/wtmp -p wa -k session From b9a4503558a966af2fde6d517cca7a2f500aede5 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 30 Jan 2025 10:19:42 +0000 Subject: [PATCH 164/327] Updated and tested rules Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 58 +++++++++++++++--------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index c162bc0..b9e632c 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -11,11 +11,11 @@ {% if rhel9cis_rule_6_3_3_2 %} {% set syscalls = ["execve"] %} {% set arch_syscalls = [] %} -{% for syscall in syscalls %} +{%- for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} -{% endfor %} +{% endfor -%} -a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation -a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation {% endif %} @@ -26,7 +26,7 @@ {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k time-change @@ -38,7 +38,7 @@ {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale @@ -59,13 +59,13 @@ {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access {% endif %} {% if rhel9cis_rule_6_3_3_8 %} -w /etc/group -p wa -k identity @@ -82,61 +82,61 @@ {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chmod","fchmod","fchmodat"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k perm_mod +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% endif %} {% if rhel9cis_rule_6_3_3_10 %} {% set syscalls = ["mount"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} +{{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k mounts +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts {% endif %} {% if rhel9cis_rule_6_3_3_11 %} -w /var/run/utmp -p wa -k session @@ -155,8 +155,8 @@ {{ arch_syscalls.append( syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k delete --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=unset -k delete +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete {% endif %} {% if rhel9cis_rule_6_3_3_14 %} -w /etc/selinux -p wa -k MAC-policy @@ -175,7 +175,7 @@ -a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k usermod {% endif %} {% if rhel9cis_rule_6_3_3_19 %} --a always,exit -F path=/usr/bin/kmod -F perm=x -F auid=>{{ prelim_min_int_uid }} -F auid!=-1 -k kernel_modules +-a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% set syscalls = ["init_module","finit_module","delete_module","create_module","query_module"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} @@ -183,7 +183,7 @@ {{ arch_syscalls.append( syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid=>{{ prelim_min_int_uid }} -F auid!=-1 -k kernel_modules +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% endif %} {% if rhel9cis_rule_6_3_3_20 %} -e 2 From fecfb7e79384aaf4caeaf3c4a7cc078e30bad690 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 30 Jan 2025 12:40:52 +0000 Subject: [PATCH 165/327] addressed issue #282 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.3.3.x.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_5/cis_5.3.3.3.x.yml b/tasks/section_5/cis_5.3.3.3.x.yml index 8fe6036..9daf71a 100644 --- a/tasks/section_5/cis_5.3.3.3.x.yml +++ b/tasks/section_5/cis_5.3.3.3.x.yml @@ -69,7 +69,7 @@ - pam block: - name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files" - ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{system,password}-auth + ansible.builtin.shell: grep -Psic -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{system,password}-auth register: discovered_pwhistory_use_authtok changed_when: false failed_when: discovered_pwhistory_use_authtok.rc not in [0, 1] @@ -81,9 +81,9 @@ - rhel9cis_disruption_high ansible.builtin.lineinfile: path: "{{ item }}" - regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok) - line: '\1\2 use_authtok' - backrefs: true + regexp: ^password\s*pam_pwhistory\.so\s*.*\s(!?use_authtok) + line: password required pam_pwhistory.so use_authtok + insertbefore: ^password.*pam_deny.so loop: - /etc/pam.d/password-auth - /etc/pam.d/system-auth From e121cb4992c1bae9f7fffef8113cb51fe100539c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 30 Jan 2025 15:34:30 +0000 Subject: [PATCH 166/327] Fix quoting Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index ef84113..eadb9b5 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -95,7 +95,7 @@ loop: - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: account required pam_faillock.so } + - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add lines password-auth" when: not rhel9cis_allow_authselect_updates @@ -108,7 +108,7 @@ loop: - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: account required pam_faillock.so } + - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: From 761f8517c42f7ad3a23ba9106e23b95c25402b87 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 30 Jan 2025 15:34:42 +0000 Subject: [PATCH 167/327] fix spacing Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.3.1.x.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 19e1c44..1730521 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -24,7 +24,7 @@ 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 + replace: \1 \2\3 loop: - password - system @@ -126,4 +126,3 @@ loop: - password - system - notify: Authselect update From f9478c0e39a0e01898d424839caebf9e188632f6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 3 Feb 2025 18:04:46 +0000 Subject: [PATCH 168/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.23.2 → v8.23.3](https://github.com/gitleaks/gitleaks/compare/v8.23.2...v8.23.3) - [github.com/ansible-community/ansible-lint: v25.1.0 → v25.1.1](https://github.com/ansible-community/ansible-lint/compare/v25.1.0...v25.1.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a802c69..e4e845e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.23.2 + rev: v8.23.3 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.1.0 + rev: v25.1.1 hooks: - id: ansible-lint name: Ansible-lint From 49807a096b9f64016577da6997761005f24b7703 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 7 Feb 2025 12:20:45 +0000 Subject: [PATCH 169/327] updated logic on 7.2.9 Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.2.x.yml | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 2a33f33..cc1825c 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -287,15 +287,15 @@ warn_control_id: '7.2.9' block: - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" - ansible.builtin.shell: find /home/ -name "\.*" -perm /g+w,o+w + ansible.builtin.shell: find /home/ -name "\.*" changed_when: false - failed_when: discovered_homedir_dot_files.rc not in [ 0, 1 ] + failed_when: discovered_homedir_hidden_files.rc not in [ 0, 1 ] check_mode: false - register: discovered_homedir_dot_files + register: discovered_homedir_hidden_files - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.debug: msg: @@ -303,16 +303,18 @@ - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.import_tasks: file: warning_facts.yml - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" when: - - discovered_homedir_dot_files.stdout | length > 0 + - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - with_items: "{{ discovered_homedir_dot_files.stdout_lines }}" + owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" From 5e722198656c2053f7a192624abbb83184adecc7 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Feb 2025 17:53:49 +0000 Subject: [PATCH 170/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.1.1 → v25.1.2](https://github.com/ansible-community/ansible-lint/compare/v25.1.1...v25.1.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e4e845e..401d32e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.1.1 + rev: v25.1.2 hooks: - id: ansible-lint name: Ansible-lint From 2078657ceb9994de5142b7a6761edbb5a7733351 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 20 Feb 2025 10:22:11 +0000 Subject: [PATCH 171/327] added fix for #293 thanks to @machikanta Signed-off-by: Mark Bolwell --- defaults/main.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index 3f6202b..1735ce8 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1303,3 +1303,9 @@ rhel9cis_suid_sgid_adjust: false ## Control 7.1.11 - Ensure no world writable files exist # Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable. rhel9cis_no_world_write_adjust: true + + +## Control 7.2.9 +# This allows ansible to alter the dot files as per rule if found +# When set to true this will align with benchmark - can impact a running system if not tested sufficiently +rhel9cis_dotperm_ansiblemanaged: false From d6a560b2c8df1ce22fb111dac7186e92b76d51b7 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 20 Feb 2025 11:54:14 +0000 Subject: [PATCH 172/327] rsyslog_#294 thanks to @alopezgcp Signed-off-by: Mark Bolwell --- defaults/main.yml | 134 +++++++++++++--------- tasks/section_6/cis_6.2.3.x.yml | 4 +- tasks/section_6/main.yml | 1 + templates/etc/logrotate.d/rsyslog.conf.j2 | 11 -- templates/etc/logrotate.d/rsyslog_log.j2 | 26 +++++ 5 files changed, 107 insertions(+), 69 deletions(-) delete mode 100644 templates/etc/logrotate.d/rsyslog.conf.j2 create mode 100644 templates/etc/logrotate.d/rsyslog_log.j2 diff --git a/defaults/main.yml b/defaults/main.yml index 1735ce8..546e0e7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1100,14 +1100,68 @@ rhel9cis_aide_cron: # ## Preferred method of logging ## Whether rsyslog or journald preferred method for local logging -## Control 6.2.3 | Configure rsyslog -## Control 6.2.1 | Configure journald -# This variable governs which logging service should be used, choosing between 'rsyslog'(CIS recommendation) -# or 'journald'(only one is implemented) will trigger the execution of the associated subsection, as the-best +## Controls 6.2.1.x | Configure systemd-journald service +## Controls 6.2.2.x | Configured journald +## Controls 6.2.3.x | Configure rsyslog + +# This variable governs which logging service should be used, choosing between 'rsyslog' +# or 'journald'(CIS recommendation) will trigger the execution of the associated subsection, as the-best # practices are written wholly independent of each other. rhel9cis_syslog: journald -## Control 6.2.2.x & 6.2.3.x - Ensure rsyslog is not configured to receive logs from a remote client +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy +# Current variable configures the max amount of disk space the logs will use(thus, journal files +# will not grow without bounds) +# The variables below related to journald, please set these to your site specific values +# These variable specifies how much disk space the journal may use up at most +# Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes. +# See https://www.freedesktop.org/software/systemd/man/journald.conf.html for more information. +rhel9cis_journald_systemmaxuse: 10M +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy +# Current variable configures the amount of disk space to keep free for other uses. +rhel9cis_journald_systemkeepfree: 100G +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy +# This variable configures how much disk space the journal may use up at most. +# Similar with 'rhel9cis_journald_systemmaxuse', but related to runtime space. +rhel9cis_journald_runtimemaxuse: 10M +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy +# This variable configures the actual amount of disk space to keep free +# Similar with 'rhel9cis_journald_systemkeepfree', but related to runtime space. +rhel9cis_journald_runtimekeepfree: 100G +## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy +# Current variable governs the settings for log retention(how long the log files will be kept). +# Thus, it specifies the maximum time to store entries in a single journal +# file before rotating to the next one. Set to 0 to turn off this feature. +# The given values is interpreted as seconds, unless suffixed with the units +# `year`, `month`, `week`, `day`, `h` or `m` to override the default time unit of seconds. +# Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks +# ATTENTION: Uncomment the keyword below when values are set! +rhel9cis_journald_maxfilesec: 1month + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to +# URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port +# number may be specified after a colon (":"), otherwise 19532 will be used by default. +rhel9cis_journal_upload_url: 192.168.50.42 +## The paths below have the default paths/files, but allow user to create custom paths/filenames + +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the private key file used by the remote journal +# server to authenticate itself to the client. This key is used alongside the server's +# public certificate to establish secure communication. +rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to the public certificate file of the remote journal +# server. This certificate is used to verify the authenticity of the remote server. +rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" +## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +# This variable specifies the path to a file containing one or more public certificates +# of certificate authorities (CAs) that the client trusts. These trusted certificates are used +# to validate the authenticity of the remote server's certificate. +rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" +# ATTENTION: Uncomment the keyword below when values are set! + +# Control 6.2.3.x - Ensure rsyslog is not configured to receive logs from a remote client # This variable expresses whether the system is used as a log server or not. If set to: # - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. # - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity @@ -1155,57 +1209,25 @@ rhel9cis_remote_log_retrycount: 100 # of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). rhel9cis_remote_log_queuesize: 1000 -## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured -# 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to -# URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port -# number may be specified after a colon (":"), otherwise 19532 will be used by default. -rhel9cis_journal_upload_url: 192.168.50.42 -## The paths below have the default paths/files, but allow user to create custom paths/filenames - -## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to the private key file used by the remote journal -# server to authenticate itself to the client. This key is used alongside the server's -# public certificate to establish secure communication. -rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" -## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to the public certificate file of the remote journal -# server. This certificate is used to verify the authenticity of the remote server. -rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" -## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured -# This variable specifies the path to a file containing one or more public certificates -# of certificate authorities (CAs) that the client trusts. These trusted certificates are used -# to validate the authenticity of the remote server's certificate. -rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" -# ATTENTION: Uncomment the keyword below when values are set! - -## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy -# Current variable configures the max amount of disk space the logs will use(thus, journal files -# will not grow without bounds) -# The variables below related to journald, please set these to your site specific values -# These variable specifies how much disk space the journal may use up at most -# Specify values in bytes or use K, M, G, T, P, E as units for the specified sizes. -# See https://www.freedesktop.org/software/systemd/man/journald.conf.html for more information. -rhel9cis_journald_systemmaxuse: 10M -## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy -# Current variable configures the amount of disk space to keep free for other uses. -rhel9cis_journald_systemkeepfree: 100G -## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy -# This variable configures how much disk space the journal may use up at most. -# Similar with 'rhel9cis_journald_systemmaxuse', but related to runtime space. -rhel9cis_journald_runtimemaxuse: 10M -## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy -# This variable configures the actual amount of disk space to keep free -# Similar with 'rhel9cis_journald_systemkeepfree', but related to runtime space. -rhel9cis_journald_runtimekeepfree: 100G -## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy -# Current variable governs the settings for log retention(how long the log files will be kept). -# Thus, it specifies the maximum time to store entries in a single journal -# file before rotating to the next one. Set to 0 to turn off this feature. -# The given values is interpreted as seconds, unless suffixed with the units -# `year`, `month`, `week`, `day`, `h` or `m` to override the default time unit of seconds. -# Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks -# ATTENTION: Uncomment the keyword below when values are set! -rhel9cis_journald_maxfilesec: 1month +## Control 6.2.3.8 rsyslog rotate +# This variable configures whether to set your own rsyslog logrotate setting alternate to logrotate default settings +#Please refer to logrotate options to match your site requirements +# This sets when to rotate +rhel9cis_rsyslog_logrotate_rotated_when: weekly +# This sets how many rotations of the file to keep +rhel9cis_rsyslog_logrotate_rotatation_keep: 4 +# This defines whether to set various options or not +# these are taken from logrotate options +# Setting +# true will carry out the setting. +# false will either set no/not or not add the option +rhel9cis_rsyslog_logrotate_compress: true +rhel9cis_rsyslog_logrotate_missingok: true +rhel9cis_rsyslog_logrotate_notifempty: true +rhel9cis_rsyslog_logrotate_create: true +# Extra options that can be added according to rsyslog documentation +# Uncomment and add the required options e.g. mode owner group +#rhel9cis_rsyslog_logrotate_create_opts: ## Control 6.3.2.1 - Ensure audit_backlog_limit is sufficient # This variable represents the audit backlog limit, i.e., the maximum number of audit records that the diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 9333697..9d26acf 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -256,8 +256,8 @@ - name: "6.2.3.8 | PATCH | Ensure logrotate is configured | set rsyslog conf" ansible.builtin.template: - src: etc/logrotate.d/rsyslog.conf.j2 - dest: /etc/logrotate.d/rsyslog.conf + src: etc/logrotate.d/rsyslog_log.j2 + dest: /etc/logrotate.d/rsyslog_log owner: root group: root mode: 'g-wx,o-rwx' diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index a1909dc..dda7ee5 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -5,6 +5,7 @@ file: cis_6.1.x.yml - name: "SECTION | 6.2.1 | Configure systemd-journald service" + when: rhel9cis_syslog == 'journald' ansible.builtin.import_tasks: file: cis_6.2.1.x.yml diff --git a/templates/etc/logrotate.d/rsyslog.conf.j2 b/templates/etc/logrotate.d/rsyslog.conf.j2 deleted file mode 100644 index 2423b24..0000000 --- a/templates/etc/logrotate.d/rsyslog.conf.j2 +++ /dev/null @@ -1,11 +0,0 @@ -/var/log/rsyslog/*.log { - {{ rhel9cis_rsyslog_logrotate_rotated }} - rotate {{ rhel9cis_rsyslog_logrotate_keep }} - {% if rhel9cis_rsyslog_logrotate_compress %}compress{% else %}nocompress{% endif %} - {% if rhel9cis_rsyslog_logrotate_missingok %}missingok{% else %}missingok{% endif %} - {% if rhel9cis_rsyslog_logrotate_notifempty %}notifempty{% else %}ifempty{% endif %} - {% if rhel9cis_rsyslog_logrotate_create %}create {{ rhel9cis_rsyslog_logrotate_create_opts }}{% endif %} - postrotate - /usr/bin/systemctl reload rsyslog.service >/dev/null || true - endscript -} diff --git a/templates/etc/logrotate.d/rsyslog_log.j2 b/templates/etc/logrotate.d/rsyslog_log.j2 new file mode 100644 index 0000000..8acb53e --- /dev/null +++ b/templates/etc/logrotate.d/rsyslog_log.j2 @@ -0,0 +1,26 @@ +/var/log/rsyslog/*.log { + {{ rhel9cis_rsyslog_logrotate_rotated_when }} + rotate {{ rhel9cis_rsyslog_logrotate_rotatation_keep }} +{% if rhel9cis_rsyslog_logrotate_compress %} + compress +{% else %} + nocompress +{% endif %} +{% if rhel9cis_rsyslog_logrotate_missingok %} + missingok +{% else %} + nomissingok +{% endif %} +{% if rhel9cis_rsyslog_logrotate_notifempty %} + notifempty +{% else %} + ifempty +{% endif %} +{% if rhel9cis_rsyslog_logrotate_create %} + create{% if rhel9cis_rsyslog_logrotate_create_opts is defined %} {{ rhel9cis_rsyslog_logrotate_create_opts }}{% endif %} +{% endif %} + + postrotate + /usr/bin/systemctl reload rsyslog.service >/dev/null || true + endscript +} From 3441894ab4392a3619e68c6beb35cdce9bc69a81 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 20 Feb 2025 11:55:59 +0000 Subject: [PATCH 173/327] Lint update Signed-off-by: Mark Bolwell --- defaults/main.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 546e0e7..f5c38b1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1211,7 +1211,7 @@ rhel9cis_remote_log_queuesize: 1000 ## Control 6.2.3.8 rsyslog rotate # This variable configures whether to set your own rsyslog logrotate setting alternate to logrotate default settings -#Please refer to logrotate options to match your site requirements +# Please refer to logrotate options to match your site requirements # This sets when to rotate rhel9cis_rsyslog_logrotate_rotated_when: weekly # This sets how many rotations of the file to keep @@ -1227,7 +1227,7 @@ rhel9cis_rsyslog_logrotate_notifempty: true rhel9cis_rsyslog_logrotate_create: true # Extra options that can be added according to rsyslog documentation # Uncomment and add the required options e.g. mode owner group -#rhel9cis_rsyslog_logrotate_create_opts: +# rhel9cis_rsyslog_logrotate_create_opts: ## Control 6.3.2.1 - Ensure audit_backlog_limit is sufficient # This variable represents the audit backlog limit, i.e., the maximum number of audit records that the @@ -1326,7 +1326,6 @@ rhel9cis_suid_sgid_adjust: false # Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable. rhel9cis_no_world_write_adjust: true - ## Control 7.2.9 # This allows ansible to alter the dot files as per rule if found # When set to true this will align with benchmark - can impact a running system if not tested sufficiently From eb77cdd36763e65a9dabf3c08238f4684b3fbe66 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 20 Feb 2025 11:56:30 +0000 Subject: [PATCH 174/327] Added precommit exclusion Signed-off-by: Mark Bolwell --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f67408e..de8046f 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,6 @@ benchparse/ # GitHub Action/Workflow files .github/ + +# Precommit exclusions +.ansible/ From f9c7ff5949c6b476bc8cf7df6ee5fddd0fc57a6d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Feb 2025 17:24:15 +0000 Subject: [PATCH 175/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.23.3 → v8.24.0](https://github.com/gitleaks/gitleaks/compare/v8.23.3...v8.24.0) - [github.com/ansible-community/ansible-lint: v25.1.2 → v25.1.3](https://github.com/ansible-community/ansible-lint/compare/v25.1.2...v25.1.3) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 401d32e..4791982 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.23.3 + rev: v8.24.0 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.1.2 + rev: v25.1.3 hooks: - id: ansible-lint name: Ansible-lint From 8cc3738fda2c745b73bd1f7c36342084479d5fda Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 08:23:24 +0000 Subject: [PATCH 176/327] added pre-commit badge Signed-off-by: Mark Bolwell --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a16287d..d3bf75a 100644 --- a/README.md +++ b/README.md @@ -27,6 +27,7 @@ ![Issues Open](https://img.shields.io/github/issues-raw/ansible-lockdown/RHEL9-CIS?label=Open%20Issues) ![Issues Closed](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/RHEL9-CIS?label=Closed%20Issues&&color=success) ![Pull Requests](https://img.shields.io/github/issues-pr/ansible-lockdown/RHEL9-CIS?label=Pull%20Requests) +[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) ![License](https://img.shields.io/github/license/ansible-lockdown/RHEL9-CIS?label=License) From 48a471a037ccb4cc67658f1e50ede9d22d1d3f93 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 08:23:46 +0000 Subject: [PATCH 177/327] issue #296 thanks to @dbsanders Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index ef15f1a..12390b3 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -190,7 +190,7 @@ regexp: \s*umask line: "umask {{ rhel9cis_root_umask }}" create: true - mode: 'u+x,go-rwx' + mode: 'u-x,go-rwx' - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: From 5c919fb19da8e7216e690dca9ade67b1d523d412 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 08:27:12 +0000 Subject: [PATCH 178/327] added #298 & #299 thanks to @brent-bean Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.2.1.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml index 00e949b..945c2e4 100644 --- a/tasks/section_6/cis_6.2.2.1.x.yml +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -17,7 +17,7 @@ name: systemd-journal-remote state: present -- name: "6.2.2.1.2 | PATCH | Ensure systemd-journal-remote authentication is configured" +- name: "6.2.2.1.2 | PATCH | Ensure systemd-journal-upload authentication is configured" when: - rhel9cis_rule_6_2_2_1_2 - not rhel9cis_system_is_log_server @@ -40,7 +40,7 @@ - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'} - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'} -- name: "6.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled and active" +- name: "6.2.2.1.3 | PATCH | Ensure systemd-journal-upload is enabled and active" when: - not rhel9cis_system_is_log_server - rhel9cis_rule_6_2_2_1_3 From 40078515fe95fa31cab24e4bd00c3c0e7eec370c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 11:01:35 +0000 Subject: [PATCH 179/327] updated 1.4.2 thanks to @brent-bean #300 Signed-off-by: Mark Bolwell --- handlers/main.yml | 9 ++++++++ tasks/section_1/cis_1.4.x.yml | 40 +++++++++++++++++++++++++++++++---- vars/main.yml | 3 +++ 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 3c51ddf..1a3b66e 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -144,6 +144,15 @@ state: remounted listen: "Remount /var/log/audit" +- name: "Remounting /boot/efi" + vars: + mount_point: '/boot/efi' + ansible.posix.mount: + path: "{{ mount_point }}" + state: remounted + notify: Change_requires_reboot + listen: "Remount /boot/efi" + - name: Reload sysctl ansible.builtin.command: sysctl --system changed_when: true diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index d422f14..ee941c0 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -29,7 +29,8 @@ - rule_1.4.2 - NIST800-53R5_AC-3 block: - - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured" + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | bios based system" + when: rhel9cis_legacy_boot ansible.builtin.file: path: "/boot/grub2/{{ item.path }}" owner: root @@ -39,6 +40,37 @@ modification_time: preserve access_time: preserve loop: - - { path: 'grub.cfg', mode: '0700' } - - { path: 'grubenv', mode: 'go-rwx' } - - { path: 'user.cfg', mode: 'go-rwx' } + - { path: 'grub.cfg', mode: 'u-x,go-rwx' } + - { path: 'grubenv', mode: 'u-x,go-rwx' } + - { path: 'user.cfg', mode: 'u-x,go-rwx' } + + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system" + when: not rhel9cis_legacy_boot + vars: + efi_mount_options: ['umask=0077','fmask=0077','uid=0','gid=0'] + block: + - name: "1.4.2 | AUDIT | Ensure permissions on bootloader config are configured | efi based system | capture current state" + ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | cut -d ' ' -f4 + changed_when: false + register: discovered_efi_fstab + + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" + when: item not in discovered_efi_fstab.stdout + ansible.builtin.set_fact: + efi_mount_opts_addition: "{{ efi_mount_opts_addition + item + ',' }}" + loop: "{{ efi_mount_options }}" + + - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Add mount options" + ansible.builtin.lineinfile: + path: /etc/fstab + regexp: (.*/boot/efi\s*\w*\s*){{ discovered_efi_fstab.stdout }}(.*) + line: \1{{ discovered_efi_fstab.stdout + efi_mount_opts_addition }}\2 + backrefs: true + notify: Remount /boot/efi + + - debug: + msg: + - "{{ discovered_efi_fstab.stdout }}" + - "{{ efi_mount_opts_addition }}" + + - pause: diff --git a/vars/main.yml b/vars/main.yml index c1d0fb3..cdca90d 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -22,6 +22,9 @@ rhel9cis_allowed_crypto_policies_modules: warn_control_list: "" warn_count: 0 +# Default empty values for 1.4.2 +efi_mount_opts_addition: '' + gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys" ## Controls 6.3.3.x - Audit template From d6fb1734e3a3b9b4104e19e65f91813026fe2217 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 11:27:36 +0000 Subject: [PATCH 180/327] fixed thanks to @brent-bean #301 Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index b9e632c..66ef19d 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -23,6 +23,7 @@ -w {{ rhel9cis_sudolog_location }} -p wa -k sudo_log_file {% endif %} {% if rhel9cis_rule_6_3_3_4 %} +{% set syscalls = ["adjtimex","settimeofday"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} @@ -31,6 +32,14 @@ {% endfor %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k time-change -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k time-change +{% set syscalls = ["clock_settime"] %} +{% set arch_syscalls = [] %} +{% for syscall in syscalls %} +{% if syscall in supported_syscalls %} +{{ arch_syscalls.append(syscall) }} +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change +{% endif %} +{% endfor %} -w /etc/localtime -p wa -k time-change {% endif %} {% if rhel9cis_rule_6_3_3_5 %} From 12be5388ffb49d508a49b4fb3dd0278b6ae9f639 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 12:26:19 +0000 Subject: [PATCH 181/327] improved logic Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.4.x.yml | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index ee941c0..004bfca 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -50,7 +50,7 @@ efi_mount_options: ['umask=0077','fmask=0077','uid=0','gid=0'] block: - name: "1.4.2 | AUDIT | Ensure permissions on bootloader config are configured | efi based system | capture current state" - ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | cut -d ' ' -f4 + ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | awk -F" " '{print $4}' changed_when: false register: discovered_efi_fstab @@ -67,10 +67,3 @@ line: \1{{ discovered_efi_fstab.stdout + efi_mount_opts_addition }}\2 backrefs: true notify: Remount /boot/efi - - - debug: - msg: - - "{{ discovered_efi_fstab.stdout }}" - - "{{ efi_mount_opts_addition }}" - - - pause: From ed1bc1c074ad0c626d6a184f141f3712bd96db50 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 12:26:46 +0000 Subject: [PATCH 182/327] 7.1.10 extended in case file absent Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.1.x.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/section_7/cis_7.1.x.yml b/tasks/section_7/cis_7.1.x.yml index 83c83a0..b23fb89 100644 --- a/tasks/section_7/cis_7.1.x.yml +++ b/tasks/section_7/cis_7.1.x.yml @@ -169,6 +169,8 @@ owner: root group: root mode: 'u-x,go-wx' + failed_when: discovered_file_exists.state not in '[ file, absent ]' + register: discovered_file_exists - name: "7.1.11 | PATCH | Ensure world writable files and directories are secured" when: From 8cd7d765c52737bc334599be7fd923299cef19c2 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 12:26:58 +0000 Subject: [PATCH 183/327] updated layout Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 66ef19d..4d9c0d3 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -37,6 +37,7 @@ {% for syscall in syscalls %} {% if syscall in supported_syscalls %} {{ arch_syscalls.append(syscall) }} +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change {% endif %} {% endfor %} @@ -50,8 +51,8 @@ {{ arch_syscalls.append(syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k system-locale +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k 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 @@ -178,7 +179,7 @@ -a always,exit -F path=/usr/bin/setfacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_chng {% endif %} {% if rhel9cis_rule_6_3_3_17 %} --a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k priv_chng +-a always,exit -F path=/usr/bin/chacl -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_chng {% endif %} {% if rhel9cis_rule_6_3_3_18 %} -a always,exit -F path=/usr/sbin/usermod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k usermod From 5a612675e2e8ca9e03a8281c390b0cde8c9e1f29 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 14:04:01 +0000 Subject: [PATCH 184/327] improve authselect logic Signed-off-by: Mark Bolwell --- tasks/main.yml | 8 +------- tasks/section_5/cis_5.3.2.x.yml | 4 +--- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 2e5049c..a0a58f8 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -116,17 +116,11 @@ fail_msg: "You still have the default name for your authselect profile" - name: "Check authselect profile is selected | Check current profile" - ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}' + ansible.builtin.shell: authselect list changed_when: false failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] register: prelim_authselect_current_profile - - name: "Check authselect profile is selected | Ensure profile name is set" - ansible.builtin.assert: - that: prelim_authselect_current_profile 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: "Ensure root password is set" when: rhel9cis_rule_5_4_2_4 tags: diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index eadb9b5..5917019 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -14,9 +14,7 @@ - rule_5.3.2.1 block: - name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles" - when: - - rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or - prelim_authselect_current_profile.stdout is not defined + when: rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}" changed_when: false args: From 74f17b7ee8e052f11cb2d830fd3d1c4c7573dea1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 14:04:13 +0000 Subject: [PATCH 185/327] updated logic Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.4.1.yml | 42 ++++++++++++++------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/tasks/section_6/cis_6.2.4.1.yml b/tasks/section_6/cis_6.2.4.1.yml index 814c46c..9e8b9b3 100644 --- a/tasks/section_6/cis_6.2.4.1.yml +++ b/tasks/section_6/cis_6.2.4.1.yml @@ -8,6 +8,8 @@ - patch - logfiles - rule_6.2.4.1 + - NIST800-53R5_AC-3 + - NIST800-53R5_MP-2 block: - name: "6.2.4.1 | AUDIT | Ensure access to all logfiles has been configured | find log files" ansible.builtin.shell: find /var/log/ -type f -exec ls {} \; @@ -15,43 +17,35 @@ failed_when: false register: discovered_logfiles - - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions SSSD min 660" when: - discovered_logfiles.stdout_lines | length > 0 - - ('audit.log' in item or 'journal' in item) or - item == '/var/log/secure' or - item == '/var/log/syslog' or - item == '/var/log/messages' or - item == '/var/log/auth.log' + - item is match("/var/log/(gdm|sssd)") ansible.builtin.file: path: "{{ item }}" - mode: 'u-x,g-wx,o-rwx' + mode: 'ug-x,o-rwx' failed_when: discovered_logfile_list.state not in '[ file, absent ]' register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" - - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions tmp min 664" when: - discovered_logfiles.stdout_lines | length > 0 - - ('anaconda' in item or 'dnf' in item or 'secure' in item or 'messages' in item or 'hawkey' in item) - ansible.builtin.file: - path: "{{ item }}" - mode: 'u-x,g-x,o-rwx' - failed_when: discovered_logfile_list.state not in '[ file, absent ]' - register: discovered_logfile_list - loop: "{{ discovered_logfiles.stdout_lines }}" - - - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" - when: - - discovered_logfiles.stdout_lines | length > 0 - - ('sssd' in item or 'lastlog' in item) or - item == "/var/log/btmp" or - item == "/var/log/utmp" or - item == "/var/log/wtmp" or - item == "/var/log/lastlog" + - item is match("/var/log/((u|b|w)tmp*|lastlog)") ansible.builtin.file: path: "{{ item }}" mode: 'ug-x,o-wx' failed_when: discovered_logfile_list.state not in '[ file, absent ]' register: discovered_logfile_list loop: "{{ discovered_logfiles.stdout_lines }}" + + - name: "6.2.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions else all 640" + when: + - discovered_logfiles.stdout_lines | length > 0 + - item is not match("/var/log/((u|b|w)tmp*|lastlog|sssd)") + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-x,g-wx,o-rwx' + failed_when: discovered_logfile_list.state not in '[ file, absent ]' + register: discovered_logfile_list + loop: "{{ discovered_logfiles.stdout_lines }}" From 4d8cc6eb607ebc8d7f3b481de0736763a118acea Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 26 Feb 2025 14:04:22 +0000 Subject: [PATCH 186/327] updated minclass Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index f5c38b1..da5ca20 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -923,7 +923,7 @@ rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # Options are: minclass or credits # ensure only one is selected rhel9cis_passwd_complex_option: minclass # pragma: allowlist secret -rhel9cis_passwd_minclass: 3 +rhel9cis_passwd_minclass: 4 # rhel9cis_passwd_complex: credits rhel9cis_passwd_dcredit: -1 rhel9cis_passwd_ucredit: -2 From 1bfde74ad6ce5385fbdfc2f9d99456f66d6a3f67 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 27 Feb 2025 13:02:54 +0000 Subject: [PATCH 187/327] Improve logic Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.4.x.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 004bfca..8d8c21b 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -57,10 +57,11 @@ - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" when: item not in discovered_efi_fstab.stdout ansible.builtin.set_fact: - efi_mount_opts_addition: "{{ efi_mount_opts_addition + item + ',' }}" + efi_mount_opts_addition: "{{ efi_mount_opts_addition + ',' + item }}" loop: "{{ efi_mount_options }}" - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Add mount options" + when: efi_mount_opts_addition | length > 0 ansible.builtin.lineinfile: path: /etc/fstab regexp: (.*/boot/efi\s*\w*\s*){{ discovered_efi_fstab.stdout }}(.*) From a1a719fbe7026dbf0d550bc8b394a09fac7b1890 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 27 Feb 2025 13:47:25 +0000 Subject: [PATCH 188/327] lint update Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.4.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index 8d8c21b..d3534cd 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -47,7 +47,7 @@ - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system" when: not rhel9cis_legacy_boot vars: - efi_mount_options: ['umask=0077','fmask=0077','uid=0','gid=0'] + efi_mount_options: ['umask=0077', 'fmask=0077', 'uid=0', 'gid=0'] block: - name: "1.4.2 | AUDIT | Ensure permissions on bootloader config are configured | efi based system | capture current state" ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | awk -F" " '{print $4}' From 683177e46fd0cfc8a3e4a4a98adbc3a4948d6b7f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:33:56 +0100 Subject: [PATCH 189/327] issue #305 addressed Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.1.x.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 3afa31c..2d861e8 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -96,15 +96,21 @@ - rule_6.2.1.4 block: - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when rsyslog" - when: rhel9cis_syslog == "rsyslog" + when: + - rhel9cis_syslog == "rsyslog" + - "'systemd-journald' in ansible_facts.packages" ansible.builtin.systemd: name: systemd-journald state: stopped enabled: false - name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when journald" - when: rhel9cis_syslog == "journald" + when: + - rhel9cis_syslog == "journald" + - "'rsyslog' in ansible_facts.packages" ansible.builtin.systemd: name: rsyslog state: stopped enabled: false + register: discovered_rsyslog_service + From b616f70d862527715ffd6d0092a87efe3b3a1512 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:35:07 +0100 Subject: [PATCH 190/327] addressed #306 Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index e49e733..98ede95 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -657,7 +657,7 @@ - postfix - NIST800-53R5_CM-7 - rule_2.1.21 - notify: Restart_postfix + notify: Restart postfix ansible.builtin.lineinfile: path: /etc/postfix/main.cf regexp: "^(#)?inet_interfaces" From cedf510b94abb6220981d87b29cb349f5418f5c8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:36:27 +0100 Subject: [PATCH 191/327] addressed #309 Signed-off-by: Mark Bolwell --- tasks/section_2/cis_2.1.x.yml | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 98ede95..28e372d 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -25,7 +25,7 @@ when: - not rhel9cis_autofs_services - rhel9cis_autofs_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: autofs enabled: false @@ -57,7 +57,7 @@ when: - not rhel9cis_avahi_server - rhel9cis_avahi_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -90,7 +90,7 @@ when: - not rhel9cis_dhcp_server - rhel9cis_dhcp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -123,7 +123,7 @@ when: - not rhel9cis_dns_server - rhel9cis_dns_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: named.service enabled: false @@ -153,7 +153,7 @@ when: - not rhel9cis_dnsmasq_server - rhel9cis_dnsmasq_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: dnsmasq.service enabled: false @@ -184,7 +184,7 @@ when: - not rhel9cis_samba_server - rhel9cis_samba_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: smb.service enabled: false @@ -215,7 +215,7 @@ when: - not rhel9cis_ftp_server - rhel9cis_ftp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: vsftpd.service enabled: false @@ -249,7 +249,7 @@ when: - not rhel9cis_message_server - rhel9cis_message_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -285,7 +285,7 @@ when: - not rhel9cis_nfs_server - rhel9cis_nfs_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: nfs-server.service enabled: false @@ -302,7 +302,7 @@ - nis - NIST800-53R5_CM-7 - rule_2.1.10 - notify: Systemd_daemon_reload + notify: Systemd daemon reload block: - name: "2.1.10 | PATCH | Ensure nis server services are not in use | Remove package" when: @@ -344,7 +344,7 @@ when: - not rhel9cis_print_server - rhel9cis_print_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -378,7 +378,7 @@ when: - not rhel9cis_rpc_server - rhel9cis_rpc_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -412,7 +412,7 @@ when: - not rhel9cis_rsync_server - rhel9cis_rsync_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -445,7 +445,7 @@ when: - not rhel9cis_snmp_server - rhel9cis_snmp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: snmpd.service enabled: false @@ -476,7 +476,7 @@ when: - not rhel9cis_telnet_server - rhel9cis_telnet_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: telnet.socket enabled: false @@ -506,7 +506,7 @@ when: - not rhel9cis_tftp_server - rhel9cis_tftp_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: "{{ item }}" enabled: false @@ -540,7 +540,7 @@ when: - not rhel9cis_squid_server - rhel9cis_squid_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: squid.service enabled: false @@ -580,7 +580,7 @@ when: - not rhel9cis_httpd_server - rhel9cis_httpd_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: httpd.service enabled: false @@ -591,7 +591,7 @@ when: - not rhel9cis_nginx_server - rhel9cis_nginx_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: ngnix.service enabled: false @@ -621,7 +621,7 @@ when: - not rhel9cis_xinetd_server - rhel9cis_xinetd_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: xinetd.service enabled: false From 7b1c8e9ef0f3654ef65e86606508ceca9d0e4b24 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:37:58 +0100 Subject: [PATCH 192/327] additional fix for #309 Signed-off-by: Mark Bolwell --- tasks/section_3/cis_3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index e8934d4..68a66de 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -86,7 +86,7 @@ when: - not rhel9cis_bluetooth_service - rhel9cis_bluetooth_mask - notify: Systemd_daemon_reload + notify: Systemd daemon reload ansible.builtin.systemd: name: bluetooth.service enabled: false From 82904557c7443a584988c5badf9bfa9f1550befd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 12:38:51 +0100 Subject: [PATCH 193/327] updated workflows Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 1 + .github/workflows/main_pipeline_validation.yml | 2 ++ 2 files changed, 3 insertions(+) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index c9328cb..10750a2 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - devel + - benchmark* paths: - '**.yml' - '**.sh' diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index ab11c37..6792a00 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - main + - latest paths: - '**.yml' - '**.sh' @@ -23,6 +24,7 @@ # 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 From 576531e9862c596da454e1283cdd549cf6806827 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 14:50:40 +0100 Subject: [PATCH 194/327] fetch audit and compliance facts added Signed-off-by: Mark Bolwell --- defaults/main.yml | 17 +++++++++ tasks/fetch_audit_output.yml | 46 +++++++++++++++++++++++ tasks/main.yml | 32 ++++++++++++++++ templates/etc/ansible/compliance_facts.j2 | 39 +++++++++++++++++++ 4 files changed, 134 insertions(+) create mode 100644 tasks/fetch_audit_output.yml create mode 100644 templates/etc/ansible/compliance_facts.j2 diff --git a/defaults/main.yml b/defaults/main.yml index da5ca20..f2bd882 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -33,6 +33,9 @@ rhel9cis_section7: true rhel9cis_level_1: true rhel9cis_level_2: true +# Create managed not custom local_facts files +Create_benchmark_facts: true +ansible_facts_path: /etc/ansible/facts.d ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting # 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. @@ -107,6 +110,20 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' +## Ability to collect and take audit files moving to a centralised location +# This enables the collection of the files from the host +fetch_audit_output: false + +# Method of getting,uploading the summary files +## Ensure access and permissions are avaiable for these to occur. +## options are +# fetch - fetches from server and moves to location on the ansible controller (could be a mount point available to controller) +# copy - copies file to a location available to the managed node +audit_output_collection_method: fetch + +# Location to put the audit files +audit_output_destination: /opt/audit_summaries/ + ### Goss Settings ## ####### END ######## diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml new file mode 100644 index 0000000..c6f7b5e --- /dev/null +++ b/tasks/fetch_audit_output.yml @@ -0,0 +1,46 @@ +--- + +# Stage to copy audit output to a centralised location + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller" + when: audit_output_collection_method == "fetch" + ansible.builtin.fetch: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + flat: true + failed_when: false + register: discovered_audit_fetch_state + loop: + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + become: false + +# Added this option for continuity but could be changed by adjusting the variable audit_conf_dest +# Allowing backup to one location +- name: "FETCH_AUDIT_FILES | Copy files to location available to managed node" + when: audit_output_collection_method == "copy" + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + mode: 'u-x,go-wx' + flat: true + failed_when: false + register: discovered_audit_fetch_copy_state + loop: + - pre_audit_outfile + - post_audit_outfile + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + when: + - (discovered_audit_fetch_state is defined and not discovered_audit_fetch_state.changed) or + (discovered_audit_copy_state is defined and not discovered_audit_copy_state.changed) + block: + - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + ansible.builtin.debug: + msg: "Warning!! Unable to write to localhost {{ audit_output_destination }} for audit file copy" + + - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + vars: + warn_control_id: "FETCH_AUDIT_FILES" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/main.yml b/tasks/main.yml index a0a58f8..ccd6c1d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -209,11 +209,43 @@ - name: "Run post_remediation audit" when: run_audit + tags: always ansible.builtin.import_tasks: file: post_remediation_audit.yml +- name: Add ansible file showing Benchmark and levels applied + when: Create_benchmark_facts + tags: + - always + - benchmark + block: + - name: Create ansible facts directory + ansible.builtin.file: + path: "{{ ansible_facts_path }}" + state: directory + owner: root + group: root + mode: 'u=rwx,go=rx' + + - name: Create ansible facts file + ansible.builtin.template: + src: etc/ansible/compliance_facts.j2 + dest: "{{ ansible_facts_path }}/compliance_facts.fact" + owner: root + group: root + mode: "u-x,go-wx" + +- name: Fetch audit files + when: + - fetch_audit_output + - run_audit + tags: always + ansible.builtin.import_tasks: + file: fetch_audit_output.yml + - name: "Show Audit Summary" when: run_audit + tags: always ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 new file mode 100644 index 0000000..1e7d896 --- /dev/null +++ b/templates/etc/ansible/compliance_facts.j2 @@ -0,0 +1,39 @@ +# CIS Hardening Carried out +# Added as part of ansible-lockdown CIS baseline +# provided by Mindpoint Group - A Tyto Athene Company + +[Benchmark_Details] +# Benchmark release +Benchmark_release = CIS-{{ benchmark_version }} +Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} +# If options set (doesn't mean it ran all controls) +level_1_hardening_enabled = {{ rhel9cis_level_1 }} +level_2_hardening_enabled = {{ rhel9cis_level_2 }} + +{% if ansible_run_tags | length > 0 %} +# If tags used to stipulate run level +{% if 'level1-server' in ansible_run_tags %} +Level_1_Server_tag_run = true +{% endif %} +{% if 'level2-server' in ansible_run_tags %} +Level_2_Server_tag_run = true +{% endif %} +{% if 'level1-workstation' in ansible_run_tags %} +Level_1_workstation_tag_run = true +{% endif %} +{% if 'level2-workstation' in ansible_run_tags %} +Level_2_workstation_tag_run = true +{% endif %} +{% endif %} + +[Benchmark_Audit_Details] +{% if run_audit %} +# Audit run +audit_file_location_local = {{ audit_log_dir }} +{% if not audit_only %} +audit_summary = {{ post_audit_results }} +{% endif %} +{% if fetch_audit_output %} +audit_files_location_central = {{ audit_output_destination }} +{% endif %} +{% endif %} From 04666c219c9a1eb751419852ba752c355b3040c1 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 31 Mar 2025 15:13:46 +0100 Subject: [PATCH 195/327] Added for #288 ansible_facts Signed-off-by: Mark Bolwell --- templates/etc/ansible/compliance_facts.j2 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index 1e7d896..ffa366c 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -2,7 +2,7 @@ # Added as part of ansible-lockdown CIS baseline # provided by Mindpoint Group - A Tyto Athene Company -[Benchmark_Details] +[benchmark_details] # Benchmark release Benchmark_release = CIS-{{ benchmark_version }} Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} @@ -26,14 +26,14 @@ Level_2_workstation_tag_run = true {% endif %} {% endif %} -[Benchmark_Audit_Details] +[benchmark_audit_details] {% if run_audit %} # Audit run -audit_file_location_local = {{ audit_log_dir }} +audit_file_local_location = {{ audit_log_dir }} {% if not audit_only %} audit_summary = {{ post_audit_results }} {% endif %} {% if fetch_audit_output %} -audit_files_location_central = {{ audit_output_destination }} +audit_files_centralized_location = {{ audit_output_destination }} {% endif %} {% endif %} From fc2e153ce90350576e8ae83b91893edca0bc9ddf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 07:55:08 +0100 Subject: [PATCH 196/327] updated section naming Signed-off-by: Mark Bolwell --- templates/etc/ansible/compliance_facts.j2 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index ffa366c..f313bec 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -2,7 +2,7 @@ # Added as part of ansible-lockdown CIS baseline # provided by Mindpoint Group - A Tyto Athene Company -[benchmark_details] +[lockdown_details] # Benchmark release Benchmark_release = CIS-{{ benchmark_version }} Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} @@ -26,7 +26,7 @@ Level_2_workstation_tag_run = true {% endif %} {% endif %} -[benchmark_audit_details] +[lockdown_audit_details] {% if run_audit %} # Audit run audit_file_local_location = {{ audit_log_dir }} From 9bbf5b7a81d8a4db1048cc055318363df4c3c9cb Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 08:08:28 +0100 Subject: [PATCH 197/327] updated var name to remove capital Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 +- tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index f2bd882..32c4679 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -34,7 +34,7 @@ rhel9cis_level_1: true rhel9cis_level_2: true # Create managed not custom local_facts files -Create_benchmark_facts: true +create_benchmark_facts: true ansible_facts_path: /etc/ansible/facts.d ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting diff --git a/tasks/main.yml b/tasks/main.yml index ccd6c1d..57fd8fd 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -214,7 +214,7 @@ file: post_remediation_audit.yml - name: Add ansible file showing Benchmark and levels applied - when: Create_benchmark_facts + when: create_benchmark_facts tags: - always - benchmark From bd425a068d4b23e16d8793a1fb94a205323bd33c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 1 Apr 2025 08:14:02 +0100 Subject: [PATCH 198/327] lint updates Signed-off-by: Mark Bolwell --- tasks/main.yml | 6 +++--- tasks/section_1/cis_1.4.x.yml | 2 +- tasks/section_6/cis_6.2.1.x.yml | 1 - 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 57fd8fd..00281da 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -116,7 +116,7 @@ fail_msg: "You still have the default name for your authselect profile" - name: "Check authselect profile is selected | Check current profile" - ansible.builtin.shell: authselect list + ansible.builtin.command: authselect list changed_when: false failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ] register: prelim_authselect_current_profile @@ -216,8 +216,8 @@ - name: Add ansible file showing Benchmark and levels applied when: create_benchmark_facts tags: - - always - - benchmark + - always + - benchmark block: - name: Create ansible facts directory ansible.builtin.file: diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index d3534cd..c6c3aac 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -57,7 +57,7 @@ - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" when: item not in discovered_efi_fstab.stdout ansible.builtin.set_fact: - efi_mount_opts_addition: "{{ efi_mount_opts_addition + ',' + item }}" + efi_mount_opts_addition: "{{ efi_mount_opts_addition + ',' + item }}" loop: "{{ efi_mount_options }}" - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Add mount options" diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 2d861e8..fa75880 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -113,4 +113,3 @@ state: stopped enabled: false register: discovered_rsyslog_service - From 97baa4afe04097d319d36233e85732255a90f419 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 7 Apr 2025 17:34:10 +0000 Subject: [PATCH 199/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.24.0 → v8.24.2](https://github.com/gitleaks/gitleaks/compare/v8.24.0...v8.24.2) - [github.com/ansible-community/ansible-lint: v25.1.3 → v25.2.1](https://github.com/ansible-community/ansible-lint/compare/v25.1.3...v25.2.1) - [github.com/adrienverge/yamllint.git: v1.35.1 → v1.37.0](https://github.com/adrienverge/yamllint.git/compare/v1.35.1...v1.37.0) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4791982..c12360b 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.0 + rev: v8.24.2 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.1.3 + rev: v25.2.1 hooks: - id: ansible-lint name: Ansible-lint @@ -65,7 +65,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.35.1 # or higher tag + rev: v1.37.0 # or higher tag hooks: - id: yamllint name: Check YAML Lint From ba57380a72a12f49342ac9e84e87e6600142b45a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 14 Apr 2025 17:21:59 +0000 Subject: [PATCH 200/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.24.2 → v8.24.3](https://github.com/gitleaks/gitleaks/compare/v8.24.2...v8.24.3) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c12360b..99408de 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.2 + rev: v8.24.3 hooks: - id: gitleaks From 52f5f23b00b06d795e55bd94e10b2bd2723cd1e8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 11:04:33 +0100 Subject: [PATCH 201/327] improve ansible facts conditionals Signed-off-by: Mark Bolwell --- tasks/main.yml | 13 ++++++++----- templates/etc/ansible/compliance_facts.j2 | 1 + 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 00281da..e285e8d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -213,13 +213,16 @@ ansible.builtin.import_tasks: file: post_remediation_audit.yml -- name: Add ansible file showing Benchmark and levels applied - when: create_benchmark_facts +- name: Add ansible file showing Benchmark and levels applied if audit details not present + when: + - create_benchmark_facts + - (post_audit_summary is defined) or + (ansible_local['compliance_facts']['lockdown_audit_details']['audit_summary'] is undefined and post_audit_summary is undefined) tags: - always - benchmark block: - - name: Create ansible facts directory + - name: Create ansible facts directory if audit facts not present ansible.builtin.file: path: "{{ ansible_facts_path }}" state: directory @@ -227,13 +230,13 @@ group: root mode: 'u=rwx,go=rx' - - name: Create ansible facts file + - name: Create ansible facts file and levels applied if audit facts not present ansible.builtin.template: src: etc/ansible/compliance_facts.j2 dest: "{{ ansible_facts_path }}/compliance_facts.fact" owner: root group: root - mode: "u-x,go-wx" + mode: 'u-x,go=r' - name: Fetch audit files when: diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 index f313bec..f8725e1 100644 --- a/templates/etc/ansible/compliance_facts.j2 +++ b/templates/etc/ansible/compliance_facts.j2 @@ -29,6 +29,7 @@ Level_2_workstation_tag_run = true [lockdown_audit_details] {% if run_audit %} # Audit run +audit_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} audit_file_local_location = {{ audit_log_dir }} {% if not audit_only %} audit_summary = {{ post_audit_results }} From 3d4bc2ab3d35bb1f58a56c1d42cf364f30010987 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 11:07:15 +0100 Subject: [PATCH 202/327] Update name and conditionals Signed-off-by: Mark Bolwell --- tasks/fetch_audit_output.yml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml index c6f7b5e..563b699 100644 --- a/tasks/fetch_audit_output.yml +++ b/tasks/fetch_audit_output.yml @@ -2,7 +2,7 @@ # Stage to copy audit output to a centralised location -- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller" +- name: "POST | FETCH | Fetch files and copy to controller" when: audit_output_collection_method == "fetch" ansible.builtin.fetch: src: "{{ item }}" @@ -17,7 +17,7 @@ # Added this option for continuity but could be changed by adjusting the variable audit_conf_dest # Allowing backup to one location -- name: "FETCH_AUDIT_FILES | Copy files to location available to managed node" +- name: "POST | FETCH | Copy files to location available to managed node" when: audit_output_collection_method == "copy" ansible.builtin.copy: src: "{{ item }}" @@ -25,21 +25,21 @@ mode: 'u-x,go-wx' flat: true failed_when: false - register: discovered_audit_fetch_copy_state + register: discovered_audit_copy_state loop: - - pre_audit_outfile - - post_audit_outfile + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" -- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" +- name: "POST | FETCH | Fetch files and copy to controller | Warning if issues with fetch_audit_files" when: - - (discovered_audit_fetch_state is defined and not discovered_audit_fetch_state.changed) or - (discovered_audit_copy_state is defined and not discovered_audit_copy_state.changed) + - (audit_output_collection_method == "fetch" and not discovered_audit_fetch_state.changed) or + (audit_output_collection_method == "copy" and not discovered_audit_copy_state.changed) block: - - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + - name: "POST | FETCH | Fetch files and copy to controller | Warning if issues with fetch_audit_files" ansible.builtin.debug: msg: "Warning!! Unable to write to localhost {{ audit_output_destination }} for audit file copy" - - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + - name: "POST | FETCH | Fetch files and copy to controller | Warning if issues with fetch_audit_files" vars: warn_control_id: "FETCH_AUDIT_FILES" ansible.builtin.import_tasks: From ec57b85fdf5de6054fd7b42fe59975d6547241d6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 11:11:19 +0100 Subject: [PATCH 203/327] Updated 5.3.3.1.1 regex issue #315 thanks to @jrdbarnes Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.3.3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 1730521..0aadbe3 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -23,7 +23,7 @@ - rhel9cis_disruption_high 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+(.*$) + regexp: ^(\s*auth\s+(?:requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$) replace: \1 \2\3 loop: - password From b04570dfe4086b7063632c48b433d6198ac5baf5 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 11:40:49 +0100 Subject: [PATCH 204/327] removed legacy option Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 1377f9f..39c9f7d 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -9,14 +9,6 @@ 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: 'go-wx' - src: "{{ pre_audit_outfile }}" - - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: From 4aeac7e6625133b4bac1aaed68a32a11c2752ab0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 11:41:46 +0100 Subject: [PATCH 205/327] typos and tidy up Signed-off-by: Mark Bolwell --- defaults/main.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 32c4679..eaf33a1 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,7 +1,8 @@ --- + # defaults file for rhel9-cis # WARNING: -# These values may be overriden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: +# These values may be overridden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: # https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_variables.html#variable-precedence-where-should-i-put-a-variable # Run the OS validation check @@ -36,6 +37,7 @@ rhel9cis_level_2: true # Create managed not custom local_facts files create_benchmark_facts: true ansible_facts_path: /etc/ansible/facts.d + ## Section 1.6 - Mandatory Access Control # This variable governs whether SELinux is disabled or not. If SELinux is NOT DISABLED by setting # 'rhel9cis_selinux_disable' to 'true', the 1.6 subsection will be executed. @@ -85,7 +87,7 @@ 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 -# you will need to access to either github or the file already dowmloaded +# you will need to access to either github or the file already downloaded get_audit_binary_method: download ## if get_audit_binary_method - copy the following needs to be updated for your environment From ce43c573ee5435653a32119926bd94e47359da21 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 15 Apr 2025 12:51:42 +0100 Subject: [PATCH 206/327] update tags and issue #311 thanks to @rilatu Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 46 ++++++++++++++++++++--------------- 1 file changed, 27 insertions(+), 19 deletions(-) diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 296ebf9..99176fd 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -6,7 +6,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - permissions - rule_5.1.1 - NIST800-53R5_AC-3 @@ -23,7 +23,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - permissions - rule_5.1.2 - NIST800-53R5_AC-3 @@ -53,7 +53,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.3 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 @@ -166,7 +166,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.7 - NIST800-53R5_AC-3 - NIST800-53R5_MP-2 @@ -195,6 +195,8 @@ path: "{{ rhel9cis_sshd_config_file }}" regexp: "^DenyUsers" line: "DenyUsers {{ rhel9cis_sshd_denyusers }}" + insertbefore: "^Match" + firstmatch: true validate: sshd -t -f %s notify: Restart sshd @@ -213,7 +215,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.8 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -231,7 +233,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.9 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -261,7 +263,7 @@ - level2-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.10 - NIST800-53R5_CM-7 block: @@ -287,7 +289,7 @@ - level1-server - level1-workstation - patch - - sshs + - sshd - rule_5.1.11 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -317,7 +319,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.12 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -337,7 +339,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.13 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -348,6 +350,8 @@ path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' + insertbefore: "^Match" + firstmatch: true validate: sshd -t -f %s notify: Restart sshd @@ -357,13 +361,15 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.14 - NIST800-53R5_CM-6 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" + insertbefore: "^Match" + firstmatch: true validate: sshd -t -f %s notify: Restart sshd @@ -373,7 +379,7 @@ - level1-server - level1-workstation - patch - - sshs + - sshd - rule_5.1.15 - NIST800-53R5_AU-3 - NIST800-53R5_AU-12 @@ -382,6 +388,8 @@ path: "{{ rhel9cis_sshd_config_file }}" regexp: ^(?i)(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' + insertbefore: "^Match" + firstmatch: true validate: sshd -t -f %s notify: Restart sshd @@ -391,7 +399,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.16 - NIST800-53R5_AU-3 ansible.builtin.lineinfile: @@ -407,7 +415,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.17 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -427,7 +435,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.18 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -447,7 +455,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.19 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -467,7 +475,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.20 - NIST800-53R5_AC-6 block: @@ -491,7 +499,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.21 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 @@ -511,7 +519,7 @@ - level1-server - level1-workstation - patch - - ssh + - sshd - rule_5.1.22 - NIST800-53R5_CM-1 - NIST800-53R5_CM-2 From de63984cd8ef4bd83163ab99dd7453862f943471 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 22 Apr 2025 16:10:53 -0400 Subject: [PATCH 207/327] Typo fixes Signed-off-by: Frederick Witty --- README.md | 2 +- defaults/main.yml | 4 ++-- templates/ansible_vars_goss.yml.j2 | 10 +++++----- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d3bf75a..098c50a 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ This is managed using tags: - level2-server - level2-workstation -The control found in defaults main also need to reflect this as this control the testing thet takes place if you are using the audit component. +The control found in defaults main also need to reflect this as this control the testing that takes place if you are using the audit component. ## Coming from a previous release diff --git a/defaults/main.yml b/defaults/main.yml index eaf33a1..071e55b 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1046,14 +1046,14 @@ rhel9cis_bash_umask: '0027' # 0027 or more restrictive # These are discovered via logins.def if set true rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. max_int_uid: 65533 diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index ad44fb3..7cb906b 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -34,7 +34,7 @@ rhel9cis_selinux_disable: {{ rhel9cis_selinux_disable }} # UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: {{ rhel9cis_legacy_boot }} -## Benchmark name used by audting control role +## Benchmark name used by auditing control role # The audit variable found at the base ## metadata for Audit benchmark benchmark_version: 'v2.0.0' @@ -151,7 +151,7 @@ rhel9cis_rule_1_8_8: {{ rhel9cis_rule_1_8_8 }} rhel9cis_rule_1_8_9: {{ rhel9cis_rule_1_8_9 }} rhel9cis_rule_1_8_10: {{ rhel9cis_rule_1_8_10 }} -# Section 2 rules are controling Services (Special Purpose Services, and service clients) +# Section 2 rules are controlling Services (Special Purpose Services, and service clients) ## Configure Server Services rhel9cis_rule_2_1_1: {{ rhel9cis_rule_2_1_1 }} rhel9cis_rule_2_1_2: {{ rhel9cis_rule_2_1_2 }} @@ -625,21 +625,21 @@ rhel9cis_authselect_custom_profile_name: {{ rhel9cis_authselect_custom_profile_n # These are discovered via logins.def if set true rhel9cis_discover_int_uid: {{ rhel9cis_discover_int_uid }} # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `dicover_int_uid` has +# Note that the value will be dynamically overwritten if variable `discover_int_uid` has # been set to `true`. max_int_uid: 65533 ## Section6 vars ## Control 6.1.2 AIDE schedule -# how aide sceduler runs can be one of cron or timer +# how aide scheduler runs can be one of cron or timer rhel9cis_aide_scan: {{ rhel9cis_aide_scan }} # These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. From 7173eba3f68faf6e7e8b72f6d417798491a3cc36 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 22 Apr 2025 16:29:43 -0400 Subject: [PATCH 208/327] Typo fixes v2 Signed-off-by: Frederick Witty --- defaults/main.yml | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 071e55b..9358939 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -12,7 +12,7 @@ os_check: true # Disruption is high ## Run tests that are considered higher risk and could have a system impact if not properly tested ## Default false -## Will be fine if clean new unconfigured build +## Will be fine if clean new un-configured build rhel9cis_disruption_high: false ## Switching on/off specific baseline sections @@ -46,7 +46,7 @@ rhel9cis_selinux_disable: false # UEFI boot('/etc/grub2-efi.cfg') or in case of BIOS legacy-boot('/etc/grub2.cfg'). rhel9cis_legacy_boot: false -## Benchmark name used by audting control role +## Benchmark name used by auditing control role # The audit variable found at the base ## metadata for Audit benchmark benchmark_version: 'v2.0.0' @@ -112,12 +112,12 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' -## Ability to collect and take audit files moving to a centralised location +## Ability to collect and take audit files moving to a centralized location # This enables the collection of the files from the host fetch_audit_output: false # Method of getting,uploading the summary files -## Ensure access and permissions are avaiable for these to occur. +## Ensure access and permissions are available for these to occur. ## options are # fetch - fetches from server and moves to location on the ansible controller (could be a mount point available to controller) # copy - copies file to a location available to the managed node @@ -514,7 +514,7 @@ rhel9cis_rule_7_2_9: true ## Section 1 vars -## Ability to enabe debug on mounts to assist in troubleshooting +## Ability to enable debug on mounts to assist in troubleshooting # Mount point changes are set based upon facts created in Prelim # these then build the variable and options that is passed to the handler to set the mount point for the controls in section1. rhel9cis_debug_mount_data: false @@ -722,7 +722,7 @@ rhel9cis_bluetooth_mask: false rhel9cis_ipv6_required: true ## 3.1.2 wireless network requirements -# if wireless adapetr found allow network manager to be installed +# if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules @@ -730,15 +730,15 @@ rhel9cis_install_network_manager: false rhel9cis_is_router: false # This variable governs if the task which updates sysctl(including sysctl reload) is executed. -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_sysctl_update: false # This variable governs if the task which flushes the IPv4 routing table is executed(forcing subsequent connections to # use the new configuration). -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv4_route: false # This variable governs if the task which flushes the IPv6 routing table is executed(forcing subsequent connections to # use the new configuration). -# NOTE: The current default value is likely to be overriden by other further tasks(via 'set_fact'). +# NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv6_route: false # Section 4 vars @@ -890,13 +890,13 @@ rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD # To create a new profile (best for greenfield fresh sites not configured) # This allows creation of a custom profile using an existing one to build from -# will only create if profiel does not already exist +# will only create if profile does not already exist ## options true or false rhel9cis_authselect_custom_profile_create: true ## Controls: # - 5.3.2.1 - Ensure custom authselect profile is used # Settings in place now will fail, they are placeholders 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. +# options and ways to configure this control needs to be enabled and settings adjusted to minimize risk. # This variable configures the name of the custom profile to be created and selected. # To be changed from default - cis_example_profile @@ -1046,14 +1046,14 @@ rhel9cis_bash_umask: '0027' # 0027 or more restrictive # These are discovered via logins.def if set true rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `discover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `discover_int_uid` has +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. max_int_uid: 65533 From 350b30dfe4d117395dcf25ae21cab713c0440c59 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 22 Apr 2025 16:32:47 -0400 Subject: [PATCH 209/327] prelim_ prefix added to max_int_uid and min_int_uid Signed-off-by: Frederick Witty --- defaults/main.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9358939..385d160 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1048,14 +1048,14 @@ rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID # Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. -min_int_uid: 1000 +prelim_min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID # Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. -max_int_uid: 65533 +prelim_max_int_uid: 65533 ## Section6 vars ## Control 6.1.x - allow aide to be configured From 42024903e3eb83901f44dc4bf8596e785ad77d46 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Wed, 23 Apr 2025 12:47:22 -0400 Subject: [PATCH 210/327] revamp set facts premlim_ max_int_uid and prelim_min_int_uid Signed-off-by: Frederick Witty --- defaults/main.yml | 4 ++-- tasks/prelim.yml | 21 ++++++++++++--------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 385d160..9358939 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1048,14 +1048,14 @@ rhel9cis_discover_int_uid: true # This variable sets the minimum number from which to search for UID # Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. -prelim_min_int_uid: 1000 +min_int_uid: 1000 ### Controls: # - Ensure local interactive user home directories exist # - Ensure local interactive users own their home directories # This variable sets the maximum number at which the search stops for UID # Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has # been set to `true`. -prelim_max_int_uid: 65533 +max_int_uid: 65533 ## Section6 vars ## Control 6.1.x - allow aide to be configured diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1ec355b..dbd1493 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -320,24 +320,27 @@ patterns: '*.conf,*.rules' register: prelim_auditd_conf_files -- name: "PRELIM | AUDIT | Discover Interactive UID MIN and MIN from logins.def" +- name: "PRELIM | AUDIT | Discover Interactive UID_MIN and UID_MAX from /etc/login.defs" when: rhel9cis_discover_int_uid tags: always block: - - name: "PRELIM | AUDIT | Capture UID_MIN information from logins.def" - ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}' + - name: "PRELIM | AUDIT | Capture UID_MIN from /etc/login.defs" + ansible.builtin.command: awk '/^UID_MIN/ {print $2}' /etc/login.defs changed_when: false + failed_when: false register: prelim_uid_min_id - - name: "PRELIM | AUDIT | Capture UID_MAX information from logins.def" - ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}' + - name: "PRELIM | AUDIT | Capture UID_MAX from /etc/login.defs" + ansible.builtin.command: awk '/^UID_MAX/ {print $2}' /etc/login.defs changed_when: false + failed_when: false register: prelim_uid_max_id - - name: "PRELIM | AUDIT | Set Fact for interactive uid/gid" - ansible.builtin.set_fact: - prelim_min_int_uid: "{{ prelim_uid_min_id.stdout }}" - prelim_max_int_uid: "{{ prelim_uid_max_id.stdout }}" +- name: "PRELIM | AUDIT | Set facts for interactive UID/GID ranges" + tags: always + ansible.builtin.set_fact: + prelim_min_int_uid: "{{ prelim_uid_min_id.stdout | default(min_int_uid) }}" + prelim_max_int_uid: "{{ prelim_uid_max_id.stdout | default(max_int_uid) }}" - name: "PRELIM | AUDIT | Gather the package facts after prelim" tags: From e27e413f943d00253c3c4d702cbc6bb6d0efaf9b Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Wed, 23 Apr 2025 16:04:16 -0400 Subject: [PATCH 211/327] Update URL in defaults/main Signed-off-by: Frederick Witty --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 9358939..91261b7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -102,7 +102,7 @@ audit_content: git # 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 +### https://github.com/ansible-lockdown/RHEL9-CIS-Audit/archive/refs/heads/benchmark-v1.0.0.tar.gz audit_conf_source: "some path or url to copy from" # Destination for the audit content to be placed on managed node From dd909b48c8aff1f5fb63560eb611ccd8084e0b62 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 25 Apr 2025 11:47:17 -0400 Subject: [PATCH 212/327] Fix for #320 thank you @kodebach Signed-off-by: Frederick Witty --- Changelog.md | 4 ++++ .../policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 4bd1c86..34b9c2c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,9 @@ # Changes to rhel9CIS +## 2.0.0 - Based on CIS v2.0.0 + +- #320 - thanks to @kodebach + ## 1.1.6 - Based on CIS v1.0.0 - #190 - thanks to @ipruteanu-sie diff --git a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 index d325a11..393cf88 100644 --- a/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 +++ b/templates/etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2 @@ -1,4 +1,4 @@ # This is a subpolicy to disable weak ciphers # for the SSH protocol (libssh and OpenSSH) # Carried out as part of CIS Benchmark rules combined 1.6.6 and 5.1.4 -cipher@SSH ={% if rhel9cis_rule_1_6_6 %} -CHACHA20-POLY1305{% endif %}{% if rhel9cis_rule_5_1_5 %} -3DES-CBC -AES-128-CBC -AES-192-CBC -AES-256-CBC{% endif %} +cipher@SSH ={% if rhel9cis_rule_1_6_6 %} -CHACHA20-POLY1305{% endif %}{% if rhel9cis_rule_5_1_4 %} -3DES-CBC -AES-128-CBC -AES-192-CBC -AES-256-CBC{% endif %} From 48c05f038f24e660a94a1c8db9f53f23eabb5158 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 25 Apr 2025 14:36:58 -0400 Subject: [PATCH 213/327] Fix for #322 thank @mindrb Signed-off-by: Frederick Witty --- Changelog.md | 3 ++- defaults/main.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 34b9c2c..4accf38 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,7 +2,8 @@ ## 2.0.0 - Based on CIS v2.0.0 -- #320 - thanks to @kodebach +- #322 - thanks to @mindrb +- #320 - thanks to @anup-ad ## 1.1.6 - Based on CIS v1.0.0 diff --git a/defaults/main.yml b/defaults/main.yml index 91261b7..6a360fa 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -588,7 +588,7 @@ rhel9cis_crypto_policy_module: '' # - 1.7.2 - Ensure local login warning banner is configured properly # - 1.7.3 - Ensure remote login warning banner is configured properly # This variable stores the content for the Warning Banner(relevant for issue, issue.net, motd). -rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and reported. +rhel9cis_warning_banner: Authorized users only. All activity may be monitored and reported. # End Banner ## Control 1.8.x - Settings for GDM From 5e2e4db20e955f90a024b17d92626a82bff461c8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 19 May 2025 17:24:24 +0000 Subject: [PATCH 214/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.24.3 → v8.26.0](https://github.com/gitleaks/gitleaks/compare/v8.24.3...v8.26.0) - [github.com/ansible-community/ansible-lint: v25.2.1 → v25.4.0](https://github.com/ansible-community/ansible-lint/compare/v25.2.1...v25.4.0) - [github.com/adrienverge/yamllint.git: v1.37.0 → v1.37.1](https://github.com/adrienverge/yamllint.git/compare/v1.37.0...v1.37.1) --- .pre-commit-config.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 99408de..ebc85d7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.3 + rev: v8.26.0 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.2.1 + rev: v25.4.0 hooks: - id: ansible-lint name: Ansible-lint @@ -65,7 +65,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.37.0 # or higher tag + rev: v1.37.1 # or higher tag hooks: - id: yamllint name: Check YAML Lint From 4948d3cb095955447032292831c907733b355151 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:22:30 +0100 Subject: [PATCH 215/327] added ignore comments in file Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 86c1cac..70f79c6 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -4,7 +4,7 @@ tags: always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.command: cat /etc/passwd + ansible.builtin.command: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false register: prelim_passwd_file_audit From 8d5a32bc392ce53c9d94f0e6aeff7c07a572de29 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:25:42 +0100 Subject: [PATCH 216/327] added rhel9cis_rsyslog_ansiblemanage conditional Signed-off-by: Mark Bolwell --- tasks/section_6/main.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tasks/section_6/main.yml b/tasks/section_6/main.yml index dda7ee5..dbff078 100644 --- a/tasks/section_6/main.yml +++ b/tasks/section_6/main.yml @@ -20,7 +20,9 @@ file: cis_6.2.2.x.yml - name: "SECTION | 6.2.3 | Configure rsyslog" - when: rhel9cis_syslog == 'rsyslog' + when: + - rhel9cis_syslog == 'rsyslog' + - rhel9cis_rsyslog_ansiblemanaged ansible.builtin.import_tasks: file: cis_6.2.3.x.yml From 2b37d0d7321dec9511f61a0064764ac779b8cb4e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:30:17 +0100 Subject: [PATCH 217/327] added check_mode logic Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.1.x.yml | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index c000fe1..1db531b 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -58,6 +58,10 @@ dest: /var/lib/aide/aide.db.gz remote_src: true mode: 'ug-wx,o-rwx' + register: aide_db_cp + failed_when: + - not ansible_check_mode + - aide_db_cp.failed - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked" when: @@ -119,4 +123,7 @@ /usr/sbin/aureport 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/autrace p+i+n+u+g+s+b+acl+xattrs+sha512 - validate: aide -D --config %s + register: aide_file_integrity_check + failed_when: + - not ansible_check_mode + - aide_file_integrity_check.failed From 15bf03c75490746568ef21a610236fc714f0630c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 14:34:30 +0100 Subject: [PATCH 218/327] added check mode logic Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index dbd1493..a0fc2fe 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -25,6 +25,7 @@ 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 + check_mode: false register: prelim_interactive_usernames - name: "PRELIM | AUDIT | Interactive User accounts home directories" @@ -32,6 +33,7 @@ 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 + check_mode: false register: prelim_interactive_users_home - name: "PRELIM | AUDIT | Interactive UIDs" @@ -39,6 +41,7 @@ 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 + check_mode: false register: prelim_interactive_uids - name: "PRELIM | AUDIT | Capture /etc/password variables" @@ -64,6 +67,7 @@ ansible.builtin.shell: | mount | awk '{print $1, $3, $5, $6}' changed_when: false + check_mode: false register: prelim_mount_output - name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact # This is inherited and used in mountpoints tasks @@ -100,6 +104,7 @@ ansible.builtin.command: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' # noqa command-instead-of-module changed_when: false failed_when: false + check_mode: false register: prelim_check_gpg_imported - name: "PRELIM | AUDIT | Import gpg keys | Check Package" # noqa command-instead-of-module @@ -328,12 +333,14 @@ ansible.builtin.command: awk '/^UID_MIN/ {print $2}' /etc/login.defs changed_when: false failed_when: false + check_mode: false register: prelim_uid_min_id - name: "PRELIM | AUDIT | Capture UID_MAX from /etc/login.defs" ansible.builtin.command: awk '/^UID_MAX/ {print $2}' /etc/login.defs changed_when: false failed_when: false + check_mode: false register: prelim_uid_max_id - name: "PRELIM | AUDIT | Set facts for interactive UID/GID ranges" From daf5a3f4621adf7e357f2422aedecef7ccfc14f9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 15:01:16 +0100 Subject: [PATCH 219/327] changed command to shell for grep Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 70f79c6..9190421 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -4,7 +4,7 @@ tags: always block: - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd" - ansible.builtin.command: cat /etc/passwd | grep -v '^#' + ansible.builtin.shell: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false register: prelim_passwd_file_audit From 0e61e796c6633c127fa7bdf10e6c2535ec7dd98e Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 23 May 2025 11:00:13 -0400 Subject: [PATCH 220/327] Fix for #325 thank you @mindrb Signed-off-by: Frederick Witty --- Changelog.md | 2 +- tasks/section_6/cis_6.2.2.1.x.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 4accf38..edcb223 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,7 +2,7 @@ ## 2.0.0 - Based on CIS v2.0.0 -- #322 - thanks to @mindrb +- #322, #325 - thanks to @mindrb - #320 - thanks to @anup-ad ## 1.1.6 - Based on CIS v1.0.0 diff --git a/tasks/section_6/cis_6.2.2.1.x.yml b/tasks/section_6/cis_6.2.2.1.x.yml index 945c2e4..aa2415d 100644 --- a/tasks/section_6/cis_6.2.2.1.x.yml +++ b/tasks/section_6/cis_6.2.2.1.x.yml @@ -35,7 +35,7 @@ regexp: "{{ item.regexp }}" line: "{{ item.line }}" loop: - - { regexp: 'URL=', line: 'URL={{ rhel9cis_remote_log_server }}'} + - { regexp: 'URL=', line: 'URL={{ rhel9cis_journal_upload_url }}'} - { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel9cis_journal_upload_serverkeyfile }}'} - { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'} - { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'} From f83e5a69a2399c47e139b356c4c8714a9005257b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 23 May 2025 16:05:01 +0100 Subject: [PATCH 221/327] interactive users ilogic improvements thanks to @polski-g Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 16 +++++++--------- tasks/section_5/cis_5.4.1.x.yml | 8 ++++---- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- tasks/section_7/cis_7.2.x.yml | 8 ++++---- vars/main.yml | 3 +++ 5 files changed, 20 insertions(+), 19 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index a0fc2fe..c1edb39 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -23,18 +23,16 @@ - 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 }' + 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":"$3":"$6 }' changed_when: false check_mode: false - register: prelim_interactive_usernames + register: prelim_interactive_users_raw -- name: "PRELIM | AUDIT | Interactive User accounts home directories" +- name: "PRELIM | AUDIT | Interactive Users (reformat)" 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 - check_mode: false - register: prelim_interactive_users_home + ansible.builtin.set_fact: + prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + loop: "{{ prelim_interactive_users_raw.stdout_lines }}" - name: "PRELIM | AUDIT | Interactive UIDs" tags: always @@ -205,7 +203,7 @@ tags: - always block: - - name: "PRELIM | AUDIT | Discover is wirelss adapter on system" + - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 6a492e5..1962101 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -29,7 +29,7 @@ - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" when: - discovered_max_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" @@ -60,7 +60,7 @@ - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" when: - discovered_min_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" @@ -91,7 +91,7 @@ - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" when: - discovered_warn_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames.stdout + - item in prelim_interactive_usernames | map(attribute='username') | list - rhel9cis_force_user_warnage ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" changed_when: true @@ -140,7 +140,7 @@ register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - when: item in prelim_interactive_usernames.stdout + when: item in prelim_interactive_usernames | map(attribute='username') | list ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 12390b3..a8eb4d0 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -195,7 +195,7 @@ - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: - rhel9cis_rule_5_4_2_7 - - "item.id not in prelim_interactive_usernames.stdout" + - "item.id not in prelim_interactive_usernames | map(attribute='username')" - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high @@ -220,7 +220,7 @@ when: - rhel9cis_rule_5_4_2_8 - rhel9cis_disruption_high - - "item.id not in prelim_interactive_usernames.stdout" + - "item.id not in prelim_interactive_usernames | map(attribute='username')" - "'root' not in item.id" tags: - level1-server diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index cc1825c..8706877 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -256,7 +256,7 @@ etype: group permissions: rx state: present - loop: "{{ prelim_interactive_users_home.stdout_lines }}" + loop: "{{ prelim_interactive_users | map(attribute='home') | list }}" - name: "7.2.8 | PATCH | Ensure local interactive user home directories are configured | Set other ACL" when: not system_is_container @@ -266,7 +266,7 @@ etype: other permissions: 0 state: present - loop: "{{ prelim_interactive_users_home.stdout_lines }}" + loop: "{{ prelim_interactive_users | map(attribute='home') | list }}" - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured" when: @@ -315,6 +315,6 @@ ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" diff --git a/vars/main.yml b/vars/main.yml index cdca90d..5eed07c 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -22,6 +22,9 @@ rhel9cis_allowed_crypto_policies_modules: warn_control_list: "" warn_count: 0 +# list of dicts of interactive users, filled in during prelim.yml +prelim_interactive_users: [] + # Default empty values for 1.4.2 efi_mount_opts_addition: '' From f564135e72384a79f2f99f0ac9d0bf7d90bddfdc Mon Sep 17 00:00:00 2001 From: polski_g Date: Thu, 8 May 2025 11:17:29 -0400 Subject: [PATCH 222/327] Check for existence of sshd_config.d/50-redhat.conf before trying to modify it Signed-off-by: polski-g --- tasks/prelim.yml | 8 ++++++++ tasks/section_5/cis_5.1.x.yml | 2 ++ 2 files changed, 10 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index c1edb39..b8f39d6 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -246,6 +246,14 @@ mode: 'go-rwx' state: touch +- name: "PRELIM | PATCH | sshd_config.d/50-redhat.conf exists" + when: + - rhel9cis_rule_5_1_10 or + rhel9cis_rule_5_1_11 + ansible.builtin.stat: + path: /etc/ssh/sshd_config.d/50-redhat.conf + register: discovered_sshd_50_redhat_file + - name: "PRELIM | AUDIT | Capture pam security related files" tags: always ansible.builtin.find: diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 99176fd..eaee7de 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -276,6 +276,7 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" + when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: ^(?i)(#|)\s*X11Forwarding @@ -298,6 +299,7 @@ - NIST800-53R5_IA-5 block: - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" + when: discovered_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf regexp: ^(?i)(#|)\s*GSSAPIAuthentication From 4e49532e2030320148fcb272dca5a2950b4e2575 Mon Sep 17 00:00:00 2001 From: polski_g Date: Thu, 8 May 2025 10:52:21 -0400 Subject: [PATCH 223/327] Variablize network-manager package name Signed-off-by: polski-g --- defaults/main.yml | 1 + tasks/section_3/cis_3.1.x.yml | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 6a360fa..c55f93a 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -724,6 +724,7 @@ rhel9cis_ipv6_required: true ## 3.1.2 wireless network requirements # if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false +rhel9cis_network_manager_package_name: NetworkManager # 3.3 System network parameters (host only OR host and router) # This variable governs whether specific CIS rules # concerned with acceptance and routing of packages are skipped. diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 68a66de..a20c0e9 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -39,7 +39,7 @@ warn_control_id: '3.1.2' block: - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool" - when: "'network-manager' in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name in ansible_facts.packages" ansible.builtin.command: nmcli radio wifi changed_when: false failed_when: false @@ -48,19 +48,19 @@ - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed" when: - - "'network-manager' in ansible_facts.packages" + - "rhel9cis_network_manager_package_name in ansible_facts.packages" - "'enabled' in discovered_wifi_status.stdout" ansible.builtin.command: nmcli radio all off changed_when: discovered_nmcli_radio_off.rc == 0 register: discovered_nmcli_radio_off - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.debug: msg: "Warning!! You need to disable wireless interfaces manually since network-manager is not installed" - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Set warning count" - when: "'network-manager' not in ansible_facts.packages" + when: "rhel9cis_network_manager_package_name not in ansible_facts.packages" ansible.builtin.import_tasks: file: warning_facts.yml From fb9577f7d9c5f4f41efce4454ab626f1a579f367 Mon Sep 17 00:00:00 2001 From: polski_g Date: Thu, 8 May 2025 10:53:27 -0400 Subject: [PATCH 224/327] Fix typo in variable name discovered_group_check Signed-off-by: polski-g --- tasks/section_7/cis_7.2.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 8706877..cb01c21 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -220,7 +220,7 @@ - name: "7.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 }}" + msg: "Warning!! The following group names are duplicates: {{ discovered_group_check.stdout_lines }}" - name: "7.2.7 | AUDIT | Ensure no duplicate group names exist | Set warning count" when: discovered_group_check.stdout | length > 0 From 68579ae85e7ff7613bd9ae89f66fd96cd57374f8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 26 May 2025 17:23:15 +0000 Subject: [PATCH 225/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.4.0 → v25.5.0](https://github.com/ansible-community/ansible-lint/compare/v25.4.0...v25.5.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ebc85d7..ddcc701 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.4.0 + rev: v25.5.0 hooks: - id: ansible-lint name: Ansible-lint From d136bfa381f6b2766782fbca28b60b1c1def55e6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 10:22:30 +0100 Subject: [PATCH 226/327] Updated variable naming for interactive_users Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- tasks/section_5/cis_5.4.1.x.yml | 8 ++++---- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index c1edb39..7d3b295 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -31,7 +31,7 @@ - name: "PRELIM | AUDIT | Interactive Users (reformat)" tags: always ansible.builtin.set_fact: - prelim_interactive_usernames: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" + prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" - name: "PRELIM | AUDIT | Interactive UIDs" diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 1962101..7fcfb0b 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -29,7 +29,7 @@ - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" when: - discovered_max_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_maxdays ansible.builtin.user: name: "{{ item }}" @@ -60,7 +60,7 @@ - name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS" when: - discovered_min_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" @@ -91,7 +91,7 @@ - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS" when: - discovered_warn_days.stdout_lines | length > 0 - - item in prelim_interactive_usernames | map(attribute='username') | list + - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_warnage ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" changed_when: true @@ -140,7 +140,7 @@ register: discovered_passwdlck_user_list - name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts" - when: item in prelim_interactive_usernames | map(attribute='username') | list + when: item in prelim_interactive_users | map(attribute='username') | list ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}" changed_when: true loop: "{{ discovered_passwdlck_user_list.stdout_lines }}" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index a8eb4d0..26985a3 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -195,7 +195,7 @@ - name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell" when: - rhel9cis_rule_5_4_2_7 - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - item.id not in rhel9cis_system_users_shell - "'root' not in item.id" - rhel9cis_disruption_high @@ -220,7 +220,7 @@ when: - rhel9cis_rule_5_4_2_8 - rhel9cis_disruption_high - - "item.id not in prelim_interactive_usernames | map(attribute='username')" + - "item.id not in prelim_interactive_users | map(attribute='username')" - "'root' not in item.id" tags: - level1-server From 5dc2541731f3e544939f44d112a94bc6af015974 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 14:57:29 +0100 Subject: [PATCH 227/327] Updated passwd variable name Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 6 +++--- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- tasks/section_7/cis_7.2.x.yml | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 9190421..9f137cb 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -7,11 +7,11 @@ ansible.builtin.shell: cat /etc/passwd | grep -v '^#' changed_when: false check_mode: false - register: prelim_passwd_file_audit + register: prelim_capture_passwd_file - - name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries" + - name: "PRELIM | 5.4.2 | 7.2.8 | Split passwd entries" ansible.builtin.set_fact: - rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" + prelim_captured_passwd_data: "{{ prelim_capture_passwd_file.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" loop: "{{ prelim_passwd_file_audit.stdout_lines }}" vars: ld_passwd_regex: >- diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 26985a3..37a4e11 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -212,7 +212,7 @@ ansible.builtin.user: name: "{{ item.id }}" shell: /usr/sbin/nologin - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" @@ -235,6 +235,6 @@ ansible.builtin.user: name: "{{ item.id }}" password_lock: true - loop: "{{ rhel9cis_passwd }}" + loop: "{{ prelim_captured_passwd_data }}" loop_control: label: "{{ item.id }}" diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index 8706877..c63ee2f 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -243,7 +243,7 @@ state: directory owner: "{{ item.id }}" group: "{{ item.gid }}" - loop: "{{ rhel9cis_passwd | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" + loop: "{{ prelim_captured_passwd_data | selectattr('uid', '>=', prelim_min_int_uid | int) | selectattr('uid', '<=', prelim_max_int_uid | int) | list }}" loop_control: label: "{{ item.id }}" @@ -315,6 +315,6 @@ ansible.builtin.file: path: '{{ item }}' mode: 'go-w' - owner: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ rhel9cis_passwd | selectattr('dir', 'in', prelim_interactive_users_raw.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" From c4070c341b99a7ca2a76de22bc41e545d0fbf88f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:35:34 +0100 Subject: [PATCH 228/327] Updated logic on 7.2.9 tasks Signed-off-by: Mark Bolwell --- tasks/section_7/cis_7.2.x.yml | 64 ++++++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 13 deletions(-) diff --git a/tasks/section_7/cis_7.2.x.yml b/tasks/section_7/cis_7.2.x.yml index c63ee2f..90da743 100644 --- a/tasks/section_7/cis_7.2.x.yml +++ b/tasks/section_7/cis_7.2.x.yml @@ -286,8 +286,8 @@ vars: warn_control_id: '7.2.9' block: - - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Check for files" - ansible.builtin.shell: find /home/ -name "\.*" + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured" + ansible.builtin.shell: find {{ prelim_interactive_users_home.stdout_lines | list | join(' ') }} -name "\.*" -type f changed_when: false failed_when: discovered_homedir_hidden_files.rc not in [ 0, 1 ] check_mode: false @@ -296,25 +296,63 @@ - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Warning on files found" when: - discovered_homedir_hidden_files.stdout | length > 0 - - rhel9cis_dotperm_ansiblemanaged + - not rhel9cis_dotperm_ansiblemanaged 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." + - "Warning!! Please investigate that hidden files found in users home directories match control requirements." - - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Set warning count" + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Set warning count" when: - discovered_homedir_hidden_files.stdout | length > 0 - - rhel9cis_dotperm_ansiblemanaged + - not rhel9cis_dotperm_ansiblemanaged ansible.builtin.import_tasks: file: warning_facts.yml - - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured" when: - discovered_homedir_hidden_files.stdout | length > 0 - rhel9cis_dotperm_ansiblemanaged - ansible.builtin.file: - path: '{{ item }}' - mode: 'go-w' - owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" - group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" - with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" + block: + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Changes files if configured .bash_history & .netrc" + when: + - discovered_homedir_hidden_files.stdout | length > 0 + - item | basename in ['.bash_history','.netrc'] + ansible.builtin.file: + path: "{{ item }}" + mode: 'u-x,go-rwx' + failed_when: discovered_dot_bash_history_to_change.state not in '[ file, absent ]' + register: discovered_dot_bash_history_to_change + loop: "{{ discovered_homedir_hidden_files.stdout_lines }}" + + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Changes files if configured file mode" + ansible.builtin.file: + path: '{{ item }}' + mode: 'u-x,go-wx' + failed_when: discovered_dot_bash_history_to_change.state not in '[ file, absent ]' + register: discovered_dot_bash_history_to_change + loop: "{{ discovered_homedir_hidden_files.stdout_lines }}" + + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | Changes files ownerships" + ansible.builtin.file: + path: "{{ item }}" + owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + failed_when: discovered_dot_bash_history_to_change.state not in '[ file, absent ]' + register: discovered_dot_bash_history_to_change + loop: "{{ discovered_homedir_hidden_files.stdout_lines }}" + + - name: "7.2.9 | PATCH | Ensure local interactive user dot files access is configured | Changes files if configured" + ansible.builtin.file: + path: '{{ item }}' + mode: 'go-w' + owner: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='uid') | last }}" + group: "{{ prelim_captured_passwd_data | selectattr('dir', 'in', prelim_interactive_users_home.stdout_lines) | selectattr('dir', 'in', item) | map(attribute='gid') | last }}" + with_items: "{{ discovered_homedir_hidden_files.stdout_lines }}" + + - name: "7.2.9 | AUDIT | Ensure local interactive user dot files access is configured | rename .forward or .rhosts files" + when: + - item | basename in ['.forward','.rhosts'] + - item is not search ("CIS") + ansible.builtin.command: "mv {{ item }} {{ item }}_CIS_TOBEREVIEWED" + changed_when: true + loop: "{{ discovered_homedir_hidden_files.stdout_lines }}" From 210535bf4f14b00b5f9de8c7dab8c291e646f7bf Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:36:04 +0100 Subject: [PATCH 229/327] updated loop var name Signed-off-by: Mark Bolwell --- tasks/parse_etc_password.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/parse_etc_password.yml b/tasks/parse_etc_password.yml index 9f137cb..c7ed865 100644 --- a/tasks/parse_etc_password.yml +++ b/tasks/parse_etc_password.yml @@ -12,7 +12,7 @@ - name: "PRELIM | 5.4.2 | 7.2.8 | Split passwd entries" ansible.builtin.set_fact: prelim_captured_passwd_data: "{{ prelim_capture_passwd_file.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}" - loop: "{{ prelim_passwd_file_audit.stdout_lines }}" + loop: "{{ prelim_capture_passwd_file.stdout_lines }}" vars: ld_passwd_regex: >- ^(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*):(?P[^:]*) From f740d89b54c77aca6056571fad56124f6907f018 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 15:36:39 +0100 Subject: [PATCH 230/327] Added user home discovery Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 7d3b295..4c170a1 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -34,6 +34,14 @@ prelim_interactive_users: "{{ prelim_interactive_users | default([]) + [dict([('username', item.split(':')[0]), ('uid', item.split(':')[1]), ('home', item.split(':')[2])])] }}" loop: "{{ prelim_interactive_users_raw.stdout_lines }}" +- 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" && $7 != "/dev/null") { print $6 }' + changed_when: false + check_mode: false + register: prelim_interactive_users_home + - name: "PRELIM | AUDIT | Interactive UIDs" tags: always ansible.builtin.shell: > From cb475d336892def111d1817363afa48aa1ff6ed4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 28 May 2025 16:10:28 +0100 Subject: [PATCH 231/327] fixed typo on post audit file name Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 54d5785..68e7035 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -33,7 +33,7 @@ when: audit_format == "documentation" block: - name: Post Audit | Capture audit data if documentation format - ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' + ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false register: post_audit_summary From 30d7e3a7616e9d938c8c208cfe6003c053f84255 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:25:10 +0000 Subject: [PATCH 232/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.26.0 → v8.27.0](https://github.com/gitleaks/gitleaks/compare/v8.26.0...v8.27.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index ddcc701..79d19fb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.26.0 + rev: v8.27.0 hooks: - id: gitleaks From 1bff329a058de7a7148108f3423cf5a636287edf Mon Sep 17 00:00:00 2001 From: polski-g Date: Tue, 3 Jun 2025 11:35:05 -0400 Subject: [PATCH 233/327] auditd: ensure check mode runs non-destructive call to ausyscall --dump Signed-off-by: polski-g --- tasks/auditd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7b86b94..0fa0b32 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -7,6 +7,7 @@ - name: "POST | AUDITD | Set supported_syscalls variable" ansible.builtin.shell: ausyscall --dump | awk '{print $2}' changed_when: false + check_mode: false failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] register: discovered_auditd_syscalls From 5226f14b3e61eb23e740aac886520ddd309e7242 Mon Sep 17 00:00:00 2001 From: polski-g Date: Fri, 6 Jun 2025 10:03:47 -0400 Subject: [PATCH 234/327] fetch of auditd logfile should run in check_mode Signed-off-by: polski-g --- tasks/prelim.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index ced76ce..0081cc6 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -317,6 +317,7 @@ tags: always ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }' changed_when: false + check_mode: false register: prelim_auditd_logfile - name: "PRELIM | AUDIT | Audit conf and rules files | list files" From 2ce05a345ddb7ddc3c4c00d121ef3b05c91dbb4c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 9 Jun 2025 17:24:11 +0000 Subject: [PATCH 235/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.27.0 → v8.27.2](https://github.com/gitleaks/gitleaks/compare/v8.27.0...v8.27.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 79d19fb..cbcb7a4 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.27.0 + rev: v8.27.2 hooks: - id: gitleaks From 30bb04b1d487b19b8663bda48283a9c457340b8b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 12 Jun 2025 12:10:44 +0100 Subject: [PATCH 236/327] updates root password check Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index e285e8d..fe50b10 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -132,7 +132,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false register: prelim_root_passwd_set From 9f50effd30052ff24c0a02c8e47c6b7e437238cd Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:01:10 +0100 Subject: [PATCH 237/327] updated logic Signed-off-by: Mark Bolwell --- tasks/main.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/main.yml b/tasks/main.yml index fe50b10..43ec09c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,6 +134,7 @@ - name: "Ensure root password is set" ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false + failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set - name: "Ensure root password is set" From 51b20d383d98965bf44290388edbc9322bcb7a28 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:07:27 +0100 Subject: [PATCH 238/327] Renamed variable to prelim Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index ced76ce..0a3c42a 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -260,7 +260,7 @@ rhel9cis_rule_5_1_11 ansible.builtin.stat: path: /etc/ssh/sshd_config.d/50-redhat.conf - register: discovered_sshd_50_redhat_file + register: prelim_sshd_50_redhat_file - name: "PRELIM | AUDIT | Capture pam security related files" tags: always From b2308ac31097f1e44bffb0e0c2a9b7978c47f891 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:07:55 +0100 Subject: [PATCH 239/327] fixed typos in logic Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.1.2.3.x.yml | 4 ++-- tasks/section_1/cis_1.1.2.4.x.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.3.x.yml b/tasks/section_1/cis_1.1.2.3.x.yml index 998d1ba..635648d 100644 --- a/tasks/section_1/cis_1.1.2.3.x.yml +++ b/tasks/section_1/cis_1.1.2.3.x.yml @@ -21,12 +21,12 @@ register: discovered_home_mount - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_home_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index e0afd4e..f89fe3f 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -22,12 +22,12 @@ register: discovered_var_mount - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml From 18fc4ea585f7f3812e391ebc0ca75cf2528f741e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:08:56 +0100 Subject: [PATCH 240/327] updated conditional var name and regex best practices Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.1.x.yml | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index eaee7de..3fd366c 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -276,10 +276,10 @@ notify: Restart sshd - name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override" - when: discovered_sshd_50_redhat_file.stat.exists + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*X11Forwarding + regexp: (?i)^(#|)\s*X11Forwarding line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}' validate: sshd -t -f %s notify: Restart sshd @@ -299,10 +299,10 @@ - NIST800-53R5_IA-5 block: - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file" - when: discovered_sshd_50_redhat_file.stat.exists + when: prelim_sshd_50_redhat_file.stat.exists ansible.builtin.lineinfile: path: /etc/ssh/sshd_config.d/50-redhat.conf - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -310,7 +310,7 @@ - name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*GSSAPIAuthentication + regexp: (?i)^(#|)\s*GSSAPIAuthentication line: GSSAPIAuthentication no validate: sshd -t -f %s notify: Restart sshd @@ -330,7 +330,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*HostbasedAuthentication + regexp: (?i)^(#|)\s*HostbasedAuthentication line: 'HostbasedAuthentication no' validate: sshd -t -f %s notify: Restart sshd @@ -350,7 +350,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*IgnoreRhosts + regexp: (?i)^(#|)\s*IgnoreRhosts line: 'IgnoreRhosts yes' insertbefore: "^Match" firstmatch: true @@ -368,7 +368,7 @@ - NIST800-53R5_CM-6 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LoginGraceTime + regexp: (?i)^(#|)\s*LoginGraceTime line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}" insertbefore: "^Match" firstmatch: true @@ -388,7 +388,7 @@ - NIST800-53R5_SI-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*LogLevel + regexp: (?i)^(#|)\s*LogLevel line: 'LogLevel {{ rhel9cis_ssh_loglevel }}' insertbefore: "^Match" firstmatch: true @@ -426,7 +426,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxStartups + regexp: (?i)^(#|)\s*MaxStartups line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}' validate: sshd -t -f %s notify: Restart sshd @@ -446,7 +446,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*MaxSessions + regexp: (?i)^(#|)\s*MaxSessions line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}' validate: sshd -t -f %s notify: Restart sshd @@ -466,7 +466,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitEmptyPasswords + regexp: (?i)^(#|)\s*PermitEmptyPasswords line: 'PermitEmptyPasswords no' validate: sshd -t -f %s notify: Restart sshd @@ -484,7 +484,7 @@ - name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file" ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitRootLogin + regexp: (?i)^(#|)\s*PermitRootLogin line: 'PermitRootLogin no' validate: sshd -t -f %s notify: Restart sshd @@ -510,7 +510,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*PermitUserEnvironment + regexp: (?i)^(#|)\s*PermitUserEnvironment line: 'PermitUserEnvironment no' validate: sshd -t -f %s notify: Restart sshd @@ -530,7 +530,7 @@ - NIST800-53R5_IA-5 ansible.builtin.lineinfile: path: "{{ rhel9cis_sshd_config_file }}" - regexp: ^(?i)(#|)\s*UsePAM + regexp: (?i)^(#|)\s*UsePAM line: 'UsePAM yes' validate: sshd -t -f %s notify: Restart sshd From 7bef2eda62c06b670893f13111f45a5d87a04650 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:12:27 +0100 Subject: [PATCH 241/327] added check_mode false Signed-off-by: Mark Bolwell --- tasks/auditd.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 7b86b94..0fa0b32 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -7,6 +7,7 @@ - name: "POST | AUDITD | Set supported_syscalls variable" ansible.builtin.shell: ausyscall --dump | awk '{print $2}' changed_when: false + check_mode: false failed_when: discovered_auditd_syscalls.rc not in [ 0, 1 ] register: discovered_auditd_syscalls From ca14eeb1476ef4594de5ecc1ac658300663ee971 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 10:18:26 +0100 Subject: [PATCH 242/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.md b/Changelog.md index edcb223..83157e9 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ # Changes to rhel9CIS +## 2.0.1 - Based on CIS v2.0.0 + +- Thanks to @polski-g several issues and improvements added +- Improved testing for 50-redhat.conf for ssh +- 5.1.x regexp improvements +- Improved root password check + ## 2.0.0 - Based on CIS v2.0.0 - #322, #325 - thanks to @mindrb From 35d0bf9c4be05139e540edad74873690e57d576f Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 13:19:14 +0100 Subject: [PATCH 243/327] updated auditing conditionals Signed-off-by: Mark Bolwell --- tasks/prelim.yml | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 0a3c42a..1eed552 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -4,9 +4,7 @@ # List users in order to look files inside each home directory - name: "PRELIM | Include audit specific variables" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: - setup_audit - run_audit @@ -14,9 +12,7 @@ file: audit.yml - name: "PRELIM | Include pre-remediation audit tasks" - when: - - run_audit or audit_only - - setup_audit + when: run_audit or audit_only or setup_audit tags: run_audit ansible.builtin.import_tasks: pre_remediation_audit.yml From 3173b74481ebcab6448bc37ed0c863313a8d77a8 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:21:45 +0100 Subject: [PATCH 244/327] updated grep command 1.3.1.6 Signed-off-by: Mark Bolwell --- tasks/section_1/cis_1.3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/cis_1.3.1.x.yml b/tasks/section_1/cis_1.3.1.x.yml index 198ae7b..ad7d844 100644 --- a/tasks/section_1/cis_1.3.1.x.yml +++ b/tasks/section_1/cis_1.3.1.x.yml @@ -106,7 +106,7 @@ warn_control_id: '1.3.1.6' block: - name: "1.3.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 }' + ansible.builtin.shell: ps -eZ | grep unconfined_service_t | grep -Evw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }' register: discovered_unconf_services failed_when: false changed_when: false From 3ea5b92259d5998129b0274043571c66ab44dac3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 16 Jun 2025 17:22:31 +0100 Subject: [PATCH 245/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 83157e9..ede8f72 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ - Improved testing for 50-redhat.conf for ssh - 5.1.x regexp improvements - Improved root password check +- egrep command changed to grep -E ## 2.0.0 - Based on CIS v2.0.0 From 908ac57db767d6952c057db34d55faaa87a998e6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:26:01 +0100 Subject: [PATCH 246/327] enabled fetch report and updated title Signed-off-by: Mark Bolwell --- tasks/audit_only.yml | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 39c9f7d..a33cb94 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -1,19 +1,17 @@ --- -- name: Audit_Only | Create local Directories for hosts - when: fetch_audit_files - ansible.builtin.file: - mode: 'u+x,go-w' - path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}" - recurse: true - state: directory - delegate_to: localhost - become: false + +- name: Audit_only | Fetch audit files + when: + - fetch_audit_output + - audit_only + ansible.builtin.import_tasks: + file: fetch_audit_output.yml - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" -- name: Audit_only | Stop Playbook Audit Only selected +- name: Audit_only | Stop task for host as audit_only selected when: audit_only - ansible.builtin.meta: end_play + ansible.builtin.meta: end_host From 515d5c3bf77a87385aea862e496e8502a5a50141 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:26:48 +0100 Subject: [PATCH 247/327] added changed_when to resolve false warning message Signed-off-by: Mark Bolwell --- tasks/fetch_audit_output.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml index 563b699..e440185 100644 --- a/tasks/fetch_audit_output.yml +++ b/tasks/fetch_audit_output.yml @@ -8,6 +8,7 @@ src: "{{ item }}" dest: "{{ audit_output_destination }}" flat: true + changed_when: true failed_when: false register: discovered_audit_fetch_state loop: From 72dfe581e970267fe500ee84365439a0f16c6fe6 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 19 Jun 2025 16:27:53 +0100 Subject: [PATCH 248/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Changelog.md b/Changelog.md index edcb223..57ac1bc 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,11 @@ # Changes to rhel9CIS +## Based on CIS v2.0.0 + +Update to audit_only to allow fetching results +resolved false warning for fetch audit +fix root user check + ## 2.0.0 - Based on CIS v2.0.0 - #322, #325 - thanks to @mindrb From bd1547313a69a7750ad1a312796b35e081346646 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 20 Jun 2025 11:28:19 +0100 Subject: [PATCH 249/327] Fix logic and notes for in crypto policy building Signed-off-by: Mark Bolwell --- Changelog.md | 1 + defaults/main.yml | 4 ++-- handlers/main.yml | 2 +- tasks/main.yml | 2 +- vars/main.yml | 6 ++++++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Changelog.md b/Changelog.md index 3cb8dad..331a17e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Update to audit_only to allow fetching results resolved false warning for fetch audit fix root user check +Improved documentation and variable compilation for crypto policies ## 2.0.1 - Based on CIS v2.0.0 diff --git a/defaults/main.yml b/defaults/main.yml index c55f93a..23312e5 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -580,8 +580,8 @@ rhel9cis_crypto_policy: 'DEFAULT' ## Control 1.6 # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, -# using 'rhel9cis_allowed_crypto_policies_modules' variable. -rhel9cis_crypto_policy_module: '' +# using those listed in the 'rhel9cis_allowed_crypto_policies_modules' variable. +rhel9cis_additional_crypto_policy_module: '' ## Controls: # - 1.7.1 - Ensure message of the day is configured properly diff --git a/handlers/main.yml b/handlers/main.yml index 1a3b66e..4bc5a08 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -186,7 +186,7 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}:{{ rhel9cis_additional_crypto_policy_module }}" notify: Set Crypto Policy - name: Set Crypto Policy diff --git a/tasks/main.yml b/tasks/main.yml index 43ec09c..25bb7bc 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -61,7 +61,7 @@ - crypto - NIST800-53R5_SC-6 ansible.builtin.assert: - that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules + that: rhel9cis_additional_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules fail_msg: "Crypto policy module is not a permitted version" success_msg: "Crypto policy module is a permitted version" diff --git a/vars/main.yml b/vars/main.yml index 5eed07c..9337d58 100644 --- a/vars/main.yml +++ b/vars/main.yml @@ -7,10 +7,16 @@ rhel9cis_allowed_crypto_policies: - 'FUTURE' - 'FIPS' +# Following is left blank for ability to build string +rhel9cis_crypto_policy_module: '' + +# Do not adjust these are recognized as part of the CIS benchmark and used during testing rhel9cis_allowed_crypto_policies_modules: + # Recognized by CIS as possible extra options - 'OSPP' - 'AD-SUPPORT' - 'AD-SUPPORT-LEGACY' + # The following are already included in 1.6.x controls - 'NO-SHA1' - 'NO-SSHCBC' - 'NO-SSHETM' From 37f4d0c9f09c34410c9b8893de37f5046d9db347 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 20 Jun 2025 12:15:13 +0100 Subject: [PATCH 250/327] fixed crypto logic Signed-off-by: Mark Bolwell --- handlers/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlers/main.yml b/handlers/main.yml index 4bc5a08..1894300 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -186,7 +186,7 @@ - name: Update Crypto Policy ansible.builtin.set_fact: - rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}:{{ rhel9cis_additional_crypto_policy_module }}" + rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{{ rhel9cis_crypto_policy_module }}{% if rhel9cis_additional_crypto_policy_module | length > 0 %}:{{ rhel9cis_additional_crypto_policy_module }}{% endif %}" notify: Set Crypto Policy - name: Set Crypto Policy From fc2f5895ced1fbee59d117f05d86b925b8b7912a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 17:27:59 +0000 Subject: [PATCH 251/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.5.0 → v25.6.1](https://github.com/ansible-community/ansible-lint/compare/v25.5.0...v25.6.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cbcb7a4..a4d0a42 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.5.0 + rev: v25.6.1 hooks: - id: ansible-lint name: Ansible-lint From 5ed6abd5d330939df5dd17efa46784fccf33bea1 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Thu, 26 Jun 2025 13:29:42 +0300 Subject: [PATCH 252/327] Fixing issue https://code.siemens.com/infosec-pss-gov/security-crafter-baseline-automations/ansible-lockdown/rhel9-cis/-/issues/42 . Signed-off-by: Diana-Maria Dumitru --- templates/audit/99_auditd.rules.j2 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4d9c0d3..6c852e3 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -58,6 +58,8 @@ -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/hostname -p wa -k system-locale +-w /etc/NetworkManager -p wa -k system-locale {% endif %} {% if rhel9cis_rule_6_3_3_6 %} {% for proc in discovered_priv_procs.stdout_lines -%} From ed699a50ba5991beb4d5e93b0ec8e51f32d81677 Mon Sep 17 00:00:00 2001 From: Diana-Maria Dumitru Date: Thu, 26 Jun 2025 13:35:51 +0300 Subject: [PATCH 253/327] Fixing issue https://code.siemens.com/infosec-pss-gov/security-crafter-baseline-automations/ansible-lockdown/rhel9-cis/-/issues/43 . Signed-off-by: Diana-Maria Dumitru --- tasks/auditd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/auditd.yml b/tasks/auditd.yml index 0fa0b32..9ada459 100644 --- a/tasks/auditd.yml +++ b/tasks/auditd.yml @@ -25,7 +25,7 @@ dest: /etc/audit/rules.d/99_auditd.rules owner: root group: root - mode: 'u-x,go-wx' + mode: 'u-x,g-wx,o-rwx' diff: "{{ discovered_auditd_rules_file.stat.exists }}" # Only run diff if not a new file register: discovered_auditd_rules_template_updated notify: From 23338ccd314d433049606b36114d6d32c004d5e3 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 27 Jun 2025 11:12:07 -0400 Subject: [PATCH 254/327] Addresses #318 - Thank you @kodebach & @bgro Signed-off-by: Frederick Witty --- Changelog.md | 12 +++++++----- tasks/main.yml | 5 ++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/Changelog.md b/Changelog.md index 331a17e..53cf91d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,11 +1,13 @@ # Changes to rhel9CIS -## Based on CIS v2.0.0 +## 2.0.1 - Based on CIS v2.0.0 -Update to audit_only to allow fetching results -resolved false warning for fetch audit -fix root user check -Improved documentation and variable compilation for crypto policies +- Update to audit_only to allow fetching results +- resolved false warning for fetch audit +- fix root user check +- Improved documentation and variable compilation for crypto policies +- Addresses #318 - Thank you @kodebach & @bgro + - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check task/main.yml ## 2.0.1 - Based on CIS v2.0.0 diff --git a/tasks/main.yml b/tasks/main.yml index 25bb7bc..460acc8 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -101,10 +101,9 @@ - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: - that: - - not prelim_ansible_user_password_set.stdout.startswith("!") + that: (not prelim_ansible_user_password_set.stdout.startswith("!")) or (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access" - success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user" + success_msg: "The local account {{ ansible_env.SUDO_USER }} is not locked or included in the exception list for rule 5.2.4" - name: "Check authselect profile is selected" when: rhel9cis_allow_authselect_updates From ac276f34fc8e5773e232fc51b90446df796b9fb5 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 27 Jun 2025 11:15:19 -0400 Subject: [PATCH 255/327] ChangeLog versioning fix Signed-off-by: Frederick Witty --- Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 53cf91d..b6db646 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,13 +1,13 @@ # Changes to rhel9CIS -## 2.0.1 - Based on CIS v2.0.0 +## 2.0.2 - Based on CIS v2.0.0 - Update to audit_only to allow fetching results - resolved false warning for fetch audit - fix root user check - Improved documentation and variable compilation for crypto policies - Addresses #318 - Thank you @kodebach & @bgro - - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check task/main.yml + - Improved logic for 5.2.4 to exclude rhel9cis_sudoers_exclude_nopasswd_list in pre-check tasks/main.yml ## 2.0.1 - Based on CIS v2.0.0 From 7ec2c9bf5efa92a2b90697d7d9f4d239dc08f4e7 Mon Sep 17 00:00:00 2001 From: davidalexander83 Date: Wed, 2 Jul 2025 12:32:20 +1000 Subject: [PATCH 256/327] Fix re.error due to (?i) not at start of re 6.2.2.3 and 6.2.2.4 cause issues due to current re syntax: ^(?i)(\s*compress=) re.error: global flags not at the start of the expression at position 1 Fix removes ^ which resolves issue without affecting functionality. Signed-off-by: davidalexander83 --- tasks/section_6/cis_6.2.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_6/cis_6.2.2.x.yml b/tasks/section_6/cis_6.2.2.x.yml index a57efe2..fe0f8c4 100644 --- a/tasks/section_6/cis_6.2.2.x.yml +++ b/tasks/section_6/cis_6.2.2.x.yml @@ -50,7 +50,7 @@ - name: "6.2.2.3 | PATCH | Ensure journald Compress is configured | comment out current entries" ansible.builtin.replace: path: /etc/systemd/journald.conf - regexp: ^(?i)(\s*compress=) + regexp: (?i)(\s*compress=) replace: '#\1' - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured" @@ -76,5 +76,5 @@ - name: "6.2.2.4 | PATCH | Ensure journald Storage is configured | comment out current entries" ansible.builtin.replace: path: /etc/systemd/journald.conf - regexp: ^(?i)(\s*storage=) + regexp: (?i)(\s*storage=) replace: '#\1' From 55744fe599d9764a0d261b9075aa997ddfcdea26 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Wed, 2 Jul 2025 13:48:17 +0300 Subject: [PATCH 257/327] Fixing documentation of the vars. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 673 ++++++++++++++++++++++++++++------------------ 1 file changed, 410 insertions(+), 263 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 23312e5..71fe932 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -134,6 +134,7 @@ audit_output_destination: /opt/audit_summaries/ # PLEASE NOTE: These work in coordination with the section # group variables and tags. # You must enable an entire section in order for the variables below to take effect. +## Section 1 Fixes # Section 1 is Initial setup (FileSystem Configuration, Configure Software Updates, Filesystem Integrity Checking, Secure Boot Settings, # Additional Process Hardening, Mandatory Access Control, Command Line Warning Banners, and GNOME Display Manager) # Filesystem kernel modules @@ -180,7 +181,6 @@ rhel9cis_rule_1_1_2_7_1: true rhel9cis_rule_1_1_2_7_2: true rhel9cis_rule_1_1_2_7_3: true rhel9cis_rule_1_1_2_7_4: true - # Package Mgmt # Config Pkg Repos rhel9cis_rule_1_2_1_1: true @@ -189,7 +189,6 @@ rhel9cis_rule_1_2_1_3: true rhel9cis_rule_1_2_1_4: true # Package updates rhel9cis_rule_1_2_2_1: true - # Selinux rhel9cis_rule_1_3_1_1: true rhel9cis_rule_1_3_1_2: true @@ -199,17 +198,14 @@ rhel9cis_rule_1_3_1_5: true rhel9cis_rule_1_3_1_6: true rhel9cis_rule_1_3_1_7: true rhel9cis_rule_1_3_1_8: true - # Bootloader rhel9cis_rule_1_4_1: true rhel9cis_rule_1_4_2: true - # Additional Process Hardening rhel9cis_rule_1_5_1: true rhel9cis_rule_1_5_2: true rhel9cis_rule_1_5_3: true rhel9cis_rule_1_5_4: true - # Config system wide Crypto rhel9cis_rule_1_6_1: true rhel9cis_rule_1_6_2: true @@ -218,7 +214,6 @@ rhel9cis_rule_1_6_4: true rhel9cis_rule_1_6_5: true rhel9cis_rule_1_6_6: true rhel9cis_rule_1_6_7: true - # Command line warning banners rhel9cis_rule_1_7_1: true rhel9cis_rule_1_7_2: true @@ -226,7 +221,6 @@ rhel9cis_rule_1_7_3: true rhel9cis_rule_1_7_4: true rhel9cis_rule_1_7_5: true rhel9cis_rule_1_7_6: true - # Gnome Display Manager rhel9cis_rule_1_8_1: true rhel9cis_rule_1_8_2: true @@ -239,8 +233,9 @@ rhel9cis_rule_1_8_8: true rhel9cis_rule_1_8_9: true rhel9cis_rule_1_8_10: true -# Section 2 rules are controling Services (Special Purpose Services, and service clients) -## Configure Server Services +## Section 2 Fixes +# Section 2 rules are controlling Services (Special Purpose Services, and service clients) +# Configure Server Services rhel9cis_rule_2_1_1: true rhel9cis_rule_2_1_2: true rhel9cis_rule_2_1_3: true @@ -263,21 +258,18 @@ rhel9cis_rule_2_1_19: true rhel9cis_rule_2_1_20: true rhel9cis_rule_2_1_21: true rhel9cis_rule_2_1_22: true - -## Configure Client Services +# Configure Client Services rhel9cis_rule_2_2_1: true rhel9cis_rule_2_2_2: true rhel9cis_rule_2_2_3: true rhel9cis_rule_2_2_4: true rhel9cis_rule_2_2_5: true - -## Configure Time Synchronization +# Configure Time Synchronization rhel9cis_rule_2_3_1: true rhel9cis_rule_2_3_2: true rhel9cis_rule_2_3_3: true - -## Job Schedulers -### cron +# Job Schedulers +# cron rhel9cis_rule_2_4_1_1: true rhel9cis_rule_2_4_1_2: true rhel9cis_rule_2_4_1_3: true @@ -286,15 +278,16 @@ rhel9cis_rule_2_4_1_5: true rhel9cis_rule_2_4_1_6: true rhel9cis_rule_2_4_1_7: true rhel9cis_rule_2_4_1_8: true -### at +# at rhel9cis_rule_2_4_2_1: true -# Section 3 Network -## Network Devices +## Section 3 Fixes +# Section 3 rules are used for securely configuring the network configuration(kernel params, ACL, Firewall settings) +# Network Devices rhel9cis_rule_3_1_1: true rhel9cis_rule_3_1_2: true rhel9cis_rule_3_1_3: true -## Network Kernel Modules +# Network Kernel Modules rhel9cis_rule_3_2_1: true rhel9cis_rule_3_2_2: true rhel9cis_rule_3_2_3: true @@ -312,8 +305,10 @@ rhel9cis_rule_3_3_9: true rhel9cis_rule_3_3_10: true rhel9cis_rule_3_3_11: true -# Section 4 Firewalls -## Firewall utility +## Section 4 Fixes +# Section 4 rules are Logging and Auditing (Configure System Accounting (auditd), +# Configure Data Retention, and Configure Logging) +# Firewall utility rhel9cis_rule_4_1_1: true rhel9cis_rule_4_1_2: true ## Configure firewalld @@ -325,8 +320,10 @@ rhel9cis_rule_4_3_2: true rhel9cis_rule_4_3_3: true rhel9cis_rule_4_3_4: true -## Section 5 -## 5.1. Configure SSH Server +## Section 5 Fixes +# Section 5 rules control Access, Authentication, and Authorization (Configure time-based job schedulers, +# Configure sudo, Configure SSH Server, Configure PAM and User Accounts and Environment) +# Configure SSH Server rhel9cis_rule_5_1_1: true rhel9cis_rule_5_1_2: true rhel9cis_rule_5_1_3: true @@ -349,7 +346,7 @@ rhel9cis_rule_5_1_19: true rhel9cis_rule_5_1_20: true rhel9cis_rule_5_1_21: true rhel9cis_rule_5_1_22: true -## 5.2 Configure Privilege Escalation +# 5.2 Configure Privilege Escalation rhel9cis_rule_5_2_1: true rhel9cis_rule_5_2_2: true rhel9cis_rule_5_2_3: true @@ -381,7 +378,7 @@ rhel9cis_rule_5_3_3_2_6: true rhel9cis_rule_5_3_3_2_7: true rhel9cis_rule_5_3_3_2_8: true # 5.3.3.3 Configure pam_pwhistory module -# This are added as part of 5.3.2.4 using jinja2 template +# These are added as part of 5.3.2.4 using jinja2 template rhel9cis_rule_5_3_3_3_1: true rhel9cis_rule_5_3_3_3_2: true rhel9cis_rule_5_3_3_3_3: true @@ -412,17 +409,18 @@ rhel9cis_rule_5_4_3_1: true rhel9cis_rule_5_4_3_2: true rhel9cis_rule_5_4_3_3: true -# Section 6 Logging and Auditing -## 6.1 Configure Integrity Checking +## Section 6 Fixes +# Section 6 rules control Logging and Auditing +# Configure Integrity Checking rhel9cis_rule_6_1_1: true rhel9cis_rule_6_1_2: true rhel9cis_rule_6_1_3: true -## 6.2.1 Configure systemd-journald service +# 6.2.1 Configure systemd-journald service rhel9cis_rule_6_2_1_1: true rhel9cis_rule_6_2_1_2: true rhel9cis_rule_6_2_1_3: true rhel9cis_rule_6_2_1_4: true -## 6.2.2.x Configure journald +# 6.2.2.x Configure journald rhel9cis_rule_6_2_2_1_1: true rhel9cis_rule_6_2_2_1_2: true rhel9cis_rule_6_2_2_1_3: true @@ -430,7 +428,7 @@ rhel9cis_rule_6_2_2_1_4: true rhel9cis_rule_6_2_2_2: true rhel9cis_rule_6_2_2_3: true rhel9cis_rule_6_2_2_4: true -## 6.2.3 Configure rsyslog +# 6.2.3 Configure rsyslog rhel9cis_rule_6_2_3_1: true rhel9cis_rule_6_2_3_2: true rhel9cis_rule_6_2_3_3: true @@ -439,20 +437,20 @@ rhel9cis_rule_6_2_3_5: true rhel9cis_rule_6_2_3_6: true rhel9cis_rule_6_2_3_7: true rhel9cis_rule_6_2_3_8: true -## 6.2.4 Configure Logfiles +# 6.2.4 Configure Logfiles rhel9cis_rule_6_2_4_1: true -## 6.3 Configure Auditing -## 6.3.1 Configure auditd Service +# 6.3 Configure Auditing +# 6.3.1 Configure auditd Service rhel9cis_rule_6_3_1_1: true rhel9cis_rule_6_3_1_2: true rhel9cis_rule_6_3_1_3: true rhel9cis_rule_6_3_1_4: true -## 6.3.2 Configure Data Retention +# 6.3.2 Configure Data Retention rhel9cis_rule_6_3_2_1: true rhel9cis_rule_6_3_2_2: true rhel9cis_rule_6_3_2_3: true rhel9cis_rule_6_3_2_4: true -## 6.3.3 Configure auditd Rules +# 6.3.3 Configure auditd Rules rhel9cis_rule_6_3_3_1: true rhel9cis_rule_6_3_3_2: true rhel9cis_rule_6_3_3_3: true @@ -474,7 +472,7 @@ rhel9cis_rule_6_3_3_18: true rhel9cis_rule_6_3_3_19: true rhel9cis_rule_6_3_3_20: true rhel9cis_rule_6_3_3_21: true -## 6.3.4 Configure auditd File Access +# 6.3.4 Configure auditd File Access rhel9cis_rule_6_3_4_1: true rhel9cis_rule_6_3_4_2: true rhel9cis_rule_6_3_4_3: true @@ -486,8 +484,9 @@ rhel9cis_rule_6_3_4_8: true rhel9cis_rule_6_3_4_9: true rhel9cis_rule_6_3_4_10: true -# Section 7 System Maintenance -## 7.1 System File Permissions +## Section 7 Fixes +# Section 7 rules control System Maintenance +# System File Permissions rhel9cis_rule_7_1_1: true rhel9cis_rule_7_1_2: true rhel9cis_rule_7_1_3: true @@ -501,7 +500,7 @@ rhel9cis_rule_7_1_10: true rhel9cis_rule_7_1_11: true rhel9cis_rule_7_1_12: true rhel9cis_rule_7_1_13: true -## 7.2 Local User and Group Settings +# 7.2 Local User and Group Settings rhel9cis_rule_7_2_1: true rhel9cis_rule_7_2_2: true rhel9cis_rule_7_2_3: true @@ -530,12 +529,12 @@ rhel9cis_tmp_svc: false # Setting to `true` will allow a test on the package and force the import of the key rhel9cis_force_gpg_key_import: true -## Control 1.2.4 +## Control 1.2.1.3 # When installing RHEL from authorized Red Hat source, RHEL will come with default YUM repository. NOT having a default YUM # repo ('rhel9cis_rhel_default_repo' set as 'false'), in conjunction with 'rhel9cis_rule_enable_repogpg' set as 'True', will enable the tasks # which check the GPG signatures for all the individual YUM repositories. rhel9cis_rhel_default_repo: true -## Control 1.2.4 +## Control 1.2.1.3 # When 'rhel9cis_rule_enable_repogpg' is set to 'true'(in conjunction with 'rhel9cis_rhel_default_repo':'false'), conditions are met for # enabling the GPG signatures-check for all the individual YUM repositories. If GPG signatures-check is enabled on repositories which do not # support it(like RedHat), installation of packages will fail. @@ -547,7 +546,7 @@ rhel9cis_rule_enable_repogpg: true # and may prevent some services from running. Requires SELinux not being disabled (by # having 'rhel9cis_selinux_disable' var set as 'true'), otherwise setting will be ignored. rhel9cis_selinux_pol: targeted -## Control 1.6.1.3|4 - SELinux configured and not disabled +## Control 1.3.1.3|4|5 - SELinux policy settings # This variable contains a specific SELinux mode, respectively: # - 'enforcing': SELinux policy IS enforced, therefore denies operations based on SELinux policy # rules. If system was installed with SELinux, this is enabled by default. @@ -569,7 +568,7 @@ rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pr # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: true -## Control 1.6 +## Controls 1.6.x # This variable contains the value to be set as the system-wide crypto policy. Current rule enforces NOT USING # 'LEGACY' value(as it is less secure, it just ensures compatibility with legacy systems), therefore # possible values for this variable are, as explained by RedHat docs: @@ -577,12 +576,21 @@ rhel9cis_set_boot_pass: true # -'FUTURE': conservative security level that is believed to withstand any near-term future attacks # -'FIPS': A level that conforms to the FIPS140-2 requirements rhel9cis_crypto_policy: 'DEFAULT' -## Control 1.6 +## Controls 1.6.x and Controls 5.1.x +# This variable contains the value of the crypto policy module(combinations of policies and +# sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, +# using 'rhel9cis_allowed_crypto_policies_modules' variable, which currently are: +# - 'OSPP' +# - 'AD-SUPPORT' +# - 'AD-SUPPORT-LEGACY' +rhel9cis_crypto_policy_module: '' +## Controls 1.6.x # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, # using those listed in the 'rhel9cis_allowed_crypto_policies_modules' variable. rhel9cis_additional_crypto_policy_module: '' + ## Controls: # - 1.7.1 - Ensure message of the day is configured properly # - 1.7.2 - Ensure local login warning banner is configured properly @@ -592,7 +600,12 @@ rhel9cis_warning_banner: Authorized users only. All activity may be monitored an # End Banner ## Control 1.8.x - Settings for GDM -## 1.8 GDM graphical interface +# This variable governs whether rules dealing with GUI specific packages(and/or their settings) should +# be executed either to: +# - secure GDM, if GUI is needed('rhel9cis_gui: true') +# - or remove GDM and X-Windows-system, if no GUI is needed('rhel9cis_gui: false') +# The value of this variable is set automatically, if gnome is present this variable +# will always have `true` as a value, and `false` otherwise. rhel9cis_gui: "{{ prelim_gnome_present.stat.exists | default(false) }}" # This variable specifies the GNOME configuration database file to which configurations are written. # (See "https://help.gnome.org/admin/system-admin-guide/stable/dconf-keyfiles.html.en") @@ -640,92 +653,145 @@ rhel9cis_chrony_server_makestep: "1.0 3" # improve the reliability, because multiple sources will need to correspond with each other. rhel9cis_chrony_server_minsources: 2 -# Service configuration -# Options are -# Service -# - false - removes package -# - true - leaves package installed -# Mask -# - false - leaves service in current status -# - true - sets service name to masked -# -# Setting both Service and Mask to false will remove the package if exists +### +### The set of rules that make up section 2.1, are used for ensuring that +### certain services are not installed on the OS. +### The following list of variables contain two types: the ones that end in '_services', and the ones that end in '_mask' +### in '_mask'. For completely removing a service both those variables referencing that service shall be set to 'false'. +### For masking a service the type that ends in '_mask' shall be set to 'true'. +### Set this variable to `true` to keep service `autofs`; otherwise, the service is uninstalled. +### + +########################################### + +## Controls 2.1.x - Configure Server Services +# Set this variable to `true` to keep service `autofs`; otherwise, the service is uninstalled. rhel9cis_autofs_services: false +# Set this variable to `true` to mask service `autofs`. rhel9cis_autofs_mask: false +# Set this variable to `true` to keep service `avahi`; otherwise, the service is uninstalled. rhel9cis_avahi_server: false +# Set this variable to `true` to mask service `avahi`. rhel9cis_avahi_mask: false +# Set this variable to `true` to keep service `dhcp`; otherwise, the service is uninstalled. rhel9cis_dhcp_server: false +# Set this variable to `true` to mask service `dhcp`. rhel9cis_dhcp_mask: false +# Set this variable to `true` to keep service `dns`; otherwise, the service is uninstalled. rhel9cis_dns_server: false +# Set this variable to `true` to mask service `dns`. rhel9cis_dns_mask: false +# Set this variable to `true` to keep service `dnsmasq`; otherwise, the service is uninstalled. rhel9cis_dnsmasq_server: false +# Set this variable to `true` to mask service `dnsmasq`. rhel9cis_dnsmasq_mask: false +# Set this variable to `true` to keep service `samba`; otherwise, the service is uninstalled. rhel9cis_samba_server: false +# Set this variable to `true` to mask service `samba`. rhel9cis_samba_mask: false +# Set this variable to `true` to keep service `ftp`; otherwise, the service is uninstalled. rhel9cis_ftp_server: false +# Set this variable to `true` to mask service `ftp`. rhel9cis_ftp_mask: false +# Set this variable to `true` to keep service `message`; otherwise, the service is uninstalled. rhel9cis_message_server: false # This is for messaging dovecot and cyrus-imap +# Set this variable to `true` to mask service `message`. rhel9cis_message_mask: false +# Set this variable to `true` to keep service `nfs`; otherwise, the service is uninstalled. rhel9cis_nfs_server: true +# Set this variable to `true` to mask service `nfs`. rhel9cis_nfs_mask: true +# Set this variable to `true` to keep service `nis`; otherwise, the service is uninstalled. rhel9cis_nis_server: true # set to mask if nis client required +# Set this variable to `true` to mask service `nis`. rhel9cis_nis_mask: false +# Set this variable to `true` to keep service `print`; otherwise, the service is uninstalled. rhel9cis_print_server: false # replaces cups +# Set this variable to `true` to mask service `print`. rhel9cis_print_mask: false +# Set this variable to `true` to keep service `rpc`; otherwise, the service is uninstalled. rhel9cis_rpc_server: true +# Set this variable to `true` to mask service `rpc`. rhel9cis_rpc_mask: true +# Set this variable to `true` to keep service `rsync`; otherwise, the service is uninstalled. rhel9cis_rsync_server: false +# Set this variable to `true` to mask service `rsync`. rhel9cis_rsync_mask: false +# Set this variable to `true` to keep service `snmp`; otherwise, the service is uninstalled. rhel9cis_snmp_server: false +# Set this variable to `true` to mask service `snmp`. rhel9cis_snmp_mask: false +# Set this variable to `true` to keep service `telnet`; otherwise, the service is uninstalled. rhel9cis_telnet_server: false +# Set this variable to `true` to mask service `telnet`. rhel9cis_telnet_mask: false +# Set this variable to `true` to keep service `tftp`; otherwise, the service is uninstalled. rhel9cis_tftp_server: false +# Set this variable to `true` to mask service `tftp`. rhel9cis_tftp_mask: false +# Set this variable to `true` to keep service `squid`; otherwise, the service is uninstalled. rhel9cis_squid_server: false +# Set this variable to `true` to mask service `squid`. rhel9cis_squid_mask: false +# Set this variable to `true` to keep service `httpd`; otherwise, the service is uninstalled. rhel9cis_httpd_server: false +# Set this variable to `true` to mask service `httpd`. rhel9cis_httpd_mask: false +# Set this variable to `true` to keep service `nginx`; otherwise, the service is uninstalled. rhel9cis_nginx_server: false +# Set this variable to `true` to mask service `nginx`. rhel9cis_nginx_mask: false +# Set this variable to `true` to keep service `xinetd`; otherwise, the service is uninstalled. rhel9cis_xinetd_server: false +# Set this variable to `true` to mask service `xinetd`. rhel9cis_xinetd_mask: false +# Set this variable to `true` to keep service `xwindow`; otherwise, the service is uninstalled. rhel9cis_xwindow_server: false # will remove mask not an option + +## Control 2.1.21 - Ensure mail transfer agent is configured for local-only mode +# This variable if set to 'false', ensures that the mail transfer agent is configured for +# local-only mode. rhel9cis_is_mail_server: false -## Section 2.3 Service clients +## Section 2.2 Service clients +## Control - 2.2.1 - Ensure FTP client is not installed +# Set this variable to `true` to keep package `ftp`; otherwise, the package is uninstalled. rhel9cis_ftp_client: false +## Control - 2.2.2 - Ensure LDAP client is not installed +# Set this variable to `true` to keep package `openldap-clients`; otherwise, the package is uninstalled. rhel9cis_openldap_clients_required: false +## Control - 2.2.3 - Ensure nis client is not installed +# Set this variable to `true` to keep package `nis`(`ypbind`); otherwise, the package is uninstalled. rhel9cis_ypbind_required: false # Same package as NIS server +## Control - 2.2.4 - Ensure telnet client is not installed +# Set this variable to `true` to keep package `telnet`; otherwise, the package is uninstalled. rhel9cis_telnet_required: false +## Control - 2.2.5 - Ensure tftp client is not installed +# Set this variable to `true` to keep package `tftp`; otherwise, the package is uninstalled. rhel9cis_tftp_client: false ## Section 3 vars -## Sysctl -# Service configuration -# Options are -# Service -# - false - removes package -# - true - leaves package installed -# Mask -# - false - leaves service in current status -# - true - sets service name to masked -# -# Setting both Service and Mask to false will remove the package if exists -# -rhel9cis_bluetooth_service: false -rhel9cis_bluetooth_mask: false -## 3.1 IPv6 requirement toggle +## Control 3.1.1 - Ensure IPv6 status is identified # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: true -## 3.1.2 wireless network requirements +## Control 3.1.2 - Ensure wireless interfaces are disabled # if wireless adapter found allow network manager to be installed rhel9cis_install_network_manager: false +# This variable holds the name of the network manager package, and it is used +# as a conditional to implement control 3.1.2. If the network manager package +# is present on the system then the control will be implemented! rhel9cis_network_manager_package_name: NetworkManager -# 3.3 System network parameters (host only OR host and router) + +## Control 3.1.3 - Ensure bluetooth services are not in use +# Set this variable to `true` to keep service `bluetooth`; otherwise, the service is uninstalled. +rhel9cis_bluetooth_service: false +# Set this variable to `true` to mask service `bluetooth`. +rhel9cis_bluetooth_mask: false + +## Controls 3.3.x System network parameters (host only OR host and router) # This variable governs whether specific CIS rules # concerned with acceptance and routing of packages are skipped. rhel9cis_is_router: false @@ -742,7 +808,8 @@ rhel9cis_flush_ipv4_route: false # NOTE: The current default value is likely to be overridden by other further tasks(via 'set_fact'). rhel9cis_flush_ipv6_route: false -# Section 4 vars +## Section 4 vars + ### Firewall Service to install and configure - Options are: # 1) either 'firewalld' # 2) or 'nftables' @@ -752,27 +819,27 @@ rhel9cis_flush_ipv6_route: false #### masked = leave package if installed and mask the service rhel9cis_firewall: firewalld -## Control 4.2.x - Ensure firewalld default zone is set +## Control 4.2.2 - Ensure firewalld loopback traffic is configured # This variable will set the firewalld default zone(that is used for everything that is not explicitly bound/assigned # to another zone): if there is no zone assigned to a connection, interface or source, only the default zone is used. rhel9cis_default_zone: public -## Controls 4.3.x nftables - -## 4.3.1 Ensure nftables base chains exist -# This variable governs if a nftables base chain(entry point for packets from the networking stack) will be automatically -# created, if needed. Without a chain, a hook for input, forward, and delete, packets that would flow through those -# chains will not be touched by nftables. -rhel9cis_nft_tables_autochaincreate: true - -## 4.3.2 Create tables if required +## Controls 4.3.x +# This variable governs if a table will be automatically created in nftables. Without a table (no default one), nftables +# will not filter network traffic, so if this variable is set to 'false' and no tables exist, an alarm will be triggered! rhel9cis_nft_tables_autonewtable: true # This variable stores the name of the table to be used when configuring nftables(creating chains, configuring loopback # traffic, established connections, default deny). If 'rhel9cis_nft_tables_autonewtable' is set as true, a new table will # be created using as name the value stored by this variable. rhel9cis_nft_tables_tablename: filter -## Section5 vars +## Control 4.3.1 - Ensure nftables base chains exist +# This variable governs if a nftables base chain(entry point for packets from the networking stack) will be automatically +# created, if needed. Without a chain, a hook for input, forward, and delete, packets that would flow through those +# chains will not be touched by nftables. +rhel9cis_nft_tables_autochaincreate: true + +## Section 5 vars ## Section 5.1 - SSH @@ -781,32 +848,30 @@ rhel9cis_nft_tables_tablename: filter # Otherwise, the default value is '/etc/ssh/ssh_config'. rhel9cis_sshd_config_file: /etc/ssh/sshd_config -## Controls: -## - 5.1.7 - Ensure SSH access is limited +## Control 5.1.7 - Ensure sshd access is configured # This variable, if specified, configures a list of USER name patterns, separated by spaces, to allow SSH # access for users whose user name matches one of the patterns. This is done # by setting the value of `AllowUsers` option in `/etc/ssh/sshd_config` file. # If an USER@HOST format will be used, the specified user will be allowed only on that particular host. rhel9cis_sshd_allowusers: "{% if ansible_facts.user_id != 'root' %}{{ ansible_facts.user_id }}{% elif ansible_env.SUDO_USER is defined %}{{ ansible_env.SUDO_USER }}{% endif %}" - +## Control 5.1.7 - Ensure sshd access is configured # (String) This variable, if specified, configures a list of GROUP name patterns, separated by spaces, to allow SSH access # for users whose primary group or supplementary group list matches one of the patterns. This is done # by setting the value of `AllowGroups` option in `/etc/ssh/sshd_config` file. rhel9cis_sshd_allowgroups: "" - +## Control 5.1.7 - Ensure sshd access is configured # This variable, if specified, configures a list of USER name patterns, separated by spaces, to prevent SSH access # for users whose user name matches one of the patterns. This is done # by setting the value of `DenyUsers` option in `/etc/ssh/sshd_config` file. # If an USER@HOST format will be used, the specified user will be restricted only on that particular host. rhel9cis_sshd_denyusers: "nobody" - +## Control 5.1.7 - Ensure sshd access is configured # This variable, if specified, configures a list of GROUP name patterns, separated by spaces, # to prevent SSH access for users whose primary group or supplementary group list matches one of the patterns. This is done # by setting the value of `DenyGroups` option in `/etc/ssh/sshd_config` file. rhel9cis_sshd_denygroups: "" -## - 5.1.9 - ClientAlive and CountMax -# default settings allow 45 seconds e.g. count x interval +## Control 5.1.9 - Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured # This variable sets the maximum number of unresponsive "keep-alive" messages # that can be sent from the server to the client before the connection is considered # inactive and thus, closed. @@ -816,17 +881,19 @@ rhel9cis_sshd_clientalivecountmax: 3 # keep the connection alive and prevent it being terminated due to inactivity. rhel9cis_sshd_clientaliveinterval: 15 -## Control 5.1.12 - disable forwarding +## Control 5.1.10 - Ensure sshd DisableForwarding is enabled # By Default this will also disablex11 forwarding # set 'yes' if x11 is required this can be changed to run in /etc/ssh/ssh_config.d/50-redhat.conf +# This variable's value is used in the `/etc/ssh/ssh_config.d/50-redhat.conf` file to +# disable X11Forwarding. If X11 is required, set this variable's value to `yes`! rhel9cis_sshd_x11forwarding: 'no' -## - 5.2.14 - Ensure SSH LoginGraceTime is set to one minute or less +## Control 5.1.14 - Ensure SSH LoginGraceTime is set to one minute or less # This variable specifies the amount of seconds allowed for successful authentication to # the SSH server. rhel9cis_sshd_logingracetime: 60 -## Control 5.2.15 - Ensure SSH LogLevel is appropriate +## Control 5.1.15 - Ensure SSH LogLevel is appropriate # This variable is used to control the verbosity of the logging produced by the SSH server. # The options for setting it are as follows: # - `QUIET`: Minimal logging; @@ -838,19 +905,19 @@ rhel9cis_sshd_logingracetime: 60 # - `DEBUG(x)`: Whereas x = debug level 1 to 3, DEBUG=DEBUG1. rhel9cis_ssh_loglevel: INFO -## Control 5.1.16 MaxAuthTries configured +## Control 5.1.16 - Ensure sshd MaxAuthTries is configured # The MaxAuthTries parameter specifies the maximum number of authentication # attempts permitted per connection. When the login failure count reaches half the # number, error messages will be written to the syslog file detailing the login failure. rhel9cis_ssh_maxauthtries: '4' -## Control 5.1.17 MaxStartups +## Control 5.1.17 - Ensure sshd MaxStartups is configured # The MaxStartups parameter specifies the maximum number of concurrent unauthenticated connections to the SSH daemon. rhel9cis_ssh_maxstartups: '10:30:60' -## Control 5.1.18 - Ensure SSH MaxSessions is set to 10 or less +## Control 5.1.18 - Ensure sshd MaxSessions is configured # This variable value specifies the maximum number of open sessions that are permitted from -# a given location +# a given location. CIS recommends it to be 10 or less. rhel9cis_ssh_maxsessions: 4 ## Control 5.2.x - Ensure sudo log file exists @@ -859,162 +926,201 @@ rhel9cis_ssh_maxsessions: 4 # This variable defines the path and file name of the sudo log file. rhel9cis_sudolog_location: "/var/log/sudo.log" -## Control 5.2.x -Ensure sudo authentication timeout is configured correctly +## Control 5.2.4 - Ensure users must provide password for escalation +# The following variable specifies a list of users that should not be required to provide a password +# for escalation. Feel free to edit it according to your needs. +rhel9cis_sudoers_exclude_nopasswd_list: + - ec2-user + - vagrant + +## Control 5.2.6 - Ensure sudo authentication timeout is configured correctly # This variable sets the duration (in minutes) during which a user's authentication credentials # are cached after successfully authenticating using "sudo". This allows the user to execute # multiple commands with elevated privileges without needing to re-enter their password for each # command within the specified time period. CIS requires a value of at most 15 minutes. rhel9cis_sudo_timestamp_timeout: 15 -## Control 5.2.4 -# This will leave NOPASSWD intact for these users -rhel9cis_sudoers_exclude_nopasswd_list: - - ec2-user - - vagrant - -## Control 5.2 - Ensure access to the 'su' command is restricted +## Control 5.2.7 - Ensure access to the 'su' command is restricted # This variable determines the name of the group of users that are allowed to use the su command. # CIS requires that such a group be CREATED(named according to site policy) and be kept EMPTY. rhel9cis_sugroup: sugroup -## 5.3.x PAM and Authselect +## Controls 5.3.x PAM and Authselect # 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. rhel9cis_allow_authselect_updates: true -## +## Control 5.3.1.2 - Ensure latest version of authselect is installed +# The following variables controls the implementation of control 5.3.1.2. +# If you want the latest version to be installed set this variable's value +# to `true`. rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD or using ipa-client-install ## PAM AND Authselect -# To create a new profile (best for greenfield fresh sites not configured) -# This allows creation of a custom profile using an existing one to build from -# will only create if profile does not already exist -## options true or false -rhel9cis_authselect_custom_profile_create: true -## Controls: -# - 5.3.2.1 - Ensure custom authselect profile is used -# Settings in place now will fail, they are placeholders 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 minimize risk. +## Controls 5.3.x + # This variable configures the name of the custom profile to be created and selected. -# To be changed from default - cis_example_profile +# To be changed from default - cis_example_profile. This setting needs to be adjusted +# in order to minimise risk. rhel9cis_authselect_custom_profile_name: cis_example_profile # Name of the existing authselect profile to copy - options can be found with # ```authselect list``` on the host to be configured rhel9cis_authselect_default_profile_to_copy: "sssd --symlink-meta" -## Controls -# - 5.3.3. - Ensure lockout for failed password attempts is configured -# - 5.5.3 - Ensure password reuse is limited -# - 5.5.4 - Ensure password hashing algorithm is SHA-512 -# - 5.4.2 - Ensure authselect includes with-faillock -# - 5.3.3.1.1 +## Control 5.3.3.1.1 - # This variable sets the amount of tries a password can be entered, before a user is locked. rhel9cis_pam_faillock_deny: 5 -# - 5.3.3.1.2 +## Control 5.3.3.2, 5.3.2.2 # This variable sets the amount of time a user will be unlocked after the max amount of -# password failures. +# password failures. rhel9cis_pam_faillock_unlock_time: 900 -# This variable represents the number of password change cycles, after which -# an user can re-use a password. -# CIS requires a value of 5 or more. -# 5.3.3.1.3 Locking even deny root or root unlock times -# rhel9cis_pamroot_lock_option options are -# even_deny_root -# root_unlock_time = {{ rhel9cis_root_unlock_time }} -rhel9cis_root_unlock_time: 60 -rhel9cis_pamroot_lock_option: even_deny_root -# rhel9cis_pamroot_lock_option: "root_unlock_time = {{ rhel9cis_root_unlock_time }}" -# 5.3.3.2.1 - password difok +## Control 5.3.3.1.3 - Ensure password failed attempts lockout includes root account +# This variable is used in the task that ensures that even the root account +# is included in the password failed attempts lockout measure. +# The following variable is used in the 'regexp' field. This field is used to find the +# line in the file. If the line matches the regular expression, it will be replaced +# with the line parameter's value. +rhel9cis_pamroot_lock_option: even_deny_root + +## Control 5.3.3.2.1 - Ensure password number of changed characters is configured +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password number of changed characters is configured' control. rhel9cis_passwd_difok_file: etc/security/pwquality.conf.d/50-pwdifok.conf # pragma: allowlist secret +# This variable's value represents the minimum number of characters that must be different between +# the new password and the old password. It helps ensure that users don't create new passwords that +# are too similar to their previous ones, enhancing security. CIS states that this value should be at least 2. rhel9cis_passwd_difok_value: 2 -# 5.3.3.2.2 - password minlength +## Control 5.3.3.2.2 - Ensure minimum password length is configured +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure minimum password length is configured' control. rhel9cis_passwd_minlen_file: etc/security/pwquality.conf.d/50-pwlength.conf # pragma: allowlist secret +# This variable specifies the minimum length that a password must have to be considered valid. +# CIS states that this value should be at least 14. rhel9cis_passwd_minlen_value: 14 -# 5.3.3.2.3 - password complex +## Control 5.3.3.2.3 - Ensure password complexity is configured +# The following variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password complexity is configured' control. rhel9cis_passwd_complex_file: etc/security/pwquality.conf.d/50-pwcomplexity.conf # pragma: allowlist secret -# Choose if using minclass or credits options -# Options are: minclass or credits -# ensure only one is selected +# This variable holds the options for configuring the password complexity. +# Options supported are: 'minclass' or 'credits'. rhel9cis_passwd_complex_option: minclass # pragma: allowlist secret +# The following variable sets the password complexity via 'minclass'. The 'minclass' option provides +# the minimum number of classes of characters required in a new password. (digits, uppercase, lowercase, others). e.g. +# For example a value of 4 would mean that it requires digits, uppercase, lower case, and special characters. rhel9cis_passwd_minclass: 4 -# rhel9cis_passwd_complex: credits +# The following variables set the password complexity via the 'credits' option. +# Each of the variables represents a requirement for complexity. +# The 'dcredit' variable is the maximum credit for having digits in the new password. +# If less than 0 it is the minimum number of digits in the new password. +# e.g. dcredit = -1 requires at least one digit rhel9cis_passwd_dcredit: -1 +# The 'ucredit' variable is the maximum credit for having uppercase characters in the new password. +# If less than 0 it is the minimum number of uppercase characters in the new password. +# e.g. ucredit = -1 requires at least one uppercase character rhel9cis_passwd_ucredit: -2 +# The 'ocredit' variable is the maximum credit for having other characters in the new password. +# If less than 0 it is the minimum number of other characters in the new password. +# e.g. ocredit = -1 requires at least one special character rhel9cis_passwd_ocredit: 0 +# The 'lcredit' variable is the maximum credit for having lowercase characters in the new password. +# If less than 0 it is the minimum number of lowercase characters in the new password. +# e.g. lcredit = -1 requires at least one lowercase character rhel9cis_passwd_lcredit: -2 -# 5.3.3.2.4 - password maxrepeat +## Control 5.3.3.2.4 - Ensure password same consecutive characters is configured +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password same consecutive characters is configured' control. rhel9cis_passwd_maxrepeat_file: etc/security/pwquality.conf.d/50-pwrepeat.conf # pragma: allowlist secret +# The following variable sets the maximum number of allowed same consecutive characters in a new password. rhel9cis_passwd_maxrepeat_value: 3 -# 5.3.3.2.5 - password maxsequence +## Control 5.3.3.2.5 - Ensure password maximum sequential characters is configured +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password maximum sequential characters is configured' control. rhel9cis_passwd_maxsequence_file: etc/security/pwquality.conf.d/50-pwmaxsequence.conf # pragma: allowlist secret +# The following variable sets the maximum length of monotonic character sequences in the new password. +# Examples of such sequence are '12345' or 'fedcb' . The check is disabled if the value is 0 . rhel9cis_passwd_maxsequence_value: 3 -# 5.3.3.2.6 - password dictcheck +## Control 5.3.3.2.6 - Ensure password dictionary check is enabled +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password dictionary check is enabled' control rhel9cis_passwd_dictcheck_file: etc/security/pwquality.conf.d/50-pwdictcheck.conf # pragma: allowlist secret +# The following variable's value sets whether to check for the words from the cracklib dictionary. +# When set to '1', this option enables dictionary checks, ensuring that passwords are not based on common +# dictionary words, which helps prevent users from choosing easily guessable passwords. +# When set to '0', dictionary checks are disabled. CIS states that it shall always be set to '1'. rhel9cis_passwd_dictcheck_value: 1 -# 5.3.3.2.7 - password quality enforce -rhel9cis_passwd_quality_enforce_file: etc/security/pwquality.conf.d/50-pwquality_enforce.conf # pragma: allowlist secret +# This variable is used in one of the config files to ensure password quality checking is enforced rhel9cis_passwd_quality_enforce_value: 1 -# 5.3.3.2.8 - password quality enforce for root included with 5.3.3.2.7 +## Control 5.3.3.2.7 - Ensure password quality is enforced for the root user +# This variable holds the path to the configuration file that will be created (or overwritten if already existing) +# in order to implement the 'Ensure password quality is enforced for the root user' control. rhel9cis_passwd_quality_enforce_root_file: etc/security/pwquality.conf.d/50-pwroot.conf # pragma: allowlist secret +# The following variable enforces that the root user must adhere to the same password quality policies as other users. rhel9cis_passwd_quality_enforce_root_value: enforce_for_root # pragma: allowlist secret -# PWhistory -## 5.3.3.3.1 remember history -# rhel9cis_pamd_pwhistory_remember: - is the number of old passwords to remember +## Control 5.3.3.3.1 - Ensure password history remember is configured +# This variable represents the number of password change cycles, after which +# a user can re-use a password. CIS requires a value of 24 or more. rhel9cis_pamd_pwhistory_remember: 24 -# 5.3.3.4.x +## Controls 5.3.3.4.3, 5.4.1.4 +# The following variable's value represents the hashing algorithm used rhel9cis_passwd_hash_algo: sha512 # pragma: allowlist secret -## Control 5.6.1.1 - Ensure password expiration is 365 days or less +## Control 5.4.1.1 - Ensure password expiration is 365 days or less # This variable governs after how many days a password expires. # CIS requires a value of 365 or less. rhel9cis_pass_max_days: 365 -## Control 5.6.1.2 - Ensure minimum days between password changes is 7 or more +# The following variable allows the forcing of setting user_max_days for logins. +# This can break current connecting user access +rhel9cis_force_user_maxdays: false +## Control 5.4.1.2 - Ensure minimum days between password changes is 7 or more # This variable specifies the minimum number of days allowed between changing # passwords. CIS requires a value of at least 1. rhel9cis_pass_min_days: 7 -## Control 5.6.1.3 - Ensure password expiration warning days is 7 or more +# The following variable allows the force setting of minimum days between changing the password +# This can break current connecting user access +rhel9cis_force_user_mindays: false +## Control 5.4.1.3 - Ensure password expiration warning days is 7 or more # This variable governs, how many days before a password expires, the user will be warned. # CIS requires a value of at least 7. rhel9cis_pass_warn_age: 7 +#The following variable allows the forcing of number of days before warning users of password expiry +# This can break current connecting user access +rhel9cis_force_user_warnage: false -## Control 5.4.1.x - Ensure inactive password lock is 30 days or less +## Control 5.4.1.5 - Ensure inactive password lock is configured rhel9cis_inactivelock: # This variable specifies the number of days of inactivity before an account will be locked. # CIS requires a value of 30 days or less. lock_days: 30 -## 5.4.1.x Allow the forcing of setting user_max_days for logins. -# This can break current connecting user access -rhel9cis_force_user_maxdays: false - -## 5.4.1.x Allow the force setting of minimum days between changing the password -# This can break current connecting user access -rhel9cis_force_user_mindays: false - -## 5.4.1.x Allow the forcing of of number of days before warning users of password expiry -# This can break current connecting user access -rhel9cis_force_user_warnage: false - -## Control 5.4.1.x - Ensure all users last password change date is in the past +## Control 5.4.1.6 - Ensure all users last password change date is in the past # Allow ansible to expire password for account with a last changed date in the future. Setting it # to 'false' will just display users in violation, while 'true' will expire those users passwords. rhel9cis_futurepwchgdate_autofix: true -# 5.4.2.x +## Control 5.4.2.6 - Ensure root user umask is configured +# The following variable specifies the "umask" to configure for the root user. +# The user file-creation mode mask ( umask ) is used to determine the file +# permission for newly created directories and files. In Linux, the default +# permissions for any newly created directory is 0777 ( rwxrwxrwx ), and for +# any newly created file it is 0666 ( rw-rw-rw- ). The umask modifies the default +# Linux permissions by restricting (masking) these permissions. The umask is not +# simply subtracted, but is processed bitwise. Bits set in the umask are cleared +# in the resulting file mode. CIS recommends setting 'umask' to '0027' or more +# restrictive. rhel9cis_root_umask: '0027' # 0027 or more restrictive ## Control 5.4.2.7 - Ensure system accounts are secured | Set nologin @@ -1036,52 +1142,38 @@ rhel9cis_shell_session_timeout: 900 # - `/etc/bash.bashrc`. rhel9cis_shell_session_file: /etc/profile.d/tmout.sh -## Control 5.4.3.2 bash umask +## Control 5.4.3.3 - Ensure default user umask is configured +# The following variable specifies the "umask" to set in the `/etc/bash.bashrc` and `/etc/profile`. +# The value needs to be `027` or more restrictive to comply with CIS standards. rhel9cis_bash_umask: '0027' # 0027 or more restrictive -### Controls: -# - 5.6.2 - Ensure system accounts are secured -# - 6.2.10 - Ensure local interactive user home directories exist -# - 6.2.11 - Ensure local interactive users own their home directories -# UID settings for interactive users -# These are discovered via logins.def if set true -rhel9cis_discover_int_uid: true -# This variable sets the minimum number from which to search for UID -# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has -# been set to `true`. -min_int_uid: 1000 -### Controls: -# - Ensure local interactive user home directories exist -# - Ensure local interactive users own their home directories -# This variable sets the maximum number at which the search stops for UID -# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has -# been set to `true`. -max_int_uid: 65533 +## Section 6 vars -## Section6 vars -## Control 6.1.x - allow aide to be configured +## Control 6.1.1 - Ensure AIDE is installed # AIDE is a file integrity checking tool, similar in nature to Tripwire. # While it cannot prevent intrusions, it can detect unauthorized changes # to configuration files by alerting when the files are changed. Review # the AIDE quick start guide and AIDE documentation before proceeding. -# By setting this variable to `true`, all of the settings related to AIDE will be applied! +# By setting this variable to `true`, all the settings related to AIDE +# will be applied! rhel9cis_config_aide: true - -# If DB file older than below will automatically rebuild DB +# This variable sets a maximum allowed age of the AIDE database file until +# the file is rebuilt. If the file is older than the value below, the role +# will automatically rebuild the database file. # e.g. options:1w = 1 week, 1d = 1day 1h = 1 hour rhel9cis_aide_db_file_age: 1w - -# If aide already setup this forces a new DB to be created +# If AIDE is already setup this variable forces a new database +# file to be created. rhel9cis_aide_db_recreate: false - -# allows to change db file, not config need to be adjusted too +# This variable is used to check if there is already an existing database file +# created by AIDE on the target system. If it is not present, the role will generate +# a database file with the same name as the value of this variable. rhel9cis_aide_db_file: /var/lib/aide/aide.db.gz -## Control 6.1.2 AIDE cron settings - -## How the aide schedule is run either cron or timer +## Control 6.1.2 - Ensure filesystem integrity is regularly checked +# The following variable sets how AIDE is scanned. +# Available options are either cron or timer. rhel9cis_aide_scan: cron - # These are the crontab settings for periodical checking of the filesystem's integrity using AIDE. # The sub-settings of this variable provide the parameters required to configure # the cron job on the target system. @@ -1117,13 +1209,12 @@ rhel9cis_aide_cron: # can be given in the range `0-7` (both `0` and `7` represent Sunday); several weekdays # can be concatenated with commas. aide_weekday: '*' -# + ## Preferred method of logging ## Whether rsyslog or journald preferred method for local logging ## Controls 6.2.1.x | Configure systemd-journald service ## Controls 6.2.2.x | Configured journald ## Controls 6.2.3.x | Configure rsyslog - # This variable governs which logging service should be used, choosing between 'rsyslog' # or 'journald'(CIS recommendation) will trigger the execution of the associated subsection, as the-best # practices are written wholly independent of each other. @@ -1158,36 +1249,31 @@ rhel9cis_journald_runtimekeepfree: 100G # ATTENTION: Uncomment the keyword below when values are set! rhel9cis_journald_maxfilesec: 1month -## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured +## Control 6.2.2.1.2 - Ensure systemd-journal-upload authentication is configured # 'rhel9cis_journal_upload_url' is the ip address to upload the journal entries to # URL value may specify either just the hostname or both the protocol and hostname. 'https' is the default. The port # number may be specified after a colon (":"), otherwise 19532 will be used by default. rhel9cis_journal_upload_url: 192.168.50.42 -## The paths below have the default paths/files, but allow user to create custom paths/filenames - ## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured # This variable specifies the path to the private key file used by the remote journal # server to authenticate itself to the client. This key is used alongside the server's -# public certificate to establish secure communication. +# public certificate to establish secure communication. The path below has the default +# path/file, but it is also allowed for a user to create its custom path/filename. rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem" ## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured # This variable specifies the path to the public certificate file of the remote journal -# server. This certificate is used to verify the authenticity of the remote server. +# server. This certificate is used to verify the authenticity of the remote server. The path +# below has the default path/file, but it is also allowed for a user to create its custom +# path/filename. rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem" ## Control 6.2.2.1.2 - Ensure systemd-journal-remote is configured # This variable specifies the path to a file containing one or more public certificates # of certificate authorities (CAs) that the client trusts. These trusted certificates are used -# to validate the authenticity of the remote server's certificate. +# to validate the authenticity of the remote server's certificate. The path below has the default +## path/file, but it is also allowed for a user to create its custom path/filename. rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem" # ATTENTION: Uncomment the keyword below when values are set! -# Control 6.2.3.x - Ensure rsyslog is not configured to receive logs from a remote client -# This variable expresses whether the system is used as a log server or not. If set to: -# - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. -# - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity -# from local attacks on remote clients) -rhel9cis_system_is_log_server: false - ## Control 6.2.3.5 | PATCH | Ensure logging is configured # This variable governs if current Ansible role should manage syslog settings # in /etc/rsyslog.conf file, namely mail, news and misc(warn, messages) @@ -1229,27 +1315,40 @@ rhel9cis_remote_log_retrycount: 100 # of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). rhel9cis_remote_log_queuesize: 1000 +# Control 6.2.3.7 - Ensure rsyslog is not configured to receive logs from a remote client +# This variable expresses whether the system is used as a log server or not. If set to: +# - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. +# - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity +# from local attacks on remote clients) +rhel9cis_system_is_log_server: false + ## Control 6.2.3.8 rsyslog rotate -# This variable configures whether to set your own rsyslog logrotate setting alternate to logrotate default settings -# Please refer to logrotate options to match your site requirements -# This sets when to rotate +# This variable configures whether to set your own rsyslog logrotate setting +# alternate to logrotate default settings. Please refer to logrotate options +# to match your site requirements +# This variable sets when to rotate rhel9cis_rsyslog_logrotate_rotated_when: weekly -# This sets how many rotations of the file to keep +# This variable sets how many rotations of the file to keep rhel9cis_rsyslog_logrotate_rotatation_keep: 4 -# This defines whether to set various options or not -# these are taken from logrotate options -# Setting -# true will carry out the setting. -# false will either set no/not or not add the option +# The following variable defines whether to set the compress option +# or not. Setting it to `true` will carry out the setting. rhel9cis_rsyslog_logrotate_compress: true +# The following variable defines whether to set the missingok option +# or not. Setting it to `true` will carry out the setting. rhel9cis_rsyslog_logrotate_missingok: true +# The following variable defines whether to set the notifempty option +# or not. Setting it to `true` will carry out the setting. rhel9cis_rsyslog_logrotate_notifempty: true +# The following variable defines whether to set extra options that can +# be defined in the `rhel9cis_rsyslog_logrotate_create_opts` variable +# The variable can be found underneath this variable, in a commented +# state. rhel9cis_rsyslog_logrotate_create: true # Extra options that can be added according to rsyslog documentation # Uncomment and add the required options e.g. mode owner group # rhel9cis_rsyslog_logrotate_create_opts: -## Control 6.3.2.1 - Ensure audit_backlog_limit is sufficient +## Control 6.3.1.3 - Ensure audit_backlog_limit is sufficient # This variable represents the audit backlog limit, i.e., the maximum number of audit records that the # system can buffer in memory, if the audit subsystem is unable to process them in real-time. # Buffering in memory is useful in situations, where the audit system is overwhelmed @@ -1258,13 +1357,14 @@ rhel9cis_rsyslog_logrotate_create: true rhel9cis_audit_back_log_limit: 8192 ## Controls 6.3.2.x - What to do when log files fill up + ## Control 6.3.2.1 - Ensure audit log storage size is configured # This variable specifies the maximum size in MB that an audit log file can reach # before it is archived or deleted to make space for the new audit data. # This should be set based on your sites policy. CIS does not provide a specific value. rhel9cis_auditd_max_log_file_size: 10 -## Control 6.3.2.2 +## Control 6.3.2.2 - Ensure audit logs are not automatically deleted # This variable determines what action the audit system should take when the maximum # size of a log file is reached. # The options for setting this variable are as follows: @@ -1276,36 +1376,63 @@ rhel9cis_auditd_max_log_file_size: 10 # CIS prescribes the value `keep_logs`. rhel9cis_auditd_max_log_file_action: keep_logs -## Control 6.3.2.3 -# This variable determines how the system should act in case of issues with disk -# The disk_full_action parameter tells the system what action to take when no free space is available on the partition that holds the audit log files. +## Control 6.3.2.3 - Ensure system is disabled when audit logs are full +# This variable determines how the system should act in case of issues with the disk. +# The disk_full_action parameter tells the system what action to take when no free space is +# available on the partition that holds the audit log files. # Valid values are ignore, syslog, rotate, exec, suspend, single, and halt. -# -# The disk_error_action parameter tells the system what action to take when an error is detected on the partition that holds the audit log files. -# Valid values are ignore, syslog, exec, suspend, single, and halt. -# # CIS prescribes # disk_full_action parameter: -# Set to halt - the auditd daemon will shutdown the system when the disk partition containing the audit logs becomes full. -# Set to single - the auditd daemon will put the computer system in single user mode when the disk partition containing the audit logs becomes full. -# -# disk_error_action parameter: -# Set to halt - the auditd daemon will shutdown the system when an error is detected on the partition that holds the audit log files. -# Set to single - the auditd daemon will put the computer system in single user mode when an error is detected on the partition that holds the audit log files. -# Set to syslog - the auditd daemon will issue no more than 5 consecutive warnings to syslog when an error is detected on the partition that holds the audit log files. +# Set to halt - the auditd daemon will shutdown the system when the disk partition containing +# the audit logs becomes full. +# Set to single - the auditd daemon will put the computer system in single user mode when the +# disk partition containing the audit logs becomes full. rhel9cis_auditd_disk_full_action: halt +# This variable determines how the system should act in case of issues with the disk. +# The disk_error_action parameter tells the system what action to take when an error is detected +# on the partition that holds the audit log files. +# Valid values are ignore, syslog, exec, suspend, single, and halt. +# disk_error_action parameter: +# Set to halt - the auditd daemon will shutdown the system when an error is detected on the +# partition that holds the audit log files. +# Set to single - the auditd daemon will put the computer system in single user mode when +# an error is detected on the partition that holds the audit log files. +# Set to syslog - the auditd daemon will issue no more than 5 consecutive warnings to syslog +# when an error is detected on the partition that holds the audit log files. rhel9cis_auditd_disk_error_action: syslog -# Control 6.3.2.4 -# Wait to do when space left is low. -# The space_left_action parameter tells the system what action to take when the system has detected that it is starting to get low on disk space. -# Valid values are ignore, syslog, rotate, email, exec, suspend, single, and halt. -# The admin_space_left_action parameter tells the system what action to take when the system has detected that it is low on disk space. -# Valid values are ignore, syslog, rotate, email, exec, suspend, single, and halt. +# Control 6.3.2.4 - Ensure system warns when audit logs are low on space +# This variable tells the system what action to take when the system has detected +# that it is starting to get low on disk space. +# The options for setting this variable are as follows: +# "ignore" - the system does nothing when presented with the aforementioned issue; +# "syslog" - a message is sent to the system log about disk space running low; +# "email" - the system sends an email notification to the email address +# specified in the "action_mail_acct" variable; +# "exec" - the system executes a custom command when disk space is running +# low; +# "suspend" - the system suspends recording audit events until more space is available; +# "single" - the audit daemon will put the computer system in single user mode; +# "halt" - the system is halted when disk space is critically low; +# CIS prescribes either 'email', 'exec', `single` or `halt`. rhel9cis_auditd_space_left_action: email +# This variable tells the system what action to take when the system has detected +# that it is low on disk space. +# The options for setting this variable are as follows: +# "ignore" - the system does nothing when presented with the aforementioned issue; +# "syslog" - a message is sent to the system log about disk space running low; +# "email" - the system sends an email notification to the email address +# specified in the "action_mail_acct" variable; +# "exec" - the system executes a custom command when disk space is running +# low; +# "suspend" - the system suspends recording audit events until more space is available; +# "single" - the audit daemon will put the computer system in single user mode; +# "halt" - the system is halted when disk space is critically low; +# CIS prescribes either `halt` or `single`. rhel9cis_auditd_admin_space_left_action: halt -# This value governs if the below extra-vars for auditd should be used by the role +# This value governs if the below extra-vars (found in the `rhel9cis_auditd_extra_conf`) +# for auditd should be used by the role. rhel9cis_auditd_extra_conf_usage: false # 6.3.3.x allow exceptions for UID in auditd config @@ -1317,18 +1444,27 @@ rhel9cis_auditd_uid_exclude: - 1999 # This can be used to configure other keys in auditd.conf -# Example: rhel9cis_auditd_extra_conf: + # This variable governs the threshold(MegaBytes) under which the audit daemon should perform a + # specific action to alert that the system is running low on disk space. Must be lower than + # the 'space_left' variable. admin_space_left: '10%' # Section 7 Vars -# 7.1.12 Ensure no files or directories without an owner and a group exist -rhel9cis_exclude_unowned_search_path: (! -path "/run/user/*" -a ! -path "/proc/*" -a ! -path "*/containerd/*" -a ! -path "*/kubelet/pods/*" -a ! -path "*/kubelet/plugins/*" -a ! -path "/sys/fs/cgroup/memory/*" -a ! -path "/var/*/private/*") +## Control 7.1.11 - Ensure no world writable files exist +# The following variable is a toggle for enabling/disabling the automated +# removal of world-writable permissions from all files. +# Possible values are `true` and `false`. +rhel9cis_no_world_write_adjust: true -# Control 7.1.12 +## Control 7.1.12 - Ensure no files or directories without an owner and a group exist +# This variable holds the part of the command that helps detect which files and +# directories do not have an owner and an affiliated group. +rhel9cis_exclude_unowned_search_path: (! -path "/run/user/*" -a ! -path "/proc/*" -a ! -path "*/containerd/*" -a ! -path "*/kubelet/pods/*" -a ! -path "*/kubelet/plugins/*" -a ! -path "/sys/fs/cgroup/memory/*" -a ! -path "/var/*/private/*") # The value of this variable specifies the owner that will be set for unowned files and directories. rhel9cis_unowned_owner: root +# The value of this variable specifies the group that will be set for ungrouped files and directories. rhel9cis_ungrouped_group: root # This variable is a toggle for enabling/disabling the automated # setting of an owner (specified in variable `rhel9cis_unowned_owner`) @@ -1336,17 +1472,28 @@ rhel9cis_ungrouped_group: root # Possible values are `true` and `false`. rhel9cis_ownership_adjust: true -## Control 7.1.13 +## Control 7.1.13 - Ensure SUID and SGID files are reviewed # This variable is a toggle for enabling/disabling the automated removal # of the SUID bit from all files on all mounts. # Possible values are `true` and `false`. rhel9cis_suid_sgid_adjust: false -## Control 7.1.11 - Ensure no world writable files exist -# Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable. -rhel9cis_no_world_write_adjust: true +## Control 7.2.8 - Ensure local interactive user home directories are configured +# UID settings for interactive users +# These are discovered via logins.def if set true +rhel9cis_discover_int_uid: true +# This variable sets the minimum number from which to search for UID +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has +# been set to `true`. +min_int_uid: 1000 +# This variable sets the maximum number at which the search stops for UID +# Note that the value will be dynamically overwritten if variable `rhel9cis_discover_int_uid` has +# been set to `true`. +max_int_uid: 65533 -## Control 7.2.9 -# This allows ansible to alter the dot files as per rule if found -# When set to true this will align with benchmark - can impact a running system if not tested sufficiently +## Control 7.2.9 - Ensure local interactive user dot files access is configured +# This variable is a toggle foe enabling/disabling the automated modification of +# permissions on dot files. +# Possible values are `true` and `false` +# This setting can impact a running system if not tested sufficiently rhel9cis_dotperm_ansiblemanaged: false From a55675089457ad2c34820ac0c83888f1f6f8c933 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Thu, 3 Jul 2025 13:03:08 +0300 Subject: [PATCH 258/327] Fixing issue https://code.siemens.com/infosec-pss-gov/security-crafter-baseline-automations/ansible-lockdown/rhel9-cis/-/issues/41. Signed-off-by: Diana-Maria Dumitru --- tasks/section_5/cis_5.4.2.x.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 37a4e11..9a93947 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -135,6 +135,22 @@ ansible.builtin.set_fact: root_paths: "{{ discovered_root_paths.stdout }}" + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for presence of non-dirs" + ansible.builtin.stat: + path: "{{ item }}" + loop: "{{ discovered_root_paths_split.stdout_lines }}" + register: paths_stat + + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Create dirs for some paths that are not dirs" + ansible.builtin.file: + path: "{{ item.item }}" + state: directory + owner: root + group: root + mode: 'go-w' + loop: "{{ paths_stat.results }}" + when: not item.stat.exists + - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" when: discovered_root_paths is defined ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"' From 778877f3f3f14317ab7df650634010941b6e5bb3 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Fri, 4 Jul 2025 10:50:45 +0300 Subject: [PATCH 259/327] Small fixes. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 71fe932..4f3bdb7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1,5 +1,4 @@ --- - # defaults file for rhel9-cis # WARNING: # These values may be overridden by other vars-setting options(e.g. like the below 'container_vars_file'), as explained here: @@ -13,7 +12,7 @@ os_check: true ## Run tests that are considered higher risk and could have a system impact if not properly tested ## Default false ## Will be fine if clean new un-configured build -rhel9cis_disruption_high: false +rhel9cis_disruption_high: true ## Switching on/off specific baseline sections # These variables govern whether the tasks of a particular section are to be executed when running the role. @@ -68,10 +67,17 @@ change_requires_reboot: false ### Goss is required on the remote host ### ### 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) +## Audit setup +# Audits are carried out using Goss. This variable +# determines whether execution of the role prepares for auditing +# by installing the required binary. setup_audit: false -# enable audits to run - this runs the audit and get the latest content +## Enable audits to run - this runs the audit and get the latest content +# This variable governs whether the audit using the +# separately maintained audit role using Goss +# is carried out. +# This runs the audit and gets 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 @@ -95,8 +101,16 @@ get_audit_binary_method: download ## e.g copy from ansible control node to remote host audit_bin_copy_location: /some/accessible/path -# how to get audit files onto host options +## How to retrieve the audit role +# The role for auditing is maintained separately. +# This variable specifies the method of how to get the audit role # options are git/copy/archive/get_url other e.g. if you wish to run from already downloaded conf +# onto the system. The options are as follows: +# - 'git': clone audit content from GitHub REPOSITORY, set up via `audit_file_git` var, and +# VERSION(e.g. branch, tag name), set up via `audit_git_version` var. +# - 'copy': copy from path as specified in variable `audit_conf_copy`. +# - 'archive': same as 'copy', only that the specified filepath needs to be unpacked. +# - 'get_url': Download from url as specified in variable `audit_files_url` audit_content: git # If using either archive, copy, get_url: @@ -311,7 +325,7 @@ rhel9cis_rule_3_3_11: true # Firewall utility rhel9cis_rule_4_1_1: true rhel9cis_rule_4_1_2: true -## Configure firewalld +# Configure firewalld rhel9cis_rule_4_2_1: true rhel9cis_rule_4_2_2: true # Configure nftables From 21fd466ec65f28f52be2fdfd17c0ab21aabf94b9 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Fri, 4 Jul 2025 11:58:08 +0300 Subject: [PATCH 260/327] Small fixes part 2. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 4f3bdb7..ca37f6f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1232,7 +1232,7 @@ rhel9cis_aide_cron: # This variable governs which logging service should be used, choosing between 'rsyslog' # or 'journald'(CIS recommendation) will trigger the execution of the associated subsection, as the-best # practices are written wholly independent of each other. -rhel9cis_syslog: journald +rhel9cis_syslog: rsyslog ## Control 6.2.1.3 - Ensure journald log rotation is configured per site policy # Current variable configures the max amount of disk space the logs will use(thus, journal files From dfd5eb9a922b81f987e1666423b3ff236d7b6c75 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Fri, 4 Jul 2025 13:44:46 +0300 Subject: [PATCH 261/327] Small fixes part 3. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index ca37f6f..933efb7 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -604,7 +604,6 @@ rhel9cis_crypto_policy_module: '' # using those listed in the 'rhel9cis_allowed_crypto_policies_modules' variable. rhel9cis_additional_crypto_policy_module: '' - ## Controls: # - 1.7.1 - Ensure message of the day is configured properly # - 1.7.2 - Ensure local login warning banner is configured properly @@ -976,7 +975,6 @@ rhel9cis_authselect_pkg_update: false # NOTE the risks if system is using SSSD ## Controls 5.3.x - # This variable configures the name of the custom profile to be created and selected. # To be changed from default - cis_example_profile. This setting needs to be adjusted # in order to minimise risk. @@ -1110,7 +1108,7 @@ rhel9cis_force_user_mindays: false # This variable governs, how many days before a password expires, the user will be warned. # CIS requires a value of at least 7. rhel9cis_pass_warn_age: 7 -#The following variable allows the forcing of number of days before warning users of password expiry +# The following variable allows the forcing of number of days before warning users of password expiry # This can break current connecting user access rhel9cis_force_user_warnage: false From d25b472283950e2ff5b29aa4c1951323d574c0aa Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Fri, 4 Jul 2025 13:50:05 +0300 Subject: [PATCH 262/327] Fixing order of configs. Signed-off-by: Diana-Maria Dumitru --- templates/audit/99_auditd.rules.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 6c852e3..4fa4516 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -56,9 +56,9 @@ -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/hostname -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/hostname -p wa -k system-locale -w /etc/NetworkManager -p wa -k system-locale {% endif %} {% if rhel9cis_rule_6_3_3_6 %} From 4329591c906d5301e2ecd5155309b820ea9d181a Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Tue, 8 Jul 2025 09:37:29 +0300 Subject: [PATCH 263/327] Fixing inconsistencies between rule ids in title, tags and when. Signed-off-by: Diana-Maria Dumitru --- tasks/section_1/cis_1.1.2.6.x.yml | 2 +- tasks/section_1/cis_1.1.2.7.x.yml | 2 +- tasks/section_3/cis_3.3.x.yml | 4 ++-- tasks/section_5/cis_5.4.2.x.yml | 2 +- tasks/section_6/cis_6.3.4.x.yml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tasks/section_1/cis_1.1.2.6.x.yml b/tasks/section_1/cis_1.1.2.6.x.yml index 765de3d..b27e4cc 100644 --- a/tasks/section_1/cis_1.1.2.6.x.yml +++ b/tasks/section_1/cis_1.1.2.6.x.yml @@ -1,6 +1,6 @@ --- -- name: "1/.1 | PATCH | Ensure /var/log is a separate partition" +- name: "1.1.2.6.1 | PATCH | Ensure /var/log is a separate partition" when: - rhel9cis_rule_1_1_2_6_1 - required_mount not in prelim_mount_names diff --git a/tasks/section_1/cis_1.1.2.7.x.yml b/tasks/section_1/cis_1.1.2.7.x.yml index 2dc5939..b4513dd 100644 --- a/tasks/section_1/cis_1.1.2.7.x.yml +++ b/tasks/section_1/cis_1.1.2.7.x.yml @@ -1,6 +1,6 @@ --- -- name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition" +- name: "1.1.2.7.1 | PATCH | Ensure /var/log/audit is a separate partition" when: - rhel9cis_rule_1_1_2_7_1 - required_mount not in prelim_mount_names diff --git a/tasks/section_3/cis_3.3.x.yml b/tasks/section_3/cis_3.3.x.yml index 123928e..0281f12 100644 --- a/tasks/section_3/cis_3.3.x.yml +++ b/tasks/section_3/cis_3.3.x.yml @@ -240,12 +240,12 @@ - rule_3.3.9 - NIST800-53R5_AU-3 block: - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact" + - name: "3.3.9 | PATCH | Ensure suspicious packets are logged | Set Fact" ansible.builtin.set_fact: rhel9cis_sysctl_update: true rhel9cis_flush_ipv4_route: true - - name: "3.3.4 | PATCH | Ensure suspicious packets are logged" + - name: "3.3.9 | PATCH | Ensure suspicious packets are logged" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf" diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index 37a4e11..867e1af 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -61,7 +61,7 @@ - level1-server - level1-workstation - patch - - rule_5.4.2.2 + - rule_5.4.2.3 - user - system - NIST800-53R5_CM-1 diff --git a/tasks/section_6/cis_6.3.4.x.yml b/tasks/section_6/cis_6.3.4.x.yml index 74de70a..b044abc 100644 --- a/tasks/section_6/cis_6.3.4.x.yml +++ b/tasks/section_6/cis_6.3.4.x.yml @@ -27,9 +27,9 @@ - level2-workstation - patch - auditd - - rule_6.3.4.1 - rule_6.3.4.2 - rule_6.3.4.3 + - rule_6.3.4.4 - NIST800-53R5_AU-3 ansible.builtin.file: path: "{{ prelim_auditd_logfile.stdout }}" From b182abf2aad5e2a7df4d8a6bd449dc93cdbd631c Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Tue, 8 Jul 2025 16:38:12 +0300 Subject: [PATCH 264/327] Fixing inconsistencies for importing tasks from section 1. Signed-off-by: Diana-Maria Dumitru --- tasks/section_1/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 5d99f48..c540fab 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -41,7 +41,7 @@ file: cis_1.2.2.x.yml - name: "SECTION | 1.3.1 | Configure SELinux" - ansible.builtin.include_tasks: + ansible.builtin.import_tasks: file: cis_1.3.1.x.yml - name: "SECTION | 1.4 | Configure Bootloader" From 76a680bb5926de2cdff49319e3efeb5cae2fdc06 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Wed, 9 Jul 2025 12:13:45 +0300 Subject: [PATCH 265/327] Fixing minor documentation issues. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 933efb7..1457d12 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -35,6 +35,7 @@ rhel9cis_level_2: true # Create managed not custom local_facts files create_benchmark_facts: true +# The path where the ansible facts file is created if audit facts are not present ansible_facts_path: /etc/ansible/facts.d ## Section 1.6 - Mandatory Access Control @@ -776,7 +777,7 @@ rhel9cis_ftp_client: false rhel9cis_openldap_clients_required: false ## Control - 2.2.3 - Ensure nis client is not installed # Set this variable to `true` to keep package `nis`(`ypbind`); otherwise, the package is uninstalled. -rhel9cis_ypbind_required: false # Same package as NIS server +rhel9cis_ypbind_required: false ## Control - 2.2.4 - Ensure telnet client is not installed # Set this variable to `true` to keep package `telnet`; otherwise, the package is uninstalled. rhel9cis_telnet_required: false @@ -827,7 +828,7 @@ rhel9cis_flush_ipv6_route: false # 1) either 'firewalld' # 2) or 'nftables' #### Some control allow for services to be removed or masked -#### The options are under each heading +#### The options are under each heading: #### absent = remove the package #### masked = leave package if installed and mask the service rhel9cis_firewall: firewalld @@ -1223,7 +1224,6 @@ rhel9cis_aide_cron: aide_weekday: '*' ## Preferred method of logging -## Whether rsyslog or journald preferred method for local logging ## Controls 6.2.1.x | Configure systemd-journald service ## Controls 6.2.2.x | Configured journald ## Controls 6.2.3.x | Configure rsyslog @@ -1327,7 +1327,7 @@ rhel9cis_remote_log_retrycount: 100 # of rsyslog forwarding must be enabled('rhel9cis_remote_log_server: true'). rhel9cis_remote_log_queuesize: 1000 -# Control 6.2.3.7 - Ensure rsyslog is not configured to receive logs from a remote client +## Control 6.2.3.7 - Ensure rsyslog is not configured to receive logs from a remote client # This variable expresses whether the system is used as a log server or not. If set to: # - 'false', current system will act as a log CLIENT, thus it should NOT receive data from other hosts. # - 'true', current system will act as a log SERVER, enabling centralised log management(by protecting log integrity @@ -1447,7 +1447,7 @@ rhel9cis_auditd_admin_space_left_action: halt # for auditd should be used by the role. rhel9cis_auditd_extra_conf_usage: false -# 6.3.3.x allow exceptions for UID in auditd config +## Controls 6.3.3.x allow exceptions for UID in auditd config ## Advanced option found in auditd post # This variable governs if defining user exceptions for auditd logging is acceptable. rhel9cis_allow_auditd_uid_user_exclusions: false @@ -1504,7 +1504,7 @@ min_int_uid: 1000 max_int_uid: 65533 ## Control 7.2.9 - Ensure local interactive user dot files access is configured -# This variable is a toggle foe enabling/disabling the automated modification of +# This variable is a toggle for enabling/disabling the automated modification of # permissions on dot files. # Possible values are `true` and `false` # This setting can impact a running system if not tested sufficiently From ad8e73c3ee02a395ff490c8e4982360561b2b62f Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Wed, 9 Jul 2025 13:28:33 +0300 Subject: [PATCH 266/327] Fixing minor documentation issues part 2. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 1457d12..3e5a0eb 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -92,9 +92,12 @@ fetch_audit_files: false 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 -# you will need to access to either github or the file already downloaded +## How to retrieve audit binary(Goss) +# Options are 'copy' or 'download' - detailed settings at the bottom of this file +# - if 'copy': +# - the filepath mentioned via the below 'audit_bin_copy_location' var will be used to access already downloaded Goss +# - if 'download': +# - the GitHub Goss-releases URL will be used for a fresh-download, via 'audit_bin_url' and 'audit_pkg_arch_name' vars get_audit_binary_method: download ## if get_audit_binary_method - copy the following needs to be updated for your environment From f90e896b0c736de908380248b58b35164149ff52 Mon Sep 17 00:00:00 2001 From: "Tomuta, Diana Maria (T CST SCC-RO)" Date: Wed, 9 Jul 2025 14:21:19 +0300 Subject: [PATCH 267/327] Fixing minor documentation issues part 3. Signed-off-by: Diana-Maria Dumitru --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 3e5a0eb..d50aecf 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -1416,7 +1416,7 @@ rhel9cis_auditd_disk_full_action: halt # when an error is detected on the partition that holds the audit log files. rhel9cis_auditd_disk_error_action: syslog -# Control 6.3.2.4 - Ensure system warns when audit logs are low on space +## Control 6.3.2.4 - Ensure system warns when audit logs are low on space # This variable tells the system what action to take when the system has detected # that it is starting to get low on disk space. # The options for setting this variable are as follows: From b62a414abb71466f4e50eb41a7d7415fd8e057fe Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 21 Jul 2025 17:28:55 +0000 Subject: [PATCH 268/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.27.2 → v8.28.0](https://github.com/gitleaks/gitleaks/compare/v8.27.2...v8.28.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a4d0a42..dec2081 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.27.2 + rev: v8.28.0 hooks: - id: gitleaks From 876e261d1f311a2add28b0c50b265649f17ebb97 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Aug 2025 09:53:09 +0100 Subject: [PATCH 269/327] fixed issues for permissions when using fetch thanks to @steve-hayes Signed-off-by: Mark Bolwell --- tasks/pre_remediation_audit.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 61959fa..250f987 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -70,7 +70,7 @@ mode: 'go-rwx' - name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] - ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" From 4b62f0fc3518352b1d0d36758f7945bfa8fa05b9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 4 Aug 2025 09:56:30 +0100 Subject: [PATCH 270/327] Updated post steps inline with pre steps for file permissions Signed-off-by: Mark Bolwell --- tasks/post_remediation_audit.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 68e7035..357a23f 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,22 +1,13 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] - ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}" AUDIT_FILE: goss.yml -- name: Post Audit | ensure audit files readable by users - ansible.builtin.file: - path: "{{ item }}" - mode: '0644' - state: file - loop: - - "{{ post_audit_outfile }}" - - "{{ pre_audit_outfile }}" - - name: Post Audit | Capture audit data if json format when: audit_format == "json" block: From cfbbb3339a988f65512c180bfe6667f90ce13c53 Mon Sep 17 00:00:00 2001 From: Michael Hicks Date: Mon, 11 Aug 2025 15:12:17 -0700 Subject: [PATCH 271/327] renames 3 uses of ansible.builtin.systemd_service to ansible.builtin.systemd to maintain ansible 2.12+ compat. Fixes #379 Signed-off-by: Michael Hicks --- handlers/main.yml | 2 +- tasks/section_6/cis_6.1.x.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/handlers/main.yml b/handlers/main.yml index 1894300..1ef6ccf 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -263,7 +263,7 @@ listen: Restart auditd - name: Start auditd process - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: auditd state: started listen: Restart auditd diff --git a/tasks/section_6/cis_6.1.x.yml b/tasks/section_6/cis_6.1.x.yml index 1db531b..a29118a 100644 --- a/tasks/section_6/cis_6.1.x.yml +++ b/tasks/section_6/cis_6.1.x.yml @@ -91,13 +91,13 @@ - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: aidecheck.service enabled: true - name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service" when: rhel9cis_aide_scan == "timer" - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: aidecheck.timer state: started enabled: true From 553f18e9926bb6e6ba7772e470375b44c709bdf5 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 15:13:33 +0100 Subject: [PATCH 272/327] updated pre-commit-hooks version Signed-off-by: Mark Bolwell --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index dec2081..aa27650 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: v5.0.0 + rev: v6.0.0 hooks: # Safety - id: detect-aws-credentials From b21569c62dd7a15c269c9c928a2c61c4c5a81d9b Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:00:36 +0100 Subject: [PATCH 273/327] added update for gdm and giu packages Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 ++ tasks/section_1/main.yml | 1 + 2 files changed, 3 insertions(+) diff --git a/defaults/main.yml b/defaults/main.yml index d50aecf..98efbba 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -617,6 +617,8 @@ rhel9cis_warning_banner: Authorized users only. All activity may be monitored an # End Banner ## Control 1.8.x - Settings for GDM +# do not run Control 1.8.x if using a display manager different than gdm +rhel10cis_display_manager: "gdm" # This variable governs whether rules dealing with GUI specific packages(and/or their settings) should # be executed either to: # - secure GDM, if GUI is needed('rhel9cis_gui: true') diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index c540fab..29687b3 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -61,5 +61,6 @@ file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" + when: rhel10cis_display_manager == 'gdm' ansible.builtin.import_tasks: file: cis_1.8.x.yml From fd2bfb7437215591945e4c0261f651f8e5eb04b0 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:03:11 +0100 Subject: [PATCH 274/327] improved prelim tests for 5.2.4 Signed-off-by: Mark Bolwell --- tasks/main.yml | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/tasks/main.yml b/tasks/main.yml index 460acc8..191ea25 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -93,11 +93,14 @@ block: - name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" # noqa name[template] ansible.builtin.assert: - that: - - prelim_ansible_user_password_set.stdout | length != 0 - - prelim_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" + that: | + ( + ((prelim_ansible_user_password_set.stdout | length != 0) and (prelim_ansible_user_password_set.stdout != "!!" )) + or + (ansible_env.SUDO_USER in rhel10cis_sudoers_exclude_nopasswd_list) + ) + fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set or or the user is not included in the exception list for rule 5.2.4 - It can break access" + success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user or the user is included in the exception list for rule 5.2.4" - name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template] ansible.builtin.assert: From cddad90a236347d6e20841488371363809bd2b99 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:04:07 +0100 Subject: [PATCH 275/327] enabled different locale characters in password check Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index 191ea25..83aff0c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,7 +134,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From 7428f269e74586716c11bb9404c240cd9cc39007 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:09:51 +0100 Subject: [PATCH 276/327] changed rsyslog to insert before line134 Signed-off-by: Mark Bolwell --- tasks/section_6/cis_6.2.3.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_6/cis_6.2.3.x.yml b/tasks/section_6/cis_6.2.3.x.yml index 9d26acf..eaa3bd1 100644 --- a/tasks/section_6/cis_6.2.3.x.yml +++ b/tasks/section_6/cis_6.2.3.x.yml @@ -131,7 +131,7 @@ *.=warning;*.=err -/var/log/warn *.crit /var/log/warn *.*;mail.none;news.none /var/log/messages - insertafter: '#### RULES ####' + insertbefore: '# ### sample forwarding rule ###' notify: Restart rsyslog - name: "6.2.3.5 | PATCH | Ensure logging is configured | Local log settings" From f0fb7011226b5f25f34766bbe07f71eeae5279ea Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:10:37 +0100 Subject: [PATCH 277/327] updated var naming on 5.4.2.5 Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_5/cis_5.4.2.x.yml b/tasks/section_5/cis_5.4.2.x.yml index b3dd7d9..b291cc2 100644 --- a/tasks/section_5/cis_5.4.2.x.yml +++ b/tasks/section_5/cis_5.4.2.x.yml @@ -139,7 +139,7 @@ ansible.builtin.stat: path: "{{ item }}" loop: "{{ discovered_root_paths_split.stdout_lines }}" - register: paths_stat + register: discovered_root_paths_stat - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Create dirs for some paths that are not dirs" ansible.builtin.file: @@ -148,7 +148,7 @@ owner: root group: root mode: 'go-w' - loop: "{{ paths_stat.results }}" + loop: "{{ discovered_root_paths_stat.results }}" when: not item.stat.exists - name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs" From f8d95213671abb8a0bfc39a6144380f1e22e8c26 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 15 Aug 2025 16:19:07 +0100 Subject: [PATCH 278/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Changelog.md b/Changelog.md index b6db646..68ba2d4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,12 @@ # Changes to rhel9CIS +## 2.0.3 - Based on CIS v2.0.0 + +- addressed issue 371 thanks to @bgro and kodebach +- addressed issue 350 thanks to @chrispipo +- addressed issue 364 thanks to @polski-g +- pre-commit update + ## 2.0.2 - Based on CIS v2.0.0 - Update to audit_only to allow fetching results From 7af8f5fe2426aba27d477e40f22c1df8cf658b06 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 25 Aug 2025 17:29:58 +0000 Subject: [PATCH 279/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.6.1 → v25.8.2](https://github.com/ansible-community/ansible-lint/compare/v25.6.1...v25.8.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index aa27650..4ae1ee6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.6.1 + rev: v25.8.2 hooks: - id: ansible-lint name: Ansible-lint From 88507f95166a0be477f87df1c71df15aa48ac489 Mon Sep 17 00:00:00 2001 From: polski-g Date: Thu, 28 Aug 2025 13:15:29 -0400 Subject: [PATCH 280/327] 5.4.1.1: shell command should run in check_mode Signed-off-by: polski-g --- tasks/section_5/cis_5.4.1.x.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 7fcfb0b..58cd936 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -24,6 +24,7 @@ ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass_max_days }} || $5< {{ rhel9cis_pass_max_days }} || $5 == -1)){print $1}' /etc/shadow" changed_when: false failed_when: false + check_mode: false register: discovered_max_days - name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS" From de7555aa1045fb30caeb292f34d74a9ad8e69920 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 2 Sep 2025 17:14:30 -0400 Subject: [PATCH 281/327] Update Changelog with fixes Signed-off-by: Frederick Witty --- Changelog.md | 2 +- tasks/prelim.yml | 20 +++++++------------- tasks/section_1/cis_1.6.x.yml | 5 +++-- tasks/section_4/cis_4.3.x.yml | 2 +- 4 files changed, 12 insertions(+), 17 deletions(-) diff --git a/Changelog.md b/Changelog.md index 68ba2d4..af7476e 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,7 +1,7 @@ # Changes to rhel9CIS ## 2.0.3 - Based on CIS v2.0.0 - +- update command to shell module on tasks - addressed issue 371 thanks to @bgro and kodebach - addressed issue 350 thanks to @chrispipo - addressed issue 364 thanks to @polski-g diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 715b0cb..bd69172 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -167,6 +167,7 @@ current_crypto_module: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[1] }}" - name: "PRELIM | AUDIT | Set facts based on boot type" + tags: always block: - name: "PRELIM | AUDIT | Check whether machine is UEFI-based" ansible.builtin.stat: @@ -185,17 +186,14 @@ grub2_path: /etc/grub2-efi.cfg - name: "PRELIM | AUDIT | Discover Gnome Desktop Environment" - tags: - - always + tags: always ansible.builtin.stat: path: /usr/share/gnome/gnome-version.xml register: prelim_gnome_present - name: "PRELIM | PATCH | Install dconf if gui installed" - when: - - rhel9cis_gui - tags: - - always + when: rhel9cis_gui + tags: always ansible.builtin.package: name: dconf state: present @@ -204,8 +202,7 @@ when: - rhel9cis_rule_3_1_2 - not system_is_container - tags: - - always + tags: always block: - name: "PRELIM | AUDIT | Discover is wireless adapter on system" ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless @@ -251,9 +248,7 @@ state: touch - name: "PRELIM | PATCH | sshd_config.d/50-redhat.conf exists" - when: - - rhel9cis_rule_5_1_10 or - rhel9cis_rule_5_1_11 + when: rhel9cis_rule_5_1_10 or rhel9cis_rule_5_1_11 ansible.builtin.stat: path: /etc/ssh/sshd_config.d/50-redhat.conf register: prelim_sshd_50_redhat_file @@ -361,7 +356,6 @@ prelim_max_int_uid: "{{ prelim_uid_max_id.stdout | default(max_int_uid) }}" - name: "PRELIM | AUDIT | Gather the package facts after prelim" - tags: - - always + tags: always ansible.builtin.package_facts: manager: auto diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index c418324..0530645 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -21,12 +21,14 @@ tags: - level1-server - level1-workstation + - sshd - automated - patch - rule_1.6.2 - NIST800-53R5_SC-8 - NIST800-53R5_IA-5 - - NIST800-53R5_AC-17- NIST800-53R5_SC-6 + - NIST800-53R5_AC-17 + - NIST800-53R5_SC-6 ansible.builtin.lineinfile: path: /etc/sysconfig/sshd regexp: ^CRYPTO_POLICY\s*= @@ -76,7 +78,6 @@ - rule_1.6.4 - NIST800-53R5_SC-6 block: - - name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion" ansible.builtin.template: src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2 diff --git a/tasks/section_4/cis_4.3.x.yml b/tasks/section_4/cis_4.3.x.yml index 4e23998..4398df2 100644 --- a/tasks/section_4/cis_4.3.x.yml +++ b/tasks/section_4/cis_4.3.x.yml @@ -81,7 +81,7 @@ register: discovered_nftables_inconnectionrule - name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules" - ansible.builtin.command: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state' + 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: discovered_nftables_outconnectionrule From 1c9c1b919c77e747bd1bfab5a414c849f10b3655 Mon Sep 17 00:00:00 2001 From: polski-g Date: Wed, 3 Sep 2025 09:55:00 -0400 Subject: [PATCH 282/327] 1.4.2: grep command should run in check_mode Signed-off-by: polski-g --- tasks/section_1/cis_1.4.x.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/section_1/cis_1.4.x.yml b/tasks/section_1/cis_1.4.x.yml index c6c3aac..5969dff 100644 --- a/tasks/section_1/cis_1.4.x.yml +++ b/tasks/section_1/cis_1.4.x.yml @@ -52,6 +52,7 @@ - name: "1.4.2 | AUDIT | Ensure permissions on bootloader config are configured | efi based system | capture current state" ansible.builtin.shell: grep "^[^#;]" /etc/fstab | grep '/boot/efi' | awk -F" " '{print $4}' changed_when: false + check_mode: false register: discovered_efi_fstab - name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured | efi based system | Build Options" From b0ec6c48208d026e59939c6b9750e033a6bc00d0 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 5 Sep 2025 16:24:11 -0400 Subject: [PATCH 283/327] Fix for #384, thank you @polski-g Signed-off-by: Frederick Witty --- Changelog.md | 1 + defaults/main.yml | 2 +- tasks/main.yml | 2 +- tasks/section_1/main.yml | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index af7476e..fb4a9f4 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ # Changes to rhel9CIS ## 2.0.3 - Based on CIS v2.0.0 +- addressed issue #384 thank you @polski-g - update command to shell module on tasks - addressed issue 371 thanks to @bgro and kodebach - addressed issue 350 thanks to @chrispipo diff --git a/defaults/main.yml b/defaults/main.yml index 98efbba..344e195 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -618,7 +618,7 @@ rhel9cis_warning_banner: Authorized users only. All activity may be monitored an ## Control 1.8.x - Settings for GDM # do not run Control 1.8.x if using a display manager different than gdm -rhel10cis_display_manager: "gdm" +rhel9cis_display_manager: "gdm" # This variable governs whether rules dealing with GUI specific packages(and/or their settings) should # be executed either to: # - secure GDM, if GUI is needed('rhel9cis_gui: true') diff --git a/tasks/main.yml b/tasks/main.yml index 83aff0c..968debd 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -97,7 +97,7 @@ ( ((prelim_ansible_user_password_set.stdout | length != 0) and (prelim_ansible_user_password_set.stdout != "!!" )) or - (ansible_env.SUDO_USER in rhel10cis_sudoers_exclude_nopasswd_list) + (ansible_env.SUDO_USER in rhel9cis_sudoers_exclude_nopasswd_list) ) fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set or or the user is not included in the exception list for rule 5.2.4 - It can break access" success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user or the user is included in the exception list for rule 5.2.4" diff --git a/tasks/section_1/main.yml b/tasks/section_1/main.yml index 29687b3..fff557b 100644 --- a/tasks/section_1/main.yml +++ b/tasks/section_1/main.yml @@ -61,6 +61,6 @@ file: cis_1.7.x.yml - name: "SECTION | 1.8 | Gnome Display Manager" - when: rhel10cis_display_manager == 'gdm' + when: rhel9cis_display_manager == 'gdm' ansible.builtin.import_tasks: file: cis_1.8.x.yml From 413ccb96b7131dcc7c3427cf806758b7223b8038 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Fri, 5 Sep 2025 16:39:55 -0400 Subject: [PATCH 284/327] Update cryto policy based controls with improved logic Signed-off-by: Frederick Witty --- Changelog.md | 1 + defaults/main.yml | 1 + tasks/prelim.yml | 3 +-- tasks/section_1/cis_1.6.x.yml | 9 ++++++++- tasks/section_5/cis_5.1.x.yml | 3 +++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index fb4a9f4..252418c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ # Changes to rhel9CIS ## 2.0.3 - Based on CIS v2.0.0 +- improvment on crypto policy managed controls with var logic - addressed issue #384 thank you @polski-g - update command to shell module on tasks - addressed issue 371 thanks to @bgro and kodebach diff --git a/defaults/main.yml b/defaults/main.yml index 344e195..b829873 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -595,6 +595,7 @@ rhel9cis_set_boot_pass: true # -'FIPS': A level that conforms to the FIPS140-2 requirements rhel9cis_crypto_policy: 'DEFAULT' ## Controls 1.6.x and Controls 5.1.x +rhel9cis_crypto_policy_ansible_managed: true # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, # using 'rhel9cis_allowed_crypto_policies_modules' variable, which currently are: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index bd69172..1368993 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -136,8 +136,7 @@ register: prelim_systemd_coredump - name: "PRELIM | PATCH | Setup crypto-policy" - when: - - rhel9cis_rule_1_6_1 + when: rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 0530645..6f3d6af 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -1,7 +1,9 @@ --- - name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" - when: rhel9cis_rule_1_6_1 + when: + - rhel9cis_rule_1_6_1 + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -39,6 +41,7 @@ when: - rhel9cis_rule_1_6_3 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -69,6 +72,7 @@ when: - rhel9cis_rule_1_6_4 - "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -99,6 +103,7 @@ when: - rhel9cis_rule_1_6_5 - "'NO-SSHCBC' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -129,6 +134,7 @@ when: - rhel9cis_rule_1_6_6 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -159,6 +165,7 @@ when: - rhel9cis_rule_1_6_7 - "'NO-SSHETM' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 3fd366c..ee384d3 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -80,6 +80,7 @@ when: - rhel9cis_rule_5_1_4 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -108,6 +109,7 @@ when: - rhel9cis_rule_5_1_5 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation @@ -136,6 +138,7 @@ when: - rhel9cis_rule_5_1_6 - "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module" + - rhel9cis_crypto_policy_ansible_managed tags: - level1-server - level1-workstation From 2dfa9266a8ce9f0d08b210302c523e8b8058e0f8 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Mon, 8 Sep 2025 11:54:57 -0400 Subject: [PATCH 285/327] Update cryto policy var to standard Signed-off-by: Frederick Witty --- defaults/main.yml | 6 +++--- tasks/prelim.yml | 2 +- tasks/section_1/cis_1.6.x.yml | 12 ++++++------ tasks/section_5/cis_5.1.x.yml | 6 +++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index b829873..c46ece3 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -586,7 +586,9 @@ rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword' # pr # This variable governs whether a bootloader password should be set in '/boot/grub2/user.cfg' file. rhel9cis_set_boot_pass: true -## Controls 1.6.x +## Controls 1.6.x and Controls 5.1.x +# This variable governs if current Ansible role should manage system-wide crypto policy. +rhel9cis_crypto_policy_ansiblemanaged: true # This variable contains the value to be set as the system-wide crypto policy. Current rule enforces NOT USING # 'LEGACY' value(as it is less secure, it just ensures compatibility with legacy systems), therefore # possible values for this variable are, as explained by RedHat docs: @@ -594,8 +596,6 @@ rhel9cis_set_boot_pass: true # -'FUTURE': conservative security level that is believed to withstand any near-term future attacks # -'FIPS': A level that conforms to the FIPS140-2 requirements rhel9cis_crypto_policy: 'DEFAULT' -## Controls 1.6.x and Controls 5.1.x -rhel9cis_crypto_policy_ansible_managed: true # This variable contains the value of the crypto policy module(combinations of policies and # sub-policies) to be allowed as default setting. Allowed options are defined in 'vars/main.yml' file, # using 'rhel9cis_allowed_crypto_policies_modules' variable, which currently are: diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 1368993..7321267 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -136,7 +136,7 @@ register: prelim_systemd_coredump - name: "PRELIM | PATCH | Setup crypto-policy" - when: rhel9cis_crypto_policy_ansible_managed + when: rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation diff --git a/tasks/section_1/cis_1.6.x.yml b/tasks/section_1/cis_1.6.x.yml index 6f3d6af..8aace04 100644 --- a/tasks/section_1/cis_1.6.x.yml +++ b/tasks/section_1/cis_1.6.x.yml @@ -3,7 +3,7 @@ - name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy" when: - rhel9cis_rule_1_6_1 - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -41,7 +41,7 @@ when: - rhel9cis_rule_1_6_3 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -72,7 +72,7 @@ when: - rhel9cis_rule_1_6_4 - "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -103,7 +103,7 @@ when: - rhel9cis_rule_1_6_5 - "'NO-SSHCBC' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -134,7 +134,7 @@ when: - rhel9cis_rule_1_6_6 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -165,7 +165,7 @@ when: - rhel9cis_rule_1_6_7 - "'NO-SSHETM' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index ee384d3..42ca036 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -80,7 +80,7 @@ when: - rhel9cis_rule_5_1_4 - "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -109,7 +109,7 @@ when: - rhel9cis_rule_5_1_5 - "'NO-SHA1' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation @@ -138,7 +138,7 @@ when: - rhel9cis_rule_5_1_6 - "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module" - - rhel9cis_crypto_policy_ansible_managed + - rhel9cis_crypto_policy_ansiblemanaged tags: - level1-server - level1-workstation From 5794114b3e2207655b173a098c0b01bdc9a2474a Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 9 Sep 2025 15:12:01 -0400 Subject: [PATCH 286/327] Update prelim logic to address #382 Signed-off-by: Frederick Witty --- Changelog.md | 1 + tasks/main.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 252418c..9e27290 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ # Changes to rhel9CIS ## 2.0.3 - Based on CIS v2.0.0 +- addressed issue #382 to improve regex logic on 5.4.2.4 - improvment on crypto policy managed controls with var logic - addressed issue #384 thank you @polski-g - update command to shell module on tasks diff --git a/tasks/main.yml b/tasks/main.yml index 968debd..760ee1b 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,7 +134,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set, SHA512 crypt|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From e61cafb59be8b9c447fab098d9e3acb77de723dd Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 9 Sep 2025 15:59:30 -0400 Subject: [PATCH 287/327] addressed issue #387, thank you @fragglexarmy Signed-off-by: Frederick Witty --- Changelog.md | 1 + tasks/section_5/cis_5.4.1.x.yml | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 9e27290..099c93d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,7 @@ # Changes to rhel9CIS ## 2.0.3 - Based on CIS v2.0.0 +- addressed issue #387, thank you @fragglexarmy - addressed issue #382 to improve regex logic on 5.4.2.4 - improvment on crypto policy managed controls with var logic - addressed issue #384 thank you @polski-g diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index 7fcfb0b..3ea1c99 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -64,7 +64,7 @@ - rhel9cis_force_user_mindays ansible.builtin.user: name: "{{ item }}" - password_expire_max: "{{ rhel9cis_pass_min_days }}" + password_expire_min: "{{ rhel9cis_pass_min_days }}" loop: "{{ discovered_min_days.stdout_lines }}" - name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured" From d92ec8c5640319995ea3f33e3409f8c9d0230d75 Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Tue, 9 Sep 2025 16:31:14 -0400 Subject: [PATCH 288/327] typo fix Signed-off-by: Frederick Witty --- Changelog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index 099c93d..ec3d9aa 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,7 +3,7 @@ ## 2.0.3 - Based on CIS v2.0.0 - addressed issue #387, thank you @fragglexarmy - addressed issue #382 to improve regex logic on 5.4.2.4 -- improvment on crypto policy managed controls with var logic +- improvement on crypto policy managed controls with var logic - addressed issue #384 thank you @polski-g - update command to shell module on tasks - addressed issue 371 thanks to @bgro and kodebach From 392c3f90161f23b61a9eba5f4166073318a5f21e Mon Sep 17 00:00:00 2001 From: polski-g Date: Tue, 2 Sep 2025 12:15:45 -0400 Subject: [PATCH 289/327] Support section 5 modularization corrected trailing whitespace Signed-off-by: polski-g --- defaults/main.yml | 6 ++++ tasks/section_5/main.yml | 65 +++++++++++++++++++++++----------------- 2 files changed, 44 insertions(+), 27 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index 98efbba..ed3cf59 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -18,11 +18,17 @@ rhel9cis_disruption_high: true # These variables govern whether the tasks of a particular section are to be executed when running the role. # E.g: If you want to execute the tasks of Section 1 you should set the "_section1" variable to true. # If you do not want the tasks from that section to get executed you simply set the variable to "false". +# Some sections support sub-section modularization. The super-section and sub-section must both be true +# for the sub-section to execute. rhel9cis_section1: true rhel9cis_section2: true rhel9cis_section3: true rhel9cis_section4: true rhel9cis_section5: true +rhel9cis_section5_1: true +rhel9cis_section5_2: true +rhel9cis_section5_3: true +rhel9cis_section5_4: true rhel9cis_section6: true rhel9cis_section7: true diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index ae908ac..c4dacff 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -5,45 +5,56 @@ - name: "SECTION | 5.1 | Configure SSH Server" when: - "'openssh-server' in ansible_facts.packages" + - rhel9cis_section5_1 ansible.builtin.import_tasks: file: cis_5.1.x.yml - name: "SECTION | 5.2 | Configure privilege escalation" + when: + - - rhel9cis_section5_2 ansible.builtin.import_tasks: file: cis_5.2.x.yml -- name: "SECTION | 5.3.1.x | Configure PAM software packages" - ansible.builtin.import_tasks: - file: cis_5.3.1.x.yml +- name: "SECTION | 5.3" + when: + - rhel9cis_section5_3 + block: + - name: "SECTION | 5.3.1.x | Configure PAM software packages" + ansible.builtin.import_tasks: + file: cis_5.3.1.x.yml -- name: "SECTION | 5.3.2.x | Configure authselect" - ansible.builtin.import_tasks: - file: cis_5.3.2.x.yml + - name: "SECTION | 5.3.2.x | Configure authselect" + ansible.builtin.import_tasks: + file: cis_5.3.2.x.yml -- name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" - ansible.builtin.import_tasks: - file: cis_5.3.3.1.x.yml + - name: "SECTION | 5.3.3.1.x | Configure pam_faillock module" + ansible.builtin.import_tasks: + file: cis_5.3.3.1.x.yml -- name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" - ansible.builtin.import_tasks: - file: cis_5.3.3.2.x.yml + - name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module" + ansible.builtin.import_tasks: + file: cis_5.3.3.2.x.yml -- name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" - ansible.builtin.import_tasks: - file: cis_5.3.3.3.x.yml + - name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module" + ansible.builtin.import_tasks: + file: cis_5.3.3.3.x.yml -- name: "SECTION | 5.3.3.4.x | Configure pam_unix module" - ansible.builtin.import_tasks: - file: cis_5.3.3.4.x.yml + - name: "SECTION | 5.3.3.4.x | Configure pam_unix module" + ansible.builtin.import_tasks: + file: cis_5.3.3.4.x.yml -- name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" - ansible.builtin.import_tasks: - file: cis_5.4.1.x.yml +- name: "SECTION | 5.4" + when: + - rhel9cis_section5_4 + block: + - name: "SECTION | 5.4.1.x | Configure shadow password suite parameters" + ansible.builtin.import_tasks: + file: cis_5.4.1.x.yml -- name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" - ansible.builtin.import_tasks: - file: cis_5.4.2.x.yml + - name: "SECTION | 5.4.2.x | Configure root and system accounts and environment" + ansible.builtin.import_tasks: + file: cis_5.4.2.x.yml -- name: "SECTION | 5.4.3.x | Configure user default environment" - ansible.builtin.import_tasks: - file: cis_5.4.3.x.yml + - name: "SECTION | 5.4.3.x | Configure user default environment" + ansible.builtin.import_tasks: + file: cis_5.4.3.x.yml From 2557470054c9d784bcda461299ee9f542865b7a8 Mon Sep 17 00:00:00 2001 From: polski-g Date: Thu, 28 Aug 2025 13:55:41 -0400 Subject: [PATCH 290/327] 5.3.2.2: fix regex failing to match whitespace Fixed yamllint (colons) issues Signed-off-by: polski-g --- tasks/section_5/cis_5.3.2.x.yml | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/tasks/section_5/cis_5.3.2.x.yml b/tasks/section_5/cis_5.3.2.x.yml index 5917019..6e1919c 100644 --- a/tasks/section_5/cis_5.3.2.x.yml +++ b/tasks/section_5/cis_5.3.2.x.yml @@ -91,9 +91,15 @@ insertafter: "{{ item.after | default(omit) }}" line: "{{ item.line }}" loop: - - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+preauth" + after: "auth\\s+required\\s+pam_env.so" # yamllint disable-line rule:colons + line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+authfail" + before: "auth\\s+required\\s+pam_deny.so" + line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "account\\s+required\\s+pam_faillock.so" + before: "account\\s+required\\s+pam_unix.so" + line: "account required pam_faillock.so" # yamllint disable-line rule:colons - name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add lines password-auth" when: not rhel9cis_allow_authselect_updates @@ -104,9 +110,15 @@ insertafter: "{{ item.after | default(omit) }}" line: "{{ item.line }}" loop: - - { regexp: auth\s*required\s*pam_faillock.so preauth, after: auth\s*required\s*pam_env.so, line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: auth\s*required\s*pam_faillock.so authfail, before: auth\s*required\s*pam_deny.so, line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" } - - { regexp: account\s*required\s*pam_faillock.so, before: account\s*required\s*pam_unix.so, line: "account required pam_faillock.so" } + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+preauth" + after: "auth\\s+required\\s+pam_env.so" # yamllint disable-line rule:colons + line: "auth required pam_faillock.so preauth silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "auth\\s+required\\s+pam_faillock.so\\s+authfail" + before: "auth\\s+required\\s+pam_deny.so" + line: "auth required pam_faillock.so authfail silent deny=3 unlock_timeout={{ rhel9cis_pam_faillock_unlock_time }}" # yamllint disable-line rule:colons + - regexp: "account\\s+required\\s+pam_faillock.so" + before: "account\\s+required\\s+pam_unix.so" + line: "account required pam_faillock.so" # yamllint disable-line rule:colons - name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled" when: From 03d42ba8ced44b8fe8e3f23b2d449753826c62b2 Mon Sep 17 00:00:00 2001 From: Danny Beuker Date: Mon, 22 Sep 2025 09:57:55 +0200 Subject: [PATCH 291/327] Suggestion for the missing assert parameter Signed-off-by: Danny Beuker --- tasks/pre_remediation_audit.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index 250f987..cf8d8c7 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -57,6 +57,7 @@ - name: Pre Audit Setup | If audit ensure goss is available when: not prelim_goss_available.stat.exists ansible.builtin.assert: + that: prelim_goss_available['stat']['exists'] == true 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 From 2c0b5134b15331ff375963f23749229ee15e16bb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Sep 2025 17:39:44 +0000 Subject: [PATCH 292/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.8.2 → v25.9.0](https://github.com/ansible-community/ansible-lint/compare/v25.8.2...v25.9.0) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4ae1ee6..7fd561a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.8.2 + rev: v25.9.0 hooks: - id: ansible-lint name: Ansible-lint From d63f58972deb487e5119405d74b536aa58ab0e97 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 10:32:24 +0100 Subject: [PATCH 293/327] fixed typo Signed-off-by: Mark Bolwell --- tasks/section_5/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/main.yml b/tasks/section_5/main.yml index c4dacff..09a2fdd 100644 --- a/tasks/section_5/main.yml +++ b/tasks/section_5/main.yml @@ -11,7 +11,7 @@ - name: "SECTION | 5.2 | Configure privilege escalation" when: - - - rhel9cis_section5_2 + - rhel9cis_section5_2 ansible.builtin.import_tasks: file: cis_5.2.x.yml From d2b371432eb6959cf2fb62def22434e5d2c06263 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 10:32:52 +0100 Subject: [PATCH 294/327] issue #393 addressed thanks to @fragglexarmy Signed-off-by: Mark Bolwell --- tasks/section_5/cis_5.4.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_5/cis_5.4.1.x.yml b/tasks/section_5/cis_5.4.1.x.yml index ea6eb11..badca42 100644 --- a/tasks/section_5/cis_5.4.1.x.yml +++ b/tasks/section_5/cis_5.4.1.x.yml @@ -94,7 +94,7 @@ - discovered_warn_days.stdout_lines | length > 0 - item in prelim_interactive_users | map(attribute='username') | list - rhel9cis_force_user_warnage - ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}" + ansible.builtin.command: "chage --warndays {{ rhel9cis_pass_warn_age }} {{ item }}" changed_when: true loop: "{{ discovered_warn_days.stdout_lines }}" From ed5942f4941c2e6331a9ae5f0444ba609e9e397e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 10:37:12 +0100 Subject: [PATCH 295/327] workflows updated Signed-off-by: Mark Bolwell --- .../workflows/devel_pipeline_validation.yml | 242 +++++++++--------- .../workflows/main_pipeline_validation.yml | 223 ++++++++-------- 2 files changed, 229 insertions(+), 236 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index 10750a2..deac4d7 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -4,16 +4,16 @@ on: # yamllint disable-line rule:truthy pull_request_target: - types: [opened, reopened, synchronize] - branches: - - devel - - benchmark* - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + types: [opened, reopened, synchronize] + branches: + - devel + - benchmark* + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' # Allow manual running of workflow workflow_dispatch: @@ -27,133 +27,131 @@ # 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 + 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. + steps: + - uses: actions/first-interaction@main + with: + repo_token: ${{ secrets.GITHUB_TOKEN }} + issue_message: |- + Congrats on opening your first issue 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. + 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 + # 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: + steps: - - name: Git clone the lockdown repository to test - uses: actions/checkout@v4 - with: - ref: ${{ github.event.pull_request.head.sha }} + - 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 + - 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 }} + # 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 }} + # 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: DEBUG - Show IaC files + if: env.ENABLE_DEBUG == 'true' + run: | + echo "OSVAR = $OSVAR" + echo "benchmark_type = $benchmark_type" + pwd + env: + # Imported from GitHub variables this is used to load the relevant OS.tfvars file + OSVAR: ${{ vars.OSVAR }} + benchmark_type: ${{ vars.BENCHMARK_TYPE }} - - 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 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 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 + - 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 + - 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 + # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - name: Sleep to 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 + # 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 + # 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 + - 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 6792a00..6c1d2ea 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -4,16 +4,16 @@ on: # yamllint disable-line rule:truthy pull_request_target: - types: [opened, reopened, synchronize] - branches: - - main - - latest - paths: - - '**.yml' - - '**.sh' - - '**.j2' - - '**.ps1' - - '**.cfg' + types: [opened, reopened, synchronize] + branches: + - main + - latest + paths: + - '**.yml' + - '**.sh' + - '**.j2' + - '**.ps1' + - '**.cfg' # Allow permissions for AWS auth permissions: @@ -24,123 +24,118 @@ # 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: 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 - # 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: - steps: + - name: Git clone the lockdown repository to test + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - - 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 - - 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 }} - # 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 }} - # 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" + 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: 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 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 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 + - 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 + - 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 + # Aws deployments taking a while to come up insert sleep or playbook fails - - name: Sleep to allow system to come up - run: sleep ${{ vars.BUILD_SLEEPTIME }} + - name: Sleep to 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 + # 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 + # 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 + - 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 From 81eadd4a6f81d58d3f2c7e4434ece27c842516b9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 12:59:44 +0100 Subject: [PATCH 296/327] max-concurrent audit option added Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 ++ tasks/post_remediation_audit.yml | 2 +- tasks/pre_remediation_audit.yml | 3 ++- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index d7719ba..ed14e51 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -88,6 +88,8 @@ setup_audit: false 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 +# Ability to limit the number of concurrent processes used by goss (default 50) +audit_max_concurrent: 50 ## Only run Audit do not remediate audit_only: false diff --git a/tasks/post_remediation_audit.yml b/tasks/post_remediation_audit.yml index 357a23f..5e9419c 100644 --- a/tasks/post_remediation_audit.yml +++ b/tasks/post_remediation_audit.yml @@ -1,7 +1,7 @@ --- - name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template] - ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -m {{ audit_max_concurrent }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index cf8d8c7..dd9efb4 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -1,4 +1,5 @@ --- + - name: Pre Audit Setup | Setup the LE audit when: setup_audit tags: setup_audit @@ -71,7 +72,7 @@ mode: 'go-rwx' - name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template] - ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] + ansible.builtin.shell: "umask 0022 && {{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -m {{ audit_max_concurrent }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length] changed_when: true environment: AUDIT_BIN: "{{ audit_bin }}" From 6f167140d1a3b1c1c713793ec17850f83a0c7c68 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Wed, 1 Oct 2025 13:00:14 +0100 Subject: [PATCH 297/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Changelog.md b/Changelog.md index ec3d9aa..85eab9c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,15 @@ # Changes to rhel9CIS + +## 2.0.4 - Based on CIS v2.0.0 + +- addressed issue #393 thank you to @fragglexarmy +- addressed issue #394 thank you to @dbeuker +- addressed issues #390 and #391 thanks to @polski-g +- Added max-concurrent options for audit +- work flow updates +- audit logic improvements + ## 2.0.3 - Based on CIS v2.0.0 - addressed issue #387, thank you @fragglexarmy - addressed issue #382 to improve regex logic on 5.4.2.4 From 319c7a8fbbf3e159002c0fde14ca926ab5425e69 Mon Sep 17 00:00:00 2001 From: polski-g Date: Thu, 8 May 2025 10:59:55 -0400 Subject: [PATCH 298/327] ensure check mode runs all non-destructive tasks Signed-off-by: polski-g --- tasks/prelim.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 7321267..7c31c25 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -114,6 +114,7 @@ ansible.builtin.shell: rpm -qi redhat-release | grep Signature # noqa command-instead-of-module changed_when: false failed_when: false + check_mode: false register: prelim_os_gpg_package_valid - name: "PRELIM | PATCH | Force keys to be imported" # noqa command-instead-of-module @@ -207,6 +208,7 @@ ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless register: discover_wireless_adapters changed_when: false + check_mode: false failed_when: discover_wireless_adapters.rc not in [ 0, 1 ] - name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present" From 7aa911b3541617cd71677c1ebcdcf5a0eba1a8ce Mon Sep 17 00:00:00 2001 From: Thomas Rumbaut Date: Thu, 2 Oct 2025 10:06:44 +0200 Subject: [PATCH 299/327] Update cis_3.2.x.yml (add dccp to blacklist instead of cramfs Signed-off-by: Thomas Rumbaut --- tasks/section_3/cis_3.2.x.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tasks/section_3/cis_3.2.x.yml b/tasks/section_3/cis_3.2.x.yml index a49d907..415d966 100644 --- a/tasks/section_3/cis_3.2.x.yml +++ b/tasks/section_3/cis_3.2.x.yml @@ -25,8 +25,8 @@ - name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | blacklist" ansible.builtin.lineinfile: path: /etc/modprobe.d/blacklist.conf - regexp: "^(#)?blacklist cramfs(\\s|$)" - line: "blacklist cramfs" + regexp: "^(#)?blacklist dccp(\\s|$)" + line: "blacklist dccp" create: true mode: 'u-x,go-rwx' From eb2fc50dc7bb89d416deb81223bd06ac6cf8b5e3 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 13:47:01 +0100 Subject: [PATCH 300/327] updated to latest version Signed-off-by: Mark Bolwell --- README.md | 194 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 117 insertions(+), 77 deletions(-) diff --git a/README.md b/README.md index 098c50a..5c75173 100644 --- a/README.md +++ b/README.md @@ -6,59 +6,93 @@ --- +## Public Repository 📣 + ![Org Stars](https://img.shields.io/github/stars/ansible-lockdown?label=Org%20Stars&style=social) ![Stars](https://img.shields.io/github/stars/ansible-lockdown/RHEL9-CIS?label=Repo%20Stars&style=social) ![Forks](https://img.shields.io/github/forks/ansible-lockdown/RHEL9-CIS?style=social) -![followers](https://img.shields.io/github/followers/ansible-lockdown?style=social) +![Followers](https://img.shields.io/github/followers/ansible-lockdown?style=social) [![Twitter URL](https://img.shields.io/twitter/url/https/twitter.com/AnsibleLockdown.svg?style=social&label=Follow%20%40AnsibleLockdown)](https://twitter.com/AnsibleLockdown) - -![Ansible Galaxy Quality](https://img.shields.io/ansible/quality/61781?label=Quality&&logo=ansible) ![Discord Badge](https://img.shields.io/discord/925818806838919229?logo=discord) +![License](https://img.shields.io/github/license/ansible-lockdown/RHEL9-CIS?label=License) + +## Lint & Pre-Commit Tools 🔧 + +[![Pre-Commit.ci](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/pre-commit-ci.json)](https://results.pre-commit.ci/latest/github/ansible-lockdown/RHEL9-CIS/devel) +![YamlLint](https://img.shields.io/badge/yamllint-Present-brightgreen?style=flat&logo=yaml&logoColor=white) +![Ansible-Lint](https://img.shields.io/badge/ansible--lint-Present-brightgreen?style=flat&logo=ansible&logoColor=white) + +## Community Release Information 📂 + ![Release Branch](https://img.shields.io/badge/Release%20Branch-Main-brightgreen) -![Release Tag](https://img.shields.io/github/v/release/ansible-lockdown/RHEL9-CIS) -![Release Date](https://img.shields.io/github/release-date/ansible-lockdown/RHEL9-CIS) +![Release Tag](https://img.shields.io/github/v/tag/ansible-lockdown/RHEL9-CIS?label=Release%20Tag&&color=success) +![Main Release Date](https://img.shields.io/github/release-date/ansible-lockdown/RHEL9-CIS?label=Release%20Date) +![Benchmark Version Main](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/benchmark-version-main.json) +![Benchmark Version Devel](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/RHEL9-CIS/benchmark-version-devel.json) [![Main Pipeline Status](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/main_pipeline_validation.yml/badge.svg?)](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/main_pipeline_validation.yml) [![Devel Pipeline Status](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/devel_pipeline_validation.yml/badge.svg?)](https://github.com/ansible-lockdown/RHEL9-CIS/actions/workflows/devel_pipeline_validation.yml) + + ![Devel Commits](https://img.shields.io/github/commit-activity/m/ansible-lockdown/RHEL9-CIS/devel?color=dark%20green&label=Devel%20Branch%20Commits) - -![Issues Open](https://img.shields.io/github/issues-raw/ansible-lockdown/RHEL9-CIS?label=Open%20Issues) -![Issues Closed](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/RHEL9-CIS?label=Closed%20Issues&&color=success) +![Open Issues](https://img.shields.io/github/issues-raw/ansible-lockdown/RHEL9-CIS?label=Open%20Issues) +![Closed Issues](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/RHEL9-CIS?label=Closed%20Issues&&color=success) ![Pull Requests](https://img.shields.io/github/issues-pr/ansible-lockdown/RHEL9-CIS?label=Pull%20Requests) -[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) - -![License](https://img.shields.io/github/license/ansible-lockdown/RHEL9-CIS?label=License) --- -### Community +## Subscriber Release Information 🔐 -Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users. +![Private Release Branch](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/release-branch.json) +![Private Benchmark Version](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/benchmark-version.json) + +[![Private Remediate Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/remediate.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation.yml) +[![Private GPO Pipeline](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/gpo.json)](https://github.com/ansible-lockdown/Private-RHEL9-CIS/actions/workflows/main_pipeline_validation_gpo.yml) + +![Private Pull Requests](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/prs.json) +![Private Closed Issues](https://img.shields.io/endpoint?url=https://ansible-lockdown.github.io/github_linux_IaC/badges/Private-RHEL9-CIS/issues-closed.json) --- -## Caution(s) +## Looking for support? 🤝 + +[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_WINDOWS_2022_cis) + +[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_WINDOWS_2022_cis) + +### Community 💬 + +On our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users + +--- + +## 🚨 Caution(s) 🚨 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. - Testing is the most important thing you can do. -- 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 RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode. +- Check Mode is not guaranteed! 🚫 The role will complete in check mode without errors, but it is not supported and should be used with caution. - 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 +- To use release version please point to main branch and relevant release for the cis benchmark you wish to work with. - Did we mention testing?? --- +## Coming From A Previous Release ⏪ + +CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. +This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. + +Further details can be seen in the [Changelog](./ChangeLog.md) + +--- + ## Matching a security Level for CIS It is possible to to only run level 1 or level 2 controls for CIS. @@ -71,14 +105,34 @@ This is managed using tags: The control found in defaults main also need to reflect this as this control the testing that takes place if you are using the audit component. -## Coming from a previous release +--- +## Requirements ✅ -CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release. -This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly. +**General:** -Further details can be seen in the [Changelog](./Changelog.md) +- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible -## Auditing (new) + - [Main Ansible documentation page](https://docs.ansible.com) + - [Ansible Getting Started](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html) + - [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) + - [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html) +- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup. +- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. + +**Technical Dependencies:** + +RHEL Family OS 9 + +- 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.8 +- Ansible 2.12+ +- python-def +- libselinux-python + +--- + +## Auditing 🔍 This can be turned on or off within the defaults/main.yml file with the variable run_audit. The value is false by default, please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role. @@ -109,7 +163,7 @@ PLAY RECAP ********************************************************************* default : ok=270 changed=23 unreachable=0 failed=0 skipped=140 rescued=0 ignored=0 ``` -## Documentation +## Documentation 📖 - [Read The Docs](https://ansible-lockdown.readthedocs.io/en/latest/) - [Getting Started](https://www.lockdownenterprise.com/docs/getting-started-with-lockdown#GH_AL_RH9_cis) @@ -117,38 +171,32 @@ default : ok=270 changed=23 unreachable=0 failed=0 s - [Per-Host Configuration](https://www.lockdownenterprise.com/docs/per-host-lockdown-enterprise-configuration#GH_AL_RH9_cis) - [Getting the Most Out of the Role](https://www.lockdownenterprise.com/docs/get-the-most-out-of-lockdown-enterprise#GH_AL_RH9_cis) -## Requirements - -**General:** - -- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible - - - [Main Ansible documentation page](https://docs.ansible.com) - - [Ansible Getting Started](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html) - - [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html) - - [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html) -- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup. -- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file. - -**Technical Dependencies:** - -RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported. - -- 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.8 -- Ansible 2.12+ -- python-def -- libselinux-python ## Role Variables This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main.yml file or with extra vars within the project, job, workflow, etc. -## Tags +## Tags 🏷️ -There are many tags available for added control precision. Each control has it's own set of tags noting what level, if it's scored/notscored, what OS element it relates to, if it's a patch or audit, and the rule number. +There are many tags available for added control precision. Each control has its own set of tags noting what level, what OS element it relates to, whether it's a patch or audit, and the rule number. Additionally, NIST references follow a specific conversion format for consistency and clarity. +### Conversion Format for NIST References: + + 1. Standard Prefix: + + - All references are prefixed with "NIST". + + 2. Standard Types: + + - "800-53" references are formatted as NIST800-53. + - "800-53r5" references are formatted as NIST800-53R5 (with 'R' capitalized). + - "800-171" references are formatted as NIST800-171. + + 3. Details: + + - Section and subsection numbers use periods (.) for numeric separators. + - Parenthetical elements are separated by underscores (_), e.g., IA-5(1)(d) becomes IA-5_1_d. + - Subsection letters (e.g., "b") are appended with an underscore. Below is an example of the tag section from a control within this role. Using this example if you set your run to skip all controls with the tag services, this task will be skipped. The opposite can also happen where you run only controls tagged with services. ```sh @@ -162,33 +210,34 @@ Below is an example of the tag section from a control within this role. Using th - rule_2.2.4 ``` -## Community Contribution + +## Community Contribution 🧑‍🤝‍🧑 We encourage you (the community) to contribute to this role. Please read the rules below. -- Your work is done in your own individual branch. Make sure to Signed-off and GPG sign all commits you intend to merge. +- Your work is done in your own individual branch. Make sure to Signed-off-by and GPG sign all commits you intend to merge. - All community Pull Requests are pulled into the devel branch -- Pull Requests into devel will confirm your commits have a GPG signature, Signed-off, and a functional test before being approved +- Pull Requests into devel will confirm your commits have a GPG signature, Signed-off-by, and a functional test before being approved - Once your changes are merged and a more detailed review is complete, an authorized member will merge your changes into the main branch for a new release +## Pipeline Testing 🔄 + +uses: + +- ansible-core 2.16 +- ansible collections - pulls in the latest version based on requirements file +- runs the audit using the devel branch +- This is an automated test that occurs on pull requests into devel +- self-hosted runners using OpenTofu + ## Known Issues Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow gpgcheck(rule_1.2.1.2) or repo_gpgcheck (rule_1.2.1.3) this will cause issues during the playbook unless or a workaround is found. -## Pipeline Testing -uses: +## Local Testing 💻 -- ansible-core 2.12 -- ansible collections - pulls in the latest version based on requirements file -- runs the audit using the devel branch -- This is an automated test that occurs on pull requests into devel - -## Local Testing - -Molecule can be used to work on this role and test in distinct _scenarios_. - -### examples +### example ```bash molecule test -s default @@ -198,24 +247,15 @@ molecule verify -s localhost local testing uses: -- ansible 2.13.3 +- ansible-core - molecule 4.0.1 - molecule-docker 2.0.0 - molecule-podman 2.0.2 - molecule-vagrant 1.0.0 - molecule-azure 0.5.0 -## Added Extras -- [pre-commit](https://pre-commit.com) can be tested and can be run from within the directory - -```sh -pre-commit run -``` - -## Credits and Thanks - -Based on an original concept by Sam Doran +## Credits and Thanks 🙏 Massive thanks to the fantastic community and all its members. From 64e7aab306b81d5de857cb414ba040432bdabfde Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 13:48:29 +0100 Subject: [PATCH 301/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index 85eab9c..4d9dc7c 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,6 +6,7 @@ - addressed issue #393 thank you to @fragglexarmy - addressed issue #394 thank you to @dbeuker - addressed issues #390 and #391 thanks to @polski-g +- addressed issue #398 thanks to trumbaut - Added max-concurrent options for audit - work flow updates - audit logic improvements From 4c91e7477fa1f7194f80de9cd00ec765d4690a93 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 2 Oct 2025 13:59:03 +0100 Subject: [PATCH 302/327] fixed typos Signed-off-by: Mark Bolwell --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 5c75173..65a8fca 100644 --- a/README.md +++ b/README.md @@ -58,9 +58,9 @@ ## Looking for support? 🤝 -[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_WINDOWS_2022_cis) +[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_RHEL9-CIS) -[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_WINDOWS_2022_cis) +[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_RHEL9-CIS) ### Community 💬 @@ -95,7 +95,7 @@ Further details can be seen in the [Changelog](./ChangeLog.md) ## Matching a security Level for CIS -It is possible to to only run level 1 or level 2 controls for CIS. +It is possible to only run level 1 or level 2 controls for CIS. This is managed using tags: - level1-server From 9df94973d72687e31855446045deee5417adbf48 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 3 Oct 2025 07:56:30 +0100 Subject: [PATCH 303/327] added badge workflows Signed-off-by: Mark Bolwell --- .../benchmark_tracking_controller.yml | 38 +++++++++++++++++++ .github/workflows/export_badges_private.yml | 27 +++++++++++++ .github/workflows/export_badges_public.yml | 19 ++++++++++ 3 files changed, 84 insertions(+) create mode 100644 .github/workflows/benchmark_tracking_controller.yml create mode 100644 .github/workflows/export_badges_private.yml create mode 100644 .github/workflows/export_badges_public.yml diff --git a/.github/workflows/benchmark_tracking_controller.yml b/.github/workflows/benchmark_tracking_controller.yml new file mode 100644 index 0000000..0d9f515 --- /dev/null +++ b/.github/workflows/benchmark_tracking_controller.yml @@ -0,0 +1,38 @@ +--- + +# GitHub schedules all cron jobs in UTC. +# This expression will run the job every day at 9 AM Eastern Time during Daylight Saving Time (mid-March to early November). +# This expression will run the job every day at 8 AM Eastern Time during Standard Time (early November to mid-March). + +name: Central Benchmark Orchestrator + +on: + push: + branches: + - latest + schedule: + - cron: '0 6 * * *' # Runs daily at 9 AM ET + workflow_dispatch: + +jobs: + call-benchmark-tracker: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'latest') + name: Start Benchmark Tracker + uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_track.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }} + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} + + call-monitor-promotions: + if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + name: Monitor Promotions and Auto-Promote + uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_promote.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + TEAMS_WEBHOOK_URL: ${{ secrets.TEAMS_WEBHOOK_URL }} + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} + DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} diff --git a/.github/workflows/export_badges_private.yml b/.github/workflows/export_badges_private.yml new file mode 100644 index 0000000..d316cbf --- /dev/null +++ b/.github/workflows/export_badges_private.yml @@ -0,0 +1,27 @@ +--- + +name: Export Private Repo Badges + +# Use different minute offsets with the same hourly pattern: +# Repo Group Suggested Cron Expression Explanation +# Group A 0 */6 * * * Starts at top of hour +# Group B 10 */6 * * * Starts at 10 after +# And So On + +on: + push: + branches: + - latest + schedule: + - cron: '0 */6 * * *' + workflow_dispatch: + +jobs: + export-badges: + if: github.event_name == 'workflow_dispatch' || (github.event_name == 'schedule' && startsWith(github.repository, 'ansible-lockdown/Private-')) || (github.event_name == 'push' && github.ref_name == 'latest') + uses: ansible-lockdown/github_linux_IaC/.github/workflows/export_badges_private.yml@self_hosted + with: + # Full org/repo path passed for GitHub API calls (e.g., ansible-lockdown/Private-Windows-2016-CIS) + repo_name: ${{ github.repository }} + secrets: + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} diff --git a/.github/workflows/export_badges_public.yml b/.github/workflows/export_badges_public.yml new file mode 100644 index 0000000..fa4b27f --- /dev/null +++ b/.github/workflows/export_badges_public.yml @@ -0,0 +1,19 @@ +--- + +name: Export Public Repo Badges + +on: + push: + branches: + - main + - devel + workflow_dispatch: + +jobs: + export-badges: + if: github.repository_visibility == 'public' && (github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && (github.ref_name == 'devel' || github.ref_name == 'main'))) + uses: ansible-lockdown/github_linux_IaC/.github/workflows/export_badges_public.yml@self_hosted + with: + repo_name: ${{ github.repository }} + secrets: + BADGE_PUSH_TOKEN: ${{ secrets.BADGE_PUSH_TOKEN }} From 6500e39f4265eb7e7f2ebd414c0d4def366585d9 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 3 Oct 2025 08:19:07 +0100 Subject: [PATCH 304/327] Added fix for #399 thanks to @trumbaut Signed-off-by: Mark Bolwell --- Changelog.md | 2 +- tasks/section_5/cis_5.1.x.yml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Changelog.md b/Changelog.md index 4d9dc7c..d4b1b78 100644 --- a/Changelog.md +++ b/Changelog.md @@ -6,7 +6,7 @@ - addressed issue #393 thank you to @fragglexarmy - addressed issue #394 thank you to @dbeuker - addressed issues #390 and #391 thanks to @polski-g -- addressed issue #398 thanks to trumbaut +- addressed issue #398 & #399 thanks to trumbaut - Added max-concurrent options for audit - work flow updates - audit logic improvements diff --git a/tasks/section_5/cis_5.1.x.yml b/tasks/section_5/cis_5.1.x.yml index 42ca036..dc450ea 100644 --- a/tasks/section_5/cis_5.1.x.yml +++ b/tasks/section_5/cis_5.1.x.yml @@ -41,8 +41,8 @@ ansible.builtin.file: path: "{{ item.path }}" owner: root - group: root - mode: 'u-x,go-rwx' + group: "{{ 'ssh_keys' if (item.gr_name == 'ssh_keys') else 'root' }}" + mode: "{{ 'u-x,g-wx,o-rwx' if (item.gr_name == 'ssh_keys') else 'u-x,go-rwx' }}" loop: "{{ discovered_ssh_private_host_key.files }}" loop_control: label: "{{ item.path }}" From de4b2cfa5cf80371436abb74f40bad59a68479c0 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 6 Oct 2025 17:51:08 +0000 Subject: [PATCH 305/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.9.0 → v25.9.1](https://github.com/ansible-community/ansible-lint/compare/v25.9.0...v25.9.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 7fd561a..e633b2a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.9.0 + rev: v25.9.1 hooks: - id: ansible-lint name: Ansible-lint From 51668530a951cea132383eb884a2f4150e23425d Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 9 Oct 2025 14:10:29 -0400 Subject: [PATCH 306/327] update workflow benchmark_tracking_controller Signed-off-by: Frederick Witty --- .../benchmark_tracking_controller.yml | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/.github/workflows/benchmark_tracking_controller.yml b/.github/workflows/benchmark_tracking_controller.yml index 0d9f515..039ec0d 100644 --- a/.github/workflows/benchmark_tracking_controller.yml +++ b/.github/workflows/benchmark_tracking_controller.yml @@ -1,8 +1,22 @@ --- # GitHub schedules all cron jobs in UTC. -# This expression will run the job every day at 9 AM Eastern Time during Daylight Saving Time (mid-March to early November). -# This expression will run the job every day at 8 AM Eastern Time during Standard Time (early November to mid-March). +# ────────────────────────────────────────────────────────────────────────────── +# Schedule: +# - '0 13 * * *' runs at 13:00 UTC every day. +# - This corresponds to: +# • 9:00 AM Eastern **during Daylight Saving Time** (mid-Mar → early-Nov) +# • 8:00 AM Eastern **during Standard Time** (early-Nov → mid-Mar) +# +# Job routing: +# - call-benchmark-tracker: +# • Runs on manual dispatch, and on pushes to the 'latest' branch. +# - call-monitor-promotions: +# • Runs on schedule or manual dispatch **only in repos named ansible-lockdown/Private-***. +# • Skips automatically in public repos (e.g., Windows-2022-CIS) to avoid false failures. +# +# Defense-in-depth: +# - The called promotion workflow may still keep its own guard to ensure only Private-* repos execute it. name: Central Benchmark Orchestrator @@ -11,11 +25,12 @@ on: branches: - latest schedule: - - cron: '0 6 * * *' # Runs daily at 9 AM ET + - cron: '0 13 * * *' # 13:00 UTC → 9 AM ET (DST) / 8 AM ET (Standard Time) workflow_dispatch: jobs: call-benchmark-tracker: + # Run on manual dispatch OR when 'latest' branch receives a push if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && github.ref_name == 'latest') name: Start Benchmark Tracker uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_track.yml@self_hosted @@ -27,7 +42,8 @@ jobs: DISCORD_WEBHOOK_URL: ${{ secrets.DISCORD_WEBHOOK_URL }} call-monitor-promotions: - if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch' + # Run on schedule or manual dispatch, but only for Private-* repos + if: (github.event_name == 'schedule' || github.event_name == 'workflow_dispatch') && startsWith(github.repository, 'ansible-lockdown/Private-') name: Monitor Promotions and Auto-Promote uses: ansible-lockdown/github_linux_IaC/.github/workflows/benchmark_promote.yml@self_hosted with: From 451dce8aa79ac8e9b89584e2390d18d6cddcbeb1 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 13 Oct 2025 17:38:43 +0000 Subject: [PATCH 307/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.9.1 → v25.9.2](https://github.com/ansible-community/ansible-lint/compare/v25.9.1...v25.9.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e633b2a..0091b2a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.9.1 + rev: v25.9.2 hooks: - id: ansible-lint name: Ansible-lint From 278813694bf95e426743dc728fcb6661fa91ac80 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:23:56 +0100 Subject: [PATCH 308/327] Updated permissions Signed-off-by: Mark Bolwell --- .github/workflows/devel_pipeline_validation.yml | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index deac4d7..8fd728a 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -17,12 +17,6 @@ # 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: @@ -30,6 +24,10 @@ welcome: runs-on: ubuntu-latest + permissions: + issues: write + pull-requests: write + steps: - uses: actions/first-interaction@main with: @@ -45,6 +43,13 @@ playbook-test: # The type of runner that the job will run on runs-on: self-hosted + + # Allow permissions for AWS auth + permissions: + id-token: write + contents: read + pull-requests: read + env: ENABLE_DEBUG: ${{ vars.ENABLE_DEBUG }} # Imported as a variable by terraform From afcfda9ef06d8e40b0b6f3de8f02217e604f2d3c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:24:49 +0100 Subject: [PATCH 309/327] compliant with 2.19 Signed-off-by: Mark Bolwell --- templates/audit/99_auditd.rules.j2 | 98 +++++------------------------- 1 file changed, 14 insertions(+), 84 deletions(-) diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4fa4516..c3c2b6c 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -10,12 +10,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_2 %} {% set syscalls = ["execve"] %} -{% set arch_syscalls = [] %} -{%- for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor -%} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation -a always,exit -F arch=b32 -C euid!=uid -F auid!=unset -S {{ arch_syscalls|join(',') }} -k user_emulation {% endif %} @@ -24,33 +19,18 @@ {% endif %} {% if rhel9cis_rule_6_3_3_4 %} {% set syscalls = ["adjtimex","settimeofday"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k time-change -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k time-change {% set syscalls = ["clock_settime"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F a0=0x0 -k time-change -{% endif %} -{% endfor %} -w /etc/localtime -p wa -k time-change {% endif %} {% if rhel9cis_rule_6_3_3_5 %} {% set syscalls = ["sethostname","setdomainname"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k system-locale -w /etc/issue -p wa -k system-locale @@ -68,12 +48,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_7 %} {% set syscalls = ["creat","open","openat","truncate","ftruncate"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F exit=-EPERM -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F exit=-EACCES -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k access @@ -91,62 +66,27 @@ {% endif %} {% if rhel9cis_rule_6_3_3_9 %} {% set syscalls = ["chmod","fchmod","fchmodat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chmod","fchmod","fchmodat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["chown","fchown","lchown","fchownat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k perm_mod {% endif %} {% if rhel9cis_rule_6_3_3_10 %} {% set syscalls = ["mount"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append(syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k mounts {% endif %} @@ -161,12 +101,7 @@ {% endif %} {% if rhel9cis_rule_6_3_3_13 %} {% set syscalls = ["unlink","unlinkat","rename","renameat"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete -a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k delete {% endif %} @@ -189,12 +124,7 @@ {% if rhel9cis_rule_6_3_3_19 %} -a always,exit -F path=/usr/bin/kmod -F perm=x -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% set syscalls = ["init_module","finit_module","delete_module","create_module","query_module"] %} -{% set arch_syscalls = [] %} -{% for syscall in syscalls %} -{% if syscall in supported_syscalls %} -{{ arch_syscalls.append( syscall) }} -{% endif %} -{% endfor %} +{% set arch_syscalls = syscalls | select("in", supported_syscalls) | list %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>={{ prelim_min_int_uid }} -F auid!=unset -k kernel_modules {% endif %} {% if rhel9cis_rule_6_3_3_20 %} From f8cdf84e95a45525444100041fd00629960ab657 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:26:07 +0100 Subject: [PATCH 310/327] Added benchmark_version variable Signed-off-by: Mark Bolwell --- templates/ansible_vars_goss.yml.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/ansible_vars_goss.yml.j2 b/templates/ansible_vars_goss.yml.j2 index 7cb906b..cbaa125 100644 --- a/templates/ansible_vars_goss.yml.j2 +++ b/templates/ansible_vars_goss.yml.j2 @@ -37,7 +37,7 @@ rhel9cis_legacy_boot: {{ rhel9cis_legacy_boot }} ## Benchmark name used by auditing control role # The audit variable found at the base ## metadata for Audit benchmark -benchmark_version: 'v2.0.0' +benchmark_version: {{ benchmark_version }} benchmark: RHEL9-CIS From ea17b0adc23e272801ef31a67592bee5042b8899 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:26:42 +0100 Subject: [PATCH 311/327] removed legacy option Signed-off-by: Mark Bolwell --- defaults/main.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index ed14e51..fbe81eb 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -94,8 +94,6 @@ audit_max_concurrent: 50 ## 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 in audit_only mode -fetch_audit_files: false # 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 ############################# From 5354111505c088b47fb53689363fbd4b8e451345 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:27:27 +0100 Subject: [PATCH 312/327] improved audit logic Signed-off-by: Mark Bolwell --- tasks/pre_remediation_audit.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tasks/pre_remediation_audit.yml b/tasks/pre_remediation_audit.yml index dd9efb4..410473e 100644 --- a/tasks/pre_remediation_audit.yml +++ b/tasks/pre_remediation_audit.yml @@ -85,6 +85,7 @@ - name: Pre Audit | Capture audit data if json format ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4 changed_when: false + failed_when: pre_audit_summary.stderr | length > 0 register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary @@ -97,6 +98,7 @@ - name: Pre Audit | Capture audit data if documentation format ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' ' changed_when: false + failed_when: pre_audit_summary.stderr | length > 0 register: pre_audit_summary - name: Pre Audit | Set Fact for audit summary From 8ec8ebc8167ef99946ab4d7a7950c8b0b82fca9c Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Thu, 16 Oct 2025 15:29:26 +0100 Subject: [PATCH 313/327] updated Signed-off-by: Mark Bolwell --- Changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Changelog.md b/Changelog.md index d4b1b78..737f860 100644 --- a/Changelog.md +++ b/Changelog.md @@ -10,6 +10,7 @@ - Added max-concurrent options for audit - work flow updates - audit logic improvements +- auditd template 2.19 compatible ## 2.0.3 - Based on CIS v2.0.0 - addressed issue #387, thank you @fragglexarmy From e1dd9fd283b7b92cc74846a0feb6dbbb01ef5fbc Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 16 Oct 2025 15:12:19 -0400 Subject: [PATCH 314/327] Add workflow to auto add new issues to project Signed-off-by: Frederick Witty --- .../workflows/add_repo_issue_to_gh_project.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 .github/workflows/add_repo_issue_to_gh_project.yml diff --git a/.github/workflows/add_repo_issue_to_gh_project.yml b/.github/workflows/add_repo_issue_to_gh_project.yml new file mode 100644 index 0000000..4a056eb --- /dev/null +++ b/.github/workflows/add_repo_issue_to_gh_project.yml @@ -0,0 +1,17 @@ +--- + +name: Add Repo Issue to ALD GH project +on: + issues: + types: + - opened + - reopened + - transferred +jobs: + add-to-project: + runs-on: ubuntu-latest + steps: + - uses: actions/add-to-project@main + with: + project-url: https://github.com/orgs/ansible-lockdown/projects/1 + github-token: ${{ secrets.GITHUB_TOKEN }} From 4c41656a3b642c3ba620b4df5eaafd7f3f382f7b Mon Sep 17 00:00:00 2001 From: Frederick Witty Date: Thu, 23 Oct 2025 08:28:06 -0400 Subject: [PATCH 315/327] .github standardization Signed-off-by: Frederick Witty --- .../add_repo_issue_to_gh_project.yml | 2 +- .github/workflows/update_galaxy.yml | 19 ------------------- 2 files changed, 1 insertion(+), 20 deletions(-) delete mode 100644 .github/workflows/update_galaxy.yml diff --git a/.github/workflows/add_repo_issue_to_gh_project.yml b/.github/workflows/add_repo_issue_to_gh_project.yml index 4a056eb..80d7344 100644 --- a/.github/workflows/add_repo_issue_to_gh_project.yml +++ b/.github/workflows/add_repo_issue_to_gh_project.yml @@ -14,4 +14,4 @@ jobs: - uses: actions/add-to-project@main with: project-url: https://github.com/orgs/ansible-lockdown/projects/1 - github-token: ${{ secrets.GITHUB_TOKEN }} + github-token: ${{ secrets.ALD_GH_PROJECT }} diff --git a/.github/workflows/update_galaxy.yml b/.github/workflows/update_galaxy.yml deleted file mode 100644 index b6ee6a1..0000000 --- a/.github/workflows/update_galaxy.yml +++ /dev/null @@ -1,19 +0,0 @@ ---- - - name: update galaxy - - on: - push: - branches: - - main - jobs: - update_role: - runs-on: ubuntu-latest - steps: - - name: Checkout repo - uses: actions/checkout@v4 - - - name: Action Ansible Galaxy Release ${{ github.ref_name }} - uses: ansible-actions/ansible-galaxy-action@main - with: - galaxy_api_key: ${{ secrets.GALAXY_API_KEY }} From 0ec943073cad7d805b08cdbc11bf8c925e2611ae Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 17:45:49 +0000 Subject: [PATCH 316/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.28.0 → v8.29.0](https://github.com/gitleaks/gitleaks/compare/v8.28.0...v8.29.0) - [github.com/ansible-community/ansible-lint: v25.9.2 → v25.11.0](https://github.com/ansible-community/ansible-lint/compare/v25.9.2...v25.11.0) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0091b2a..4aa6519 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.28.0 + rev: v8.29.0 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.9.2 + rev: v25.11.0 hooks: - id: ansible-lint name: Ansible-lint From 539ac4f5cc6b1646ed18343d6915dbef60c894d8 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 24 Nov 2025 17:42:03 +0000 Subject: [PATCH 317/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.29.0 → v8.29.1](https://github.com/gitleaks/gitleaks/compare/v8.29.0...v8.29.1) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 4aa6519..9d80577 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,7 +41,7 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.29.0 + rev: v8.29.1 hooks: - id: gitleaks From 72602c63fade97c61e2845f3beae665d98580f1e Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Tue, 25 Nov 2025 09:28:00 +0000 Subject: [PATCH 318/327] add fix provided by @kpi-nourman via discord community Signed-off-by: Mark Bolwell --- templates/etc/dconf/db/gdm.d/01-banner-message.j2 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 index 901e9e0..ec42bfc 100644 --- a/templates/etc/dconf/db/gdm.d/01-banner-message.j2 +++ b/templates/etc/dconf/db/gdm.d/01-banner-message.j2 @@ -4,4 +4,4 @@ [org/gnome/login-screen] banner-message-enable=true -banner-message-text="{{ rhel9cis_warning_banner }}" +banner-message-text="{{ rhel9cis_warning_banner | trim | replace("\n", "\\n") }}" From 52452b1e3c71d6fbb427edbc477234174420df16 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Fri, 28 Nov 2025 14:51:43 +0000 Subject: [PATCH 319/327] issues 413 addressed thansk to @bbaassssiiee Signed-off-by: Mark Bolwell --- Changelog.md | 4 +++- tasks/main.yml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Changelog.md b/Changelog.md index 737f860..ac9c3b6 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,5 @@ # Changes to rhel9CIS - ## 2.0.4 - Based on CIS v2.0.0 - addressed issue #393 thank you to @fragglexarmy @@ -11,6 +10,9 @@ - work flow updates - audit logic improvements - auditd template 2.19 compatible +- pre-commit updates +- #410 thanks to @kpi-nourman +- #413 thanks to @bbaassssiiee ## 2.0.3 - Based on CIS v2.0.0 - addressed issue #387, thank you @fragglexarmy diff --git a/tasks/main.yml b/tasks/main.yml index 760ee1b..6f97141 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,7 +134,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Password set|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(\*LOCK\*|Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From 571711f11e0d8a988fee79a2f24eaf918768add4 Mon Sep 17 00:00:00 2001 From: Mark Bolwell Date: Mon, 1 Dec 2025 10:23:25 +0000 Subject: [PATCH 320/327] updated with correct fix thanks to @bbaassssiiee Signed-off-by: Mark Bolwell --- tasks/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/main.yml b/tasks/main.yml index 6f97141..4d1887d 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -134,7 +134,7 @@ - rule_5.4.2.4 block: - name: "Ensure root password is set" - ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(\*LOCK\*|Password set|Password locked)" + ansible.builtin.shell: LC_ALL=C passwd -S root | grep -E "(Alternate authentication|Password set|Password locked)" changed_when: false failed_when: prelim_root_passwd_set.rc not in [ 0, 1 ] register: prelim_root_passwd_set From 322404a6921f2709b4066e3745c7dc5d181314e3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Dec 2025 17:41:29 +0000 Subject: [PATCH 321/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/gitleaks/gitleaks: v8.29.1 → v8.30.0](https://github.com/gitleaks/gitleaks/compare/v8.29.1...v8.30.0) - [github.com/ansible-community/ansible-lint: v25.11.0 → v25.12.1](https://github.com/ansible-community/ansible-lint/compare/v25.11.0...v25.12.1) --- .pre-commit-config.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 9d80577..255180a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.29.1 + rev: v8.30.0 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.11.0 + rev: v25.12.1 hooks: - id: ansible-lint name: Ansible-lint From 62989d258b5af00fd190299d002b95635e9b8284 Mon Sep 17 00:00:00 2001 From: George Nalen Date: Fri, 19 Dec 2025 16:31:37 -0500 Subject: [PATCH 322/327] added fix to issue #416 Signed-off-by: George Nalen --- templates/etc/sysctl.d/60-disable_ipv6.conf.j2 | 3 +++ 1 file changed, 3 insertions(+) diff --git a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 index bdded40..b4b5318 100644 --- a/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 +++ b/templates/etc/sysctl.d/60-disable_ipv6.conf.j2 @@ -4,4 +4,7 @@ {% if rhel9cis_rule_3_1_1 and not rhel9cis_ipv6_required %} net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 +{% for interface in ansible_interfaces %} +net.ipv6.conf.{{ interface }}.disable_ipv6 = 1 +{% endfor %} {% endif %} From 96474159ab282aad770e038870fad2d5cfacec69 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 22 Dec 2025 17:33:38 +0000 Subject: [PATCH 323/327] [pre-commit.ci] pre-commit autoupdate MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit updates: - [github.com/ansible-community/ansible-lint: v25.12.1 → v25.12.2](https://github.com/ansible-community/ansible-lint/compare/v25.12.1...v25.12.2) --- .pre-commit-config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 255180a..dbc1d7e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -46,7 +46,7 @@ repos: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.12.1 + rev: v25.12.2 hooks: - id: ansible-lint name: Ansible-lint From beb3bfdc94ea94903bb82a3cba0d89d84c7ce60f Mon Sep 17 00:00:00 2001 From: George Nalen Date: Mon, 22 Dec 2025 16:35:08 -0500 Subject: [PATCH 324/327] added option for sysctl or kernel for disabling IPv6 Signed-off-by: George Nalen --- defaults/main.yml | 2 ++ tasks/section_3/cis_3.1.x.yml | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/defaults/main.yml b/defaults/main.yml index fbe81eb..2ad3eb2 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -802,6 +802,8 @@ rhel9cis_tftp_client: false ## Control 3.1.1 - Ensure IPv6 status is identified # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: true +# rhel9cis_ipv6_disable defines the method of disabling IPv6, sysctl vs kernel +rhel9cis_ipv6_disable: "sysctl" ## Control 3.1.2 - Ensure wireless interfaces are disabled # if wireless adapter found allow network manager to be installed diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index a20c0e9..6cd73f3 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -16,14 +16,29 @@ - rule_3.1.1 - NIST800-53R5_CM-7 block: - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh" + - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Set vars for sysctl template" + when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.set_fact: rhel9cis_sysctl_update: true rhel9cis_flush_ipv6_route: true - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable" + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable via sysctl template" + when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" + + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Find IPv6 status" + when: "'kernel' in rhel9cis_ipv6_disable_method" + ansible.builtin.command: grubby --info=ALL + changed_when: false + failed_when: false + register: discovered_rhel9cis_3_1_1_ipv6_status + + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Disable IPV6 via Kernel" + when: + - "'kernel' in rhel9cis_ipv6_disable_method" + - "'ipv6.disable=1' not in discovered_rhel9cis_3_1_1_ipv6_status.stdout" + ansible.builtin.shell: grubby --update-kernel=ALL --args="ipv6.disable=1" - name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled" when: From 2b7c8293b83667c853b44df0bd2bf38217695401 Mon Sep 17 00:00:00 2001 From: George Nalen Date: Mon, 22 Dec 2025 16:56:24 -0500 Subject: [PATCH 325/327] fixed linting issue Signed-off-by: George Nalen --- tasks/section_3/cis_3.1.x.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 6cd73f3..0c9c374 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -26,7 +26,7 @@ when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" - + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Find IPv6 status" when: "'kernel' in rhel9cis_ipv6_disable_method" ansible.builtin.command: grubby --info=ALL From d9927f005bc09bd172c94d51096cfe2a68e386af Mon Sep 17 00:00:00 2001 From: George Nalen Date: Tue, 23 Dec 2025 08:42:28 -0500 Subject: [PATCH 326/327] fixed typo in disable method var Signed-off-by: George Nalen --- defaults/main.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/defaults/main.yml b/defaults/main.yml index 2ad3eb2..f620a72 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -803,7 +803,7 @@ rhel9cis_tftp_client: false # This variable governs whether ipv6 is enabled or disabled. rhel9cis_ipv6_required: true # rhel9cis_ipv6_disable defines the method of disabling IPv6, sysctl vs kernel -rhel9cis_ipv6_disable: "sysctl" +rhel9cis_ipv6_disable_method: "sysctl" ## Control 3.1.2 - Ensure wireless interfaces are disabled # if wireless adapter found allow network manager to be installed From 29a48f7f4cc0c794760a0f1b4a8da2c92ac7d35d Mon Sep 17 00:00:00 2001 From: George Nalen Date: Tue, 23 Dec 2025 09:04:42 -0500 Subject: [PATCH 327/327] updated name info for tasks related to 3.1.1 Signed-off-by: George Nalen --- tasks/section_3/cis_3.1.x.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tasks/section_3/cis_3.1.x.yml b/tasks/section_3/cis_3.1.x.yml index 0c9c374..ff9ec46 100644 --- a/tasks/section_3/cis_3.1.x.yml +++ b/tasks/section_3/cis_3.1.x.yml @@ -16,18 +16,18 @@ - rule_3.1.1 - NIST800-53R5_CM-7 block: - - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Set vars for sysctl template" + - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Set vars for sysctl template" when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.set_fact: rhel9cis_sysctl_update: true rhel9cis_flush_ipv6_route: true - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable via sysctl template" + - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Message out implementation info" when: "'sysctl' in rhel9cis_ipv6_disable_method" ansible.builtin.debug: msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf" - - name: "3.1.1 | PATCH | Ensure IPv6 status is identified | Find IPv6 status" + - name: "3.1.1 | AUDIT | Ensure IPv6 status is identified | Find IPv6 status" when: "'kernel' in rhel9cis_ipv6_disable_method" ansible.builtin.command: grubby --info=ALL changed_when: false