Merge pull request #205 from ansible-lockdown/devel

Release to main
This commit is contained in:
uk-bolly 2024-05-01 13:53:19 +01:00 committed by GitHub
commit 7661bc0963
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
70 changed files with 1509 additions and 715 deletions

View file

@ -6,12 +6,10 @@ skip_list:
- 'schema'
- 'no-changed-when'
- 'var-spacing'
- 'fqcn-builtins'
- 'experimental'
- 'name[play]'
- 'name[casing]'
- 'name[template]'
- 'fqcn[action]'
- 'key-order[task]'
- '204'
- '305'

View file

@ -75,10 +75,6 @@
{
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
},
{
"path": "detect_secrets.filters.common.is_baseline_file",
"filename": ".config/.secrets.baseline"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
@ -113,64 +109,11 @@
{
"path": "detect_secrets.filters.regex.should_exclude_file",
"pattern": [
".config/.gitleaks-report.json"
".config/.gitleaks-report.json",
"tasks/parse_etc_password.yml"
]
}
],
"results": {
"defaults/main.yml": [
{
"type": "Secret Keyword",
"filename": "defaults/main.yml",
"hashed_secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"is_verified": false,
"line_number": 364,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "defaults/main.yml",
"hashed_secret": "fe96f7cfa2ab2224e7d015067a6f6cc713f7012e",
"is_verified": false,
"line_number": 375,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "defaults/main.yml",
"hashed_secret": "a415ab5cc17c8c093c015ccdb7e552aee7911aa4",
"is_verified": false,
"line_number": 376,
"is_secret": false
}
],
"tasks/main.yml": [
{
"type": "Secret Keyword",
"filename": "tasks/main.yml",
"hashed_secret": "2478fefdceefe2847c3aa36dc731aaad5b3cc2fb",
"is_verified": false,
"line_number": 38,
"is_secret": false
},
{
"type": "Secret Keyword",
"filename": "tasks/main.yml",
"hashed_secret": "64411efd0f0561fe4852c6e414071345c9c6432a",
"is_verified": false,
"line_number": 110,
"is_secret": false
}
],
"tasks/parse_etc_password.yml": [
{
"type": "Secret Keyword",
"filename": "tasks/parse_etc_password.yml",
"hashed_secret": "2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360",
"is_verified": false,
"line_number": 18
}
]
},
"generated_at": "2023-08-10T12:54:13Z"
"results": {},
"generated_at": "2023-09-21T14:11:05Z"
}

View file

@ -27,9 +27,9 @@
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://discord.io/ansible-lockdown) as well.
Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well.
# This workflow contains a single job which tests the playbook
# 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
@ -44,13 +44,13 @@
steps:
- name: Clone ${{ github.event.repository.name }}
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Pull in terraform code for linux servers
- name: Clone github IaC plan
uses: actions/checkout@v3
- name: Clone GitHub IaC plan
uses: actions/checkout@v4
with:
repository: ansible-lockdown/github_linux_IaC
path: .github/workflows/github_linux_IaC
@ -74,7 +74,7 @@
pwd
ls
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -82,7 +82,7 @@
id: init
run: terraform init
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -90,7 +90,7 @@
id: validate
run: terraform validate
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -111,9 +111,9 @@
# Aws deployments taking a while to come up insert sleep or playbook fails
- name: Sleep for 60 seconds
run: sleep 60s
run: sleep ${{ vars.BUILD_SLEEPTIME }}
# Run the ansible playbook
# Run the Ansibleplaybook
- name: Run_Ansible_Playbook
uses: arillso/action.playbook@master
with:
@ -125,6 +125,7 @@
env:
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_DEPRECATION_WARNINGS: "false"
ANSIBLE_INJECT_FACT_VARS: "false"
# Remove test system - User secrets to keep if necessary

View file

@ -18,7 +18,7 @@
# that can run sequentially or in parallel
jobs:
# This workflow contains a single job which tests the playbook
# 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
@ -33,13 +33,13 @@
steps:
- name: Clone ${{ github.event.repository.name }}
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
# Pull in terraform code for linux servers
- name: Clone github IaC plan
uses: actions/checkout@v3
- name: Clone GitHub IaC plan
uses: actions/checkout@v4
with:
repository: ansible-lockdown/github_linux_IaC
path: .github/workflows/github_linux_IaC
@ -63,7 +63,7 @@
pwd
ls
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -71,7 +71,7 @@
id: init
run: terraform init
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -79,7 +79,7 @@
id: validate
run: terraform validate
env:
# Imported from github variables this is used to load the relvent OS.tfvars file
# Imported from GitHub variables this is used to load the relevant OS.tfvars file
OSVAR: ${{ vars.OSVAR }}
TF_VAR_benchmark_type: ${{ vars.BENCHMARK_TYPE }}
@ -100,9 +100,9 @@
# Aws deployments taking a while to come up insert sleep or playbook fails
- name: Sleep for 60 seconds
run: sleep 60s
run: sleep ${{ vars.BUILD_SLEEPTIME }}
# Run the ansible playbook
# Run the Ansibleplaybook
- name: Run_Ansible_Playbook
uses: arillso/action.playbook@master
with:
@ -114,6 +114,7 @@
env:
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_DEPRECATION_WARNINGS: "false"
ANSIBLE_INJECT_FACT_VARS: "false"
# Remove test system - User secrets to keep if necessary

View file

@ -1,11 +1,7 @@
---
# This is a basic workflow to help you get started with Actions
name: update galaxy
# Controls when the action will run.
# Triggers the workflow on merge request events to the main branch
on:
push:
branches:
@ -14,8 +10,10 @@ jobs:
update_role:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: robertdebock/galaxy-action@master
- 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 }}
git_branch: main
galaxy_api_key: ${{ secrets.GALAXY_API_KEY }}

View file

@ -7,7 +7,7 @@ ci:
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v3.2.0
rev: v4.6.0
hooks:
# Safety
- id: detect-aws-credentials
@ -37,13 +37,13 @@ repos:
exclude: .config/.gitleaks-report.json
- repo: https://github.com/gitleaks/gitleaks
rev: v8.17.0
rev: v8.18.2
hooks:
- id: gitleaks
args: ['--baseline-path', '.config/.gitleaks-report.json']
- repo: https://github.com/ansible-community/ansible-lint
rev: v6.17.2
rev: v24.2.2
hooks:
- id: ansible-lint
name: Ansible-lint
@ -62,6 +62,6 @@ repos:
- ansible-core>=2.10.1
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.32.0 # or higher tag
rev: v1.35.1 # or higher tag
hooks:
- id: yamllint

View file

@ -30,4 +30,4 @@ rules:
trailing-spaces: enable
truthy:
allowed-values: ['true', 'false']
check-keys: false
check-keys: true

View file

@ -1,5 +1,55 @@
# Changes to rhel9CIS
## 1.1.5 - Based on CIS v1.0.0
- added new interactive user discoveries
- updated controls 6.2.10-6.2.14
- audit
- steps moved to prelim
- update to coipy and archive logic and variables
- removed vars not used
- updated quotes used in mode tasks
- pre-commit update
- issues addressed
- #190 thanks to @ipruteanu-sie
- aligned logic for user shadow suite params (aligned with other repos)
- new variables to force changes to existing users added 5.6.1.1 - 5.6.1.2
- #198 thanks to @brakkio86
## 1.1.4 - Based on CIS v1.0.0
- 1.2.1 new option for a new system to import gpg key for 1.2.1 to pass redhat only
- thanks to @ipruteanu-sie
- #156
- #165
- #180
- #181
- #183
- #184
## 1.1.3 - Based on CIS v1.0.0
- updated goss binary to 0.4.4
- moved majority of audit variables to vars/audit.yml
- new function to enable audit_only using remediation
- removed some dupes in audit config
## 1.1.2 - Based on CIS v1.0.0
- updated audit binary versions - aligned with rhel9-cis-audit
- lint updates
- .secrets updated
- file mode quoted
- updated 5.6.5 thansk to feedback from S!ghs on discord community
## 1.1.1 - Based on CIS v1.0.0
- thanks to @agbrowne
- [#90](https://github.com/ansible-lockdown/RHEL9-CIS/issues/90)
- thanks to @mnasiadka
- [#54](https://github.com/ansible-lockdown/RHEL9-CIS/pull/54)
## 1.1.0
- new workflow configuration
@ -82,7 +132,7 @@ Aligned benchmark audit version with remediate release
## 1.0.1
Control 6_2_16 new variable added thanks to @dulin_gnet on rhel8
Will not follow ynlink in hoe directoris and amend permissions.
Will not follow symlink in home directories and amend permissions.
- rhel_09_6_2_16_home_follow_symlink: false

View file

@ -40,7 +40,7 @@
### Community
Join us on our [Discord Server](https://discord.io/ansible-lockdown) to ask questions, discuss features, or just chat with other Ansible-Lockdown users.
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
@ -132,8 +132,8 @@ os_check: false
- python-def (should be included in RHEL 9)
- libselinux-python
- pip packages
- jmespath ( complete list found in requirements.txt)
- collections found in collections/requirememnts.yml
- jmespath
- collections found in collections/requirements.yml
pre-commit is available if installed on your host for pull request testing.

View file

@ -1,5 +1,14 @@
---
collections:
- 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: ansible.posix
source: https://github.com/ansible-collections/ansible.posix
type: git

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
---
- hosts: all # noqa: name[play]
- name: Apply RHEL9 CIS hardening
hosts: all
become: true
roles:
- role: "{{ playbook_dir }}"

View file

@ -5,12 +5,12 @@
- name: Pre Audit Setup | Set audit package name | 64bit
ansible.builtin.set_fact:
audit_pkg_arch_name: AMD64
when: ansible_machine == "x86_64"
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_machine == "arm64"
when: ansible_facts.machine == "arm64"
- name: Pre Audit Setup | Download audit binary
ansible.builtin.get_url:
@ -19,15 +19,15 @@
owner: root
group: root
checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}"
mode: 0555
mode: '0555'
when:
- get_audit_binary_method == 'download'
- name: Pre Audit Setup | copy audit binary
- name: Pre Audit Setup | Copy audit binary
ansible.builtin.copy:
src: "{{ audit_bin_copy_location }}"
dest: "{{ audit_bin }}"
mode: 0555
mode: '0555'
owner: root
group: root
when:

30
tasks/audit_only.yml Normal file
View file

@ -0,0 +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
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
- name: Audit_only | Show Audit Summary
when:
- audit_only
ansible.builtin.debug:
msg: "The Audit results are: {{ pre_audit_summary }}."
- name: Audit_only | Stop Playbook Audit Only selected
when:
- audit_only
ansible.builtin.meta: end_play

View file

@ -11,7 +11,7 @@
dest: /etc/audit/rules.d/99_auditd.rules
owner: root
group: root
mode: 0640
mode: '0640'
diff: "{{ rhel9cis_auditd_file.stat.exists }}" # Only run diff if not a new file
register: rhel9cis_auditd_template_updated
notify:
@ -20,7 +20,8 @@
- Restart auditd
- name: POST | AUDITD | Add Warning count for changes to template file | Warn Count # noqa no-handler
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: 'Auditd template updated, see diff output for details'
when:
@ -38,7 +39,7 @@
dest: /etc/audit/rules.d/98_auditd_exceptions.rules
owner: root
group: root
mode: 0640
mode: '0640'
diff: "{{ rhel9cis_auditd_exception_file.stat.exists }}"
notify: Restart auditd
when:

View file

@ -3,12 +3,11 @@
- name: Check OS version and family
ansible.builtin.assert:
that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('9', '==')
fail_msg: "This role can only be run against Supported OSs. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported."
success_msg: "This role is running against a supported OS {{ ansible_distribution }} {{ ansible_distribution_major_version }}"
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
- not system_is_ec2
tags:
- always
@ -23,19 +22,36 @@
- 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 | awk -F: '{print $2}'"
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 password set for {{ ansible_env.SUDO_USER }} | Assert password set and not locked"
ansible.builtin.assert:
that: rhel9cis_ansible_user_password_set.stdout | length != 0 and 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"
vars:
sudo_password_rule: rhel9cis_rule_5_3_4
- 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
@ -43,11 +59,13 @@
tags:
- user_passwd
- rule_5.3.4
vars:
sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret
- name: Ensure root password is set
block:
- name: Ensure root password is set
ansible.builtin.shell: passwd -S root | grep "Password set, SHA512 crypt"
ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)"
changed_when: false
register: root_passwd_set
@ -83,7 +101,7 @@
- system_is_container
when:
- ansible_connection == 'docker' or
ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- container_discovery
- always
@ -107,7 +125,7 @@
- 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'
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
@ -122,71 +140,76 @@
- always
- name: Include OS specific variables
ansible.builtin.include_vars: "{{ ansible_distribution }}.yml"
ansible.builtin.include_vars: "{{ ansible_facts.distribution }}.yml"
tags:
- always
- name: Include preliminary steps
ansible.builtin.import_tasks: prelim.yml
ansible.builtin.import_tasks:
file: prelim.yml
tags:
- prelim_tasks
- always
- name: run pre_remediation audit
ansible.builtin.include_tasks: pre_remediation_audit.yml
when:
- run_audit
- name: run Section 1 tasks
ansible.builtin.import_tasks: section_1/main.yml
- name: Run Section 1 tasks
ansible.builtin.import_tasks:
file: section_1/main.yml
when: rhel9cis_section1
tags:
- rhel9cis_section1
- name: run Section 2 tasks
ansible.builtin.import_tasks: section_2/main.yml
- name: Run Section 2 tasks
ansible.builtin.import_tasks:
file: section_2/main.yml
when: rhel9cis_section2
tags:
- rhel9cis_section2
- name: run Section 3 tasks
ansible.builtin.import_tasks: section_3/main.yml
- name: Run Section 3 tasks
ansible.builtin.import_tasks:
file: section_3/main.yml
when: rhel9cis_section3
tags:
- rhel9cis_section3
- name: run Section 4 tasks
ansible.builtin.import_tasks: section_4/main.yml
- name: Run Section 4 tasks
ansible.builtin.import_tasks:
file: section_4/main.yml
when: rhel9cis_section4
tags:
- rhel9cis_section4
- name: run Section 5 tasks
ansible.builtin.import_tasks: section_5/main.yml
- name: Run Section 5 tasks
ansible.builtin.import_tasks:
file: section_5/main.yml
when: rhel9cis_section5
tags:
- rhel9cis_section5
- name: run Section 6 tasks
ansible.builtin.import_tasks: section_6/main.yml
- name: Run Section 6 tasks
ansible.builtin.import_tasks:
file: section_6/main.yml
when: rhel9cis_section6
tags:
- rhel9cis_section6
- name: run auditd logic
ansible.builtin.import_tasks: auditd.yml
- name: Run auditd logic
ansible.builtin.import_tasks:
file: auditd.yml
when: update_audit_template
tags:
- always
- name: run post remediation tasks
ansible.builtin.import_tasks: post.yml
- name: Run post remediation tasks
ansible.builtin.import_tasks:
file: post.yml
tags:
- post_tasks
- always
- name: run post_remediation audit
ansible.builtin.import_tasks: post_remediation_audit.yml
- name: Run post_remediation audit
ansible.builtin.import_tasks:
file: post_remediation_audit.yml
when:
- run_audit

View file

@ -13,7 +13,7 @@
dest: "/etc/sysctl.d/{{ item }}"
owner: root
group: root
mode: 0600
mode: '0600'
register: sysctl_updated
notify: Reload sysctl
loop:
@ -46,7 +46,8 @@
- skip_reboot
- name: "POST | Warning a reboot required but skip option set | warning count"
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- change_requires_reboot
- skip_reboot

View file

@ -1,25 +1,27 @@
---
- name: "Post Audit | Run post_remediation {{ benchmark }} audit"
ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}"
- 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 }}\""
changed_when: true
environment:
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}"
AUDIT_FILE: "goss.yml"
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
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:
- name: "capture data {{ post_audit_outfile }}"
- name: capture data {{ post_audit_outfile }}
ansible.builtin.shell: "cat {{ post_audit_outfile }}"
register: post_audit
changed_when: false
@ -28,13 +30,13 @@
ansible.builtin.set_fact:
post_audit_summary: "{{ post_audit.stdout | from_json | json_query(summary) }}"
vars:
summary: 'summary."summary-line"'
when:
- audit_format == "json"
summary: summary."summary-line"
- name: Post Audit | Capture audit data if documentation format
when:
- audit_format == "documentation"
block:
- name: "Post Audit | capture data {{ post_audit_outfile }}"
- name: Post Audit | capture data {{ post_audit_outfile }}
ansible.builtin.shell: "tail -2 {{ post_audit_outfile }}"
register: post_audit
changed_when: false
@ -42,5 +44,3 @@
- name: Post Audit | Capture post-audit result
ansible.builtin.set_fact:
post_audit_summary: "{{ post_audit.stdout_lines }}"
when:
- audit_format == "documentation"

View file

@ -1,56 +1,61 @@
---
- name: Pre Audit Binary Setup | Setup the LE audit
ansible.builtin.include_tasks: LE_audit_setup.yml
- name: Pre Audit Setup | Setup the LE 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
ansible.builtin.file:
path: "{{ audit_conf_dir }}"
state: directory
mode: '0755'
- name: Pre Audit Setup | If using git for content set up
when:
- audit_content == 'git'
block:
- name: Pre Audit Setup | Install git
ansible.builtin.package:
name: git
state: present
- name: Pre Audit Setup | retrieve audit content files from git
- 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 }}"
when:
- audit_content == 'git'
- name: Pre Audit Setup | copy to audit content files to server
ansible.builtin.copy:
src: "{{ audit_local_copy }}"
dest: "{{ audit_conf_dest }}"
mode: preserve
- name: Pre Audit Setup | Copy to audit content files to server
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
ansible.builtin.unarchive:
src: "{{ audit_conf_copy }}"
dest: "{{ audit_conf_dir }}"
- name: Pre Audit Setup | Unarchive audit content files on server
when:
- audit_content == 'archived'
- audit_content == 'archive'
ansible.builtin.unarchive:
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}"
- name: Pre Audit Setup | get audit content from url
ansible.builtin.get_url:
url: "{{ audit_files_url }}"
dest: "{{ audit_conf_dir }}"
- name: Pre Audit Setup | Get audit content from 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', [] ) }}"
- name: Pre Audit Setup | Check Goss is available
when:
- run_audit
block:
- name: Pre Audit Setup | Check for goss file
ansible.builtin.stat:
@ -59,34 +64,33 @@
- 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 }}"
when:
- not goss_available.stat.exists
when:
- run_audit
- name: Pre Audit Setup | Copy ansible default vars values to test audit
tags:
- goss_template
- run_audit
when:
- run_audit
ansible.builtin.template:
src: ansible_vars_goss.yml.j2
dest: "{{ audit_vars_path }}"
mode: 0600
when:
- run_audit
tags:
- goss_template
- always
mode: '0600'
- name: "Pre Audit | Run pre_remediation {{ benchmark }} audit"
ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}"
- 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_out_dir }}"
AUDIT_FILE: "goss.yml"
AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}"
AUDIT_FILE: goss.yml
- name: Pre Audit | Capture audit data if json format
when:
- audit_format == "json"
block:
- name: "capture data {{ pre_audit_outfile }}"
- name: Pre Audit | Capture data {{ pre_audit_outfile }}
ansible.builtin.shell: "cat {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
@ -95,13 +99,13 @@
ansible.builtin.set_fact:
pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}"
vars:
summary: 'summary."summary-line"'
when:
- audit_format == "json"
summary: summary."summary-line"
- name: Pre Audit | Capture audit data if documentation format
when:
- audit_format == "documentation"
block:
- name: "Pre Audit | capture data {{ pre_audit_outfile }} | documentation format"
- name: Pre Audit | Capture data {{ pre_audit_outfile }} | documentation format
ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
@ -109,5 +113,8 @@
- name: Pre Audit | Capture pre-audit result | documentation format
ansible.builtin.set_fact:
pre_audit_summary: "{{ pre_audit.stdout_lines }}"
- name: Audit_Only | Run Audit Only
when:
- audit_format == "documentation"
- audit_only
ansible.builtin.import_tasks: audit_only.yml

View file

@ -2,6 +2,54 @@
# Preliminary tasks that should always be run
# 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
tags:
- setup_audit
- run_audit
ansible.builtin.include_vars: audit.yml
- name: PRELIM | Include pre-remediation audit tasks
when:
- 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
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 $1 }'
changed_when: false
register: discovered_interactive_usernames
- name: "PRELIM | AUDIT | Interactive User accounts home directories"
tags:
- always
ansible.builtin.shell: >
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }'
changed_when: false
register: discovered_interactive_users_home
- name: "PRELIM | AUDIT | Interactive UIDs"
tags:
- always
ansible.builtin.shell: >
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }'
changed_when: false
register: discovered_interactive_uids
- name: "PRELIM | 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
@ -12,25 +60,6 @@
- level1-workstation
- users
- name: "PRELIM | capture /etc/password variables"
ansible.builtin.include_tasks: parse_etc_password.yml
tags:
- rule_5.5.2
- rule_5.6.2
- rule_6.2.9
- rule_6.2.10
- rule_6.2.11
- rhel9cis_section5
- rhel9cis_section6
- level1-server
- name: "PRELIM | Interactive User accounts"
ansible.builtin.shell: 'cat /etc/passwd | grep -Ev "nologin|/sbin" | cut -d: -f6'
changed_when: false
register: interactive_users_home
tags:
- always
- name: "PRELIM | Gather accounts with empty password fields"
ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'"
changed_when: false
@ -97,7 +126,7 @@
- name: "PRELIM | Section 1.1 | Create list of mount points"
ansible.builtin.set_fact:
mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}"
mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}"
tags:
- level1-server
- level1-workstation
@ -133,8 +162,33 @@
state: latest
when:
- rhel9cis_rule_1_2_4
- ansible_distribution != 'RedHat'
- ansible_distribution != 'OracleLinux'
- 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"
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 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"
when:
- rhel9cis_rule_1_2_1
- rhel9cis_force_gpg_key_import
- ansible_facts.distribution == 'RedHat'
- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)"
ansible.builtin.package:
@ -191,7 +245,7 @@
path: "{{ rhel9_cis_sshd_config_file }}"
owner: root
group: root
mode: 0600
mode: '0600'
state: touch
when:
- rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config'
@ -201,27 +255,6 @@
- level1_server
- level1_workstation
- name: "PRELIM | Install authconfig"
ansible.builtin.package:
name: authconfig
state: present
become: true
when:
- rhel9cis_use_authconfig
- rhel9cis_rule_5_3_1 or
rhel9cis_rule_5_3_2 or
rhel9cis_rule_5_3_3 or
'"authconfig" not in ansible_facts.packages or
"auditd-lib" not in ansible_facts.packages'
tags:
- level1-server
- level1-workstation
- rule_5.3.1 or
rule_5.3.2 or
rule_5.3.3
- authconfig
- auditd
- name: "PRELIM | 5.3.4 | Find all sudoers files."
ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'"
changed_when: false

View file

@ -8,7 +8,7 @@
regexp: "^(#)?install squashfs(\\s|$)"
line: "install squashfs /bin/true"
create: true
mode: 0600
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist"
ansible.builtin.lineinfile:
@ -16,7 +16,7 @@
regexp: "^(#)?blacklist squashfs(\\s|$)"
line: "blacklist squashfs"
create: true
mode: 0600
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs"
community.general.modprobe:
@ -41,7 +41,7 @@
regexp: "^(#)?install udf(\\s|$)"
line: "install udf /bin/true"
create: true
mode: 0600
mode: '0600'
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist"
ansible.builtin.lineinfile:
@ -49,7 +49,7 @@
regexp: "^(#)?blacklist udf(\\s|$)"
line: "blacklist udf"
create: true
mode: 0600
mode: '0600'
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf"
community.general.modprobe:

View file

@ -7,7 +7,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.2.1'
required_mount: '/tmp'
@ -33,7 +34,7 @@
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_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
when:
@ -62,7 +63,7 @@
dest: /etc/systemd/system/tmp.mount
owner: root
group: root
mode: 0644
mode: '0644'
notify: Systemd restart tmp.mount
when:
- rhel9cis_tmp_svc

View file

@ -7,7 +7,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.3.1'
required_mount: '/var'
@ -30,8 +31,8 @@
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_mounts }}"
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

View file

@ -8,7 +8,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.4.1'
required_mount: '/var/tmp'
@ -33,7 +34,7 @@
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_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot

View file

@ -7,7 +7,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.5.1'
@ -33,7 +34,7 @@
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_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot

View file

@ -7,7 +7,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.6.1'
@ -32,7 +33,7 @@
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_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot

View file

@ -7,7 +7,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.7.1'
@ -31,14 +32,13 @@
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_mounts }}"
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_1
- rhel9cis_rule_1_1_7_2 or
rhel9cis_rule_1_1_7_3
tags:
@ -48,5 +48,4 @@
- mounts
- rule_1.1.7.2
- rule_1.1.7.3
- rule_1.1.7.4
- skip_ansible_lint

View file

@ -3,18 +3,25 @@
# 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 | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- 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 separate partition exists for /home | Present"
ansible.builtin.import_tasks: warning_facts.yml
- 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'
required_mount: '/dev/shm'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_8_1
tags:
- level1-server

View file

@ -10,7 +10,7 @@
create: true
owner: root
group: root
mode: 0600
mode: '0600'
- name: "1.1.9 | PATCH | Disable USB Storage | Edit modprobe config"
community.general.modprobe:
@ -24,7 +24,7 @@
regexp: "^(#)?blacklist usb-storage(\\s|$)"
line: "blacklist usb-storage"
create: true
mode: 0600
mode: '0600'
when:
- rhel9cis_rule_1_1_9
tags:

View file

@ -23,9 +23,9 @@
os_gpg_key_check.rc == 1
when:
- rhel9cis_rule_1_2_1
- ansible_distribution == "RedHat" or
ansible_distribution == "Rocky" or
ansible_distribution == "AlmaLinux"
- ansible_facts.distribution == "RedHat" or
ansible_facts.distribution == "Rocky" or
ansible_facts.distribution == "AlmaLinux"
tags:
- level1-server
- level1-workstation
@ -73,7 +73,8 @@
- "{{ dnf_configured.stdout_lines }}"
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Warn Count"
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.2.3'
when:
@ -111,8 +112,8 @@
when:
- rhel9cis_rule_1_2_4
- not rhel9cis_rhel_default_repo or ansible_distribution != 'RedHat'
- ansible_distribution != 'OracleLinux'
- rhel9cis_rule_enable_repogpg
- not rhel9cis_rhel_default_repo
tags:
- level1-server
- level1-workstation

View file

@ -9,14 +9,14 @@
- name: "1.3.1 | PATCH | Ensure AIDE is installed | Build AIDE DB"
ansible.builtin.shell: /usr/sbin/aide --init
changed_when: false
failed_when: false
async: 45
poll: 0
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
@ -54,20 +54,20 @@
- patch
- rule_1.3.2
- name: "1.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools"
- 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: |
/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
/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_2
- rhel9cis_rule_1_3_3
- not system_is_ec2
tags:
- level1-server

View file

@ -6,7 +6,7 @@
content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy
owner: root
group: root
mode: 0600
mode: '0600'
notify: Grub2cfg
when:
- rhel9cis_set_boot_pass

View file

@ -39,7 +39,6 @@
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
when:
- not rhel9cis_selinux_disable
- rhel9cis_rule_1_6_1_3
tags:
- level1-server
@ -54,7 +53,6 @@
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
when:
- not rhel9cis_selinux_disable
- rhel9cis_rule_1_6_1_4
tags:
- level1-server
@ -69,7 +67,6 @@
policy: "{{ rhel9cis_selinux_pol }}"
state: enforcing
when:
- not rhel9cis_selinux_disable
- rhel9cis_selinux_enforce == 'enforcing'
- rhel9cis_rule_1_6_1_5
tags:
@ -93,7 +90,8 @@
when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0
- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | warning count"
ansible.builtin.import_tasks: warning_facts.yml
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'

View file

@ -6,7 +6,7 @@
dest: /etc/motd
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_1
tags:
@ -22,7 +22,7 @@
dest: /etc/issue
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_2
tags:
@ -37,7 +37,7 @@
dest: /etc/issue.net
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_3
tags:
@ -52,7 +52,7 @@
path: /etc/motd
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_4
tags:
@ -67,7 +67,7 @@
path: /etc/issue
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_5
tags:
@ -82,7 +82,7 @@
path: /etc/issue.net
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_1_7_6
tags:

View file

@ -25,7 +25,7 @@
create: true
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
loop:
- { regexp: 'user-db', line: 'user-db:user' }
@ -38,7 +38,7 @@
dest: /etc/dconf/db/gdm.d/01-banner-message
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_2
@ -59,7 +59,7 @@
create: true
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
loop:
- { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' }
@ -87,7 +87,7 @@
create: true
owner: root
group: root
mode: 0644
mode: '0644'
loop:
- { regexp: '^user-db', line: 'user-db: user' }
- { regexp: '^system-db', line: 'system-db: local' }
@ -97,7 +97,7 @@
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: 0755
mode: '0755'
state: directory
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file"
@ -118,14 +118,14 @@
- gui
- rule_1.8.4
- name: "1.8.5 PATCH | Ensure GDM screen locks cannot be overridden"
- 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
mode: '0755'
state: directory
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file"
@ -134,7 +134,7 @@
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver"
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_5
@ -171,7 +171,7 @@
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 0755
mode: '0755'
state: directory
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file"
@ -180,7 +180,7 @@
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock"
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_7
@ -199,7 +199,7 @@
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: 0755
mode: '0755'
state: directory
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file"
@ -227,7 +227,7 @@
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 0755
mode: '0755'
state: directory
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile"
@ -236,7 +236,7 @@
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock"
owner: root
group: root
mode: 0644
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_9
@ -261,4 +261,4 @@
- level1-workstation
- patch
- gui
- rule_1.8.4
- rule_1.8.10

View file

@ -1,59 +1,77 @@
---
- name: "SECTION | 1.1.1.x | Disable unused filesystems"
ansible.builtin.import_tasks: cis_1.1.1.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.1.x.yml
- name: "SECTION | 1.1.2.x | Configure /tmp"
ansible.builtin.import_tasks: cis_1.1.2.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.2.x.yml
- name: "SECTION | 1.1.3.x | Configure /var"
ansible.builtin.import_tasks: cis_1.1.3.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.3.x.yml
- name: "SECTION | 1.1.4.x | Configure /var/tmp"
ansible.builtin.import_tasks: cis_1.1.4.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.4.x.yml
- name: "SECTION | 1.1.5.x | Configure /var/log"
ansible.builtin.import_tasks: cis_1.1.5.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.5.x.yml
- name: "SECTION | 1.1.6.x | Configure /var/log/audit"
ansible.builtin.import_tasks: cis_1.1.6.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.6.x.yml
- name: "SECTION | 1.1.7.x | Configure /home"
ansible.builtin.import_tasks: cis_1.1.7.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.7.x.yml
- name: "SECTION | 1.1.8.x | Configure /dev/shm"
ansible.builtin.import_tasks: cis_1.1.8.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.8.x.yml
- name: "SECTION | 1.1.x | Disable various mounting"
ansible.builtin.import_tasks: cis_1.1.x.yml
ansible.builtin.import_tasks:
file: cis_1.1.x.yml
- name: "SECTION | 1.2 | Configure Software Updates"
ansible.builtin.import_tasks: cis_1.2.x.yml
ansible.builtin.import_tasks:
file: cis_1.2.x.yml
- name: "SECTION | 1.3 | Filesystem Integrity Checking"
ansible.builtin.import_tasks: cis_1.3.x.yml
ansible.builtin.import_tasks:
file: cis_1.3.x.yml
when: rhel9cis_config_aide
- name: "SECTION | 1.4 | Secure Boot Settings"
ansible.builtin.import_tasks: cis_1.4.x.yml
ansible.builtin.import_tasks:
file: cis_1.4.x.yml
- name: "SECTION | 1.5 | Additional Process Hardening"
ansible.builtin.import_tasks: cis_1.5.x.yml
ansible.builtin.import_tasks:
file: cis_1.5.x.yml
- name: "SECTION | 1.6 | Mandatory Access Control"
include_tasks: cis_1.6.1.x.yml
ansible.builtin.include_tasks:
file: cis_1.6.1.x.yml
when: not rhel9cis_selinux_disable
- name: "SECTION | 1.7 | Command Line Warning Banners"
ansible.builtin.import_tasks: cis_1.7.x.yml
ansible.builtin.import_tasks:
file: cis_1.7.x.yml
- name: "SECTION | 1.8 | Gnome Display Manager"
ansible.builtin.import_tasks: cis_1.8.x.yml
ansible.builtin.import_tasks:
file: cis_1.8.x.yml
- name: "SECTION | 1.9 | Updates and Patches"
ansible.builtin.import_tasks: cis_1.9.yml
ansible.builtin.import_tasks:
file: cis_1.9.yml
- name: "SECTION | 1.10 | Crypto policies"
include_tasks: cis_1.10.yml
ansible.builtin.include_tasks:
file: cis_1.10.yml
when:
- not system_is_ec2

View file

@ -21,7 +21,7 @@
dest: /etc/chrony.conf
owner: root
group: root
mode: 0644
mode: '0644'
- name: "2.1.2 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd | 1"
ansible.builtin.lineinfile:
@ -29,7 +29,7 @@
regexp: "^(#)?OPTIONS"
line: "OPTIONS=\"-u chrony\""
create: true
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_2_1_2
- not system_is_container

View file

@ -274,8 +274,8 @@
masked: true
state: stopped
when:
- not rhel9cis_use_nfs_server
- rhel9cis_use_nfs_service
- rhel9cis_use_nfs_server
- not rhel9cis_use_nfs_service
when:
- "'nfs-utils' in ansible_facts.packages"
- rhel9cis_rule_2_2_16

View file

@ -50,7 +50,7 @@
name: ftp
state: absent
when:
- not rhel9cis_tftp_client
- not rhel9cis_ftp_client
- "'ftp' in ansible_facts.packages"
- rhel9cis_rule_2_3_4
tags:

View file

@ -25,7 +25,8 @@
- "{{ 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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '2.4'
when:

View file

@ -1,13 +1,17 @@
---
- name: "SECTION | 2.1 | Time Synchronization"
ansible.builtin.import_tasks: cis_2.1.x.yml
ansible.builtin.import_tasks:
file: cis_2.1.x.yml
- name: "SECTION | 2.2 | Special Purpose Services"
ansible.builtin.import_tasks: cis_2.2.x.yml
ansible.builtin.import_tasks:
file: cis_2.2.x.yml
- name: "SECTION | 2.3 | Service Clients"
ansible.builtin.import_tasks: cis_2.3.x.yml
ansible.builtin.import_tasks:
file: cis_2.3.x.yml
- name: "SECTION | 2.4 | Nonessential services removed"
ansible.builtin.import_tasks: cis_2.4.yml
ansible.builtin.import_tasks:
file: cis_2.4.yml

View file

@ -26,7 +26,7 @@
- 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"
- 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
@ -47,6 +47,7 @@
when: rhel_09_wifi_enabled is changed # noqa no-handler
when:
- rhel9cis_rule_3_1_2
- "'wlan' in ansible_facts.interfaces"
tags:
- level1-server
- patch
@ -59,7 +60,7 @@
ansible.builtin.template:
src: "etc/modprobe.d/modprobe.conf.j2"
dest: "/etc/modprobe.d/{{ item }}.conf"
mode: "0600"
mode: '0600'
owner: root
group: root
loop:
@ -72,7 +73,7 @@
regexp: "^(#)?blacklist tipc(\\s|$)"
line: "blacklist tipc"
create: true
mode: 0600
mode: '0600'
when:
- rhel9cis_rule_3_1_3
tags:

View file

@ -46,7 +46,8 @@
- 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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- rhel9cis_3_4_2_2_nft_tables.stdout | length == 0
- not rhel9cis_nft_tables_autonewtable
@ -193,6 +194,7 @@
- "{{ rhel9cis_3_4_2_5_servicesport.stdout_lines }}"
when:
- rhel9cis_rule_3_4_2_5
- rhel9cis_firewall == "firewalld"
tags:
- level1-server
- level1-workstation

View file

@ -1,16 +1,21 @@
---
- name: "SECTION | 3.1.x | Disable unused network protocols and devices"
ansible.builtin.import_tasks: cis_3.1.x.yml
ansible.builtin.import_tasks:
file: cis_3.1.x.yml
- name: "SECTION | 3.2.x | Network Parameters (Host Only)"
ansible.builtin.import_tasks: cis_3.2.x.yml
ansible.builtin.import_tasks:
file: cis_3.2.x.yml
- name: "SECTION | 3.3.x | Network Parameters (host and Router)"
ansible.builtin.import_tasks: cis_3.3.x.yml
ansible.builtin.import_tasks:
file: cis_3.3.x.yml
- name: "SECTION | 3.4.1.x | Firewall configuration"
ansible.builtin.import_tasks: cis_3.4.1.x.yml
ansible.builtin.import_tasks:
file: cis_3.4.1.x.yml
- name: "SECTION | 3.4.2.x | Configure firewall"
ansible.builtin.import_tasks: cis_3.4.2.x.yml
ansible.builtin.import_tasks:
file: cis_3.4.2.x.yml

View file

@ -24,28 +24,19 @@
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled"
block:
- name: "4.1.1.2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX"
ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
- 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_grub_cmdline_linux
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 | Replace existing setting"
ansible.builtin.replace:
path: /etc/default/grub
regexp: 'audit=.'
replace: 'audit=1'
notify: Grub2cfg
when: "'audit=' in rhel9cis_4_1_1_2_grub_cmdline_linux.stdout"
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing"
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_2_grub_cmdline_linux.stdout }} audit=1"'
notify: Grub2cfg
when: "'audit=' not in rhel9cis_4_1_1_2_grub_cmdline_linux.stdout"
- 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:
@ -58,28 +49,33 @@
- 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 | Get GRUB_CMDLINE_LINUX"
ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
- 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_grub_cmdline_linux
register: rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux
- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting"
ansible.builtin.replace:
path: /etc/default/grub
regexp: 'audit_backlog_limit=\d+'
replace: 'audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}'
notify: Grub2cfg
when: "'audit_backlog_limit=' in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
- 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 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing"
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_3_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"'
notify: Grub2cfg
when: "'audit_backlog_limit=' not in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
- 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:

View file

@ -4,7 +4,7 @@
ansible.builtin.lineinfile:
path: /etc/audit/auditd.conf
regexp: "^max_log_file( |=)"
line: "max_log_file = {{ rhel9cis_max_log_file_size }}"
line: "max_log_file = {{ rhel9cis_auditd['max_log_file'] }}"
notify: Restart auditd
when:
- rhel9cis_rule_4_1_2_1
@ -58,6 +58,7 @@
notify: Restart auditd
when:
- rhel9cis_auditd_extra_conf.keys() | length > 0
- rhel9cis_auditd_extra_conf_usage
tags:
- level2-server
- level2-workstation

View file

@ -99,7 +99,7 @@
- level2-workstation
- patch
- auditd
- rule_4.1.3_7
- 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"
@ -268,7 +268,7 @@
- level2-workstation
- patch
- auditd
- rule_4.1.20
- rule_4.1.3.20
- name: "4.1.3.21 | AUDIT | Ensure the running and on disk configuration is the same"
ansible.builtin.debug:

View file

@ -50,7 +50,7 @@
ansible.builtin.file:
path: "{{ audit_discovered_logfile.stdout | dirname }}"
state: directory
mode: 0750
mode: '0750'
when: not auditlog_dir.stat.mode is match('07(0|5)0')
when:
- rhel9cis_rule_4_1_4_4
@ -64,12 +64,11 @@
- name: "4.1.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive"
ansible.builtin.file:
path: "{{ item.path }}"
mode: 0640
mode: "{{ '0600' if item.mode == '0600' else '0640' }}"
loop: "{{ auditd_conf_files.files }}"
loop_control:
label: "{{ item.path }}"
when:
- item.mode != '06(0|4)0'
- rhel9cis_rule_4_1_4_5
tags:
- level2-server
@ -82,7 +81,7 @@
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
loop: "{{ auditd_conf_files.files }}"
loop: "{{ auditd_conf_files.files | default([]) }}"
loop_control:
label: "{{ item.path }}"
when:
@ -98,7 +97,7 @@
ansible.builtin.file:
path: "{{ item.path }}"
group: root
loop: "{{ auditd_conf_files.files }}"
loop: "{{ auditd_conf_files.files | default([]) }}"
loop_control:
label: "{{ item.path }}"
when:
@ -127,7 +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: '0750'
loop: "{{ audit_bins.results }}"
loop_control:

View file

@ -35,7 +35,6 @@
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_3
- rhel9cis_syslog == "rsyslog"
tags:
- level1-server
- level1-workstation

View file

@ -88,7 +88,8 @@
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: warning_facts.yml
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'

View file

@ -7,12 +7,13 @@
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: 0640
mode: "{{ '0600' if item.mode == '0600' else '0640' }}"
loop: "{{ logfiles.files }}"
loop_control:
label: "{{ item.path }}"

View file

@ -39,7 +39,8 @@
loop: "{{ log_rotates.files }}"
- name: "4.3 | AUDIT | Ensure logrotate is configured | Warning count"
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '4.3'
when: log_rotates.matched > 0

View file

@ -1,29 +1,37 @@
---
- name: "SECTION | 4.1 | Configure System Accounting (auditd)"
ansible.builtin.import_tasks: cis_4.1.1.x.yml
ansible.builtin.import_tasks:
file: cis_4.1.1.x.yml
when:
- not system_is_container
- name: "SECTION | 4.1.2 | Configure Data Retention"
ansible.builtin.import_tasks: cis_4.1.2.x.yml
ansible.builtin.import_tasks:
file: cis_4.1.2.x.yml
- name: "SECTION | 4.1.3 | Configure Auditd rules"
ansible.builtin.import_tasks: cis_4.1.3.x.yml
ansible.builtin.import_tasks:
file: cis_4.1.3.x.yml
- name: "SECTION | 4.1.4 | Configure Audit files"
ansible.builtin.import_tasks: cis_4.1.4.x.yml
ansible.builtin.import_tasks:
file: cis_4.1.4.x.yml
- name: "SECTION | 4.2 | Configure Logging"
ansible.builtin.import_tasks: cis_4.2.1.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: cis_4.2.2.x.yml
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: cis_4.2.3.yml
ansible.builtin.import_tasks:
file: cis_4.2.3.yml
- name: "SECTION | 4.3 | Configure logrotate"
ansible.builtin.import_tasks: cis_4.3.yml
ansible.builtin.import_tasks:
file: cis_4.3.yml

View file

@ -18,7 +18,7 @@
path: /etc/crontab
owner: root
group: root
mode: 0600
mode: '0600'
when:
- rhel9cis_rule_5_1_2
tags:
@ -34,7 +34,7 @@
state: directory
owner: root
group: root
mode: 0700
mode: '0700'
when:
- rhel9cis_rule_5_1_3
tags:
@ -50,7 +50,7 @@
state: directory
owner: root
group: root
mode: 0700
mode: '0700'
when:
- rhel9cis_rule_5_1_4
tags:
@ -66,7 +66,7 @@
state: directory
owner: root
group: root
mode: 0700
mode: '0700'
when:
- rhel9cis_rule_5_1_5
tags:
@ -81,7 +81,7 @@
state: directory
owner: root
group: root
mode: 0700
mode: '0700'
when:
- rhel9cis_rule_5_1_6
tags:
@ -96,7 +96,7 @@
state: directory
owner: root
group: root
mode: 0700
mode: '0700'
when:
- rhel9cis_rule_5_1_7
tags:
@ -124,7 +124,7 @@
state: '{{ "file" if rhel9cis_5_1_8_cron_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
mode: '0600'
when:
- rhel9cis_rule_5_1_8
tags:
@ -152,7 +152,7 @@
state: '{{ "file" if rhel9cis_5_1_9_at_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
mode: '0600'
when:
- rhel9cis_rule_5_1_9
tags:

View file

@ -1,11 +1,11 @@
---
- name: "5.2.1 | Ensure permissions on /etc/ssh/sshd_config are configured"
- 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
mode: '0600'
when:
- rhel9cis_rule_5_2_1
tags:
@ -31,7 +31,7 @@
path: "{{ item.path }}"
owner: root
group: root
mode: 0600
mode: '0600'
loop: "{{ rhel9cis_5_2_2_ssh_private_host_key.files }}"
loop_control:
label: "{{ item.path }}"
@ -60,7 +60,7 @@
path: "{{ item.path }}"
owner: root
group: root
mode: 0644
mode: '0644'
loop: "{{ rhel9cis_5_2_3_ssh_public_host_key.files }}"
loop_control:
label: "{{ item.path }}"
@ -150,11 +150,18 @@
- rule_5.2.6
- name: "5.2.7 | PATCH | Ensure SSH root login is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9_cis_sshd_config_file }}"
regexp: "^#PermitRootLogin|^PermitRootLogin"
line: 'PermitRootLogin no'
validate: sshd -t -f %s
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 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:
@ -225,11 +232,21 @@
- rule_5.2.11
- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9_cis_sshd_config_file }}"
regexp: "^#X11Forwarding|^X11Forwarding"
line: 'X11Forwarding no'
validate: sshd -t -f %s
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:

View file

@ -44,7 +44,7 @@
- "{{ rhel9cis_5_4_2_profiles_faillock.stdout_lines }}"
- name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Create custom profiles"
ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} with-faillock"
ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }}"
when: rhel9cis_authselect_custom_profile_select
- name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not auth select profile"

View file

@ -1,10 +1,28 @@
---
- 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'] }}"
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:
@ -12,13 +30,31 @@
- level1-workstation
- patch
- password
- rule_5.5.1.1
- rule_5.6.1.1
- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_MIN_DAYS'
line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}"
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:
@ -29,10 +65,26 @@
- rule_5.6.1.2
- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_WARN_AGE'
line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}"
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:
@ -40,7 +92,7 @@
- level1-workstation
- patch
- password
- rule_5.5.1.3
- rule_5.6.1.3
- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less"
block:
@ -97,7 +149,8 @@
- 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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- rhel9cis_5_6_1_5_user_list.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
@ -116,4 +169,4 @@
- level1-server
- level1-workstation
- patch
- rule_5.5.1.5
- rule_5.6.1.5

View file

@ -2,7 +2,7 @@
- name: "5.6.2 | PATCH | Ensure system accounts are secured"
block:
- name: "5.6.2 | Ensure system accounts are secured | Set nologin"
- name: "5.6.2 | PATCH | Ensure system accounts are secured | Set nologin"
ansible.builtin.user:
name: "{{ item.id }}"
shell: /usr/sbin/nologin
@ -50,7 +50,7 @@
state: "{{ item.state }}"
marker: "# {mark} - CIS benchmark - Ansible-lockdown"
create: true
mode: 0644
mode: '0644'
block: |
TMOUT={{ rhel9cis_shell_session_timeout.timeout }}
export TMOUT
@ -83,10 +83,10 @@
- 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.lineinfile:
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: '(?i)(umask\s*)'
line: '{{ item.line }} 027'
regexp: (?i)(umask\s+\d\d\d)
replace: '{{ item.line }} 027'
with_items:
- { path: '/etc/bashrc', line: 'umask' }
- { path: '/etc/profile', line: 'umask' }
@ -98,6 +98,30 @@
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:

View file

@ -3,24 +3,31 @@
# Access, Authentication, and Authorization
- name: "SECTION | 5.1 | Configure time-based job schedulers"
ansible.builtin.import_tasks: cis_5.1.x.yml
ansible.builtin.import_tasks:
file: cis_5.1.x.yml
- name: "SECTION | 5.2 | Configure SSH Server"
ansible.builtin.import_tasks: cis_5.2.x.yml
ansible.builtin.import_tasks:
file: cis_5.2.x.yml
when:
- "'openssh-server' in ansible_facts.packages"
- name: "SECTION | 5.3 | Configure privilege escalation"
ansible.builtin.import_tasks: cis_5.3.x.yml
ansible.builtin.import_tasks:
file: cis_5.3.x.yml
- name: "SECTION | 5.4 | Configure authselect"
ansible.builtin.import_tasks: cis_5.4.x.yml
ansible.builtin.import_tasks:
file: cis_5.4.x.yml
- name: "SECTION | 5.5 | Configure PAM "
ansible.builtin.import_tasks: cis_5.5.x.yml
ansible.builtin.import_tasks:
file: cis_5.5.x.yml
- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters"
ansible.builtin.import_tasks: cis_5.6.1.x.yml
ansible.builtin.import_tasks:
file: cis_5.6.1.x.yml
- name: "SECTION | 5.6.x | Misc. User Account Settings"
ansible.builtin.import_tasks: cis_5.6.x.yml
ansible.builtin.import_tasks:
file: cis_5.6.x.yml

View file

@ -5,7 +5,7 @@
path: /etc/passwd
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_6_1_1
tags:
@ -20,7 +20,7 @@
path: /etc/passwd-
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_6_1_2
tags:
@ -32,10 +32,10 @@
- name: "6.1.3 | PATCH | Ensure permissions on /etc/group are configured"
ansible.builtin.file:
path: /etc/group-
path: /etc/group
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_6_1_3
tags:
@ -50,7 +50,7 @@
path: /etc/group-
owner: root
group: root
mode: 0644
mode: '0644'
when:
- rhel9cis_rule_6_1_4
tags:
@ -65,7 +65,7 @@
path: /etc/shadow
owner: root
group: root
mode: 0000
mode: '0000'
when:
- rhel9cis_rule_6_1_5
tags:
@ -80,7 +80,7 @@
path: /etc/shadow-
owner: root
group: root
mode: 0000
mode: '0000'
when:
- rhel9cis_rule_6_1_6
tags:
@ -95,7 +95,7 @@
path: /etc/gshadow
owner: root
group: root
mode: 0000
mode: '0000'
when:
- rhel9cis_rule_6_1_7
tags:
@ -110,7 +110,7 @@
path: /etc/gshadow-
owner: root
group: root
mode: 0000
mode: '0000'
when:
- rhel9cis_rule_6_1_8
tags:
@ -118,7 +118,7 @@
- level1-workstation
- patch
- permissions
- rule_6.1.10
- rule_6.1.8
- name: "6.1.9 | PATCH | Ensure no world writable files exist"
block:
@ -155,7 +155,7 @@
failed_when: false
check_mode: false
register: rhel_09_6_1_10_audit
loop: "{{ ansible_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
when:
@ -173,11 +173,12 @@
- 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 | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
msg: "Warning!! Missing owner on items in {{ rhel_09_6_1_10_audit | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.10'
when: rhel_09_6_1_10_unowned_files_found
@ -201,7 +202,7 @@
failed_when: false
changed_when: false
register: rhel_09_6_1_11_audit
loop: "{{ ansible_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
when:
@ -219,16 +220,17 @@
- 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 | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
msg: "Warning!! Missing group on items in {{ rhel_09_6_1_11_audit | community.general.json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
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: warning_facts.yml
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
rhel_09_6_1_11_ungrouped_files_found: false
when:
- rhel9cis_rule_6_1_11
tags:
@ -251,7 +253,7 @@
- patch
- stickybits
- permissons
- rule_1.1.21
- rule_6.1.12
- name: "6.1.13 | AUDIT | Audit SUID executables"
block:
@ -260,7 +262,7 @@
failed_when: false
changed_when: false
register: rhel_09_6_1_13_suid_perms
loop: "{{ ansible_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
@ -275,11 +277,12 @@
- 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 | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
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
- name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist | warning"
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.13'
when: rhel9_6_1_13_suid_found
@ -302,7 +305,7 @@
failed_when: false
changed_when: false
register: rhel_09_6_1_14_sgid_perms
loop: "{{ ansible_mounts }}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
@ -317,11 +320,12 @@
- 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 | json_query('results[*].stdout_lines[*]') | flatten }}" # noqa jinja[invalid]
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
- name: "6.1.14 | AUDIT | Audit SGID executables| warning"
ansible.builtin.import_tasks: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.14'
when: rhel9_6_1_14_sgid_found
@ -353,7 +357,7 @@
content: "{{ rhel9cis_6_1_15_packages_rpm.stdout }}"
owner: root
group: root
mode: 0640
mode: '0640'
- name: "6.1.15 | AUDIT | Audit system file permissions | Message out alert for package descrepancies"
ansible.builtin.debug:
@ -362,7 +366,8 @@
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: warning_facts.yml
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

View file

@ -15,7 +15,8 @@
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: warning_facts.yml
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.2.1'
when: shadow_passwd.stdout | length >= 1
@ -59,7 +60,8 @@
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: warning_facts.yml
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
@ -71,9 +73,9 @@
- audit
- accounts
- groups
- rule_6.2.2
- rule_6.2.3
- name: "6.2.4 | AUDIT Ensure no duplicate UIDs exist"
- 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"
@ -86,8 +88,9 @@
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: warning_facts.yml
- 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'
@ -115,7 +118,8 @@
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: warning_facts.yml
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
@ -144,7 +148,8 @@
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: warning_facts.yml
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
@ -173,7 +178,8 @@
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: warning_facts.yml
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
@ -229,7 +235,7 @@
state: directory
owner: root
group: root
mode: "0755"
mode: '0755'
follow: false
loop: "{{ root_path_perms.results }}"
loop_control:
@ -272,7 +278,7 @@
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: "{{ rhel9cis_passwd | selectattr('uid', '>=', min_int_uid | int ) | selectattr('uid', '<=', max_int_uid | int ) | list }}"
loop_control:
label: "{{ item.id }}"
@ -284,7 +290,7 @@
etype: group
permissions: rx
state: present
loop: "{{ interactive_users_home.stdout_lines }}"
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"
@ -294,7 +300,7 @@
etype: other
permissions: 0
state: present
loop: "{{ interactive_users_home.stdout_lines }}"
loop: "{{ discovered_interactive_users_home.stdout_lines }}"
when: not system_is_container
when:
- rhel9cis_rule_6_2_10
@ -314,10 +320,7 @@
loop_control:
label: "{{ item.id }}"
when:
- item.uid >= min_int_uid | int
- item.id != 'nobody'
- (item.id != 'tss' and item.dir != '/dev/null')
- item.shell != '/sbin/nologin'
- item.id in discovered_interactive_usernames.stdout
- rhel9cis_rule_6_2_11
tags:
- level1-server
@ -332,13 +335,13 @@
ansible.builtin.stat:
path: "{{ item }}"
register: rhel_09_6_2_12_home_dir_perms
loop: "{{ interactive_users_home.stdout_lines }}"
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"
mode: '0750'
loop: "{{ rhel_09_6_2_12_home_dir_perms.results }}"
loop_control:
label: "{{ item }}"
@ -353,7 +356,7 @@
etype: group
permissions: rx
state: present
loop: "{{ interactive_users_home.stdout_lines }}"
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"
@ -363,7 +366,7 @@
etype: other
permissions: 0
state: present
loop: "{{ interactive_users_home.stdout_lines }}"
loop: "{{ discovered_interactive_users_home.stdout_lines }}"
when: not system_is_container
when:
- rhel9cis_rule_6_2_12
@ -379,7 +382,7 @@
ansible.builtin.file:
path: "{{ item }}/.netrc"
state: absent
loop: "{{ interactive_users_home.stdout_lines }}"
loop: "{{ discovered_interactive_users_home.stdout_lines }}"
when:
- rhel9cis_rule_6_2_13
tags:
@ -394,7 +397,7 @@
ansible.builtin.file:
path: "{{ item }}/.forward"
state: absent
loop: "{{ interactive_users_home.stdout_lines }}"
loop: "{{ discovered_interactive_users_home.stdout_lines }}"
when:
- rhel9cis_rule_6_2_14
tags:
@ -409,7 +412,7 @@
ansible.builtin.file:
path: "~{{ item }}/.rhosts"
state: absent
loop: "{{ interactive_users_home.stdout_lines }}"
loop: "{{ discovered_interactive_users_home.stdout_lines }}"
when:
- rhel9cis_rule_6_2_15
tags:

View file

@ -1,7 +1,9 @@
---
- name: "SECTION | 6.1 | System File Permissions"
ansible.builtin.import_tasks: cis_6.1.x.yml
ansible.builtin.import_tasks:
file: cis_6.1.x.yml
- name: "SECTION | 6.2 | User and Group Settings"
ansible.builtin.import_tasks: cis_6.2.x.yml
ansible.builtin.import_tasks:
file: cis_6.2.x.yml

View file

@ -7,10 +7,10 @@ benchmark_version: '1.0.0'
# 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_distribution | lower }}
host_os_distribution: {{ ansible_facts.distribution | lower }}
# timeout for each command to run where set - default = 10seconds/10000ms
timeout_ms: 60000
timeout_ms: {{ audit_cmd_timeout }}
# Taken from LE rhel9-cis
rhel9cis_section1: {{ rhel9cis_section1 }}
@ -239,7 +239,6 @@ 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_2: {{ rhel9cis_rule_4_2_1_3 }}
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 }}

View file

@ -1,4 +1,4 @@
## This file is managed by Ansible, YOUR CHANGED WILL BE LOST!
## {{ 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
@ -27,19 +27,21 @@ server {{ server }} {{ rhel9cis_chrony_server_options }}
# password is generated by a random process at install time. You may
# change it if you wish.
keyfile /etc/chrony/chrony.keys
keyfile /etc/chrony.keys
# Set runtime command key. Note that if you change the key (not the
# password) to anything other than 1 you will need to edit
# /etc/ppp/ip-up.d/chrony, /etc/ppp/ip-down.d/chrony, /etc/init.d/chrony
# and /etc/cron.weekly/chrony as these scripts use it to get the password.
# Record the rate at which the system clock gains/losses time.
driftfile /var/lib/chrony/drift
commandkey 1
# 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 }}
# I moved the driftfile to /var/lib/chrony to comply with the Debian
# filesystem standard.
# Enable kernel synchronization of the real-time clock (RTC).
{% if not rhel9cis_chrony_server_rtcsync %}#{% endif %}rtcsync
driftfile /var/lib/chrony/chrony.drift
# Increase the minimum number of selectable sources required to adjust
# the system clock.
minsources {{ rhel9cis_chrony_server_minsources }}
# Comment this line out to turn off logging.

View file

@ -1,7 +1,7 @@
## This file is managed by Ansible, YOUR CHANGES WILL BE LOST!
# IPv6 disable
{% if rhel9cis_rule_3_1_1 and rhel9cis_ipv6_required %}
{% 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
{% endif %}

View file

@ -3,3 +3,5 @@
os_gpg_key_pubkey_name: gpg-pubkey-b86b3716-61e69f29
os_gpg_key_pubkey_content: "AlmaLinux OS 9 <packager@almalinux.org> b86b3716"
# disable repo_gpgcheck due to OS default repos
rhel9cis_rule_enable_repogpg: false

View file

@ -2,3 +2,5 @@
# OS Specific Settings
os_gpg_key_pubkey_name: gpg-pubkey-8d8b756f-629e59ec
os_gpg_key_pubkey_content: "Oracle Linux (release key 1) <secalert_us@oracle.com>"
# disable repo_gpgcheck due to OS default repos
rhel9cis_rule_enable_repogpg: false

View file

@ -3,3 +3,6 @@
os_gpg_key_pubkey_name: gpg-pubkey-fd431d51-4ae0493b
os_gpg_key_pubkey_content: "Red Hat, Inc. (release key 2) <security@redhat.com> fd431d51"
# disable repo_gpgcheck due to OS default repos
rhel9cis_rule_enable_repogpg: false

40
vars/audit.yml Normal file
View file

@ -0,0 +1,40 @@
---
#### Audit Configuration Settings ####
# Timeout for those cmds that take longer to run where timeout set
audit_cmd_timeout: 120000
# if get_audit_binary_method == download change accordingly
audit_bin_url: "https://github.com/goss-org/goss/releases/download/{{ audit_bin_version.release }}/goss-linux-"
### Goss Audit Benchmark file ###
## managed by the control audit_content
# git
audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git"
audit_git_version: "benchmark_{{ benchmark_version }}"
## Goss configuration information
# Where the goss audit configuration will be stored - NOTE benchmark-audit is expected
audit_conf_dir: "{{ audit_conf_dest | default('/opt') }}/{{ benchmark }}-Audit"
# If changed these can affect other products
pre_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_pre_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}"
post_audit_outfile: "{{ audit_log_dir }}/{{ ansible_facts.hostname }}-{{ benchmark }}-{{ benchmark_version }}_post_scan_{{ ansible_facts.date_time.epoch }}.{{ audit_format }}"
## The following should not need changing
### Audit binary settings ###
audit_bin_version:
release: v0.4.4
AMD64_checksum: 'sha256:1c4f54b22fde9d4d5687939abc2606b0660a5d14a98afcd09b04b793d69acdc5'
audit_bin_path: /usr/local/bin/
audit_bin: "{{ audit_bin_path }}goss"
audit_format: json
audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_facts.hostname }}.yml"
audit_results: |
The audit results are: {{ pre_audit_summary }}
{% if not audit_only %}The post remediation audit results are: {{ post_audit_summary }}{% endif %}
Full breakdown can be found in {{ audit_log_dir }}

View file

@ -16,4 +16,4 @@ rhel9cis_allowed_crypto_policies_modules:
warn_control_list: ""
warn_count: 0
gpg_key_package: "{{ ansible_distribution | lower }}-gpg-keys"
gpg_key_package: "{{ ansible_facts.distribution | lower }}-gpg-keys"