Signed-off-by: Mark Bolwell <mark.bollyuk@gmail.com>
This commit is contained in:
Mark Bolwell 2022-01-07 09:06:18 +00:00
commit a54b5216eb
No known key found for this signature in database
GPG key ID: F734FDFC154B83FB
87 changed files with 7693 additions and 0 deletions

11
.ansible-lint Normal file
View file

@ -0,0 +1,11 @@
parseable: true
quiet: true
skip_list:
- '204'
- '305'
- '303'
- '403'
- '306'
- '602'
use_default_rules: true
verbosity: 0

6
.gitattributes vendored Normal file
View file

@ -0,0 +1,6 @@
# adding github settings to show correct language
*.sh linguist-detectable=true
*.yml linguist-detectable=true
*.ps1 linguist-detectable=true
*.j2 linguist-detectable=true
*.md linguist-documentation

46
.gitignore vendored Normal file
View file

@ -0,0 +1,46 @@
.env
*.log
*.retry
.cache
.vagrant
tests/*redhat-subscription
tests/Dockerfile
*.iso
*.box
packer_cache
delete*
ignore*
test_inv
# VSCode
.vscode
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# DS_Store
.DS_Store
._*
# Linux Editors
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
.elc
auto-save-list
tramp
.\#*
*.swp
*.swo
rh-creds.env
travis.env
# Lockdown-specific
benchparse/
*xccdf.xml
*.retry
# GitHub Action/Workflow files
.github/

23
.yamllint Normal file
View file

@ -0,0 +1,23 @@
---
ignore: |
tests/
molecule/
.gitlab-ci.yml
*molecule.yml
extends: default
rules:
indentation:
# Requiring 4 space indentation
spaces: 4
# Requiring consistent indentation within a file, either indented or not
indent-sequences: consistent
truthy: disable
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
line-length: disable

67
CONTRIBUTING.rst Normal file
View file

@ -0,0 +1,67 @@
Contributing to MindPoint Group Projects
========================================
Rules
-----
1) All commits must be GPG signed (details in Signing section)
2) All commits must have Signed-off-by (Signed-off-by: Joan Doe <joan.doe@email.com>) in the commit message (details in Signing section)
3) All work is done in your own branch
4) All pull requests go into the devel branch. There are automated checks for signed commits, signoff in commit message, and functional testing)
5) Be open and nice to eachother
Workflow
--------
- Your work is done in your own individual branch. Make sure to to Signed-off and GPG sign all commits you intend to merge
- All community Pull Requests are into the devel branch. There are automated checks for GPG signed, Signed-off in commits, and functional tests before being approved. If your pull request comes in from outside of our repo, the pull request will go into a staging branch. There is info needed from our repo for our CI/CD testing.
- 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
Signing your contribution
-------------------------
We've chosen to use the Developer's Certificate of Origin (DCO) method
that is employed by the Linux Kernel Project, which provides a simple
way to contribute to MindPoint Group projects.
The process is to certify the below DCO 1.1 text
::
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
::
Then, when it comes time to submit a contribution, include the
following text in your contribution commit message:
::
Signed-off-by: Joan Doe <joan.doe@email.com>
::
This message can be entered manually, or if you have configured git
with the correct `user.name` and `user.email`, you can use the `-s`
option to `git commit` to automatically include the signoff message.

93
Changelog.md Normal file
View file

@ -0,0 +1,93 @@
# Changes to rhel9CIS
## 1.3.3
- update to audit script
- variable for audit OS agnostic
- removal of included library module (not required)
- Issues included
- #135 - running levels - upadted tags
- #138 - auditd immutable
- #139 - 5.2.13 valus updated
- #140
- #141 - check mode update
- #142
- #143 - labels added
- #144
- #146 - undefined variable added
- #147 - removed warn statement
- #149 - shell timeout
## 1.3.2
- issues with crypto policies on ec2 - added skip for rules if system_is_ec2 variable
- cis_1.10 ## Change crypto breaks installing products
- cis_1.11 ## Change crypto breaks installing products
## 1.3.1
- CIS 1.0.1 updates
- Added Issue and PR templates
- Added better reboot logic
- Added options to ensure idempotence
- Enhanced flush handlers
- Typo fixes
- mount check improvements
- Linting fixes
- Added systemd tmp mount
- Added systemd tmpfs block
- #110 tmp.mount support
- thanks to @erpadmin
## 1.3
- extentions to LE audit capability
- more lint and layout changes
- sugroup assertion added 5.7
- added extra logic variable to authselect/config section 5.3 related
- AlmaLinux and Rocky tested (comments in readme - also rsyslog installed at build or will fail)
- section 1.1 mount work has been rewritten and systemd tmp mount options added
## 1.2.3
- #117 sugroup enhancements
- thanks to @ihotz
- #112 use of dnf module not shell
- thanks to @wolskie
## 1.2.2
- #33 mkgrub missing variable issues - efi and bios path resolution
- thanks to @mrampant & @mickey1928geo
- #102 2.2.2 xorg pkg removal extended
- thanks to @RosarioVinoth
- #104 5.4.1 pwquality logic
- thanks to @RosarioVinoth
- #107 Idempotence improvement for 4.1.1.3 and 4.1.1.4
- thanks to @andreyzher
- lint changes and updates to sync with ansible-galaxy
## v1.2.1
- bootloader and default variables
- empty strings lint updates
- #87
- rule 6.1.1 - audit only - outputs file discrepancies to {{ rhel9cis_rpm_audit_file }}
- #88
- checkmode_improvements added to relevant tasks
- PR #96
- crypto policy idempotency
## v1.2.0
- #86
- Adding on the goss auditing tool
- remove deprecated warnings
- format and layout
- general improvements
- readme updates
- use ansible package_facts
- #90
- cis fix - nfs-server not nfs
- Thanks to danderemer

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2020 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

121
README.md Normal file
View file

@ -0,0 +1,121 @@
# RHEL 9 CIS (predicted) - ALPHA
## This is purely development and those who have access to the RH developer branches for testing
### This will work on RHEL8 and derivatives currently
![Build Status](https://img.shields.io/github/workflow/status/ansible-lockdown/RHEL9-CIS/CommunityToDevel?label=Devel%20Build%20Status&style=plastic)
![Build Status](https://img.shields.io/github/workflow/status/ansible-lockdown/RHEL9-CIS/DevelToMain?label=Main%20Build%20Status&style=plastic)
![Release](https://img.shields.io/github/v/release/ansible-lockdown/RHEL9-CIS?style=plastic)
Configure RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant with RHEL8 settings (RHEL9 not yet released)
Based on [CIS RedHat Enterprise Linux 8 Benchmark v1.0.1 - 05-19-2021 ](https://www.cisecurity.org/cis-benchmarks/)
## Caution(s)
This role **will make changes to the system** which may have unintended concequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted.
This role was developed against a clean install of the Operating System. If you are implimenting 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
## Documentation
- [Getting Started](https://www.lockdownenterprise.com/docs/getting-started-with-lockdown)
- [Customizing Roles](https://www.lockdownenterprise.com/docs/customizing-lockdown-enterprise)
- [Per-Host Configuration](https://www.lockdownenterprise.com/docs/per-host-lockdown-enterprise-configuration)
- [Getting the Most Out of the Role](https://www.lockdownenterprise.com/docs/get-the-most-out-of-lockdown-enterprise)
- [Wiki](https://github.com/ansible-lockdown/RHEL9-CIS/wiki)
- [Repo GitHub Page](https://ansible-lockdown.github.io/RHEL9-CIS/)
## Auditing (new)
This can be turned on or off within the defaults/main.yml file with the variable rhel9cis_run_audit. The value is false by default, please refer to the wiki for more details.
This is a much quicker, very lightweight, checking (where possible) config compliance and live/running settings.
A new form of auditing has been develeoped, by using a small (12MB) go binary called [goss](https://github.com/aelsabbahy/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).
## Requirements
RHEL 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.)
**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 consiquences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file or the [Main Variables Wiki Page](https://github.com/ansible-lockdown/RHEL9-CIS/wiki/Main-Variables).
## Dependencies
- Python3
- Ansible 2.9+
- python-def (should be included in RHEL 9)
- 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. These variables can be found [here](https://github.com/ansible-lockdown/RHEL9-CIS/wiki/Main-Variables) in the Main Variables Wiki page. All variables are listed there along with descriptions.
## 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.
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.
```txt
tags:
- level1-server
- level1-workstation
- scored
- avahi
- services
- patch
- rule_2.2.4
```
## 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
```
## Branches
- devel - This is the default branch and the working development branch. Community pull requests will pull into this branch
- main - This is the release branch
- reports - This is a protected branch for our scoring reports, no code should ever go here
- all other branches** - Individual community member branches
## 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.
- 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
- 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

24
ansible.cfg Normal file
View file

@ -0,0 +1,24 @@
[defaults]
host_key_checking=False
display_skipped_hosts=True
system_warnings=False
command_warnings=False
nocows=1
retry_files_save_path=/dev/null
library=~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:./library
[privilege_escalation]
[paramiko_connection]
record_host_keys=False
[ssh_connection]
transfer_method=scp
[accelerate]
[selinux]
[colors]
[diff]

622
defaults/main.yml Normal file
View file

@ -0,0 +1,622 @@
---
# defaults file for rhel9-cis
rhel9cis_skip_for_travis: false
rhel9cis_system_is_container: false
# 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
rhel9cis_notauto: false
rhel9cis_section1: true
rhel9cis_section2: true
rhel9cis_section3: true
rhel9cis_section4: true
rhel9cis_section5: true
rhel9cis_section6: true
rhel9cis_level_1: true
rhel9cis_level_2: true
rhel9cis_selinux_disable: false
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
benchmark: RHEL9-CIS
# Whether to skip the reboot
rhel9cis_skip_reboot: true
#### Basic external goss audit enablement settings ####
#### Precise details - per setting can be found at the bottom of this file ####
### Goss is required on the remote host
setup_audit: false
# How to retrive goss
# 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
get_goss_file: download
# how to get audit files onto host options
# options are git/copy/get_url - use local if already available to to the host (adjust paths accordingly)
audit_content: git
# enable audits to run - this runs the audit and get the latest content
run_audit: false
# Timeout for those cmds that take longer to run where timeout set
audit_cmd_timeout: 30000
### End Goss enablements ####
#### Detailed settings found at the end of this document ####
# 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
rhel9cis_rule_1_1_1_1: true
rhel9cis_rule_1_1_1_2: 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_2: true
rhel9cis_rule_1_1_3: true
rhel9cis_rule_1_1_4: true
rhel9cis_rule_1_1_5: true
rhel9cis_rule_1_1_6: true
rhel9cis_rule_1_1_7: true
rhel9cis_rule_1_1_8: true
rhel9cis_rule_1_1_9: true
rhel9cis_rule_1_1_10: true
rhel9cis_rule_1_1_11: true
rhel9cis_rule_1_1_12: true
rhel9cis_rule_1_1_13: true
rhel9cis_rule_1_1_14: true
rhel9cis_rule_1_1_15: true
rhel9cis_rule_1_1_16: true
rhel9cis_rule_1_1_17: true
rhel9cis_rule_1_1_18: true
rhel9cis_rule_1_1_19: true
rhel9cis_rule_1_1_20: true
rhel9cis_rule_1_1_21: true
rhel9cis_rule_1_1_22: true
rhel9cis_rule_1_1_23: 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_2_5: true
rhel9cis_rule_1_3_1: true
rhel9cis_rule_1_3_2: true
rhel9cis_rule_1_3_3: true
rhel9cis_rule_1_4_1: true
rhel9cis_rule_1_4_2: true
rhel9cis_rule_1_5_1: true
rhel9cis_rule_1_5_2: true
rhel9cis_rule_1_5_3: true
rhel9cis_rule_1_6_1: true
rhel9cis_rule_1_6_2: true
rhel9cis_rule_1_7_1_1: true
rhel9cis_rule_1_7_1_2: true
rhel9cis_rule_1_7_1_3: true
rhel9cis_rule_1_7_1_4: true
rhel9cis_rule_1_7_1_5: true
rhel9cis_rule_1_7_1_6: true
rhel9cis_rule_1_7_1_7: true
rhel9cis_rule_1_8_1_1: true
rhel9cis_rule_1_8_1_2: true
rhel9cis_rule_1_8_1_3: true
rhel9cis_rule_1_8_1_4: true
rhel9cis_rule_1_8_1_5: true
rhel9cis_rule_1_8_1_6: true
rhel9cis_rule_1_8_2: true
rhel9cis_rule_1_9: true
rhel9cis_rule_1_10: true
rhel9cis_rule_1_11: true
# Section 2 rules
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_2_1_1: true
rhel9cis_rule_2_2_1_2: true
rhel9cis_rule_2_2_1_3: 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
rhel9cis_rule_2_3_1: true
rhel9cis_rule_2_3_2: true
rhel9cis_rule_2_3_3: true
# Section 3 rules
rhel9cis_rule_3_1_1: true
rhel9cis_rule_3_1_2: true
rhel9cis_rule_3_2_1: true
rhel9cis_rule_3_2_2: true
rhel9cis_rule_3_2_3: true
rhel9cis_rule_3_2_4: true
rhel9cis_rule_3_2_5: true
rhel9cis_rule_3_2_6: true
rhel9cis_rule_3_2_7: true
rhel9cis_rule_3_2_8: true
rhel9cis_rule_3_2_9: true
rhel9cis_rule_3_3_1: true
rhel9cis_rule_3_3_2: true
rhel9cis_rule_3_3_3: true
rhel9cis_rule_3_3_4: true
rhel9cis_rule_3_4_1_1: 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_3_1: true
rhel9cis_rule_3_4_3_2: true
rhel9cis_rule_3_4_3_3: true
rhel9cis_rule_3_4_3_4: true
rhel9cis_rule_3_4_3_5: true
rhel9cis_rule_3_4_3_6: true
rhel9cis_rule_3_4_3_7: true
rhel9cis_rule_3_4_3_8: true
rhel9cis_rule_3_4_4_1_1: true
rhel9cis_rule_3_4_4_1_2: true
rhel9cis_rule_3_4_4_1_3: true
rhel9cis_rule_3_4_4_1_4: true
rhel9cis_rule_3_4_4_1_5: true
rhel9cis_rule_3_4_4_2_1: true
rhel9cis_rule_3_4_4_2_2: true
rhel9cis_rule_3_4_4_2_3: true
rhel9cis_rule_3_4_4_2_4: true
rhel9cis_rule_3_4_4_2_5: true
rhel9cis_rule_3_5: true
rhel9cis_rule_3_6: true
# Section 4 rules
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: true
rhel9cis_rule_4_1_4: true
rhel9cis_rule_4_1_5: true
rhel9cis_rule_4_1_6: true
rhel9cis_rule_4_1_7: true
rhel9cis_rule_4_1_8: true
rhel9cis_rule_4_1_9: true
rhel9cis_rule_4_1_10: true
rhel9cis_rule_4_1_11: true
rhel9cis_rule_4_1_12: true
rhel9cis_rule_4_1_13: true
rhel9cis_rule_4_1_14: true
rhel9cis_rule_4_1_15: true
rhel9cis_rule_4_1_16: true
rhel9cis_rule_4_1_17: 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_2_1: true
rhel9cis_rule_4_2_2_2: true
rhel9cis_rule_4_2_2_3: true
rhel9cis_rule_4_2_3: true
rhel9cis_rule_4_3: true
# Section 5 rules
rhel9cis_rule_5_1_1: true
rhel9cis_rule_5_1_2: true
rhel9cis_rule_5_1_3: true
rhel9cis_rule_5_1_4: true
rhel9cis_rule_5_1_5: true
rhel9cis_rule_5_1_6: true
rhel9cis_rule_5_1_7: true
rhel9cis_rule_5_1_8: true
rhel9cis_rule_5_2_1: true
rhel9cis_rule_5_2_2: true
rhel9cis_rule_5_2_3: true
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_4_1: true
rhel9cis_rule_5_4_2: true
rhel9cis_rule_5_4_3: true
rhel9cis_rule_5_4_4: true
rhel9cis_rule_5_5_1_1: true
rhel9cis_rule_5_5_1_2: true
rhel9cis_rule_5_5_1_3: true
rhel9cis_rule_5_5_1_4: true
rhel9cis_rule_5_5_1_5: true
rhel9cis_rule_5_5_2: true
rhel9cis_rule_5_5_3: true
rhel9cis_rule_5_5_4: true
rhel9cis_rule_5_5_5: true
rhel9cis_rule_5_6: true
rhel9cis_rule_5_7: true
# Section 6 rules
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_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: false
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
rhel9cis_rule_6_2_17: true
rhel9cis_rule_6_2_18: true
rhel9cis_rule_6_2_19: true
rhel9cis_rule_6_2_20: true
# Service configuration booleans set true to keep service
rhel9cis_avahi_server: false
rhel9cis_cups_server: false
rhel9cis_dhcp_server: false
rhel9cis_ldap_server: false
rhel9cis_telnet_server: false
rhel9cis_nfs_server: false
rhel9cis_rpc_server: false
rhel9cis_ntalk_server: false
rhel9cis_rsyncd_server: false
rhel9cis_tftp_server: false
rhel9cis_rsh_server: false
rhel9cis_nis_server: false
rhel9cis_snmp_server: false
rhel9cis_squid_server: false
rhel9cis_smb_server: false
rhel9cis_dovecot_server: false
rhel9cis_httpd_server: false
rhel9cis_vsftpd_server: false
rhel9cis_named_server: false
rhel9cis_nfs_rpc_server: false
rhel9cis_is_mail_server: false
rhel9cis_bind: false
rhel9cis_vsftpd: false
rhel9cis_httpd: false
rhel9cis_dovecot: false
rhel9cis_samba: false
rhel9cis_squid: false
rhel9cis_net_snmp: false
rhel9cis_allow_autofs: false
## Section 1 vars
# 1.1.2
# These settings go into the /etc/fstab file for the /tmp mount settings
# The value must contain nosuid,nodev,noexec to conform to CIS standards
# rhel9cis_tmp_tmpfs_settings: "defaults,rw,nosuid,nodev,noexec,relatime 0 0"
# If set true uses the tmp.mount service else using fstab configuration
rhel9cis_tmp_svc: false
# 1.2.1
# This is the login information for your RedHat Subscription
# DO NOT USE PLAIN TEXT PASSWORDS!!!!!
# The intent here is to use a password utility like Ansible Vault here
rhel9cis_rh_sub_user: user
rhel9cis_rh_sub_password: password
# 1.2.2
# Do you require rhnsd
# RedHat Satellite Subscription items
rhel9cis_rhnsd_required: false
# 1.3.3 var log location variable
rhel9cis_varlog_location: "/var/log/sudo.log"
# xinetd required
rhel9cis_xinetd_required: false
# 1.4.2 Bootloader password
rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword'
rhel9cis_bootloader_password: random
rhel9cis_set_boot_pass: false
# 1.10/1.11 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS)
# Control 1.10 sates not ot use LEGACY and control 1.11 says to use FUTURE or FIPS.
rhel9cis_crypto_policy: "FUTURE"
# System network parameters (host only OR host and router)
rhel9cis_is_router: false
# IPv6 required
rhel9cis_ipv6_required: true
# AIDE
rhel9cis_config_aide: true
# AIDE cron settings
rhel9cis_aide_cron:
cron_user: root
cron_file: /etc/crontab
aide_job: '/usr/sbin/aide --check'
aide_minute: 0
aide_hour: 5
aide_day: '*'
aide_month: '*'
aide_weekday: '*'
# SELinux policy
rhel9cis_selinux_pol: targeted
# Whether or not to run tasks related to auditing/patching the desktop environment
rhel9cis_gui: no
# Set to 'true' if X Windows is needed in your environment
rhel9cis_xwindows_required: false
rhel9cis_openldap_clients_required: false
rhel9cis_telnet_required: false
rhel9cis_talk_required: false
rhel9cis_rsh_required: false
rhel9cis_ypbind_required: false
# 2.2.1.1 Time Synchronization - Either chrony or ntp
rhel9cis_time_synchronization: chrony
# 2.2.1.2 Time Synchronization servers - used in template file chrony.conf.j2
rhel9cis_time_synchronization_servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
- 3.pool.ntp.org
rhel9cis_chrony_server_options: "minpoll 8"
rhel9cis_ntp_server_options: "iburst"
## Section3 vars
# 3.4.2 | PATCH | Ensure /etc/hosts.allow is configured
rhel9cis_host_allow:
- "10.0.0.0/255.0.0.0"
- "172.16.0.0/255.240.0.0"
- "192.168.0.0/255.255.0.0"
# Firewall Service - either firewalld, iptables, or nftables
rhel9cis_firewall: firewalld
# 3.4.2.4 Default zone setting
rhel9cis_default_zone: public
# 3.4.2.5 Zone and Interface setting
rhel9cis_int_zone: customezone
rhel9cis_interface: eth0
rhel9cis_firewall_services:
- ssh
- dhcpv6-client
# 3.4.3.2 Set nftables new table create
rhel9cis_nft_tables_autonewtable: true
rhel9cis_nft_tables_tablename: filter
# 3.4.3.3 Set nftables new chain create
rhel9cis_nft_tables_autochaincreate: true
# Warning Banner Content (issue, issue.net, motd)
rhel9cis_warning_banner: |
Authorized uses only. All activity may be monitored and reported.
# End Banner
## Section4 vars
rhel9cis_auditd:
space_left_action: email
action_mail_acct: root
admin_space_left_action: halt
max_log_file_action: keep_logs
rhel9cis_logrotate: "daily"
# The audit_back_log_limit value should never be below 8192
rhel9cis_audit_back_log_limit: 8192
# The max_log_file parameter should be based on your sites policy
rhel9cis_max_log_file_size: 10
# RHEL-09-4.2.1.4/4.2.1.5 remote and destation log server name
rhel9cis_remote_log_server: logagg.example.com
# RHEL-09-4.2.1.5
rhel9cis_system_is_log_server: false
## Section5 vars
rhel9cis_sshd:
clientalivecountmax: 0
clientaliveinterval: 900
ciphers: "aes256-ctr,aes192-ctr,aes128-ctr"
macs: "hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com"
logingracetime: 60
# WARNING: make sure you understand the precedence when working with these values!!
# allowusers:
# allowgroups: systems dba
# denyusers:
# denygroups:
rhel9cis_pam_faillock:
attempts: 5
interval: 900
unlock_time: 900
fail_for_root: no
remember: 5
pwhash: sha512
# 5.2.5 SSH LogLevel setting. Options are INFO or VERBOSE
rhel9cis_ssh_loglevel: INFO
# 5.2.19 SSH MaxSessions setting. Must be 4 our less
rhel9cis_ssh_maxsessions: 4
rhel9cis_inactivelock:
lock_days: 30
# 5.3.1/5.3.2 Custom authselect profile settings. Settings in place now will fail, they are place holders from the control example
# Due to the way many multiple options and ways to configure this control needs to be enabled and settings adjusted to minimise risk
rhel9cis_use_authconfig: false
rhel9cis_authselect:
custom_profile_name: custom-profile
default_file_to_copy: "sssd --symlink-meta"
options: with-sudo with-faillock without-nullok
# 5.3.1 Enable automation to create custom profile settings, using the settings above
rhel9cis_authselect_custom_profile_create: false
# 5.3.2 Enable automation to select custom profile options, using the settings above
rhel9cis_authselect_custom_profile_select: false
rhel9cis_pass:
max_days: 365
min_days: 7
warn_age: 7
# Syslog system - either rsyslog or syslog-ng
rhel9cis_syslog: rsyslog
rhel9cis_rsyslog_ansiblemanaged: true
rhel9cis_vartmp:
source: /tmp
fstype: none
opts: "defaults,nodev,nosuid,noexec,bind"
enabled: no
## PAM
rhel9cis_pam_password:
minlen: "14"
minclass: "4"
# Starting GID for interactive users
rhel9cis_int_gid: 1000
# RHEL-09-5.4.5
# 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:
file: /etc/profile.d/tmout.sh
timeout: 600
# RHEL-09-5.4.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords
rhel9cis_futurepwchgdate_autofix: true
# 5.7
# rhel9cis_sugroup: sugroup # change accordingly wheel is default
# wheel users list
rhel9cis_sugroup_users: "root"
## Section6 vars
# RHEL-09_6.1.1
rhel9cis_rpm_audit_file: /var/tmp/rpm_file_check
# RHEL-09_6.1.10 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
rhel9cis_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}"
# 6.2.9
rhel9cis_dotperm_ansiblemanaged: true
#### Goss Configuration Settings ####
### Goss binary settings ###
goss_version:
release: v0.3.16
checksum: 'sha256:827e354b48f93bce933f5efcd1f00dc82569c42a179cf2d384b040d8a80bfbfb'
audit_bin_path: /usr/local/bin/
audit_bin: "{{ audit_bin_path }}goss"
audit_format: json
# if get_goss_file == download change accordingly
goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version.release }}/goss-linux-amd64"
## if get_goss_file - copy the following needs to be updated for your environment
## it is expected that it will be copied from somewhere accessible to the control node
## e.g copy from ansible control node to remote host
copy_goss_from_path: /some/accessible/path
### 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: main
# copy:
audit_local_copy: "some path to copy from"
# get_url:
audit_files_url: "some url maybe s3?"
# Where the goss audit configuration will be stored
audit_files: "/var/tmp/{{ benchmark }}-Audit/"
## Goss configuration information
# Where the goss configs and outputs are stored
audit_out_dir: '/var/tmp'
audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit/"
pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_pre_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_post_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
## The following should not need changing
goss_file: "{{ audit_conf_dir }}goss.yml"
audit_vars_path: "{{ audit_conf_dir }}/vars/{{ ansible_hostname }}.yml"
audit_results: |
The pre remediation results are: {{ pre_audit_summary }}.
The post remediation results are: {{ post_audit_summary }}.
Full breakdown can be found in {{ audit_out_dir }}

View file

@ -0,0 +1,25 @@
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Temporary Directory
Documentation=man:hier(7)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
ConditionPathIsSymbolicLink=!/tmp
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target
[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,noexec,nodev,nosuid
# Make 'systemctl enable tmp.mount' work:
[Install]
WantedBy=local-fs.target

28
group_vars/docker Normal file
View file

@ -0,0 +1,28 @@
---
ansible_user: root
# AIDE cron settings
rhel9cis_aide_cron:
cron_user: root
cron_file: /var/spool/cron/root
aide_job: '/usr/sbin/aide --check'
aide_minute: 0
aide_hour: 5
aide_day: '*'
aide_month: '*'
aide_weekday: '*'
rhel9cis_sshd:
clientalivecountmax: 3
clientaliveinterval: 300
ciphers: "aes256-ctr,aes192-ctr,aes128-ctr"
macs: "hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com"
logingracetime: 60
# - make sure you understand the precedence when working with these values!!
allowusers: vagrant
allowgroups: vagrant
denyusers: root
denygroups: root
# Workarounds for Docker
rhel9cis_skip_for_travis: true
rhel9cis_selinux_disable: true

28
group_vars/vagrant Normal file
View file

@ -0,0 +1,28 @@
---
ansible_user: vagrant
# AIDE cron settings
rhel9cis_aide_cron:
cron_user: root
cron_file: /var/spool/cron/root
aide_job: '/usr/sbin/aide --check'
aide_minute: 0
aide_hour: 5
aide_day: '*'
aide_month: '*'
aide_weekday: '*'
rhel9cis_sshd:
clientalivecountmax: 3
clientaliveinterval: 300
ciphers: 'aes256-ctr,aes192-ctr,aes128-ctr'
macs: 'hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com'
logingracetime: 60
# - make sure you understand the precedence when working with these values!!
allowusers: vagrant
allowgroups: vagrant
denyusers: root
denygroups: root
# Vagrant can touch code that Docker cannot
rhel9cis_skip_for_travis: false
rhel9cis_selinux_disable: false

134
handlers/main.yml Normal file
View file

@ -0,0 +1,134 @@
---
# handlers file for RHEL9-CIS
- name: sysctl flush ipv4 route table
become: yes
sysctl:
name: net.ipv4.route.flush
value: '1'
sysctl_set: yes
ignore_errors: yes
when: ansible_virtualization_type != "docker"
tags:
- skip_ansible_lint
- name: sysctl flush ipv6 route table
become: yes
sysctl:
name: net.ipv6.route.flush
value: '1'
sysctl_set: yes
when: ansible_virtualization_type != "docker"
- name: update sysctl
template:
src: etc/99-sysctl.conf.j2
dest: /etc/sysctl.d/99-sysctl.conf
owner: root
group: root
mode: 0600
notify: reload sysctl
when: ansible_virtualization_type != "docker"
- name: reload sysctl
sysctl:
name: net.ipv4.route.flush
value: '1'
state: present
reload: yes
ignoreerrors: yes
when: ansible_virtualization_type != "docker"
- name: systemd restart tmp.mount
become: yes
systemd:
name: tmp.mount
daemon_reload: yes
enabled: yes
masked: no
state: reloaded
- name: systemd restart var-tmp.mount
become: yes
systemd:
name: var-tmp.mount
daemon_reload: yes
enabled: yes
masked: no
state: reloaded
- name: remount tmp
command: mount -o remount /tmp
args:
warn: false
- name: restart firewalld
become: yes
service:
name: firewalld
state: restarted
- name: restart xinetd
become: yes
service:
name: xinetd
state: restarted
- name: restart sshd
become: yes
service:
name: sshd
state: restarted
- name: restart postfix
become: yes
service:
name: postfix
state: restarted
- name: reload dconf
become: yes
command: dconf update
- name: update auditd
template:
src: audit/99_auditd.rules.j2
dest: /etc/audit/rules.d/99_auditd.rules
owner: root
group: root
mode: 0600
notify: restart auditd
- name: restart auditd
command: /sbin/service auditd restart
changed_when: no
check_mode: no
failed_when: no
args:
warn: no
when:
- not rhel9cis_skip_for_travis
tags:
- skip_ansible_lint
- name: grub2cfg
command: "grub2-mkconfig -o {{ grub_cfg.stat.lnk_source }}"
ignore_errors: True
tags:
- skip_ansible_lint
- name: restart rsyslog
become: yes
service:
name: rsyslog
state: restarted
- name: restart syslog-ng
become: yes
service:
name: syslog-ng
state: restarted
- name: systemd_daemon_reload
systemd:
daemon-reload: yes

12
local.yml Normal file
View file

@ -0,0 +1,12 @@
---
- hosts: localhost
connection: local
become: true
vars:
is_container: false
roles:
- role: "{{ playbook_dir }}"
rhel9cis_system_is_container: "{{ is_container | default(false) }}"
rhel9cis_skip_for_travis: false

18
meta/main.yml Normal file
View file

@ -0,0 +1,18 @@
---
galaxy_info:
author: "Sam Doran, Josh Springer, Daniel Shepherd, Bas Meijeri, James Cassell, Mike Renfro, DFed, George Nalen, Mark Bolwell"
description: "Apply the RHEL 8 CIS"
company: "MindPoint Group"
license: MIT
role_name: rhel9_cis
min_ansible_version: 2.9.0
platforms:
- name: EL
versions:
- 9
galaxy_tags:
- system
- security
- cis
- hardening
dependencies: []

11
site.yml Normal file
View file

@ -0,0 +1,11 @@
---
- hosts: all
become: true
vars:
is_container: false
roles:
- role: "{{ playbook_dir }}"
rhel9cis_system_is_container: "{{ is_container | default(false) }}"
rhel9cis_skip_for_travis: false

22
tasks/LE_audit_setup.yml Normal file
View file

@ -0,0 +1,22 @@
---
- name: Download audit binary
get_url:
url: "{{ goss_url }}"
dest: "{{ audit_bin }}"
owner: root
group: root
checksum: "{{ goss_version.checksum }}"
mode: 0555
when:
- get_goss_file == 'download'
- name: copy audit binary
copy:
src:
dest: "{{ audit_bin }}"
mode: 0555
owner: root
group: root
when:
- get_goss_file == 'copy'

View file

@ -0,0 +1,46 @@
---
- name: "SCORED | 6.2.8 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
find:
paths:
- "{{ homedir }}"
recurse: true
file_type: any
register: rhel_09_6_2_8_results
when:
- rhel9cis_rule_6_2_8|bool
tags:
- level1
- patch
- rule_6.2.8
- name: "SCORED | 6.2.8 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
file:
path: "{{ line_item.path }}"
mode: 0640
loop: "{{ rhel_09_6_2_8_results.files }}"
loop_control:
label: "{{ line_item.path }}"
loop_var: line_item
when:
- rhel_09_6_2_8_results.files.isreg is defined
- rhel9cis_rule_6_2_8|bool
tags:
- level1
- patch
- rule_6.2.8
- name: "SCORED | 6.2.8 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
file:
path: "{{ line_item.path }}"
mode: 0750
loop: "{{ rhel_09_6_2_8_results.files }}"
loop_control:
label: "{{ line_item.path }}"
loop_var: line_item
when:
- rhel_09_6_2_8_results.files.isdir is defined
- rhel9cis_rule_6_2_8|bool
tags:
- level1
- patch
- rule_6.2.8

36
tasks/check_prereqs.yml Normal file
View file

@ -0,0 +1,36 @@
---
- name: "PREREQ | Add the required packages | Python 3"
block:
- name: Check if python36-rpm package installed
command: rpm -q python36-rpm
failed_when: ( python36_rpm_present.rc not in [ 0, 1 ] )
changed_when: false
args:
warn: false
register: python36_rpm_present
- name: Add the EPEL repository required for the python36-rpm pkg
package:
name: https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
state: present
register: epel_installed
when:
- python36_rpm_present.rc != '0'
- name: "PREREQ | Check required packages installed | Python3 "
package:
name: "{{ item }}"
state: present
register: python3reqs_installed
loop:
- python36-rpm
- libselinux-python3
- name: Disable Epel repo if installed earlier
command: yum-config-manager disable epel
when: epel_installed.changed
when:
- ( ansible_python.version.major == 3 and ansible_python.version.minor == 6 )
vars:
ansible_python_interpreter: "{{ python2_bin }}"

111
tasks/main.yml Normal file
View file

@ -0,0 +1,111 @@
---
# tasks file for RHEL9-CIS
- name: Check OS version and family
fail:
msg: "This role can only be run against RHEL 8. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported."
when:
- ansible_os_family == 'RedHat'
- ansible_distribution_major_version is version_compare('9', '!=')
tags:
- always
- name: Check ansible version
fail:
msg: You must use ansible 2.9 or greater
when: not ansible_version.full is version_compare('2.9', '>=')
tags:
- always
- name: Check crypto-policy input
assert:
that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies
- name: Check rhel9cis_bootloader_password_hash variable has been changed
assert:
that: rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword'
msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set"
when:
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_5_2
- name: "check sugroup exists if used"
block:
- name: "Check su group exists if defined"
shell: grep -w "{{ rhel9cis_sugroup }}" /etc/group
register: sugroup_exists
changed_when: false
failed_when: sugroup_exists.rc >= 2
tags:
- skip_ansible_lint
- name: Check sugroup if defined exists before continuing
assert:
that: sugroup_exists.rc == 0
msg: "The variable rhel9cis_sugroup is defined but does not exist please rectify"
when:
- rhel9cis_sugroup is defined
- rhel9cis_rule_5_7
tags:
- rule_5.7
- include: prelim.yml
become: yes
tags:
- prelim_tasks
- always
- import_tasks: pre_remediation_audit.yml
when:
- run_audit
- name: Gather the package facts
package_facts:
manager: auto
tags:
- always
- include: parse_etc_password.yml
become: yes
when: rhel9cis_section6
- include: section_1/main.yml
become: yes
when: rhel9cis_section1
tags:
- rhel9cis_section1
- include: section_2/main.yml
become: yes
when: rhel9cis_section2
- include: section_3/main.yml
become: yes
when: rhel9cis_section3
- include: section_4/main.yml
become: yes
when: rhel9cis_section4
- include: section_5/main.yml
become: yes
when: rhel9cis_section5
- include: section_6/main.yml
become: yes
when: rhel9cis_section6
- include: post.yml
become: yes
tags:
- post_tasks
- always
- import_tasks: post_remediation_audit.yml
when:
- run_audit
- name: Show Audit Summary
debug:
msg: "{{ audit_results.split('\n') }}"
when:
- run_audit

View file

@ -0,0 +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"
command: cat /etc/passwd
changed_when: no
check_mode: no
register: rhel9cis_passwd_file_audit
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries"
set_fact:
rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}"
with_items: "{{ rhel9cis_passwd_file_audit.stdout_lines }}"
vars:
ld_passwd_regex: >-
^(?P<id>[^:]*):(?P<password>[^:]*):(?P<uid>[^:]*):(?P<gid>[^:]*):(?P<gecos>[^:]*):(?P<dir>[^:]*):(?P<shell>[^:]*)
ld_passwd_yaml: |
id: >-4
\g<id>
password: >-4
\g<password>
uid: \g<uid>
gid: \g<gid>
gecos: >-4
\g<gecos>
dir: >-4
\g<dir>
shell: >-4
\g<shell>
tags:
- always

56
tasks/post.yml Normal file
View file

@ -0,0 +1,56 @@
---
# Post tasks
- name: Perform DNF package cleanup
dnf:
autoremove: yes
changed_when: no
- name: trigger update sysctl
command: /bin/true
changed_when: false
check_mode: false
notify: update sysctl
when:
- rhel9cis_rule_1_6_1 or
rhel9cis_rule_1_6_2 or
rhel9cis_rule_3_1_2 or
rhel9cis_rule_3_1_2 or
rhel9cis_rule_3_2_1 or
rhel9cis_rule_3_2_2 or
rhel9cis_rule_3_2_3 or
rhel9cis_rule_3_2_4 or
rhel9cis_rule_3_2_5 or
rhel9cis_rule_3_2_6 or
rhel9cis_rule_3_2_7 or
rhel9cis_rule_3_2_8 or
rhel9cis_rule_3_2_9
tags:
- sysctl
- name: trigger update auditd
command: /bin/true
notify: update auditd
changed_when: false
check_mode: false
when:
- rhel9cis_rule_4_1_3 or
rhel9cis_rule_4_1_4 or
rhel9cis_rule_4_1_5 or
rhel9cis_rule_4_1_6 or
rhel9cis_rule_4_1_7 or
rhel9cis_rule_4_1_8 or
rhel9cis_rule_4_1_9 or
rhel9cis_rule_4_1_10 or
rhel9cis_rule_4_1_11 or
rhel9cis_rule_4_1_12
tags:
- auditd
- name: flush handlers
meta: flush_handlers
- name: Reboot host
reboot:
when:
- not rhel9cis_skip_reboot

View file

@ -0,0 +1,43 @@
---
- name: "Post Audit | Run post_remediation {{ benchmark }} audit"
shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ post_audit_outfile }} -g {{ group_names }}"
vars:
warn: false
- name: Post Audit | ensure audit files readable by users
file:
path: "{{ item }}"
mode: 0644
state: file
loop:
- "{{ post_audit_outfile }}"
- "{{ pre_audit_outfile }}"
- name: Post Audit | Capture audit data if json format
block:
- name: "capture data {{ post_audit_outfile }}"
command: "cat {{ post_audit_outfile }}"
register: post_audit
changed_when: false
- name: Capture post-audit result
set_fact:
post_audit_summary: "{{ post_audit.stdout | from_json |json_query(summary) }}"
vars:
summary: 'summary."summary-line"'
when:
- audit_format == "json"
- name: Post Audit | Capture audit data if documentation format
block:
- name: "Post Audit | capture data {{ post_audit_outfile }}"
command: "tail -2 {{ post_audit_outfile }}"
register: post_audit
changed_when: false
- name: Post Audit | Capture post-audit result
set_fact:
post_audit_summary: "{{ post_audit.stdout_lines }}"
when:
- audit_format == "documentation"

View file

@ -0,0 +1,118 @@
---
- name: Pre Audit | Setup the audit
include_tasks: LE_audit_setup.yml
when:
- setup_audit
tags:
- setup_audit
- name: "Pre Audit | Ensure {{ audit_conf_dir }} exists"
file:
path: "{{ audit_conf_dir }}"
state: directory
mode: '0755'
- name: Pre Audit | If using git for content set up
block:
- name: Pre Audit | Install git (rh8 python3)
package:
name: git
state: present
when: ansible_distribution_major_version == 8
- name: Pre Audit | Install git (rh7 python2)
package:
name: git
state: present
vars:
ansible_python_interpreter: "{{ python2_bin }}"
when: ansible_distribution_major_version == 7
- name: Pre Audit | retrieve audit content files from git
git:
repo: "{{ audit_file_git }}"
dest: "{{ audit_conf_dir }}"
version: "{{ audit_git_version }}"
when:
- audit_content == 'git'
- name: Pre Audit | copy to audit content files to server
copy:
src: "{{ audit_local_copy }}"
dest: "{{ audit_conf_dir }}"
mode: 0644
when:
- audit_content == 'copy'
- name: Pre Audit | get audit content from url
get_url:
url: "{{ audit_files_url }}"
dest: "{{ audit_conf_dir }}"
when:
- audit_content == 'get_url'
- name: Pre Audit | Check Goss is available
block:
- name: Pre Audit | Check for goss file
stat:
path: "{{ audit_bin }}"
register: goss_available
- name: Pre Audit | If audit ensure goss is available
assert:
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 | Check whether machine is UEFI-based"
stat:
path: /sys/firmware/efi
register: rhel9_efi_boot
tags:
- goss_template
- name: Pre Audit | Copy ansible default vars values to test audit
template:
src: ansible_vars_goss.yml.j2
dest: "{{ audit_vars_path }}"
mode: 0600
when:
- run_audit
tags:
- goss_template
- name: "Pre Audit | Run pre_remediation {{ benchmark }} audit"
shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}"
vars:
warn: false
- name: Pre Audit | Capture audit data if json format
block:
- name: "Pre Audit | capture data {{ pre_audit_outfile }}"
command: "cat {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
- name: Pre Audit | Capture pre-audit result
set_fact:
pre_audit_summary: "{{ pre_audit.stdout | from_json |json_query(summary) }}"
vars:
summary: 'summary."summary-line"'
when:
- audit_format == "json"
- name: Pre Audit | Capture audit data if documentation format
block:
- name: "Pre Audit | capture data {{ pre_audit_outfile }}"
command: "tail -2 {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
- name: Pre Audit | Capture pre-audit result
set_fact:
pre_audit_summary: "{{ pre_audit.stdout_lines }}"
when:
- audit_format == "documentation"

119
tasks/prelim.yml Normal file
View file

@ -0,0 +1,119 @@
---
# Preliminary tasks that should always be run
# List users in order to look files inside each home directory
- name: "PRELIM | List users accounts"
command: "awk -F: '{print $1}' /etc/passwd"
args:
warn: no
changed_when: no
check_mode: no
register: users
- name: "PRELIM | Gather accounts with empty password fields"
shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'"
args:
warn: no
changed_when: no
check_mode: no
register: empty_password_accounts
- name: "PRELIM | Gather UID 0 accounts other than root"
shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'"
args:
warn: no
changed_when: no
check_mode: no
register: uid_zero_accounts_except_root
- name: "PRELIM | Gather system-wide crypto-policy"
shell: update-crypto-policies --show
args:
warn: no
changed_when: no
check_mode: no
register: system_wide_crypto_policy
- name: "PRELIM | if systemd coredump"
stat:
path: /etc/systemd/coredump.conf
register: systemd_coredump
when:
- rhel9cis_rule_1_6_1
- name: "PRELIM | Section 1.1 | Create list of mount points"
set_fact:
mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}"
- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)"
package:
name: audit
state: present
when: rhel9cis_level_2
- name: "PRELIM | 4.1.12 | Ensure successful file system mounts are collected"
shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null; done
changed_when: false
failed_when: false
check_mode: no
register: priv_procs
tags:
- always
- name: "PRELIM | Section 5.1 | Configure cron"
package:
name: cronie
state: present
- name: "PRELIM | Install authconfig"
package:
name: authconfig
state: present
when:
- rhel9cis_use_authconfig
- rhel9cis_rule_5_3_1 or
rhel9cis_rule_5_3_2 or
rhel9cis_rule_5_3_3
- name: "PRELIM | Set facts based on boot type"
block:
- name: "PRELIM | Check whether machine is UEFI-based"
stat:
path: /sys/firmware/efi
register: rhel_09_efi_boot
- name: "PRELIM | AUDIT | set legacy boot and grub path | Bios"
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"
set_fact:
grub2_path: /etc/grub2-efi.cfg
when: rhel_09_efi_boot.stat.exists
# - name: debug legacy boot var
# debug:
# msg: |
# legacy_boot={{ rhel9cis_legacy_boot }}
# grub2_path={{ grub2_path }}
- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats"
stat:
path: "{{ grub2_path }}"
changed_when: false
register: grub_cfg
# - name: debug grub stat
# debug:
# var: grub_cfg.stat
- name: "PRELIM | Check for rhnsd service"
shell: "systemctl show rhnsd | grep LoadState | cut -d = -f 2"
changed_when: false
check_mode: false
register: rhnsd_service_status
when:
- rhel9cis_rule_1_2_2
tags:
- skip_ansible_lint

View file

@ -0,0 +1,102 @@
---
- name: "1.1.1.1 | L1 | PATCH | Ensure mounting of cramfs filesystems is disabled"
block:
- name: "1.1.1.1 | L1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Edit modprobe config"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install cramfs(\\s|$)"
line: "install cramfs /bin/true"
create: yes
mode: 0600
- name: "1.1.1.1 | L1 | PATCH | Ensure mounting of cramfs filesystems is disabled | Disable cramfs"
modprobe:
name: cramfs
state: absent
when: ansible_connection != 'docker'
when:
- rhel9cis_rule_1_1_1_1
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.1.1.1
- cramfs
- name: "1.1.1.2 | L2 | PATCH | Ensure mounting of vFAT filesystems is limited"
block:
- name: "1.1.1.2 | L2 | PATCH | Ensure mounting of vFAT filesystems is limited | Edit modprobe config"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install vfat(\\s|$)"
line: "install vfat /bin/true"
create: yes
mode: 0600
- name: "1.1.1.2 | L2 | PATCH | Ensure mounting of vFAT filesystems is limited | Disable vFAT"
modprobe:
name: vfat
state: absent
when: ansible_connection != 'docker'
when:
- rhel9cis_rule_1_1_1_2
- rhel9cis_legacy_boot
tags:
- level2-server
- level2-workstation
- scored
- patch
- rule_1.1.1.2
- vfat
- name: "1.1.1.3 | L1 | PATCH | Ensure mounting of squashfs filesystems is disabled"
block:
- name: "1.1.1.3 | L1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Edit modprobe config"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install squashfs(\\s|$)"
line: "install squashfs /bin/true"
create: yes
mode: 0600
- name: "1.1.1.3 | L1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs"
modprobe:
name: squashfs
state: absent
when: ansible_connection != 'docker'
when:
- rhel9cis_rule_1_1_1_3
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.1.1.3
- squashfs
- name: "1.1.1.4 | L1 | PATCH | Ensure mounting of udf filesystems is disabled"
block:
- name: "1.1.1.4 | L1 | PATCH | Ensure mounting of udf filesystems is disable | Edit modprobe config"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install udf(\\s|$)"
line: "install udf /bin/true"
create: yes
mode: 0600
- name: "1.1.1.4 | L1 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf"
modprobe:
name: udf
state: absent
when: ansible_connection != 'docker'
when:
- rhel9cis_rule_1_1_1_4
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.1.1.4
- udf

View file

@ -0,0 +1,363 @@
---
- name: |
"SCORED | 1.1.2 | PATCH | Ensure /tmp is configured"
"SCORED | 1.1.3 | PATCH | Ensure nodev option set on /tmp partition"
"SCORED | 1.1.4 | PATCH | Ensure nosuid option set on /tmp partition"
"SCORED | 1.1.5 | PATCH | Ensure noexec option set on /tmp partition"
"via fstab"
mount:
name: /tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5 %}nosuid{% endif %}
notify: remount tmp
loop: "{{ ansible_mounts }}"
when:
- item.mount == "/tmp"
- not rhel9cis_tmp_svc
- rhel9cis_rule_1_1_2 or
rhel9cis_rule_1_1_3 or
rhel9cis_rule_1_1_4 or
rhel9cis_rule_1_1_5
tags:
- level1-server
- level1-workstation
- scored
- patch
- mounts
- rule_1.1.3
- rule_1.1.4
- rule_1.1.5
- name: |
"SCORED | 1.1.2 | PATCH | Ensure /tmp is configured"
"SCORED | 1.1.3 | PATCH | Ensure nodev option set on /tmp partition"
"SCORED | 1.1.4 | PATCH | Ensure nosuid option set on /tmp partition"
"SCORED | 1.1.5 | PATCH | Ensure noexec option set on /tmp partition"
"via systemd"
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 or
rhel9cis_rule_1_1_3 or
rhel9cis_rule_1_1_4 or
rhel9cis_rule_1_1_5
tags:
- level1-server
- level1-workstation
- scored
- patch
- mounts
- rule_1.1.3
- rule_1.1.4
- rule_1.1.5
- name: "1.1.6 | L2 | AUDIT | Ensure separate partition exists for /var"
block:
- name: "1.1.6 | L2 | AUDIT | Ensure separate partition exists for /var | Absent"
debug:
msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task"
register: var_mount_absent
changed_when: var_mount_absent.skipped is undefined
when:
- required_mount not in mount_names
- name: "1.1.6 | L2 | AUDIT | Ensure separate partition exists for /var | Present"
debug:
msg: "Congratulations: {{ required_mount }} exists."
when:
- required_mount in mount_names
vars:
required_mount: '/var'
when:
- rhel9cis_rule_1_1_6
tags:
- level2-server
- level2-workstation
- scored
- patch
- mounts
- rule_1.1.6
- name: "1.1.7 | L2 | AUDIT | Ensure separate partition exists for /var/tmp | skips if mount absent"
block:
- name: "1.1.7 | L2 | AUDIT | Ensure separate partition exists for /var/tmp | Absent"
debug:
msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task"
register: var_tmp_mount_absent
changed_when: var_tmp_mount_absent.skipped is undefined
when:
- required_mount not in mount_names
- name: "1.1.7 | L2 | AUDIT | Ensure separate partition exists for /var/tmp | Present"
debug:
msg: "Congratulations: {{ required_mount }} exists."
register: var_tmp_mount_present
when:
- required_mount in mount_names
vars:
required_mount: '/var/tmp'
when:
- rhel9cis_rule_1_1_7
tags:
- level2-server
- level2-workstation
- scored
- audit
- mounts
- rule_1.1.7
- name: |
"1.1.8 | L1 | PATCH | Ensure nodev option set on /var/tmp partition | skips if mount absent"
"1.1.9 | L1 | PATCH | Ensure nosuid option set on /var/tmp partition | skips if mount absent"
"1.1.10 | L1 | PATCH | Ensure noexec option set on /var/tmp partition | skips if mount absent"
mount:
name: /var/tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_10 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_9 %}nosuid{% endif %}
loop: "{{ ansible_mounts }}"
when:
- var_tmp_mount_present is defined
- item.mount == "/var/tmp"
- rhel9cis_rule_1_1_7 # This is required so the check takes place
- rhel9cis_rule_1_1_8 or
rhel9cis_rule_1_1_9 or
rhel9cis_rule_1_1_10
tags:
- level1-server
- level1-workstation
- scored
- patch
- mounts
- skip_ansible_lint
- name: "1.1.11 | L2 | AUDIT | Ensure separate partition exists for /var/log"
block:
- name: "1.1.11 | L2 | AUDIT | Ensure separate partition exists for /var/log | Absent"
debug:
msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task"
register: var_log_mount_absent
changed_when: var_log_mount_absent.skipped is undefined
when:
- required_mount not in mount_names
- name: "1.1.11 | L2 | AUDIT | Ensure separate partition exists for /var/log | Present"
debug:
msg: "Congratulations: {{ required_mount }} exists."
when:
- required_mount in mount_names
vars:
required_mount: '/var/log'
when:
- rhel9cis_rule_1_1_11
tags:
- level2-server
- level2-workstation
- scored
- audit
- mounts
- rule_1.1.11
- skip_ansible_lint
- name: "1.1.12 | L2 | AUDIT | Ensure separate partition exists for /var/log/audit"
block:
- name: "1.1.12 | L2 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent"
debug:
msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task"
register: var_log_audit_mount_absent
changed_when: var_log_audit_mount_absent.skipped is undefined
when:
- required_mount not in mount_names
- name: "1.1.12 | L2 | AUDIT | Ensure separate partition exists for /var/log/audit | Present"
debug:
msg: "Congratulations: {{ required_mount }} exists."
when:
- required_mount in mount_names
vars:
required_mount: '/var/log/audit'
when:
- rhel9cis_rule_1_1_12
tags:
- level2-server
- level2-workstation
- scored
- audit
- mounts
- rule_1.1.12
- name: "1.1.13 | L2 | AUDIT | Ensure separate partition exists for /home"
block:
- name: "1.1.13 | L2 | AUDIT | Ensure separate partition exists for /home | Absent"
debug:
msg: "Warning! {{ required_mount }} doesn't exist. This is a manual task"
register: home_mount_absent
changed_when: home_mount_absent.skipped is undefined
when:
- required_mount not in mount_names
- name: "1.1.13 | L2 | AUDIT | Ensure separate partition exists for /home | Present"
debug:
msg: "Congratulations: {{ required_mount }} exists."
register: home_mount_present
when:
- required_mount in mount_names
vars:
required_mount: '/home'
when:
- rhel9cis_rule_1_1_13
tags:
- level2-server
- level2-workstation
- scored
- audit
- mounts
- rule_1.1.13
- skip_ansible_lint
- name: "1.1.14 | L1 | PATCH | Ensure nodev option set on /home partition | skips if mount absent"
mount:
name: /home
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_14 %}nodev{% endif %}
loop: "{{ ansible_mounts }}"
when:
- home_mount_present is defined
- item.mount == "/home"
- rhel9cis_rule_1_1_14
tags:
- level1-server
- level1-workstation
- scored
- patch
- mounts
- rule_1.1.13
- skip_ansible_lint
- name: |
"1.1.15 | L1 | PATCH | Ensure nodev option set on /dev/shm partition | skips if mount absent
1.1.16 | L1 | PATCH | Ensure nosuid option set on /dev/shm partition | skips if mount absent
1.1.17 | L1 | PATCH | Ensure noexec option set on /dev/shm partition | skips if mount absent"
block:
- name: |
"1.1.15 | L1 | AUDIT | Ensure nodev option set on /dev/shm partition | Check for /dev/shm existence
1.1.16 | L1 | AUDIT | Ensure nosuid option set on /dev/shm partition | Check for /dev/shm existence
1.1.17 | L1 | AUDIT | Ensure noexec option set on /dev/shm partition | Check for /dev/shm existence"
shell: mount -l | grep -E '\s/dev/shm\s'
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_1_1_15_dev_shm_status
- name: |
"1.1.15 | L1 | PATCH | Ensure nodev option set on /dev/shm partition | skips if mount absent
1.1.16 | L1 | PATCH | Ensure nosuid option set on /dev/shm partition | skips if mount absent
1.1.17 | L1 | PATCH | Ensure noexec option set on /dev/shm partition | skips if mount absent"
mount:
name: /dev/shm
src: tmpfs
fstype: tmpfs
state: mounted
opts: defaults,{% if rhel9cis_rule_1_1_17 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_15 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_16 %}nosuid{% endif %}
when: "'dev/shm' in rhel9cis_1_1_15_dev_shm_status.stdout"
when:
- rhel9cis_rule_1_1_15 or
rhel9cis_rule_1_1_16 or
rhel9cis_rule_1_1_17
tags:
- level1-server
- level1-workstation
- scored
- patch
- mounts
- rule_1.1.15
- rule_1.1.16
- rule_1.1.17
- name: |
"1.1.18 | L1 | PATCH | Ensure nodev option set on removable media partitions"
"1.1.19 | L1 | PATCH | Ensure nosuid option set on removable media partitions"
"1.1.20 | L1 | PATCH | Ensure noexec option set on removable media partitions"
debug:
msg: "--> Not relevant"
changed_when: false
when:
- rhel9cis_rule_1_1_18 or
rhel9cis_rule_1_1_19 or
rhel9cis_rule_1_1_20
tags:
- level1-server
- level1-workstation
- notscored
- audit
- mounts
- rule_1.1.18
- rule_1.1.19
- rule_1.1.20
- name: "1.1.21 | L1 | PATCH | Ensure sticky bit is set on all world-writable directories"
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
args:
warn: no
changed_when: false
failed_when: false
when:
- rhel9cis_rule_1_1_21
tags:
- skip_ansible_lint
- level1-server
- level1-workstation
- patch
- stickybits
- permissons
- rule_1.1.21
- name: "1.1.22 | L1 | PATCH | Disable Automounting"
service:
name: autofs
enabled: no
when:
- not rhel9cis_allow_autofs
- "'autofs' in ansible_facts.packages"
- rhel9cis_rule_1_1_22
tags:
- level1-server
- level2-workstation
- patch
- mounts
- automounting
- rule_1.1.22
- name: "1.1.23 | L1 | PATCH | Disable USB Storage"
block:
- name: "1.1.23 | L1 | PATCH | Disable USB Storage | Edit modprobe config"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install usb-storage(\\s|$)"
line: "install usb-storage /bin/true"
create: yes
owner: root
group: root
mode: 0600
- name: "1.1.23 | L1 | PATCH | Disable USB Storage | Edit modprobe config"
modprobe:
name: usb-storage
state: absent
when:
- rhel9cis_rule_1_1_23
tags:
- level1-server
- level2-workstation
- patch
- mounts
- removable_storage
- rule_1.1.23

View file

@ -0,0 +1,15 @@
---
- name: "1.10 | L1 | PATCH | Ensure system-wide crypto policy is not legacy"
shell: |
update-crypto-policies --set "{{ rhel9cis_crypto_policy }}"
update-crypto-policies
when:
- rhel9cis_rule_1_10
- system_wide_crypto_policy['stdout'] == 'LEGACY'
tags:
- level1-server
- level1-workstation
- no system_is_ec2
- patch
- rule_1.10

View file

@ -0,0 +1,15 @@
---
- name: "1.11 | L2 | PATCH | Ensure system-wide crypto policy is FUTURE or FIPS"
shell: |
update-crypto-policies --set "{{ rhel9cis_crypto_policy }}"
update-crypto-policies
when:
- rhel9cis_rule_1_11
- system_wide_crypto_policy['stdout'] not in rhel9cis_allowed_crypto_policies
tags:
- level2-server
- level2-workstation
- not system_is_ec2
- patch
- rule_1.11

View file

@ -0,0 +1,100 @@
---
- name: "1.2.1 | L1 | PATCH | Ensure Red Hat Subscription Manager connection is configured"
redhat_subscription:
state: present
username: "{{ rhel9cis_rh_sub_user }}"
password: "{{ rhel9cis_rh_sub_password }}"
auto_attach: true
no_log: true
when:
- ansible_distribution == "RedHat"
- rhel9cis_rhnsd_required
- rhel9cis_rule_1_2_1
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.1
- skip_ansible_lint # Added as no_log still errors on ansuible-lint
- name: "1.2.2 | L1 | PATCH | Disable the rhnsd Daemon"
service:
name: rhnsd
state: stopped
enabled: no
masked: true
when:
- ansible_distribution == "RedHat"
- rhnsd_service_status.stdout == "loaded" and not rhel9cis_rhnsd_required
- rhel9cis_rule_1_2_2
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.2
- name: "1.2.3 | L1 | AUDIT | Ensure GPG keys are configured"
command: gpg --quiet --with-fingerprint /etc/pki/rpm-gpg/RPM-GPG-KEY-{{ ansible_distribution|lower }}-release
when:
- rhel9cis_rule_1_2_3
- ansible_distribution == "RedHat"
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.3
- name: "1.2.4 | L1 | PATCH | Ensure gpgcheck is globally activated"
block:
- name: "1.2.4 | L1 | AUDIT | Ensure gpgcheck is globally activated | Find repos"
find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: yum_repos
changed_when: false
- name: "1.2.4 | L1 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos"
replace:
name: "{{ item.path }}"
regexp: "^gpgcheck=0"
replace: "gpgcheck=1"
with_items:
- "{{ yum_repos.files }}"
when:
- rhel9cis_rule_1_2_4
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.2.4
- name: "1.2.5 | L1 | Ensure package manager repositories are configured"
block:
- name: "1.2.5 | L1 | AUDIT | Ensure package manager repositories are configured | Get repo list"
command: dnf repolist
changed_when: false
failed_when: false
register: dnf_configured
check_mode: no
args:
warn: false
- name: "1.2.5 | L1 | AUDIT | Ensure package manager repositories are configured | Display repo list"
debug:
msg:
- "Alert! Below are the configured repos. Please review and make sure all align with site policy"
- "{{ dnf_configured.stdout_lines }}"
when:
- rhel9cis_rule_1_2_5
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.5
- skip_ansible_lint

View file

@ -0,0 +1,44 @@
---
- name: "1.3.1 | L1 | PATCH | Ensure sudo is installed"
package:
name: sudo
state: present
when:
- rhel9cis_rule_1_3_1
tags:
- level1-server
- level1-workstation
- scored
- sudo
- patch
- rule_1.3.1
- name: "1.3.2 | L1 | PATCH | Ensure sudo commands use pty"
lineinfile:
dest: /etc/sudoers
line: "Defaults use_pty"
state: present
when:
- rhel9cis_rule_1_3_2
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.3.2
- name: "1.3.3 | L1 | PATCH | Ensure sudo log file exists"
lineinfile:
dest: /etc/sudoers
regexp: '^Defaults logfile='
line: 'Defaults logfile="{{ rhel9cis_varlog_location }}"'
state: present
when:
- rhel9cis_rule_1_3_3
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.3.3

View file

@ -0,0 +1,50 @@
---
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed"
block:
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed | Install AIDE"
package:
name: aide
state: present
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed | Configure AIDE"
command: /usr/sbin/aide --init -B 'database_out=file:/var/lib/aide/aide.db.gz'
changed_when: false
failed_when: false
async: 45
poll: 0
args:
creates: /var/lib/aide/aide.db.gz
when: not ansible_check_mode
when:
- rhel9cis_config_aide
- rhel9cis_rule_1_4_1
tags:
- level1-server
- level1-workstation
- scored
- aide
- patch
- rule_1.4.1
- name: "1.4.2 | L1 | PATCH | Ensure filesystem integrity is regularly checked"
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_4_2
tags:
- level1-server
- level1-workstation
- scored
- aide
- file_integrity
- patch
- rule_1.4.2

View file

@ -0,0 +1,76 @@
---
- name: "1.5.1 | L1 | PATCH | Ensure permissions on bootloader config are configured"
block:
- name: "1.5.1 | L1 | PATCH | Ensure permissions on bootloader config are configured"
file:
path: "{{ grub_cfg.stat.lnk_source }}"
owner: root
group: root
mode: 0600
- name: "1.5.1 | L1 | PATCH | Ensure permissions on bootloader config are configured | UEFI"
mount:
name: /boot/efi
src: "UUID={{ item.uuid }}"
fstype: vfat
state: present
opts: defaults,umask=0027,fmask=0077,uid=0,gid=0
passno: '0'
loop: "{{ ansible_mounts }}"
when:
- not rhel9cis_legacy_boot
- item.mount == "/boot/efi"
when:
- rhel9cis_rule_1_5_1
- grub_cfg.stat.exists
- grub_cfg.stat.islnk
tags:
- level1-server
- level1-workstation
- scored
- grub
- patch
- rule_1.5.1
- name: "1.5.2 | L1 | PATCH | Ensure bootloader password is set"
copy:
dest: /boot/grub2/user.cfg
content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}"
owner: root
group: root
mode: 0600
notify: grub2cfg
when:
- rhel9cis_set_boot_pass
- grub_pass is defined and grub_pass.passhash is defined
- grub_pass.passhash | length > 0
- rhel9cis_rule_1_5_2
tags:
- level1-server
- level1-workstation
- scored
- grub
- patch
- rule_1.5.2
- name: "1.5.3 | L1 | PATCH | Ensure authentication required for single user mode"
block:
- name: "1.5.3 | L1 | PATCH | Ensure authentication required for single user mode | Emergency service"
lineinfile:
dest: /usr/lib/systemd/system/emergency.service
regexp: '/sbin/sulogin'
line: 'ExecStart=-/usr/lib/systemd/systemd-sulogin-shell emergency'
- name: "1.5.3 | L1 | PATCH | Ensure authentication required for single user mode | Rescue service"
lineinfile:
dest: /usr/lib/systemd/system/rescue.service
regexp: '/sbin/sulogin'
line: 'ExecStart=-/usr/lib/systemd/systemd-sulogin-shell rescue'
when:
- rhel9cis_rule_1_5_3
tags:
- level1-server
- level1-workstation
- patch
- rule_1.5.3

View file

@ -0,0 +1,54 @@
---
- name: "1.6.1 | L1 | PATCH | Ensure core dumps are restricted"
block:
- name: "1.6.1 | L1 | Ensure core dumps are restricted | Update limits.conf file"
lineinfile:
state: present
dest: /etc/security/limits.conf
regexp: '^#?\\*.*core'
line: '* hard core 0'
insertbefore: '^# End of file'
- name: "1.6.1 | L1 | PATCH | Ensure core dumps are restricted | Set active kernel parameter"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- name: "1.6.1 | L1 | PATCH | Ensure core dumps are restricted | if systemd coredump"
lineinfile:
path: /etc/systemd/coredump.conf
regexp: "{{ item.regexp }}"
line: "{{ item.regexp }}{{ item.line }}"
state: present
with_items:
- {'regexp': 'Storage=', 'line': 'none'}
- {'regexp': 'ProcessSizeMax=', 'line': '0'}
notify:
- systemd_daemon_reload
when:
- systemd_coredump.stat.exists
when:
- rhel9cis_rule_1_6_1
tags:
- level1-server
- level1-workstation
- scored
- sysctl
- patch
- rule_1.6.1
- name: "1.6.2 | L1 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
when:
- rhel9cis_rule_1_6_2
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.6.2

View file

@ -0,0 +1,115 @@
---
- name: "1.7.1.1 | L2 | PATCH | Ensure SELinux is installed"
package:
name: libselinux
state: present
when:
- rhel9cis_rule_1_7_1_1
tags:
- level2-server
- level2-workstation
- scored
- patch
- rule_1.7.1.1
- name: "1.7.1.2 | L2 | PATCH | Ensure SELinux is not disabled in bootloader configuration"
replace:
dest: /etc/default/grub
regexp: '(selinux|enforcing)\s*=\s*0\s*'
replace: ''
register: selinux_grub_patch
ignore_errors: yes
notify: grub2cfg
when:
- rhel9cis_rule_1_7_1_2
tags:
- level2-server
- level2-workstation
- scored
- patch
- rule_1.7.1.2
- name: "1.7.1.3 | L2 | PATCH | Ensure SELinux policy is configured"
selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: enforcing
when:
- not rhel9cis_selinux_disable
- rhel9cis_rule_1_7_1_3
tags:
- level2-server
- level2-workstation
- scored
- selinux
- patch
- rule_1.7.1.3
- name: "1.7.1.4 | L2 | PATCH | Ensure the SELinux state is enforcing"
selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: enforcing
when:
- not rhel9cis_selinux_disable
- rhel9cis_rule_1_7_1_4
tags:
- level2-server
- level2-workstation
- scored
- selinux
- patch
- rule_1.7.1.4
- name: "1.7.1.5 | L2 | AUDIT | Ensure no unconfined daemons exist"
block:
- name: "1.7.1.5 | L2 | AUDIT | Ensure no unconfined daemons exist | Find the unconfined daemons"
shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }'
register: rhelcis_1_7_1_5_unconf_daemons
failed_when: false
changed_when: false
- name: "1.7.1.5 | L2 | AUDIT | Ensure no unconfined daemons exist | Message on no unconfined daemones"
debug:
msg: "Good News! There are no unconfined daemons found on your system"
when: rhelcis_1_7_1_5_unconf_daemons.stdout | length == 0
- name: "1.7.1.5 | L2 | AUDIT | Ensure no unconfined daemons exist | Message on unconfined daemones"
debug:
msg: "Warning! You have unconfined daemons: {{ rhelcis_1_7_1_5_unconf_daemons.stdout_lines }}"
when: rhelcis_1_7_1_5_unconf_daemons.stdout | length > 0
when:
- rhel9cis_rule_1_7_1_5
tags:
- level2-server
- level2-workstation
- audit
- rule_1.7.1.5
- name: "1.7.1.6 | L2 | PATCH | Ensure SETroubleshoot is not installed"
package:
name: setroubleshoot
state: absent
when:
- rhel9cis_rule_1_7_1_6
- "'setroubleshoot' in ansible_facts.packages"
tags:
- level2-server
- scored
- selinux
- patch
- rule_1.7.1.6
- name: "1.7.1.7 | L2 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed"
package:
name: mcstrans
state: absent
when:
- rhel9cis_rule_1_7_1_7
tags:
- level2-server
- level2-workstation
- scored
- patch
- rule_1.7.1.7

View file

@ -0,0 +1,96 @@
---
- name: "1.8.1.1 | L1 | PATCH | Ensure message of the day is configured properly"
template:
src: etc/motd.j2
dest: /etc/motd
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_1
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.8.1.1
- name: "1.8.1.2 | L1 | PATCH | Ensure local login warning banner is configured properly"
template:
src: etc/issue.j2
dest: /etc/issue
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.8.1.2
- name: "1.8.1.3 | L1 | PATCH | Ensure remote login warning banner is configured properly"
template:
src: etc/issue.net.j2
dest: /etc/issue.net
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_3
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.8.1.3
- name: "1.8.1.4 | L1 | PATCH | Ensure permissions on /etc/motd are configured"
file:
dest: /etc/motd
state: file
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_4
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.4
- name: "1.8.1.5 | L1 | PATCH | Ensure permissions on /etc/issue are configured"
file:
dest: /etc/issue
state: file
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_5
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.5
- name: "1.8.1.6 | L1 | PATCH | Ensure permissions on /etc/issue.net are configured"
file:
dest: /etc/issue.net
state: file
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_1_8_1_6
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.6

View file

@ -0,0 +1,27 @@
---
- name: "1.8.2 | L1 | PATCH | Ensure GDM login banner is configured"
lineinfile:
dest: "{{ item.file }}"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
create: yes
owner: root
group: root
mode: 0644
with_items:
- { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' }
- { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' }
- { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' }
- { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' }
- { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-enable', line: 'banner-message-enable=true' }
- { file: '/etc/dconf/db/gdm.d/01-banner-message', regexp: 'banner-message-text', line: "banner-message-text='{{ rhel9cis_warning_banner }}' " }
when:
- rhel9cis_gui
- rhel9cis_rule_1_8_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.8.2

View file

@ -0,0 +1,15 @@
---
- name: "1.9 | L1 | PATCH | Ensure updates, patches, and additional security software are installed"
package:
name: "*"
state: latest
when:
- rhel9cis_rule_1_9
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.9
- skip_ansible_lint

42
tasks/section_1/main.yml Normal file
View file

@ -0,0 +1,42 @@
---
- name: "SECTION | 1.1 | FileSystem Configurations\n
SECTION | 1.1.1.x | Disable unused filesystems"
include: cis_1.1.1.x.yml
- include: cis_1.1.x.yml
- name: "SECTION | 1.2 | Configure Software Updates"
include: cis_1.2.x.yml
- name: "SECTION | 1.3 | Configure sudo"
include: cis_1.3.x.yml
- name: "SECTION | 1.4 | Filesystem Integrity"
include: cis_1.4.x.yml
when: rhel9cis_config_aide
- name: "SECTION | 1.5 | Secure Boot Settings"
include: cis_1.5.x.yml
- name: "SECTION | 1.6 | Additional Process Hardening"
include: cis_1.6.x.yml
- name: "SECTION | 1.7 | bootloader and Mandatory Access Control"
include: cis_1.7.1.x.yml
when: not rhel9cis_selinux_disable
- name: "SECTION | 1.8 | Warning Banners"
include: cis_1.8.1.x.yml
- name: "SECTION | 1.9 | Updated and Patches"
include: cis_1.9.yml
- name: "SECTION | 1.10 | Crypto policies"
include: cis_1.10.yml
when:
- not system_is_ec2
- name: "SECTION | 1.11 | FIPS/FUTURE Crypto policies"
include: cis_1.11.yml
when:
- not system_is_ec2

View file

@ -0,0 +1,14 @@
---
- name: "2.1.1 | L1 | PATCH | Ensure xinetd is not installed"
package:
name: xinetd
state: absent
when:
- rhel9cis_rule_2_1_1
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_2.1.1

View file

@ -0,0 +1,42 @@
---
- name: "2.2.1.1 | L1 | PATCH | Ensure time synchronization is in use - service install"
package:
name: "{{ rhel9cis_time_synchronization }}"
state: present
when:
- rhel9cis_rule_2_2_1_1
- not rhel9cis_system_is_container
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.1.1
- name: "2.2.1.2 | L1 | PATCH | Ensure chrony is configured"
block:
- name: "2.2.1.2 | L1 | PATCH | Ensure chrony is configured | Set configuration"
template:
src: chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: 0644
- name: "2.2.1.2 | L1 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd | 1"
lineinfile:
dest: /etc/sysconfig/chronyd
regexp: "^(#)?OPTIONS"
line: "OPTIONS=\"-u chrony\""
state: present
create: yes
mode: 0644
when:
- rhel9cis_time_synchronization == "chrony"
- rhel9cis_rule_2_2_1_2
- not rhel9cis_system_is_container
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.1.2

View file

@ -0,0 +1,288 @@
---
- name: "2.2.2 | L1 | PATCH | Ensure X Window System is not installed"
block:
- name: "2.2.2 | L1 | AUDIT | Ensure X Window System is not installed | capture xorg-x11 packages"
shell: rpm -qa | grep xorg-x11
args:
warn: no
failed_when: xorg_x11_installed.rc >=2
check_mode: no
changed_when: false
register: xorg_x11_installed
- name: "2.2.2 | L1 | PATCH | Ensure X Window System is not installed | remove packages if found"
shell: "dnf remove {{ item }}"
args:
warn: no
with_items:
- xorg_x11_installed.stdout_lines
when: xorg_x11_installed.stdout | length > 0
when:
- not rhel9cis_xwindows_required
- rhel9cis_rule_2_2_2
tags:
- level1-server
- scored
- xwindows
- patch
- rule_2.2.2
- name: "2.2.3 | L1 | PATCH | Ensure rsync service is not enabled "
service:
name: rsyncd
state: stopped
enabled: no
when:
- not rhel9cis_rsyncd_server
- "'rsyncd' in ansible_facts.packages"
- rhel9cis_rule_2_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.3
- name: "2.2.4 | L1 | PATCH | Ensure Avahi Server is not enabled"
service:
name: avahi-daemon
state: stopped
enabled: no
when:
- not rhel9cis_avahi_server
- "'avahi' in ansible_facts.packages"
- rhel9cis_rule_2_2_4
tags:
- level1-server
- level1-workstation
- scored
- avahi
- services
- patch
- rule_2.2.4
- name: "2.2.5 | L1 | PATCH | Ensure SNMP Server is not enabled"
service:
name: snmpd
state: stopped
enabled: no
when:
- not rhel9cis_snmp_server
- "'net-snmp' in ansible_facts.packages"
- rhel9cis_rule_2_2_5
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.5
- name: "2.2.6 | L1 | PATCH | Ensure HTTP Proxy Server is not enabled"
service:
name: squid
state: stopped
enabled: no
when:
- not rhel9cis_squid_server
- "'squid' in ansible_facts.packages"
- rhel9cis_rule_2_2_6
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.6
- name: "2.2.7 | L1 | PATCH | Ensure Samba is not enabled"
service:
name: smb
state: stopped
enabled: no
when:
- not rhel9cis_smb_server
- "'samba' in ansible_facts.packages"
- rhel9cis_rule_2_2_7
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.7
- name: "2.2.8 | L1 | PATCH | Ensure IMAP and POP3 server is not enabled"
service:
name: dovecot
state: stopped
enabled: no
when:
- not rhel9cis_dovecot_server
- "'dovecot' in ansible_facts.packages"
- rhel9cis_rule_2_2_8
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.8
- name: "2.2.9 | L1 | PATCH | Ensure HTTP server is not enabled"
service:
name: httpd
state: stopped
enabled: no
when:
- not rhel9cis_httpd_server
- "'httpd' in ansible_facts.packages"
- rhel9cis_rule_2_2_9
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.9
- name: "2.2.10 | L1 | PATCH | Ensure FTP Server is not enabled"
service:
name: vsftpd
state: stopped
enabled: no
when:
- not rhel9cis_vsftpd_server
- "'vsftpd' in ansible_facts.packages"
- rhel9cis_rule_2_2_10
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.10
- name: "2.2.11 | L1 | PATCH | Ensure DNS Server is not enabled"
service:
name: named
state: stopped
enabled: no
when:
- not rhel9cis_named_server
- "'bind' in ansible_facts.packages"
- rhel9cis_rule_2_2_11
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.11
- name: "2.2.12 | L1 | PATCH | Ensure NFS is not enabled"
service:
name: nfs-server
state: stopped
enabled: no
when:
- not rhel9cis_nfs_rpc_server
- "'nfs-utils' in ansible_facts.packages"
- rhel9cis_rule_2_2_12
tags:
- level1-server
- level1-workstation
- scored
- nfs
- services
- patch
- rule_2.2.12
- name: "2.2.13 | L1 | PATCH | Ensure RPC is not enabled"
service:
name: rpcbind
state: stopped
enabled: no
when:
- not rhel9cis_nfs_rpc_server
- "'rpcbind' in ansible_facts.packages"
- rhel9cis_rule_2_2_13
tags:
- level1-server
- level1-workstation
- scored
- rpc
- services
- patch
- rule_2.2.7
- name: "2.2.14 | L1 | PATCH | Ensure LDAP server is not enabled"
service:
name: slapd
state: stopped
enabled: no
when:
- not rhel9cis_ldap_server
- "'openldap-servers' in ansible_facts.packages"
- rhel9cis_rule_2_2_14
tags:
- level1-server
- level1-workstation
- scored
- ldap
- services
- patch
- rule_2.2.6
- name: "2.2.15 | L1 | PATCH | Ensure DHCP Server is not enabled"
service:
name: dhcpd
state: stopped
enabled: no
when:
- not rhel9cis_dhcp_server
- "'dhcp' in ansible_facts.packages"
- rhel9cis_rule_2_2_15
tags:
- level1-server
- level1-workstation
- scored
- dhcp
- services
- patch
- rule_2.2.15
- name: "2.2.16 | L1 | PATCH | Ensure CUPS is not enabled"
service:
name: cups
state: stopped
enabled: no
when:
- not rhel9cis_cups_server
- "'cups' in ansible_facts.packages"
- rhel9cis_rule_2_2_16
tags:
- level1-server
- level2-workstation
- scored
- cups
- services
- patch
- rule_2.2.16
- name: "2.2.17 | L1 | PATCH | Ensure NIS Server is not enabled"
service:
name: ypserv
state: stopped
enabled: no
when:
- not rhel9cis_nis_server
- "'ypserv' in ansible_facts.packages"
- rhel9cis_rule_2_2_17
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.17
- name: "2.2.18 | L1 | PATCH | Ensure mail transfer agent is configured for local-only mode"
lineinfile:
dest: /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_18
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.1

View file

@ -0,0 +1,43 @@
---
- name: "2.3.1 | L1 | PATCH | Ensure NIS Client is not installed"
package:
name: ypbind
state: absent
when:
- not rhel9cis_ypbind_required
- "'ypbind' in ansible_facts.packages"
- rhel9cis_rule_2_3_1
tags:
- level1-server
- level1-workstation
- patch
- rule_2.3.1
- name: "2.3.2 | L1 | PATCH | Ensure telnet client is not installed"
package:
name: telnet
state: absent
when:
- not rhel9cis_telnet_required
- "'telnet' in ansible_facts.packages"
- rhel9cis_rule_2_3_2
tags:
- level1-server
- level1-workstation
- patch
- rule_2.3.2
- name: "2.3.3 | L1 | PATCH | Ensure LDAP client is not installed"
package:
name: openldap-clients
state: absent
when:
- not rhel9cis_openldap_clients_required
- "'openldap-clients' in ansible_facts.packages"
- rhel9cis_rule_2_3_3
tags:
- level1-server
- level1-workstation
- patch
- rule_2.3.3

13
tasks/section_2/main.yml Normal file
View file

@ -0,0 +1,13 @@
---
- name: "SECTION | 2.1 | xinetd"
include: cis_2.1.1.yml
- name: "SECTION | 2.2.1 | Time Synchronization"
include: cis_2.2.1.x.yml
- name: "SECTION | 2.2 | Special Purpose Services"
include: cis_2.2.x.yml
- name: "SECTION | 2.3 | Service Clients"
include: cis_2.3.x.yml

View file

@ -0,0 +1,43 @@
---
- name: "3.1.1 | L1 | PATCH | Ensure IP forwarding is disabled"
block:
- name: "3.1.1 | L1 | PATCH | Ensure IP forwarding is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- name: "3.1.1 | L1 | PATCH | Ensure IP forwarding is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- sysctl flush ipv6 route table
- update sysctl
when: rhel9cis_ipv6_required
when:
- not rhel9cis_is_router
- rhel9cis_rule_3_1_1
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.1.1
- name: "3.1.2 | L1 | PATCH | Ensure packet redirect sending is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
when:
- not rhel9cis_is_router
- rhel9cis_rule_3_1_2
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.1.2

View file

@ -0,0 +1,155 @@
---
- name: "3.2.1 | L1 | PATCH | Ensure source routed packets are not accepted"
block:
- name: "3.2.1 | L1 | PATCH | Ensure source routed packets are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- name: "3.2.1 | L1 | PATCH | Ensure source routed packets are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- sysctl flush ipv6 route table
- update sysctl
when: rhel9cis_ipv6_required
when:
- rhel9cis_rule_3_2_1
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.1
- name: "3.2.2 | L1 | PATCH | Ensure ICMP redirects are not accepted"
block:
- name: "3.2.2 | L1 | PATCH | Ensure ICMP redirects are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- name: "3.2.2 | L1 | PATCH | Ensure ICMP redirects are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- sysctl flush ipv6 route table
- update sysctl
when: rhel9cis_ipv6_required
when:
- rhel9cis_rule_3_2_2
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.2
- name: "3.2.3 | L1 | PATCH | Ensure secure ICMP redirects are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_3
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.3
- name: "3.2.4 | L1 | PATCH | Ensure suspicious packets are logged"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_4
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.4
- name: "3.2.5 | L1 | PATCH | Ensure broadcast ICMP requests are ignored"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_5
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.5
- name: "3.2.6 | L1 | PATCH | Ensure bogus ICMP responses are ignored"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_6
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.6
- name: "3.2.7 | L1 | PATCH | Ensure Reverse Path Filtering is enabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_7
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.7
- name: "3.2.8 | L1 | PATCH | Ensure TCP SYN Cookies is enabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify: update sysctl
when:
- rhel9cis_rule_3_2_8
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.8
- name: "3.2.9 | L2 | PATCH | Ensure IPv6 router advertisements are not accepted"
block:
- name: "3.2.9 | L2 | PATCH | Ensure IPv6 router advertisements are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- name: "3.2.9 | L2 | PATCH | Ensure IPv6 router advertisements are not accepted"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- sysctl flush ipv6 route table
- update sysctl
when: rhel9cis_ipv6_required
when:
- rhel9cis_ipv6_required
- rhel9cis_rule_3_2_9
tags:
- level2-server
- level2-workstation
- sysctl
- patch
- rule_3.2.9

View file

@ -0,0 +1,61 @@
---
- name: "3.3.1 | L2 | PATCH | Ensure DCCP is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install dccp(\\s|$)"
line: "install dccp /bin/true"
create: yes
mode: 0600
when:
- rhel9cis_rule_3_3_1
tags:
- level2-server
- level2-workstation
- patch
- rule_3.3.1
- name: "3.3.2 | L2 | PATCH | Ensure SCTP is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install sctp(\\s|$)"
line: "install sctp /bin/true"
create: yes
mode: 0600
when:
- rhel9cis_rule_3_3_2
tags:
- level2-server
- level2-workstation
- patch
- rule_3.3.2
- name: "3.3.3 | L2 | PATCH | Ensure RDS is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install rds(\\s|$)"
line: "install rds /bin/true"
create: yes
mode: 0600
when:
- rhel9cis_rule_3_3_3
tags:
- level2-server
- level2-workstation
- patch
- rule_3.3.3
- name: "3.3.4 | L2 | PATCH | Ensure TIPC is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install tipc(\\s|$)"
line: "install tipc /bin/true"
create: yes
mode: 0600
when:
- rhel9cis_rule_3_3_4
tags:
- level2-server
- level2-workstation
- patch
- rule_3.3.4

View file

@ -0,0 +1,13 @@
---
- name: "3.4.1.1 | L1 | PATCH | Ensure a Firewall package is installed"
package:
name: "{{ rhel9cis_firewall }}"
state: present
when:
- rhel9cis_rule_3_4_1_1
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.1.1

View file

@ -0,0 +1,102 @@
---
- name: "3.4.2.1 | L1 | PATCH | Ensure firewalld service is enabled and running"
service:
name: firewalld
state: started
enabled: yes
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_1
tags:
- level1-server
- level1-workstation
- patch
- rule_3_4_2_1
- name: "3.4.2.2 | L1 | PATCH | Ensure iptables is not enabled with firewalld"
systemd:
name: iptables
enabled: false
masked: true
ignore_errors: true
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_2
tags:
- skip_ansible_lint
- level1-server
- level1-workstation
- patch
- rule_3_4_2_2
- name: "3.4.2.3 | L1 | PATCH | Ensure nftables is not enabled with firewalld"
systemd:
name: nftables
enabled: false
masked: true
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_3_4_2_3
- name: "3.4.2.4 | L1 | PATCH | Ensure default zone is set"
command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}"
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_4
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.2.4
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone"
block:
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and polocies"
shell: "nmcli -t connection show | awk -F: '{ if($4){print $4} }' | while read INT; do firewall-cmd --get-active-zones | grep -B1 $INT; done"
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_3_4_2_5_interfacepolicy
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and polocies | Show the interface to policy"
debug:
msg:
- "The items below are the policies tied to the interfaces, please correct as needed"
- "{{ rhel9cis_3_4_2_5_interfacepolicy.stdout_lines }}"
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_5
tags:
- level1-server
- level1-workstation
- audit
- rule_3.4.2.5
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports"
block:
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports"
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: no
register: rhel9cis_3_4_2_6_servicesport
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports"
debug:
msg:
- "The items below are the services and ports that are accepted, please correct as needed"
- "{{ rhel9cis_3_4_2_6_servicesport.stdout_lines }}"
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_6
tags:
- level1-server
- level1-workstation
- audit
- rule_3.4.2.6

View file

@ -0,0 +1,264 @@
---
- name: "3.4.3.1 | L1 | PATCH | Ensure iptables are flushed with nftables"
command: ip6tables -F
when:
- rhel9cis_rule_3_4_3_1
- rhel9cis_firewall != "iptables"
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.1
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists"
block:
- name: "3.4.3.2 | L1 | AUDIT | Ensure a table exists | Check for tables"
command: nft list tables
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_2_nft_tables
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists | Show existing tables"
debug:
msg:
- "Below are the current nft tables, please review"
- "{{ rhel9cis_3_4_3_2_nft_tables.stdout_lines }}"
when: rhel9cis_3_4_3_2_nft_tables.stdout | length > 0
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists | Alert on no tables"
debug:
msg:
- "Warning! You currently have no nft tables, please review your setup"
- 'Use the command "nft create table inet <table name>" to create a new table'
when:
- rhel9cis_3_4_3_2_nft_tables.stdout | length == 0
- not rhel9cis_nft_tables_autonewtable
- name: "3.4.3.2 | L1 | PATCH | Ensure a table exists | Create table if needed"
command: nft create table inet "{{ rhel9cis_nft_tables_tablename }}"
failed_when: no
when: rhel9cis_nft_tables_autonewtable
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_2
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.2
- name: "3.4.3.3 | L1 | PATCH | Ensure nftables base chains exist"
block:
- name: "3.4.3.3 | L1 | Ensure nftables base chains exist | Get current chains for INPUT"
shell: nft list ruleset | grep 'hook input'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_input_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD"
shell: nft list ruleset | grep 'hook forward'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_forward_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT"
shell: nft list ruleset | grep 'hook output'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_output_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Display chains for review"
debug:
msg:
- "Below are the current INPUT chains"
- "{{ rhel9cis_3_4_3_3_input_chains.stdout_lines }}"
- "Below are the current FORWARD chains"
- "{{ rhel9cis_3_4_3_3_forward_chains.stdout_lines }}"
- "Below are teh current OUTPUT chains"
- "{{ rhel9cis_3_4_3_3_output_chains.stdout_lines }}"
when: not rhel9cis_nft_tables_autochaincreate
- name: "3.4.3.3 | L1 | PATCH | Ensure nftables base chains exist | Create chains if needed"
shell: "{{ item }}"
args:
warn: no
failed_when: no
with_items:
- 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_3_3
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.3
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured"
block:
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_iiflo
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_ipsaddr
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_ip6saddr
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept
when: '"iif \"lo\" accept" not in rhel9cis_3_4_3_4_iiflo.stdout'
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule"
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_3_4_ipsaddr.stdout'
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule"
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_3_4_ip6saddr.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_4
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.4
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured"
block:
- name: "3.4.3.5 | L1 | AUDIT | Ensure nftables outbound and established connections are configured | Gather incoming connection rules"
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_3_5_inconnectionrule
- name: "3.4.3.5 | L1 | AUDIT | Ensure nftables outbound and established connections are configured | Gather outbound connection rules"
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_3_5_outconnectionrule
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input tcp established accept policy"
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_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input udp established accept policy"
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_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input icmp established accept policy"
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_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output tcp new, related, established accept policy"
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_3_5_outconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output udp new, related, established accept policy"
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_3_5_outconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output icmp new, related, established accept policy"
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_3_5_outconnectionrule.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_5
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.5
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy"
block:
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_inputpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_forwardpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_outputpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_sshallowcheck
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept
when: '"tcp dport ssh accept" not in rhel9cis_3_4_3_6_sshallowcheck.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy"
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_3_6_inputpolicy.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy"
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_3_6_forwardpolicy.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy"
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_3_6_outputpolicy.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_6
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.6
- name: "3.4.3.7 | L1 | PATCH | Ensure nftables service is enabled | Check if nftables is enabled"
service:
name: nftables
enabled: yes
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_7
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.7
- name: "3.4.3.8 | L1 | PATCH | Ensure nftables rules are permanent"
lineinfile:
path: /etc/sysconfig/nftables.conf
state: present
insertafter: EOF
line: include "/etc/nftables/inet-{{ rhel9cis_nft_tables_tablename }}"
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_8
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.8

View file

@ -0,0 +1,144 @@
---
- name: "3.4.4.1.1 | L1 | PATCH | Ensure iptables default deny firewall policy"
block:
- name: "3.4.4.1.1 | L1 | PATCH | Ensure iptables default deny firewall policy | Configure ssh to be allowed"
iptables:
chain: INPUT
protocol: tcp
destination_port: "22"
jump: ACCEPT
- name: "3.4.4.1.1 | L1 | PATCH | Ensure iptables default deny firewall policy | Set drop items"
iptables:
policy: DROP
chain: "{{ item }}"
with_items:
- INPUT
- FORWARD
- OUTPUT
when:
- rhel9cis_rule_3_4_4_1_1
- rhel9cis_firewall == "iptables"
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.1.1
- name: "3.4.4.1.2 | L1 | PATCH | Ensure iptables loopback traffic is configured"
block:
- name: "3.4.4.1.2 | L1 | Ensure iptables loopback traffic is configured | INPUT Loopback ACCEPT"
iptables:
action: append
chain: INPUT
in_interface: lo
jump: ACCEPT
- name: "3.4.4.1.2 | L1 | PATCH | Ensure iptables loopback traffic is configured | OUTPUT Loopback ACCEPT"
iptables:
action: append
chain: OUTPUT
out_interface: lo
jump: ACCEPT
- name: "3.4.4.1.2 | L1 | PATCH | Ensure iptables loopback traffic is configured | INPUT Loopback 127.0.0.0/8"
iptables:
action: append
chain: INPUT
source: 127.0.0.0/8
jump: DROP
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.1.2
- name: "3.4.4.1.3 | L1 | PATCH | Ensure iptables outbound and established connections are configured"
iptables:
action: append
chain: '{{ item.chain }}'
protocol: '{{ item.protocol }}'
match: state
ctstate: '{{ item.ctstate }}'
jump: ACCEPT
with_items:
- { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' }
- { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' }
- { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' }
- { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED }
- { chain: INPUT, protocol: udp, ctstate: ESTABLISHED }
- { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED }
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.1.3
- name: "3.4.4.1.4 | L1 | PATCH | Ensure iptables firewall rules exist for all open ports"
block:
- name: "3.4.4.1.4 | L1 | AUDIT | Ensure iptables firewall rules exist for all open ports | Get list of TCP open ports"
shell: netstat -ant |grep "tcp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://'
changed_when: false
failed_when: false
register: rhel9cis_3_4_4_1_4_otcp
- name: "3.4.4.1.4 | L1 | AUDIT | Ensure iptables firewall rules exist for all open ports | Get the list of udp open ports"
shell: netstat -ant |grep "udp.*LISTEN" | awk '{ print $4 }'| sed 's/.*://'
changed_when: false
failed_when: false
register: rhel9cis_3_4_4_1_4_oudp
- name: "3.4.4.1.4 | L1 | PATCH | Ensure iptables firewall rules exist for all open ports | Adjust open tcp ports"
iptables:
action: append
chain: INPUT
protocol: tcp
destination_port: "{{ item }}"
match: state
ctstate: NEW
jump: ACCEPT
with_items:
- "{{ rhel9cis_3_4_4_1_4_otcp.stdout_lines }}"
when: rhel9cis_3_4_4_1_4_otcp.stdout is defined
- name: "3.4.4.1.4 | L1 | PATCH | Ensure iptables firewall rules exist for all open ports | Adjust open udp ports"
iptables:
action: append
chain: INPUT
protocol: udp
destination_port: "{{ item }}"
match: state
ctstate: NEW
jump: ACCEPT
with_items:
- "{{ rhel9cis_3_4_4_1_4_oudp.stdout_lines }}"
when: rhel9cis_3_4_4_1_4_otcp.stdout is defined
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.1.4
- name: "3.4.4.1.5 | L1 | PATCH | Ensure iptables service is enabled and active | Check if iptables is enabled"
service:
name: iptables
enabled: yes
state: started
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.1.5

View file

@ -0,0 +1,136 @@
---
- name: "3.4.4.2.1 | L1 | PATCH | Ensure ip6tables default deny firewall policy"
block:
- name: "3.4.4.2.1 | L1 | Ensure ip6tables default deny firewall policy | Configure ssh to be allowed"
iptables:
chain: INPUT
protocol: tcp
destination_port: "22"
jump: ACCEPT
ip_version: ipv6
- name: "3.4.4.2.1 | L1 | PATCH | Ensure ip6tables default deny firewall policy | Set drop items"
iptables:
policy: DROP
chain: "{{ item }}"
ip_version: ipv6
with_items:
- INPUT
- FORWARD
- OUTPUT
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_2_1
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.2.1
- name: "3.4.4.2.2 | L1 | PATCH | Ensure ip6tables loopback traffic is configured"
block:
- name: "3.4.4.2.2 | L1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback ACCEPT"
iptables:
action: append
chain: INPUT
in_interface: lo
jump: ACCEPT
ip_version: ipv6
- name: "3.4.4.2.2 | L1 | PATCH | Ensure ip6tables loopback traffic is configured | OUTPUT Loopback ACCEPT"
iptables:
action: append
chain: OUTPUT
out_interface: lo
jump: ACCEPT
ip_version: ipv6
- name: "3.4.4.2.2 | L1 | PATCH | Ensure ip6tables loopback traffic is configured | INPUT Loopback 127.0.0.0/8"
iptables:
action: append
chain: INPUT
source: ::1
jump: DROP
ip_version: ipv6
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_2_2
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.2.2
- name: "3.4.4.2.3 | L1 | PATCH | Ensure ip6tables outbound and established connections are configured"
iptables:
action: append
chain: '{{ item.chain }}'
protocol: '{{ item.protocol }}'
match: state
ctstate: '{{ item.ctstate }}'
jump: ACCEPT
ip_version: ipv6
with_items:
- { chain: OUTPUT, protocol: tcp, ctstate: 'NEW,ESTABLISHED' }
- { chain: OUTPUT, protocol: udp, ctstate: 'NEW,ESTABLISHED' }
- { chain: OUTPUT, protocol: icmp, ctstate: 'NEW,ESTABLISHED' }
- { chain: INPUT, protocol: tcp, ctstate: ESTABLISHED }
- { chain: INPUT, protocol: udp, ctstate: ESTABLISHED }
- { chain: INPUT, protocol: icmp, ctstate: ESTABLISHED }
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_2_3
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.2.3
- name: "3.4.4.2.4 | L1 | PATCH | Ensure ip6tables firewall rules exist for all open ports"
block:
- name: "3.4.4.2.4 | L1 | AUDIT | Ensure ip6tables firewall rules exist for all open ports | Get list of TCP6 open ports"
shell: netstat -ant |grep "tcp6.*LISTEN" | awk '{ print $4 }'| sed 's/.*://'
changed_when: false
failed_when: false
register: rhel9cis_3_4_4_2_4_otcp
- name: "3.4.4.2.4 | L1 | PATCH |Ensure ip6tables firewall rules exist for all open ports| Adjust open tcp6 ports"
iptables:
action: append
chain: INPUT
protocol: tcp
destination_port: "{{ item }}"
match: state
ctstate: NEW
jump: ACCEPT
ip_version: ipv6
with_items:
- "{{ rhel9cis_3_4_4_2_4_otcp.stdout_lines }}"
when: rhel9cis_3_4_4_2_4_otcp.stdout is defined
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_2_4
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.2.4
- name: "3.4.4.2.5 | L1 | PATCH | Ensure ip6tables service is enabled and active | Check if ip6tables is enabled"
service:
name: ip6tables
enabled: yes
state: started
when:
- rhel9cis_firewall == "iptables"
- rhel9cis_rule_3_4_4_2_5
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.4.2.5

View file

@ -0,0 +1,32 @@
---
- name: "3.5 | L1 | PATCH | Ensure wireless interfaces are disabled"
block:
- name: "3.5 | L1 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available"
command: rpm -q NetworkManager
changed_when: false
failed_when: false
check_mode: no
args:
warn: no
register: rhel_09_nmcli_available
- name: "3.5 | L1 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled"
command: 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.5 | L1 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled"
command: nmcli radio all off
changed_when: false
failed_when: false
when: rhel_09_wifi_enabled is changed
when:
- rhel9cis_rule_3_5
tags:
- level1-server
- level2-workstation
- patch
- rule_3.5

View file

@ -0,0 +1,17 @@
---
- name: "3.6 | L2 | PATCH | Disable IPv6"
replace:
dest: /etc/default/grub
regexp: '(^GRUB_CMDLINE_LINUX\s*\=\s*)(?:")(.+)(?<!ipv6.disable=1)(?:")'
replace: '\1"\2 ipv6.disable=1"'
follow: yes
notify: grub2cfg
when:
- not rhel9cis_ipv6_required
- rhel9cis_rule_3_6
tags:
- level2-server
- level2-workstation
- patch
- rule_3.6

41
tasks/section_3/main.yml Normal file
View file

@ -0,0 +1,41 @@
---
- name: "SECTION | 3.1.x | Packet and IP redirection"
include: cis_3.1.x.yml
- name: "SECTION | 3.2.x | Network Parameters (Host Only)"
include: cis_3.2.x.yml
- name: "SECTION | 3.3.x | Uncommon Network Protocols"
include: cis_3.3.x.yml
- name: "SECTION | 3.4.1.x | firewall defined"
include: cis_3.4.1.1.yml
- name: "SECTION | 3.4.2.x | firewalld firewall"
include: cis_3.4.2.x.yml
when:
- rhel9cis_firewall == "firewalld"
- name: "SECTION | 3.4.3.x | Configure nftables firewall"
include: cis_3.4.3.x.yml
when:
- rhel9cis_firewall == "nftables"
- name: "SECTION | 3.4.4.1.x | Configure iptables IPv4"
include: cis_3.4.4.1.x.yml
when:
- rhel9cis_firewall == "iptables"
- name: "SECTION | 3.4.4.2.x | Configure iptables IPv6"
include: cis_3.4.4.2.x.yml
when:
- ( rhel9cis_firewall == "iptables" and rhel9cis_ipv6_required )
- name: "SECTION | 3.5 | Configure wireless"
include: cis_3.5.yml
- name: "SECTION | 3.5 | disable IPv6"
include: cis_3.5.yml
when:
- not rhel9cis_ipv6_required

View file

@ -0,0 +1,103 @@
---
- name: "4.1.1.1 | L2 | PATCH | Ensure auditd is installed"
block:
- name: "4.1.1.1 | L2 | PATCH | Ensure auditd is installed | Install auditd packages"
package:
name: audit
state: present
when: '"auditd" not in ansible_facts.packages'
- name: "4.1.1.1 | L2 | PATCH | Ensure auditd is installed | Install auditd-lib packages"
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
- rule_4.1.1.1
- name: "4.1.1.2 | L2 | PATCH | Ensure auditd service is enabled"
service:
name: auditd
state: started
enabled: yes
when:
- not rhel9cis_skip_for_travis
- rhel9cis_rule_4_1_1_2
- ansible_connection != 'docker'
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.1.2
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled"
block:
- name: "4.1.1.3 | L2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX"
shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_4_1_1_3_grub_cmdline_linux
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting"
replace:
dest: /etc/default/grub
regexp: 'audit=.'
replace: 'audit=1'
notify: grub2cfg
when: "'audit=' in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing"
lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_3_grub_cmdline_linux.stdout }} audit=1"'
notify: grub2cfg
when: "'audit=' not in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
when:
- rhel9cis_rule_4_1_1_3
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.1.3
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient"
block:
- name: "4.1.1.4 | L2 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX"
shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_4_1_1_4_grub_cmdline_linux
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting"
replace:
dest: /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_4_grub_cmdline_linux.stdout"
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing"
lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_4_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"'
notify: grub2cfg
when: "'audit_backlog_limit=' not in rhel9cis_4_1_1_4_grub_cmdline_linux.stdout"
when:
- rhel9cis_rule_4_1_1_4
tags:
- level2-server
- level2-workstation
- patch
- rule_4.1.1.4

View file

@ -0,0 +1,53 @@
---
- name: "4.1.2.1 | L2 | PATCH | Ensure audit log storage size is configured"
lineinfile:
dest: /etc/audit/auditd.conf
regexp: "^max_log_file( |=)"
line: "max_log_file = {{ rhel9cis_max_log_file_size }}"
state: present
notify: restart auditd
when:
- rhel9cis_rule_4_1_2_1
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.2.1
- name: "4.1.2.2 | L2 | PATCH | Ensure audit logs are not automatically deleted"
lineinfile:
dest: /etc/audit/auditd.conf
regexp: "^max_log_file_action"
line: "max_log_file_action = {{ rhel9cis_auditd['max_log_file_action'] }}"
state: present
notify: restart auditd
when:
- rhel9cis_rule_4_1_2_2
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.2.2
- name: "4.1.2.3 | L2 | PATCH | Ensure system is disabled when audit logs are full"
lineinfile:
dest: /etc/audit/auditd.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
state: present
notify: restart auditd
with_items:
- { 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
- auditd
- patch
- rule_4.1.2.3

View file

@ -0,0 +1,205 @@
---
- name: "4.1.3 | L2 | PATCH | Ensure changes to system administration scope (sudoers) is collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_3
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.3
- name: "4.1.4 | L2 | PATCH | Ensure login and logout events are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_4
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.4
- name: "4.1.5 | L2 | PATCH | Ensure session initiation information is collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_5
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.5
- name: "4.1.6 | L2 | PATCH | Ensure events that modify date and time information are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_6
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.6
- name: "4.1.7 | L2 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_7
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.7
- name: "4.1.8 | L2 | PATCH | Ensure events that modify the system's network environment are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_8
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.8
- name: "4.1.9 | L2 | PATCH | Ensure discretionary access control permission modification events are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_9
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.9
- name: "4.1.10 | L2 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_10
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.10
- name: "4.1.11 | L2 | PATCH | Ensure events that modify user/group information are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_11
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.11
- name: "4.1.12 | L2 | PATCH | Ensure successful file system mounts are collected"
block:
- name: "4.1.12 | L2 | AUDIT | Ensure successful file system mounts are collected"
shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null; done
changed_when: false
failed_when: false
check_mode: no
register: priv_procs
- name: "4.1.12 | L2 | PATCH | Ensure successful file system mounts are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_12
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.12
- name: "4.1.13 | L2 | PATCH | Ensure use of privileged commands is collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_13
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.13
- name: "4.1.14 | L2 | PATCH | Ensure file deletion events by users are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_14
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.14
- name: "4.1.15 | L2 | PATCH | Ensure kernel module loading and unloading is collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_15
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.15
- name: "4.1.16 | L2 | PATCH | Ensure system administrator actions (sudolog) are collected"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_16
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.16
- name: "4.1.17 | L2 | PATCH | Ensure the audit configuration is immutable"
debug:
msg: "Control being set via Handler 'update auditd' which writes to /etc/audit.d/99_auditd.rules"
notify: update auditd
when:
- rhel9cis_rule_4_1_17
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.17

View file

@ -0,0 +1,177 @@
---
- name: "4.2.1.1 | L1 | PATCH | Ensure rsyslog installed"
package:
name: rsyslog
state: present
when:
- "'rsyslog' not in ansible_facts.packages"
- rhel9cis_rule_4_2_1_1
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.1
- name: "4.2.1.2 | L1 | PATCH | Ensure rsyslog Service is enabled"
service:
name: rsyslog
enabled: yes
when:
- rhel9cis_rule_4_2_1_2
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.2
- name: "4.2.1.3 | L1 | PATCH | Ensure rsyslog default file permissions configured"
lineinfile:
dest: /etc/rsyslog.conf
regexp: '^\$FileCreateMode'
line: '$FileCreateMode 0640'
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 | L1 | PATCH | Ensure logging is configured"
block:
- name: "4.2.1.4 | L1 | AUDIT | Ensure logging is configured | rsyslog current config message out"
command: cat /etc/rsyslog.conf
become: yes
changed_when: false
failed_when: no
check_mode: no
register: rhel_09_4_2_1_4_audit
- name: "4.2.1.4 | L1 | AUDIT | Ensure logging is configured | rsyslog current config message out"
debug:
msg:
- "These are the current logging configurations for rsyslog, please review:"
- "{{ rhel_09_4_2_1_4_audit.stdout_lines }}"
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | mail.* log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MAIL LOG SETTINGS (ANSIBLE MANAGED)"
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.4 | L1 | PATCH | Ensure logging is configured | news.crit log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} NEWS LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# news logging additions to meet CIS standards
news.crit -/var/log/news/news.crit
news.notice -/var/log/news/news.crit
insertafter: '# Save news errors of level crit and higher in a special file.'
notify: restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | Misc. log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MISC. LOG SETTINGS (ANSIBLE MANAGED)"
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.4 | L1 | PATCH | Ensure logging is configured | Local log settings"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} LOCAL LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# local log settings
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
when:
- rhel9cis_rule_4_2_1_4
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.4
- name: "4.2.1.5 | L1 | PATCH | Ensure rsyslog is configured to send logs to a remote log host"
blockinfile:
path: /etc/rsyslog.conf
state: present
block: |
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
*.* @@{{ rhel9cis_remote_log_server }}
insertafter: EOF
register: result
failed_when:
- result is failed
- result.rc != 257
notify: restart rsyslog
when:
- rhel9cis_rule_4_2_1_5
- rhel9cis_remote_log_server is defined
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.5
- rsyslog
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts."
block:
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts. | When not log host"
replace:
path: /etc/rsyslog.conf
regexp: '({{ item }})'
replace: '#\1'
notify: restart rsyslog
with_items:
- '^(\$ModLoad imtcp)'
- '^(\$InputTCPServerRun)'
when: not rhel9cis_system_is_log_server
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts. | When log host"
replace:
path: /etc/rsyslog.conf
regexp: '^#(.*{{ item }}.*)'
replace: '\1'
notify: restart rsyslog
with_items:
- 'ModLoad imtcp'
- 'InputTCPServerRun'
when: rhel9cis_system_is_log_server
when:
- rhel9cis_rule_4_2_1_6
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.6
- rsyslog

View file

@ -0,0 +1,43 @@
---
- name: "4.2.2.1 | L1 | PATCH | Ensure journald is configured to send logs to rsyslog"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#ForwardToSyslog=|^ForwardToSyslog="
line: ForwardToSyslog=yes
state: present
when:
- rhel9cis_rule_4_2_2_1
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.2.1
- name: "4.2.2.2 | L1 | PATCH | Ensure journald is configured to compress large log files"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#Compress=|^Compress="
line: Compress=yes
state: present
when:
- rhel9cis_rule_4_2_2_2
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.2.2
- name: "4.2.2.3 | L1 | PATCH | Ensure journald is configured to write logfiles to persistent disk"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#Storage=|^Storage="
line: Storage=persistent
state: present
when:
- rhel9cis_rule_4_2_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.2.3

View file

@ -0,0 +1,13 @@
---
- name: "4.2.3 | L1 | PATCH | Ensure permissions on all logfiles are configured"
command: find /var/log -type f -exec chmod g-wx,o-rwx "{}" +
changed_when: false
failed_when: false
when:
- rhel9cis_rule_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.3

View file

@ -0,0 +1,24 @@
---
- name: "4.3 | L1 | PATCH | Ensure logrotate is configured"
block:
- name: "4.3 | L1 | AUDIT | Ensure logrotate is configured | Get logrotate settings"
find:
paths: /etc/logrotate.d/
register: log_rotates
- name: "4.3 | L1 | PATCH | Ensure logrotate is configured"
replace:
path: "{{ item.path }}"
regexp: '^(\s*)(daily|weekly|monthly|yearly)$'
replace: "\\1{{ rhel9cis_logrotate }}"
with_items:
- "{{ log_rotates.files }}"
- { path: "/etc/logrotate.conf" }
when:
- rhel9cis_rule_4_3
tags:
- level1-server
- level1-workstation
- patch
- rule_4.3

23
tasks/section_4/main.yml Normal file
View file

@ -0,0 +1,23 @@
---
- name: "SECTION | 4.1| Configure System Accounting (auditd)"
include: cis_4.1.1.x.yml
- name: "SECTION | 4.1.2.x| Configure Data Retention"
include: cis_4.1.2.x.yml
- name: "SECTION | 4.1.x| Auditd rules"
include: cis_4.1.x.yml
- name: "SECTION | 4.2.x| Configure Logging"
include: cis_4.2.1.x.yml
when: rhel9cis_syslog == 'rsyslog'
- name: "SECTION | 4.2.2.x| Configure journald"
include: cis_4.2.2.x.yml
- name: "SECTION | 4.2.3 | Configure logile perms"
include: cis_4.2.3.yml
- name: "SECTION | 4.3 | Configure logrotate"
include: cis_4.3.yml

View file

@ -0,0 +1,147 @@
---
- name: "5.1.1 | L1 | PATCH | Ensure cron daemon is enabled"
service:
name: crond
enabled: yes
when:
- rhel9cis_rule_5_1_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.1
- name: "5.1.2 | L1 | PATCH | Ensure permissions on /etc/crontab are configured"
file:
dest: /etc/crontab
owner: root
group: root
mode: 0600
when:
- rhel9cis_rule_5_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.2
- name: "5.1.3 | L1 | PATCH | Ensure permissions on /etc/cron.hourly are configured"
file:
dest: /etc/cron.hourly
state: directory
owner: root
group: root
mode: 0700
when:
- rhel9cis_rule_5_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.3
- name: "5.1.4 | L1 | PATCH | Ensure permissions on /etc/cron.daily are configured"
file:
dest: /etc/cron.daily
state: directory
owner: root
group: root
mode: 0700
when:
- rhel9cis_rule_5_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.4
- name: "5.1.5 | L1 | PATCH | Ensure permissions on /etc/cron.weekly are configured"
file:
dest: /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 | L1 | PATCH | Ensure permissions on /etc/cron.monthly are configured"
file:
dest: /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 | L1 | PATCH | Ensure permissions on /etc/cron.d are configured"
file:
dest: /etc/cron.d
state: directory
owner: root
group: root
mode: 0700
when:
- rhel9cis_rule_5_1_7
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.7
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users"
block:
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Remove at.deny"
file:
dest: /etc/at.deny
state: absent
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Check if at.allow exists"
stat:
path: "/etc/at.allow"
register: p
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Ensure at.allow is restricted to authorized users"
file:
dest: /etc/at.allow
state: '{{ "file" if p.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Remove cron.deny"
file:
dest: /etc/cron.deny
state: absent
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Check if cron.allow exists"
stat:
path: "/etc/cron.allow"
register: p
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users"
file:
dest: /etc/cron.allow
state: '{{ "file" if p.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
when:
- rhel9cis_rule_5_1_8
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.8

View file

@ -0,0 +1,345 @@
---
- name: "5.2.1 | L1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured"
file:
dest: /etc/ssh/sshd_config
state: file
owner: root
group: root
mode: 0600
when:
- rhel9cis_rule_5_2_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.1
- name: "5.2.2 | L1 | PATCH | Ensure SSH access is limited"
block:
- name: "5.2.2 | L1 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^AllowUsers"
line: AllowUsers {{ rhel9cis_sshd['allowusers'] }}
notify: restart sshd
when: "rhel9cis_sshd['allowusers']|default('') | length > 0"
- name: "5.2.2 | L1 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^AllowGroups"
line: AllowGroups {{ rhel9cis_sshd['allowgroups'] }}
notify: restart sshd
when: "rhel9cis_sshd['allowgroups']|default('') | length > 0"
- name: "5.2.2 | L1 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^DenyUsers"
line: DenyUsers {{ rhel9cis_sshd['denyusers'] }}
notify: restart sshd
when: "rhel9cis_sshd['denyusers']|default('') | length > 0"
- name: "5.2.2 | L1 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^DenyGroups"
line: DenyGroups {{ rhel9cis_sshd['denygroups'] }}
notify: restart sshd
when: "rhel9cis_sshd['denygroups']|default('') | length > 0"
when:
- rhel9cis_rule_5_2_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.2
- name: "5.2.3 | L1 | PATCH | Ensure permissions on SSH private host key files are configured"
block:
- name: "5.2.3 | L1 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys"
find:
paths: /etc/ssh
patterns: 'ssh_host_*_key'
recurse: true
file_type: any
register: rhel9cis_5_2_3_ssh_private_host_key
- name: "5.2.3 | L1 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys"
file:
path: "{{ item.path }}"
owner: root
group: root
mode: 0600
with_items:
- "{{ rhel9cis_5_2_3_ssh_private_host_key.files }}"
when:
- rhel9cis_rule_5_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.3
- name: "5.2.4 | L1 | PATCH | Ensure permissions on SSH public host key files are configured"
block:
- name: "5.2.4 | L1 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys"
find:
paths: /etc/ssh
patterns: 'ssh_host_*_key.pub'
recurse: true
file_type: any
register: rhel9cis_5_2_4_ssh_public_host_key
- name: "5.2.4 | L1 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys"
file:
path: "{{ item.path }}"
owner: root
group: root
mode: 0644
with_items:
- "{{ rhel9cis_5_2_4_ssh_public_host_key.files }}"
when:
- rhel9cis_rule_5_2_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.4
- name: "5.2.5 | L1 | PATCH | Ensure SSH LogLevel is appropriate"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#LogLevel|^LogLevel"
line: 'LogLevel {{ rhel9cis_ssh_loglevel }}'
when:
- rhel9cis_rule_5_2_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.5
- name: "5.2.6 | L2 | PATCH | Ensure SSH X11 forwarding is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#X11Forwarding|^X11Forwarding"
line: 'X11Forwarding no'
when:
- rhel9cis_rule_5_2_6
tags:
- level2-server
- level1-workstation
- patch
- rule_5.2.6
- name: "5.2.7 | L1 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: '^(#)?MaxAuthTries \d'
line: 'MaxAuthTries 4'
when:
- rhel9cis_rule_5_2_7
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.7
- name: "5.2.8 | L1 | PATCH | Ensure SSH IgnoreRhosts is enabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#IgnoreRhosts|^IgnoreRhosts"
line: 'IgnoreRhosts yes'
when:
- rhel9cis_rule_5_2_8
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.8
- name: "5.2.9 | L1 | PATCH | Ensure SSH HostbasedAuthentication is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: ^#HostbasedAuthentication|^HostbasedAuthentication"
line: 'HostbasedAuthentication no'
when:
- rhel9cis_rule_5_2_9
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.9
- name: "5.2.10 | L1 | PATCH | Ensure SSH root login is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#PermitRootLogin|^PermitRootLogin"
line: 'PermitRootLogin no'
when:
- rhel9cis_rule_5_2_10
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.10
- name: "5.2.11 | L1 | PATCH | Ensure SSH PermitEmptyPasswords is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords"
line: 'PermitEmptyPasswords no'
when:
- rhel9cis_rule_5_2_11
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.11
- name: "5.2.12 | L1 | PATCH | Ensure SSH PermitUserEnvironment is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#PermitUserEnvironment|^PermitUserEnvironment"
line: 'PermitUserEnvironment no'
when:
- rhel9cis_rule_5_2_12
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.12
- name: "5.2.13 | L1 | PATCH | Ensure SSH Idle Timeout Interval is configured"
block:
- name: "5.2.13 | L1 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: '^ClientAliveInterval'
line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}"
- name: "5.2.13 | L1 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: '^ClientAliveCountMax'
line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}"
when:
- rhel9cis_rule_5_2_13
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.13
- name: "5.2.14 | L1 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#LoginGraceTime|^LoginGraceTime"
line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}"
when:
- rhel9cis_rule_5_2_14
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.14
- name: "5.2.15 | L1 | PATCH | Ensure SSH warning banner is configured"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: '^Banner'
line: 'Banner /etc/issue.net'
when:
- rhel9cis_rule_5_2_15
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.15
- name: "5.2.16 | L1 | PATCH | Ensure SSH PAM is enabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#UsePAM|^UsePAM"
line: 'UsePAM yes'
when:
- rhel9cis_rule_5_2_16
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.16
- name: "5.2.17 | L2 | PATCH | Ensure SSH AllowTcpForwarding is disabled"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#AllowTcpForwarding|^AllowTcpForwarding"
line: 'AllowTcpForwarding no'
when:
- rhel9cis_rule_5_2_17
tags:
- level2-server
- level2-workstation
- patch
- rule_5.2.17
- name: "5.2.18 | L1 | PATCH | Ensure SSH MaxStartups is configured"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#MaxStartups|^MaxStartups"
line: 'MaxStartups 10:30:60'
when:
- rhel9cis_rule_5_2_18
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.18
- name: "5.2.19 | L1 | PATCH | Ensure SSH MaxSessions is set to 4 or less"
lineinfile:
state: present
dest: /etc/ssh/sshd_config
regexp: "^#MaxSessions|^MaxSessions"
line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}'
when:
- rhel9cis_rule_5_2_19
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.19
- name: "5.2.20 | L1 | PATCH | Ensure system-wide crypto policy is not over-ridden"
shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd
args:
warn: no
notify: restart sshd
when:
- rhel9cis_rule_5_2_20
tags:
- level1-server
- level1-workstation
- patch
- rule_5.2.20

View file

@ -0,0 +1,90 @@
---
- name: "5.3.1 | L1 | PATCH | Create custom authselect profile"
block:
- name: "5.3.1 | L1 | PATCH | Create custom authselect profile | Gather profiles"
shell: 'authselect current | grep "Profile ID: custom/"'
failed_when: false
changed_when: false
check_mode: no
register: rhel9cis_5_3_1_profiles
- name: "5.3.1 | L1 | AUDIT | Create custom authselect profile | Show profiles"
debug:
msg:
- "Below are the current custom profiles"
- "{{ rhel9cis_5_3_1_profiles.stdout_lines }}"
- name: "5.3.1 | L1 | PATCH | Create custom authselect profile | Create custom profiles"
shell: authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }}
args:
warn: no
when: rhel9cis_authselect_custom_profile_create
when:
- rhel9cis_rule_5_3_1
tags:
- level1-server
- level1-workstation
- patch
- authselect
- rule_5.3.1
- name: "5.3.2 | L1 | PATCH | Select authselect profile"
block:
- name: "5.3.2 | L1 | AUDIT | Select authselect profile | Gather profiles and enabled features"
shell: "authselect current"
args:
warn: no
failed_when: false
changed_when: false
check_mode: no
register: rhel9cis_5_3_2_profiles
- name: "5.3.2 | L1 | AUDIT | Select authselect profile | Show profiles"
debug:
msg:
- "Below are the current custom profiles"
- "{{ rhel9cis_5_3_2_profiles.stdout_lines }}"
- name: "5.3.2 | L1 | PATCH | Select authselect profile | Create custom profiles"
shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }}"
args:
warn: no
when: rhel9cis_authselect_custom_profile_select
when:
- rhel9cis_rule_5_3_2
tags:
- level1-server
- level1-workstation
- patch
- authselect
- rule_5.3.2
- name: "5.3.3 | L1 | PATCH | Ensure authselect includes with-faillock"
block:
- name: "5.3.3 | L1 | AUDIT | Ensure authselect includes with-faillock | Gather profiles and enabled features"
shell: "authselect current | grep with-faillock"
failed_when: false
changed_when: false
check_mode: no
register: rhel9cis_5_3_3_profiles_faillock
- name: "5.3.3 | L1 | AUDIT | Ensure authselect includes with-faillock| Show profiles"
debug:
msg:
- "Below are the current custom profiles"
- "{{ rhel9cis_5_3_3_profiles_faillock.stdout_lines }}"
- name: "5.3.3 | L1 | PATCH | Ensure authselect includes with-faillock | Create custom profiles"
shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} with-faillock"
args:
warn: no
when: rhel9cis_authselect_custom_profile_select
when:
- rhel9cis_rule_5_3_3
tags:
- level1-server
- level1-workstation
- patch
- authselect
- rule_5.3.3

View file

@ -0,0 +1,131 @@
---
- name: |
"5.4.1 | L1 | PATCH | Ensure password creation requirements are configured
5.4.2 | L1 | PATCH | Ensure lockout for failed password attempts is configured
5.4.3 | L1 | PATCH | Ensure password reuse is limited
5.4.4 | L1 | PATCH | Ensure password hashing algorithm is SHA-512"
block:
- name: "5.4.1 | L1 | PATCH | Ensure password creation requirements are configured | Set pwquality config settings"
lineinfile:
state: present
dest: /etc/security/pwquality.conf
regexp: ^{{ item.name }}
line: "{{ item.name }} = {{ item.value }}"
with_items:
- { name: minlen, value: "{{ rhel9cis_pam_password.minlen }}" }
- { name: minclass, value: "{{ rhel9cis_pam_password.minclass }}" }
when: rhel9cis_rule_5_4_1
- name: |
"5.4.1 | L1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings
5.4.3| L1 | PATCH | Ensure password reuse is limited | Set system-auth remember settings"
lineinfile:
dest: /etc/pam.d/system-auth
state: present
regexp: '^password requisite pam_pwquality.so'
line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce-for-root retry=3 remember={{ rhel9cis_pam_faillock.remember }}"
insertbefore: '^#?password ?'
when:
- rhel9cis_rule_5_4_1 or
rhel9cis_rule_5_4_3
- name: "5.4.1 | L1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings"
lineinfile:
dest: /etc/pam.d/password-auth
state: present
regexp: '^password requisite 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_4_1
- name: "5.4.2 | L1 | PATCH | Ensure lockout for failed password attempts is configured | Add deny count and unlock time for preauth"
lineinfile:
dest: /etc/pam.d/{{ item }}
state: present
regexp: '^auth required pam_faillock.so preauth'
line: "auth required pam_faillock.so preauth silent deny={{ rhel9cis_pam_faillock.attempts }}{{ (rhel9cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel9cis_pam_faillock.unlock_time }}"
insertafter: '^#?auth ?'
with_items:
- "system-auth"
- "password-auth"
when: rhel9cis_rule_5_4_2
- name: "5.4.2 | L1 | PATCH | Ensure lockout for failed password attempts is configured | Add deny count and unlock times for authfail"
lineinfile:
dest: /etc/pam.d/{{ item }}
state: present
regexp: '^auth required pam_faillock.so authfail'
line: "auth required pam_faillock.so authfail deny={{ rhel9cis_pam_faillock.attempts }}{{ (rhel9cis_pam_faillock.fail_for_root) | ternary(' even_deny_root ',' ') }}unlock_time={{ rhel9cis_pam_faillock.unlock_time }}"
insertafter: '^#?auth ?'
with_items:
- "system-auth"
- "password-auth"
when: rhel9cis_rule_5_4_2
- name: |
"5.4.3 | L1 | PATCH | Ensure password reuse is limited | Set system-auth remember remember settings
5.4.4 | L1 | PATCH | Ensure password hashing algorithm is SHA-512 | Set system-auth pwhash settings"
lineinfile:
dest: /etc/pam.d/system-auth
state: present
regexp: '^password sufficient pam_unix.so'
line: "password sufficient pam_unix.so {{ rhel9cis_pam_faillock.pwhash }} shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}"
insertafter: '^#?password ?'
when:
- rhel9cis_rule_5_4_3 or
rhel9cis_rule_5_4_4
- name: "5.4.4 | L1 | PATCH | Ensure password hashing algorithm is SHA-512 | Set system-auth pwhash settings"
lineinfile:
dest: /etc/pam.d/password-auth
state: present
regexp: '^password sufficient pam_unix.so'
line: "password sufficient pam_unix.so {{ rhel9cis_pam_faillock.pwhash }} shadow try_first_pass use_authtok"
insertafter: '^#?password ?'
when: rhel9cis_rule_5_4_4
# The two steps below were added to keep authconfig from overwritting the above configs. This follows steps from here: https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/7/html/security_guide/chap-hardening_your_system_with_tools_and_services
# With the steps below you will score five (5) points lower due to false positive results
- name: |
"5.4.1 | L1 | PATCH | Ensure password creation requirements are configured
5.4.2 | L1 | PATCH | Ensure lockout for failed password attempts is configured
5.4.3 | L1 | PATCH | Ensure password reuse is limited
5.4.4 | L1 | PATCH | Ensure password hashing algorithm is SHA-512"
copy:
src: /etc/pam.d/{{ item }}
dest: /etc/pam.d/{{ item }}-local
remote_src: yes
owner: root
group: root
mode: '0644'
with_items:
- "system-auth"
- "password-auth"
- name: |
"5.4.1 | L1 | PATCH | Ensure password creation requirements are configured
5.4.2 | L1 | PATCH | Ensure lockout for failed password attempts is configured
5.4.3 | L1 | PATCH | Ensure password reuse is limited
5.4.4 | L1 | PATCH | Ensure password hashing algorithm is SHA-512"
file:
src: /etc/pam.d/{{ item }}-local
dest: /etc/pam.d/{{ item }}
state: link
force: yes
with_items:
- "system-auth"
- "password-auth"
when:
- rhel9cis_rule_5_4_1 or
rhel9cis_rule_5_4_2 or
rhel9cis_rule_5_4_3 or
rhel9cis_rule_5_4_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.4.1
- rule_5.4.2
- rule_5.4.3
- rule_5.4.4

View file

@ -0,0 +1,117 @@
---
- name: "5.5.1.1 | L1 | PATCH | Ensure password expiration is 365 days or less"
lineinfile:
state: present
dest: /etc/login.defs
regexp: '^PASS_MAX_DAYS'
line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}"
when:
- rhel9cis_rule_5_5_1_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1.1
- name: "5.5.1.2 | L1 | PATCH | Ensure minimum days between password changes is 7 or more"
lineinfile:
state: present
dest: /etc/login.defs
regexp: '^PASS_MIN_DAYS'
line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}"
when:
- rhel9cis_rule_5_5_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1.2
- name: "5.5.1.3 | L1 | PATCH | Ensure password expiration warning days is 7 or more"
lineinfile:
state: present
dest: /etc/login.defs
regexp: '^PASS_WARN_AGE'
line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}"
when:
- rhel9cis_rule_5_5_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1.3
- name: "5.5.1.4 | L1 | PATCH | Ensure inactive password lock is 30 days or less"
block:
- name: "5.5.1.4 | L1 | AUDIT | Ensure inactive password lock is 30 days or less | Check current settings"
shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d=
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_5_5_1_4_inactive_settings
- name: "5.5.1.4 | L1 | PATCH | Ensure inactive password lock is 30 days or less | Set default inactive setting"
command: useradd -D -f {{ rhel9cis_inactivelock.lock_days }}
when: rhel9cis_5_5_1_4_inactive_settings.stdout | length == 0
- name: "5.5.1.4 | L1 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list"
shell: 'egrep ^[^:]+:[^\!*] /etc/shadow | cut -d: -f1'
check_mode: no
register: rhel_09_5_5_1_4_audit
changed_when: false
- name: "5.5.1.4 | L1 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts"
command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}"
with_items:
- "{{ rhel_09_5_5_1_4_audit.stdout_lines }}"
when:
- rhel9cis_rule_5_5_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1.4
- name: "5.5.1.5 | L1 | PATCH | Ensure all users last password change date is in the past"
block:
- name: "5.5.1.5 | L1 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time"
shell: echo $(($(date --utc --date "$1" +%s)/86400))
failed_when: false
changed_when: false
check_mode: no
register: rhel9cis_5_5_1_5_currentut
- name: "5.5.1.5 | L1 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future"
shell: "cat /etc/shadow | awk -F: '{if($3>{{ rhel9cis_5_5_1_5_currentut.stdout }})print$1}'"
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_5_5_1_5_user_list
- name: "5.5.1.5 | L1 | AUDIT | Ensure all users last password change date is in the past | Alert no pw change in the future exist"
debug:
msg: "Good News! All accounts have PW change dates that are in the past"
when: rhel9cis_5_5_1_5_user_list.stdout | length == 0
- name: "5.5.1.5 | L1 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future"
debug:
msg: "Warning! The following accounts have the last PW change date in the future: {{ rhel9cis_5_5_1_5_user_list.stdout_lines }}"
when:
- rhel9cis_5_5_1_5_user_list.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
- name: "5.5.1.5 | L1 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future"
command: passwd --expire {{ item }}
when:
- rhel9cis_5_5_1_5_user_list | length > 0
- rhel9cis_futurepwchgdate_autofix
with_items:
- "{{ rhel9cis_5_5_1_5_user_list.stdout_lines }}"
when:
- rhel9cis_rule_5_5_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1.5

View file

@ -0,0 +1,96 @@
---
- name: "5.5.2 | L1 | PATCH | Ensure system accounts are secured"
block:
- name: "5.5.2 | L1 | Ensure system accounts are secured | Set nologin"
user:
name: "{{ item.id }}"
shell: /usr/sbin/nologin
with_items:
- "{{ rhel9cis_passwd }}"
when:
- item.id != "root"
- item.id != "sync"
- item.id != "shutdown"
- item.id != "halt"
- item.gid < rhel9cis_int_gid
- item.shell != " /bin/false"
- item.shell != " /usr/sbin/nologin"
- name: "5.5.2 | L1 | PATCH | Ensure system accounts are secured | Lock accounts"
user:
name: "{{ item.id }}"
password_lock: true
with_items:
- "{{ rhel9cis_passwd }}"
when:
- item.id != "halt"
- item.id != "shutdown"
- item.id != "sync"
- item.id != "root"
- item.gid < rhel9cis_int_gid
- item.shell != " /bin/false"
- item.shell != " /usr/sbin/nologin"
when:
- rhel9cis_rule_5_5_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.2
- name: "5.5.3 | L1 | PATCH | Ensure default user shell timeout is 900 seconds or less"
blockinfile:
create: yes
mode: 0644
dest: "{{ item.dest }}"
state: "{{ item.state }}"
marker: "# {mark} ANSIBLE MANAGED"
block: |
# Set session timeout - CIS ID RHEL-09-5.4.5
TMOUT={{ rhel9cis_shell_session_timeout.timeout }}
export TMOUT
readonly TMOUT
with_items:
- { dest: "{{ rhel9cis_shell_session_timeout.file }}", state: present }
- { dest: /etc/profile, state: "{{ (rhel9cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" }
when:
- rhel9cis_rule_5_5_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.3
- name: "5.5.4 | L1 | PATCH | Ensure default group for the root account is GID 0"
command: usermod -g 0 root
changed_when: false
failed_when: false
when:
- rhel9cis_rule_5_5_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.4
- name: "5.5.5 | L1 | PATCH | Ensure default user umask is 027 or more restrictive"
block:
- name: "5.5.5 | L1 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc"
replace:
path: /etc/bashrc
regexp: '(^\s+umask) 0[012][0-6]'
replace: '\1 027'
- name: "5.5.5 | L1 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/profile"
replace:
path: /etc/profile
regexp: '(^\s+umask) 0[012][0-6]'
replace: '\1 027'
when:
- rhel9cis_rule_5_5_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.5

View file

@ -0,0 +1,35 @@
---
# this will just display the list of consoles. The site will need to confirm the allowed consoles are correct and change manually if needed.
- name: "5.6 | L1 | AUDIT | Ensure root login is restricted to system console"
block:
- name: "5.6 | L1 | AUDIT | Ensure root login is restricted to system console | Check if securetty file exists"
stat:
path: /etc/securetty
register: rhel9cis_securetty_check
- name: "5.6 | L1 | AUDIT | Ensure root login is restricted to system console | Capture consoles"
command: cat /etc/securetty
changed_when: false
register: rhel_09_5_6_audit
when: rhel9cis_securetty_check.stat.exists
- name: "5.6 | L1 | AUDIT |Ensure root login is restricted to system console | Display Console"
debug:
msg:
- "These are the consoles with root login access, please review:"
- "{{ rhel_09_5_6_audit.stdout_lines }}"
when: rhel9cis_securetty_check.stat.exists
- name: "5.6 | L1 | AUDIT | Ensure root login is restricted to system console | Display that no securetty file exists"
debug:
msg:
- "There is no /etc/securetty file, this has been removed by default in RHEL9"
when: not rhel9cis_securetty_check.stat.exists
when:
- rhel9cis_rule_5_6
tags:
- level1-server
- level1-workstation
- audit
- rule_5.6

View file

@ -0,0 +1,22 @@
---
- name: "5.7 | L1 | PATCH | Ensure access to the su command is restricted"
block:
- name: "5.7 | L1 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid"
lineinfile:
state: present
dest: /etc/pam.d/su
regexp: '^(#)?auth\s+required\s+pam_wheel\.so'
line: 'auth required pam_wheel.so use_uid {% if rhel9cis_sugroup is defined %}group={{ rhel9cis_sugroup }}{% endif %}'
- name: "5.7 | L1 | PATCH | Ensure access to the su command is restricted | wheel group contains root"
user:
name: "{{ rhel9cis_sugroup_users }}"
groups: "{{ rhel9cis_sugroup | default('wheel') }}"
when:
- rhel9cis_rule_5_7
tags:
- level1-server
- level1-workstation
- patch
- rule_5.7

27
tasks/section_5/main.yml Normal file
View file

@ -0,0 +1,27 @@
---
- name: "SECTION | 5.1 | Configure time-based job schedulers"
include: cis_5.1.x.yml
- name: "SECTION | 5.2 | Configure SSH Server"
include: cis_5.2.x.yml
- name: "SECTION | 5.3 | Configure Profiles"
include: cis_5.3.x.yml
when:
- rhel9cis_use_authconfig
- name: "SECTION | 5.4 | Configure PAM "
include: cis_5.4.x.yml
- name: "SECTION | 5.5.1.x | Passwords and Accounts"
include: cis_5.5.1.x.yml
- name: "SECTION | 5.5.x | System Accounts and User Settings"
include: cis_5.5.x.yml
- name: "SECTION | 5.6 | Root Login"
include: cis_5.6.yml
- name: Section | 5.7 | su Command Restriction
include: cis_5.7.yml

View file

@ -0,0 +1,294 @@
---
- name: "6.1.1 | L2 | AUDIT | Audit system file permissions"
block:
- name: "6.1.1 | L2 | AUDIT | Audit system file permissions | Audit the packages"
shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto
args:
warn: no
changed_when: false
failed_when: false
register: rhel9cis_6_1_1_packages_rpm
- name: "6.1.1 | L2 | AUDIT | Audit system file permissions | Create list and warning"
block:
- name: "6.1.1 | L2 | Audit system file permissions | Add file discrepancy list to system"
copy:
dest: "{{ rhel9cis_rpm_audit_file }}"
content: "{{ rhel9cis_6_1_1_packages_rpm.stdout }}"
- name: "6.1.1 | L2 | AUDIT | Audit system file permissions | Message out alert for package descrepancies"
debug:
msg: |
"Warning! You have some package descrepancies issues.
The file list can be found in {{ rhel9cis_rpm_audit_file }}"
when: rhel9cis_6_1_1_packages_rpm.stdout|length > 0
- name: "6.1.1 | L2 | AUDIT | Audit system file permissions | Message out no package descrepancies"
debug:
msg: "Good News! There are no package descrepancies"
when: rhel9cis_6_1_1_packages_rpm.stdout|length == 0
when:
- rhel9cis_rule_6_1_1
tags:
- level2-server
- level2-workstation
- audit
- rule_6.1.1
- name: "6.1.2 | L1 | PATCH | Ensure permissions on /etc/passwd are configured"
file:
dest: /etc/passwd
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_6_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.2
- name: "6.1.3 | L1 | PATCH | Ensure permissions on /etc/passwd- are configured"
file:
dest: /etc/passwd-
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_6_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.3
- name: "6.1.4 | L1 | PATCH | Ensure permissions on /etc/shadow are configured"
file:
dest: /etc/shadow
owner: root
group: root
mode: 0000
when:
- rhel9cis_rule_6_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.4
- name: "6.1.5 | L1 | PATCH | Ensure permissions on /etc/shadow- are configured"
file:
dest: /etc/shadow-
owner: root
group: root
mode: 0000
when:
- rhel9cis_rule_6_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.5
- name: "6.1.6 | L1 | PATCH | Ensure permissions on /etc/gshadow are configured"
file:
dest: /etc/gshadow
owner: root
group: root
mode: 0000
when:
- rhel9cis_rule_6_1_6
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.6
- name: "6.1.7 | L1 | PATCH | Ensure permissions on /etc/gshadow- are configured"
file:
dest: /etc/gshadow-
owner: root
group: root
mode: 0000
when:
- rhel9cis_rule_6_1_7
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.7
- name: "6.1.8 | L1 | PATCH | Ensure permissions on /etc/group are configured"
file:
dest: /etc/group-
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_6_1_8
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.8
- name: "6.1.9 | L1 | PATCH | Ensure permissions on /etc/group- are configured"
file:
dest: /etc/group-
owner: root
group: root
mode: 0644
when:
- rhel9cis_rule_6_1_9
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.9
- name: "6.1.10 | L1 | PATCH | Ensure no world writable files exist"
block:
- name: "6.1.10 | L1 | AUDIT | Ensure no world writable files exist | Get list of world-writable files"
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_10_perms_results
- name: "6.1.10 | L1 | AUDIT | Ensure no world writable files exist | Alert no world-writable files exist"
debug:
msg: "Good news! We have not found any world-writable files on your system"
when:
- rhel_09_6_1_10_perms_results.stdout is not defined
- name: "6.1.10 | L1 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)"
file:
path: '{{ item }}'
mode: o-w
state: touch
with_items: "{{ rhel_09_6_1_10_perms_results.stdout_lines }}"
when:
- rhel_09_6_1_10_perms_results.stdout_lines is defined
- rhel9cis_no_world_write_adjust
when:
- rhel9cis_rule_6_1_10
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.10
- name: "6.1.11 | L1 | AUDIT | Ensure no unowned files or directories exist"
block:
- name: "6.1.11 | L1 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories"
command: find "{{ item.mount }}" -xdev -nouser
check_mode: false
failed_when: false
changed_when: false
with_items: "{{ ansible_mounts }}"
register: rhel_09_6_1_11_audit
when: item['device'].startswith('/dev') and not 'bind' in item['options']
- name: "6.1.11 | L1 | AUDIT | Ensure no unowned files or directories exist | Displaying any unowned files or directories"
debug:
msg: "Manual intervention is required -- missing owner on items in {{ item.item.mount }}: {{ item.stdout_lines | join(', ') }}"
with_items: "{{ rhel_09_6_1_11_audit.results }}"
when:
- item.stdout_lines is defined
- item.stdout_lines | length > 0
when:
- rhel9cis_rule_6_1_11
tags:
- level1-server
- level1-workstation
- audit
- rule_6.1.11
- name: "6.1.12 | L1 | AUDIT | Ensure no ungrouped files or directories exist"
block:
- name: "6.1.12 | L1 | AUDIT | Ensure no ungrouped files or directories exist | Finding all ungrouped files or directories"
command: find "{{ item.mount }}" -xdev -nogroup
check_mode: false
failed_when: false
changed_when: false
register: rhel_09_6_1_12_audit
with_items: "{{ ansible_mounts }}"
when: item['device'].startswith('/dev') and not 'bind' in item['options']
- name: "6.1.12 | L1 | AUDIT | Ensure no ungrouped files or directories exist | Displaying all ungrouped files or directories"
debug:
msg: "Manual intervention is required -- missing group on items in {{ item.item.mount }}: {{ item.stdout_lines | join(', ') }}"
with_items: "{{ rhel_09_6_1_12_audit.results }}"
when:
- item.stdout_lines is defined
- item.stdout_lines | length > 0
when:
- rhel9cis_rule_6_1_12
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.12
- name: "6.1.13 | L1 | AUDIT | Audit SUID executables"
block:
- name: "6.1.13 | L1 | AUDIT | Audit SUID executables | Find all SUID executables"
shell: df {{ item.mount }} -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_perms_results
with_items: "{{ ansible_mounts }}"
- name: "6.1.13 | L1 | AUDIT | Audit SUID executables | Alert no SUID executables exist"
debug:
msg: "Good news! We have not found any SUID executable files on your system"
failed_when: false
changed_when: false
when:
- rhel_09_6_1_13_perms_results.stdout is not defined
- name: "6.1.13 | L1 | AUDIT | Audit SUID executables | Alert SUID executables exist"
debug:
msg: "Manual intervention is required -- SUID set on items in {{ item.item.mount }}: {{ item.stout_lines | join(', ') }}"
with_items: "{{ rhel_09_6_1_13_perms_results.stdout_lines }}"
when:
- rhel_09_6_1_13_perms_results.stdout is defined
when:
- rhel9cis_rule_6_1_13
tags:
- level1-server
- level1-workstation
- audit
- rule_6.1.13
- name: "6.1.14 | L1 | AUDIT | Audit SGID executables"
block:
- name: "6.1.14 | L1 | AUDIT | Audit SGID executables | Find all SGID executables"
shell: df {{ item.mount }} -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_perms_results
with_items: "{{ ansible_mounts }}"
- name: "6.1.14 | L1 | AUDIT | Audit SGID executables | Alert no SGID executables exist"
debug:
msg: "Good news! We have not found any SGID executable files on your system"
failed_when: false
changed_when: false
when:
- rhel_09_6_1_14_perms_results.stdout is not defined
- name: "6.1.14 | L1 | AUDIT | Audit SGID executables | Alert SGID executables exist"
debug:
msg: "Manual intervention is required -- SGID set on items in {{ item.item.mount }}: {{ item.stout_lines | join(', ') }}"
with_items: "{{ rhel_09_6_1_14_perms_results.stdout_lines }}"
when:
- rhel_09_6_1_14_perms_results.stdout is defined
when:
- rhel9cis_rule_6_1_14
tags:
- level1-server
- level1-workstation
- patch
- rule_6.1.14

View file

@ -0,0 +1,519 @@
---
- name: "6.2.1 | L1 | AUDIT | Ensure password fields are not empty"
command: passwd -l {{ item }}
changed_when: false
failed_when: false
with_items: "{{ empty_password_accounts.stdout_lines }}"
when:
- empty_password_accounts.rc
- rhel9cis_rule_6_2_1
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.1
- name: "6.2.2 | L1 | PATCH | Ensure no legacy '+' entries exist in /etc/passwd"
command: sed -i '/^+/ d' /etc/passwd
changed_when: false
failed_when: false
when:
- rhel9cis_rule_6_2_2
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.2
- skip_ansible_lint
- name: "6.2.3 | L1 | PATCH | Ensure root PATH Integrity"
block:
- name: "6.2.3 | L1 | AUDIT | Ensure root PATH Integrity | Determine empty value"
shell: 'echo $PATH | grep ::'
check_mode: no
register: path_colon
changed_when: False
failed_when: path_colon.rc == 0
- name: "6.2.3 | L1 | AUDIT | Ensure root PATH Integrity | Determin colon end"
shell: 'echo $PATH | grep :$'
check_mode: no
register: path_colon_end
changed_when: False
failed_when: path_colon_end.rc == 0
- name: "6.2.3 | L1 | AUDIT | Ensure root PATH Integrity | Determine dot in path"
shell: "/bin/bash --login -c 'env | grep ^PATH=' | sed -e 's/PATH=//' -e 's/::/:/' -e 's/:$//' -e 's/:/\\n/g'"
check_mode: no
register: dot_in_path
changed_when: False
failed_when: '"." in dot_in_path.stdout_lines'
- name: "6.2.3 | L1 | AUDIT | Ensure root PATH Integrity | Alert on empty value, colon end, and dot in path"
debug:
msg:
- "The following paths have an empty value: {{ path_colon.stdout_lines }}"
- "The following paths have colon end: {{ path_colon_end.stdout_lines }}"
- "The following paths have a dot in the path: {{ dot_in_path.stdout_lines }}"
- name: "6.2.3 | L1 | PATCH | Ensure root PATH Integrity (Scored) | Determine rights and owner"
file: >
path='{{ item }}'
follow=yes
state=directory
owner=root
mode='o-w,g-w'
with_items: "{{ dot_in_path.stdout_lines }}"
when:
- rhel9cis_rule_6_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.3
- name: "6.2.4 | L1 | PATCH | Ensure no legacy '+' entries exist in /etc/shadow"
command: sed -i '/^+/ d' /etc/shadow
changed_when: false
failed_when: false
when:
- rhel9cis_rule_6_2_4
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.4
- skip_ansible_lint
- name: "6.2.5 | L1 | PATCH | Ensure no legacy '+' entries exist in /etc/group"
command: sed -i '/^+/ d' /etc/group
changed_when: false
failed_when: false
when:
- rhel9cis_rule_6_2_5
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.5
- skip_ansible_lint
- name: "6.2.6 | L1 | PATCH | Ensure root is the only UID 0 account"
command: passwd -l {{ item }}
changed_when: false
failed_when: false
with_items: "{{ uid_zero_accounts_except_root.stdout_lines }}"
when:
- uid_zero_accounts_except_root.rc
- rhel9cis_rule_6_2_6
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.6
- name: "6.2.7 | L1 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
block:
- name: "6.2.7 | L1 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive"
stat:
path: "{{ item }}"
with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', rhel9cis_int_gid) | selectattr('uid', '!=', 65534) | map(attribute='dir') | list }}"
register: rhel_09_6_2_7_audit
- name: "6.2.7 | L1 | AUDIT | Ensure users' home directories permissions are 750 or more restrictive"
command: find -H {{ item.0 | quote }} -not -type l -perm /027
check_mode: false
changed_when: rhel_09_6_2_7_patch_audit.stdout | length > 0
register: rhel_09_6_2_7_patch_audit
when:
- ansible_check_mode
- item.1.exists
with_together:
- "{{ rhel_09_6_2_7_audit.results | map(attribute='item') | list }}"
- "{{ rhel_09_6_2_7_audit.results | map(attribute='stat') | list }}"
loop_control:
label: "{{ item.0 }}"
- name: "6.2.7 | L1 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
file:
path: "{{ item.0 }}"
recurse: yes
mode: a-st,g-w,o-rwx
register: rhel_09_6_2_7_patch
when:
- not ansible_check_mode
- item.1.exists
with_together:
- "{{ rhel_09_6_2_7_audit.results | map(attribute='item') | list }}"
- "{{ rhel_09_6_2_7_audit.results | map(attribute='stat') | list }}"
loop_control:
label: "{{ item.0 }}"
# set default ACLs so the homedir has an effective umask of 0027
- name: "6.2.7 | L1 | PATCH | Ensure users' home directories permissions are 750 or more restrictive"
acl:
path: "{{ item.0 }}"
default: yes
state: present
recursive: yes
etype: "{{ item.1.etype }}"
permissions: "{{ item.1.mode }}"
when: not rhel9cis_system_is_container
with_nested:
- "{{ (ansible_check_mode | ternary(rhel_09_6_2_7_patch_audit, rhel_09_6_2_7_patch)).results |
rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}"
-
- etype: group
mode: rx
- etype: other
mode: '0'
when:
- rhel9cis_rule_6_2_7
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.7
- name: "6.2.8 | L1 | PATCH | Ensure users own their home directories"
file:
path: "{{ item.dir }}"
owner: "{{ item.id }}"
state: directory
with_items: "{{ rhel9cis_passwd }}"
loop_control:
label: "{{ rhel9cis_passwd_label }}"
when:
- item.uid >= rhel9cis_int_gid
- rhel9cis_rule_6_2_8
tags:
- skip_ansible_lint # settings found on 6_2_7
- level1-server
- level1-workstation
- patch
- rule_6.2.8
- name: "6.2.9 | L1 | PATCH | Ensure users' dot files are not group or world-writable"
block:
- name: "6.2.9 | L1 | AUDIT | Ensure users' dot files are not group or world-writable | Check for files"
shell: find /home/ -name "\.*" -perm /g+w,o+w
changed_when: false
failed_when: false
register: rhel9cis_6_2_9_audit
- name: "6.2.9 | L1 | AUDIT | Ensure users' dot files are not group or world-writable | Alert on files found"
debug:
msg: "Good news! We have not found any group or world-writable dot files on your sytem"
when:
- rhel9cis_6_2_9_audit.stdout is not defined
- name: "6.2.9 | L1 | PATCH | Ensure users' dot files are not group or world-writable | Changes files if configured"
file:
path: '{{ item }}'
mode: go-w
with_items: "{{ rhel9cis_6_2_9_audit.stdout_lines }}"
when:
- rhel9cis_6_2_9_audit.stdout is defined
- rhel9cis_dotperm_ansiblemanaged
when:
- rhel9cis_rule_6_2_9
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.9
- name: "6.2.10 | L1 | PATCH | Ensure no users have .forward files"
file:
state: absent
dest: "~{{ item }}/.forward"
with_items: "{{ users.stdout_lines }}"
when:
- rhel9cis_rule_6_2_10
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.10
- name: "6.2.11 | L1 | PATCH | Ensure no users have .netrc files"
file:
state: absent
dest: "~{{ item }}/.netrc"
with_items: "{{ users.stdout_lines }}"
when:
- rhel9cis_rule_6_2_11
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.11
- name: "6.2.12 | L1 | PATCH | Ensure users' .netrc Files are not group or world accessible"
command: /bin/true
changed_when: false
failed_when: false
when:
- rhel9cis_rule_6_2_12
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.12
- name: "6.2.13 | L1 | PATCH | Ensure no users have .rhosts files"
file:
state: absent
dest: "~{{ item }}/.rhosts"
with_items: "{{ users.stdout_lines }}"
when:
- rhel9cis_rule_6_2_13
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.13
- name: "6.2.14 | L1 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group"
block:
- name: "6.2.14 | L1 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Check /etc/passwd entries"
shell: pwck -r | grep 'no group' | awk '{ gsub("[:\47]",""); print $2}'
changed_when: false
failed_when: false
check_mode: false
register: passwd_gid_check
- name: "6.2.14 | L1 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print message that all groups match between passwd and group files"
debug:
msg: "Good News! There are no users that have non-existent GUIDs (Groups)"
when: passwd_gid_check.stdout is not defined
- name: "6.2.14 | L1 | AUDIT | Ensure all groups in /etc/passwd exist in /etc/group | Print warning about users with invalid GIDs missing GID entries in /etc/group"
debug:
msg: "WARNING: The following users have non-existent GIDs (Groups): {{ passwd_gid_check.stdout_lines | join (', ') }}"
when: passwd_gid_check.stdout is defined
when:
- rhel9cis_rule_6_2_14
tags:
- level1-server
- level1-workstation
- audit
- rule_6.2.14
- name: "6.2.15 | L1 | AUDIT Ensure no duplicate UIDs exist"
block:
- name: "6.2.15 | L1 | AUDIT | Ensure no duplicate UIDs exist | Check for duplicate UIDs"
shell: "pwck -r | awk -F: '{if ($3 in uid) print $1 ; else uid[$3]}' /etc/passwd"
changed_when: false
failed_when: false
register: user_uid_check
- name: "6.2.15 | L1 | AUDIT | Ensure no duplicate UIDs exist | Print message that no duplicate UIDs exist"
debug:
msg: "Good News! There are no duplicate UID's in the system"
when: user_uid_check.stdout is not defined
- name: "6.2.15 | L1 | AUDIT| Ensure no duplicate UIDs exist | Print warning about users with duplicate UIDs"
debug:
msg: "Warning: The following users have UIDs that are duplicates: {{ user_uid_check.stdout_lines }}"
when: user_uid_check.stdout is defined
when:
- rhel9cis_rule_6_2_15
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.15
- name: "6.2.16 | L1 | AUDIT | Ensure no duplicate GIDs exist"
block:
- name: "6.2.16 | L1 | AUDIT | Ensure no duplicate GIDs exist | Check for duplicate GIDs"
shell: "pwck -r | awk -F: '{if ($3 in users) print $1 ; else users[$3]}' /etc/group"
changed_when: false
failed_when: false
register: user_user_check
- name: "6.2.16 | L1 | AUDIT | Ensure no duplicate GIDs exist | Print message that no duplicate GID's exist"
debug:
msg: "Good News! There are no duplicate GIDs in the system"
when: user_user_check.stdout is not defined
- name: "6.2.16 | L1 | AUDIT | Ensure no duplicate GIDs exist | Print warning about users with duplicate GIDs"
debug:
msg: "Warning: The following groups have duplicate GIDs: {{ user_user_check.stdout_lines }}"
when: user_user_check.stdout is defined
when:
- rhel9cis_rule_6_2_16
tags:
- level1-server
- level1-workstation
- audit
- rule_6.2.16
- name: "6.2.17 | L1 | AUDIT | Ensure no duplicate user names exist"
block:
- name: "6.2.17 | L1 | AUDIT | Ensure no duplicate user names exist | Check for duplicate User Names"
shell: "pwck -r | awk -F: '{if ($1 in users) print $1 ; else users[$1]}' /etc/passwd"
changed_when: false
failed_when: false
register: user_username_check
- name: "6.2.17 | L1 | AUDIT | Ensure no duplicate user names exist | Print message that no duplicate user names exist"
debug:
msg: "Good News! There are no duplicate user names in the system"
when: user_username_check.stdout is not defined
- name: "6.2.17 | L1 | AUDIT | Ensure no duplicate user names exist | Print warning about users with duplicate User Names"
debug:
msg: "Warning: The following user names are duplicates: {{ user_username_check.stdout_lines }}"
when: user_username_check.stdout is defined
when:
- rhel9cis_rule_6_2_17
tags:
- level1-server
- level1-workstation
- audit
- rule_6.2.17
- name: "6.2.18 | L1 | AUDIT |Ensure no duplicate group names exist"
block:
- name: "6.2.18 | L1 | AUDIT | Ensure no duplicate group names exist | Check for duplicate group names"
shell: 'getent passwd | cut -d: -f1 | sort -n | uniq -d'
changed_when: false
failed_when: false
check_mode: no
register: group_group_check
- name: "6.2.18 | L1 | AUDIT | Ensure no duplicate group names exist | Print message that no duplicate groups exist"
debug:
msg: "Good News! There are no duplicate group names in the system"
when: group_group_check.stdout is defined
- name: "6.2.18 | L1 | AUDIT | Ensure no duplicate group names exist | Print warning about users with duplicate group names"
debug:
msg: "Warning: The following group names are duplicates: {{ group_group_check.stdout_lines }}"
when: group_group_check.stdout is not defined
when:
- rhel9cis_rule_6_2_18
tags:
- level1-server
- level1-workstation
- audit
- rule_6.2.18
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty"
block:
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Check for shadow group and pull group id"
shell: "getent group shadow | cut -d: -f3"
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_shadow_gid
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Check /etc/group for empty shadow group"
shell: grep ^shadow:[^:]*:[^:]*:[^:]+ /etc/group
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_empty_shadow
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Check for users assigned to shadow"
shell: "getent passwd | awk -F: '$4 == '{{ rhel9cis_shadow_gid.stdout }}' {print $1}'"
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_shadow_passwd
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Alert shadow group is empty and no users assigned"
debug:
msg:
- " Good News! The shadow group is empty and there are no users assigned to shadow"
when:
- rhel9cis_empty_shadow.stdout | length == 0
- rhel9cis_shadow_passwd.stdout | length == 0
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Alert shadow group is not empty"
debug:
msg:
- "Alert! The shadow group is not empty"
when:
- rhel9cis_empty_shadow.stdout | length > 0
- name: "6.2.19 | L1 | AUDIT | Ensure shadow group is empty | Alert users are using shadow group"
debug:
msg:
- "Alert! The following users are assigned to the shadow group, please assing them to the appropriate group"
- "{{ rhel9cis_shadow_passwd.stdout_lines }}"
when:
- rhel9cis_shadow_passwd.stdout | length > 0
when:
- rhel9cis_rule_6_2_19
tags:
- level1-server
- level1-workstation
- audit
- rule_6.2.19
- name: "6.2.20 | L1 | PATCH | Ensure all users' home directories exist"
block:
- name: "6.2.20 | L1 | AUDIT | Ensure all users' home directories exist"
stat:
path: "{{ item }}"
register: rhel_09_6_2_20_audit
with_items: "{{ rhel9cis_passwd | selectattr('uid', '>=', rhel9cis_int_gid) | selectattr('uid', '!=', 65534) | map(attribute='dir') | list }}"
- name: "6.2.20 | L1 | AUDIT | Ensure all users' home directories exist"
command: find -H {{ item.0 | quote }} -not -type l -perm /027
check_mode: false
changed_when: rhel_09_6_2_20_patch_audit.stdout | length > 0
register: rhel_09_6_2_20_patch_audit
when:
- ansible_check_mode
- item.1.exists
with_together:
- "{{ rhel_09_6_2_20_audit.results | map(attribute='item') | list }}"
- "{{ rhel_09_6_2_20_audit.results | map(attribute='stat') | list }}"
loop_control:
label: "{{ item.0 }}"
- name: "6.2.20 | L1 | PATCH | Ensure all users' home directories exist"
file:
path: "{{ item.0 }}"
recurse: yes
mode: a-st,g-w,o-rwx
register: rhel_09_6_2_20_patch
when:
- not ansible_check_mode
- item.1.exists
with_together:
- "{{ rhel_09_6_2_20_audit.results | map(attribute='item') | list }}"
- "{{ rhel_09_6_2_20_audit.results | map(attribute='stat') | list }}"
loop_control:
label: "{{ item.0 }}"
# set default ACLs so the homedir has an effective umask of 0027
- name: "6.2.20 | L1 | PATCH | Ensure all users' home directories exist"
acl:
path: "{{ item.0 }}"
default: yes
state: present
recursive: yes
etype: "{{ item.1.etype }}"
permissions: "{{ item.1.mode }}"
when: not rhel9cis_system_is_container
with_nested:
- "{{ (ansible_check_mode | ternary(rhel_09_6_2_20_patch_audit, rhel_09_6_2_20_patch)).results |
rejectattr('skipped', 'defined') | map(attribute='item') | map('first') | list }}"
-
- etype: group
mode: rx
- etype: other
mode: '0'
when:
- rhel9cis_rule_6_2_20
tags:
- level1-server
- level1-workstation
- patch
- rule_6.2.20

7
tasks/section_6/main.yml Normal file
View file

@ -0,0 +1,7 @@
---
- name: "SECTION | 6.1 | System File Permissions"
include: cis_6.1.x.yml
- name: "SECTION | 6.2 | User and Group Settings"
include: cis_6.2.x.yml

View file

@ -0,0 +1,474 @@
## metadata for Audit benchmark
benchmark_version: '1.0.1'
# Set if genuine RHEL (subscription manager check) not for derivatives e.g. CentOS
is_redhat_os: {% if ansible_distribution == "RedHat" %}true{% else %}false{% endif %}
rhel9cis_os_distribution: {{ ansible_distribution | lower }}
# timeout for each command to run where set - default = 10seconds/10000ms
timeout_ms: {{ audit_cmd_timeout }}
# Taken from LE rhel9-cis
rhel9cis_notauto: {{ rhel9cis_notauto }}
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_level_1: {{ rhel9cis_level_1 }}
rhel9cis_level_2: {{ rhel9cis_level_2 }}
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
{% if rhel9cis_legacy_boot is defined %}
rhel9cis_legacy_boot: {{ rhel9cis_legacy_boot }}
{% endif %}
rhel9cis_set_boot_pass: {{ rhel9cis_set_boot_pass }}
# 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
rhel9cis_rule_1_1_1_1: {{ rhel9cis_rule_1_1_1_1 }}
rhel9cis_rule_1_1_1_2: {{ rhel9cis_rule_1_1_1_2 }}
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_2: {{ rhel9cis_rule_1_1_2 }}
rhel9cis_rule_1_1_3: {{ rhel9cis_rule_1_1_3 }}
rhel9cis_rule_1_1_4: {{ rhel9cis_rule_1_1_4 }}
rhel9cis_rule_1_1_5: {{ rhel9cis_rule_1_1_5 }}
rhel9cis_rule_1_1_6: {{ rhel9cis_rule_1_1_6 }}
rhel9cis_rule_1_1_7: {{ rhel9cis_rule_1_1_7 }}
rhel9cis_rule_1_1_8: {{ rhel9cis_rule_1_1_8 }}
rhel9cis_rule_1_1_9: {{ rhel9cis_rule_1_1_9 }}
rhel9cis_rule_1_1_10: {{ rhel9cis_rule_1_1_10 }}
rhel9cis_rule_1_1_11: {{ rhel9cis_rule_1_1_11 }}
rhel9cis_rule_1_1_12: {{ rhel9cis_rule_1_1_12 }}
rhel9cis_rule_1_1_13: {{ rhel9cis_rule_1_1_13 }}
rhel9cis_rule_1_1_14: {{ rhel9cis_rule_1_1_14 }}
rhel9cis_rule_1_1_15: {{ rhel9cis_rule_1_1_15 }}
rhel9cis_rule_1_1_16: {{ rhel9cis_rule_1_1_16 }}
rhel9cis_rule_1_1_17: {{ rhel9cis_rule_1_1_17 }}
rhel9cis_rule_1_1_18: {{ rhel9cis_rule_1_1_18 }}
rhel9cis_rule_1_1_19: {{ rhel9cis_rule_1_1_19 }}
rhel9cis_rule_1_1_20: {{ rhel9cis_rule_1_1_20 }}
rhel9cis_rule_1_1_21: {{ rhel9cis_rule_1_1_21 }}
rhel9cis_rule_1_1_22: {{ rhel9cis_rule_1_1_22 }}
rhel9cis_rule_1_1_23: {{ rhel9cis_rule_1_1_23 }}
rhel9cis_rule_1_2_1: {% if ansible_distribution == "RedHat" %}True{% else %}False{% endif %} # Only run if Redhat and Subscribed
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 }}
rhel9cis_rule_1_2_5: {{ rhel9cis_rule_1_2_5 }}
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 }}
rhel9cis_rule_1_4_1: {{ rhel9cis_rule_1_4_1 }}
rhel9cis_rule_1_4_2: {{ rhel9cis_rule_1_4_2 }}
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 }}
rhel9cis_rule_1_6_1: {{ rhel9cis_rule_1_6_1 }}
rhel9cis_rule_1_6_2: {{ rhel9cis_rule_1_6_2 }}
rhel9cis_rule_1_7_1_1: {{ rhel9cis_rule_1_7_1_1 }}
rhel9cis_rule_1_7_1_2: {{ rhel9cis_rule_1_7_1_2 }}
rhel9cis_rule_1_7_1_3: {{ rhel9cis_rule_1_7_1_3 }}
rhel9cis_rule_1_7_1_4: {{ rhel9cis_rule_1_7_1_4 }}
rhel9cis_rule_1_7_1_5: {{ rhel9cis_rule_1_7_1_5 }}
rhel9cis_rule_1_7_1_6: {{ rhel9cis_rule_1_7_1_6 }}
rhel9cis_rule_1_7_1_7: {{ rhel9cis_rule_1_7_1_7 }}
rhel9cis_rule_1_8_1_1: {{ rhel9cis_rule_1_8_1_1 }}
rhel9cis_rule_1_8_1_2: {{ rhel9cis_rule_1_8_1_2 }}
rhel9cis_rule_1_8_1_3: {{ rhel9cis_rule_1_8_1_3 }}
rhel9cis_rule_1_8_1_4: {{ rhel9cis_rule_1_8_1_4 }}
rhel9cis_rule_1_8_1_5: {{ rhel9cis_rule_1_8_1_5 }}
rhel9cis_rule_1_8_1_6: {{ rhel9cis_rule_1_8_1_6 }}
rhel9cis_rule_1_8_2: {{ rhel9cis_rule_1_8_2 }}
rhel9cis_rule_1_9: {{ rhel9cis_rule_1_9 }}
rhel9cis_rule_1_10: {{ rhel9cis_rule_1_10 }}
rhel9cis_rule_1_11: {{ rhel9cis_rule_1_11 }}
# section 2 rules
rhel9cis_rule_2_1_1: {{ rhel9cis_rule_2_1_1 }}
rhel9cis_rule_2_2_1_1: {{ rhel9cis_rule_2_2_1_1 }}
rhel9cis_rule_2_2_1_2: {{ rhel9cis_rule_2_2_1_2 }}
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 }}
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 }}
# Section 3 rules
rhel9cis_rule_3_1_1: {{ rhel9cis_rule_3_1_1 }}
rhel9cis_rule_3_1_2: {{ rhel9cis_rule_3_1_2 }}
rhel9cis_rule_3_2_1: {{ rhel9cis_rule_3_2_1 }}
rhel9cis_rule_3_2_2: {{ rhel9cis_rule_3_2_2 }}
rhel9cis_rule_3_2_3: {{ rhel9cis_rule_3_2_3 }}
rhel9cis_rule_3_2_4: {{ rhel9cis_rule_3_2_4 }}
rhel9cis_rule_3_2_5: {{ rhel9cis_rule_3_2_5 }}
rhel9cis_rule_3_2_6: {{ rhel9cis_rule_3_2_6 }}
rhel9cis_rule_3_2_7: {{ rhel9cis_rule_3_2_7 }}
rhel9cis_rule_3_2_8: {{ rhel9cis_rule_3_2_8 }}
rhel9cis_rule_3_2_9: {{ rhel9cis_rule_3_2_9 }}
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 }}
rhel9cis_rule_3_3_4: {{ rhel9cis_rule_3_3_4 }}
rhel9cis_rule_3_4_1_1: {{ rhel9cis_rule_3_4_1_1 }}
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_5: {{ rhel9cis_rule_3_5 }}
rhel9cis_rule_3_6: {{ rhel9cis_rule_3_6 }}
# Section 4 rules
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 }}
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 }}
rhel9cis_rule_4_1_3: {{ rhel9cis_rule_4_1_3 }}
rhel9cis_rule_4_1_4: {{ rhel9cis_rule_4_1_4 }}
rhel9cis_rule_4_1_5: {{ rhel9cis_rule_4_1_5 }}
rhel9cis_rule_4_1_6: {{ rhel9cis_rule_4_1_6 }}
rhel9cis_rule_4_1_7: {{ rhel9cis_rule_4_1_7 }}
rhel9cis_rule_4_1_8: {{ rhel9cis_rule_4_1_8 }}
rhel9cis_rule_4_1_9: {{ rhel9cis_rule_4_1_9 }}
rhel9cis_rule_4_1_10: {{ rhel9cis_rule_4_1_10 }}
rhel9cis_rule_4_1_11: {{ rhel9cis_rule_4_1_11 }}
rhel9cis_rule_4_1_12: {{ rhel9cis_rule_4_1_12 }}
rhel9cis_rule_4_1_13: {{ rhel9cis_rule_4_1_13 }}
rhel9cis_rule_4_1_14: {{ rhel9cis_rule_4_1_14 }}
rhel9cis_rule_4_1_15: {{ rhel9cis_rule_4_1_15 }}
rhel9cis_rule_4_1_16: {{ rhel9cis_rule_4_1_16 }}
rhel9cis_rule_4_1_17: {{ rhel9cis_rule_4_1_17 }}
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_2_1: {{ rhel9cis_rule_4_2_2_1 }}
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_3: {{ rhel9cis_rule_4_2_3 }}
rhel9cis_rule_4_3: {{ rhel9cis_rule_4_3 }}
# Section 5
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 }}
rhel9cis_rule_5_1_4: {{ rhel9cis_rule_5_1_4 }}
rhel9cis_rule_5_1_5: {{ rhel9cis_rule_5_1_5 }}
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_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 }}
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 }}
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_4_1: {{ rhel9cis_rule_5_4_1 }}
rhel9cis_rule_5_4_2: {{ rhel9cis_rule_5_4_2 }}
rhel9cis_rule_5_4_3: {{ rhel9cis_rule_5_4_3 }}
rhel9cis_rule_5_4_4: {{ rhel9cis_rule_5_4_4 }}
rhel9cis_rule_5_5_1_1: {{ rhel9cis_rule_5_5_1_1 }}
rhel9cis_rule_5_5_1_2: {{ rhel9cis_rule_5_5_1_2 }}
rhel9cis_rule_5_5_1_3: {{ rhel9cis_rule_5_5_1_3 }}
rhel9cis_rule_5_5_1_4: {{ rhel9cis_rule_5_5_1_4 }}
rhel9cis_rule_5_5_1_5: {{ rhel9cis_rule_5_5_1_5 }}
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 }}
rhel9cis_rule_5_5_5: {{ rhel9cis_rule_5_5_5 }}
rhel9cis_rule_5_6: {{ rhel9cis_rule_5_6 }}
rhel9cis_rule_5_7: {{ rhel9cis_rule_5_7 }}
# Section 6
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_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 }}
rhel9cis_rule_6_2_17: {{ rhel9cis_rule_6_2_17 }}
rhel9cis_rule_6_2_18: {{ rhel9cis_rule_6_2_18 }}
rhel9cis_rule_6_2_19: {{ rhel9cis_rule_6_2_19 }}
rhel9cis_rule_6_2_20: {{ rhel9cis_rule_6_2_20 }}
# Service configuration booleans set true to keep service
rhel9cis_avahi_server: {{ rhel9cis_avahi_server }}
rhel9cis_cups_server: {{ rhel9cis_cups_server }}
rhel9cis_dhcp_server: {{ rhel9cis_dhcp_server }}
rhel9cis_ldap_server: {{ rhel9cis_ldap_server }}
rhel9cis_telnet_server: {{ rhel9cis_telnet_server }}
rhel9cis_nfs_server: {{ rhel9cis_nfs_server }}
rhel9cis_rpc_server: {{ rhel9cis_rpc_server }}
rhel9cis_ntalk_server: {{ rhel9cis_ntalk_server }}
rhel9cis_rsyncd_server: {{ rhel9cis_rsyncd_server }}
rhel9cis_tftp_server: {{ rhel9cis_tftp_server }}
rhel9cis_rsh_server: {{ rhel9cis_rsh_server }}
rhel9cis_nis_server: {{ rhel9cis_nis_server }}
rhel9cis_snmp_server: {{ rhel9cis_snmp_server }}
rhel9cis_squid_server: {{ rhel9cis_squid_server }}
rhel9cis_smb_server: {{ rhel9cis_smb_server }}
rhel9cis_dovecot_server: {{ rhel9cis_dovecot_server }}
rhel9cis_httpd_server: {{ rhel9cis_httpd_server }}
rhel9cis_vsftpd_server: {{ rhel9cis_vsftpd_server }}
rhel9cis_named_server: {{ rhel9cis_named_server }}
rhel9cis_nfs_rpc_server: {{ rhel9cis_nfs_rpc_server }}
rhel9cis_is_mail_server: {{ rhel9cis_is_mail_server }}
rhel9cis_bind: {{ rhel9cis_bind }}
rhel9cis_vsftpd: {{ rhel9cis_vsftpd }}
rhel9cis_httpd: {{ rhel9cis_httpd }}
rhel9cis_dovecot: {{ rhel9cis_dovecot }}
rhel9cis_samba: {{ rhel9cis_samba }}
rhel9cis_squid: {{ rhel9cis_squid }}
rhel9cis_net_snmp: {{ rhel9cis_net_snmp}}
rhel9cis_allow_autofs: {{ rhel9cis_allow_autofs }}
# client services
rhel9cis_openldap_clients_required: {{ rhel9cis_openldap_clients_required }}
rhel9cis_telnet_required: {{ rhel9cis_telnet_required }}
rhel9cis_talk_required: {{ rhel9cis_talk_required }}
rhel9cis_rsh_required: {{ rhel9cis_rsh_required }}
rhel9cis_ypbind_required: {{ rhel9cis_ypbind_required }}
# AIDE
rhel9cis_config_aide: {{ rhel9cis_config_aide }}
# aide setup via - cron, timer
rhel9_aide_scan: cron
# AIDE cron settings
rhel9cis_aide_cron:
cron_user: {{ rhel9cis_aide_cron.cron_user }}
cron_file: '{{ rhel9cis_aide_cron.cron_file }}'
aide_job: ' {{ rhel9cis_aide_cron.aide_job }}'
aide_minute: '{{ rhel9cis_aide_cron.aide_minute }}'
aide_hour: '{{ rhel9cis_aide_cron.aide_hour }}'
aide_day: '{{ rhel9cis_aide_cron.aide_day }}'
aide_month: '{{ rhel9cis_aide_cron.aide_month }}'
aide_weekday: '{{ rhel9cis_aide_cron.aide_weekday }}'
# 1.5.1 Bootloader password
rhel9cis_bootloader_password: {{ rhel9cis_bootloader_password_hash }}
rhel9cis_set_boot_pass: {{ rhel9cis_set_boot_pass }}
# 1.10 crypto
rhel9cis_crypto_policy: {{ rhel9cis_crypto_policy }}
# Warning Banner Content (issue, issue.net, motd)
rhel9cis_warning_banner: {{ rhel9cis_warning_banner }}
# End Banner
# Set to 'true' if X Windows is needed in your environment
rhel9cis_xwindows_required: {{ rhel9cis_xwindows_required }}
# Whether or not to run tasks related to auditing/patching the desktop environment
rhel9cis_gui: {{ rhel9cis_gui }}
# xinetd required
rhel9cis_xinetd_required: {{ rhel9cis_xinetd_required }}
# IPv6 required
rhel9cis_ipv6_required: {{ rhel9cis_ipv6_required }}
# System network parameters (host only OR host and router)
rhel9cis_is_router: {{ rhel9cis_is_router }}
# Time Synchronization
rhel9cis_time_synchronization: {{ rhel9cis_time_synchronization }}
rhel9cis_varlog_location: {{ rhel9cis_varlog_location }}
rhel9cis_firewall: {{ rhel9cis_firewall }}
#rhel9cis_firewall: iptables
rhel9cis_default_firewall_zone: {{ rhel9cis_default_zone }}
rhel9cis_firewall_interface:
- enp0s3
- enp0s8
rhel9cis_firewall_services: {{ rhel9cis_firewall_services }}
### Section 4
## auditd settings
rhel9cis_auditd:
space_left_action: {{ rhel9cis_auditd.space_left_action}}
action_mail_acct: {{ rhel9cis_auditd.action_mail_acct }}
admin_space_left_action: {{ rhel9cis_auditd.admin_space_left_action }}
max_log_file_action: {{ rhel9cis_auditd.max_log_file_action }}
auditd_backlog_limit: {{ rhel9cis_audit_back_log_limit }}
## syslog
rhel9_cis_rsyslog: true
### Section 5
rhel9cis_sshd_limited: false
#Note the following to understand precedence and layout
rhel9cis_sshd_access:
AllowUser:
AllowGroup:
DenyUser:
DenyGroup:
rhel9cis_ssh_strong_ciphers: Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128- gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr
rhel9cis_ssh_weak_ciphers:
3des-cbc
aes128-cbc
aes192-cbc
aes256-cbc
arcfour
arcfour128
arcfour256
blowfish-cbc
cast128-cbc
rijndael-cbc@lysator.liu.se
rhel9cis_ssh_strong_macs: MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2- 512,hmac-sha2-256
rhel9cis_ssh_weak_macs:
hmac-md5
hmac-md5-96
hmac-ripemd160
hmac-sha1
hmac-sha1-96
umac-64@openssh.com
umac-128@openssh.com
hmac-md5-etm@openssh.com
hmac-md5-96-etm@openssh.com
hmac-ripemd160-etm@openssh.com
hmac-sha1-etm@openssh.com
hmac-sha1-96-etm@openssh.com
umac-64-etm@openssh.com
umac-128-etm@openssh.com
rhel9cis_ssh_strong_kex: KexAlgorithms curve25519-sha256,curve25519-sha256@libssh.org,diffie-hellman- group14-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,ecdh-sha2-nistp521,ecdh-sha2-nistp384,ecdh-sha2-nistp256,diffie-hellman-group-exchange-sha256
rhel9cis_ssh_weak_kex:
diffie-hellman-group1-sha1
diffie-hellman-group14-sha1
diffie-hellman-group-exchange-sha1
rhel9cis_ssh_aliveinterval: "300"
rhel9cis_ssh_countmax: "3"
## PAM
rhel9cis_pam_password:
minlen: {{ rhel9cis_pam_password.minlen }}
minclass: {{ rhel9cis_pam_password.minclass }}
rhel9cis_pam_passwd_retry: "3"
# faillock or tally2
rhel9cis_accountlock: faillock
## note this is to skip tests
skip_rhel9cis_pam_passwd_auth: true
skip_rhel9cis_pam_system_auth: true
# choose one of below
rhel9cis_pwhistory_so: "14"
rhel9cis_unix_so: false
rhel9cis_passwd_remember: "5"
# logins.def password settings
rhel9cis_pass:
max_days: {{ rhel9cis_pass.max_days }}
min_days: {{ rhel9cis_pass.min_days }}
warn_age: {{ rhel9cis_pass.warn_age }}
# 5.3.1/5.3.2 Custon authselect profile settings. Settings in place now will fail, they are place holders from the control example
rhel9cis_authselect:
custom_profile_name: {{ rhel9cis_authselect['custom_profile_name'] }}
default_file_to_copy: {{ rhel9cis_authselect.default_file_to_copy }}
options: {{ rhel9cis_authselect.options }}
# 5.3.1 Enable automation to creat custom profile settings, using the setings above
rhel9cis_authselect_custom_profile_create: {{ rhel9cis_authselect_custom_profile_create }}
# 5.3.2 Enable automation to select custom profile options, using the settings above
rhel9cis_authselect_custom_profile_select: {{ rhel9cis_authselect_custom_profile_select }}
# 5.7
rhel9cis_sugroup: {{ rhel9cis_sugroup| default('wheel') }}
rhel9cis_sugroup_users: {{ rhel9cis_sugroup_users }}

View file

@ -0,0 +1,79 @@
# File created initially via RHEL9 CIS ansible-lockdown remdiation role
{% if rhel9cis_rule_4_1_3 %}
-w /etc/sudoers -p wa -k scope
-w /etc/sudoers.d/ -p wa -k scope
{% endif %}
{% if rhel9cis_rule_4_1_4 %}
-w /var/log/faillog -p wa -k logins
-w /var/log/lastlog -p wa -k logins
{% endif %}
{% if rhel9cis_rule_4_1_5 %}
-w /var/run/utmp -p wa -k session
-w /var/log/wtmp -p wa -k logins
-w /var/log/btmp -p wa -k logins
{% endif %}
{% if rhel9cis_rule_4_1_6 %}
-a always,exit -F arch=b64 -S adjtimex -S settimeofday -k time-change
-a always,exit -F arch=b32 -S adjtimex -S settimeofday -S stime -k time-change
-a always,exit -F arch=b64 -S clock_settime -k time-change
-a always,exit -F arch=b32 -S clock_settime -k time-change
-w /etc/localtime -p wa -k time-change
{% endif %}
{% if rhel9cis_rule_4_1_7 %}
-w /etc/selinux/ -p wa -k MAC-policy
-w /usr/share/selinux/ -p wa -k MAC-policy
{% endif %}
{% if rhel9cis_rule_4_1_8 %}
-a always,exit -F arch=b64 -S sethostname -S setdomainname -k system-locale
-a always,exit -F arch=b32 -S sethostname -S setdomainname -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
-w /etc/sysconfig/network -p wa -k system-locale
{% endif %}
{% if rhel9cis_rule_4_1_9 %}
-a always,exit -F arch=b32 -S chmod -S fchmod -S fchmodat -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b32 -S chown -S fchown -S fchownat -S lchown -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b32 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chmod -S fchmod -S fchmodat -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S chown -S fchown -S fchownat -S lchown -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
-a always,exit -F arch=b64 -S setxattr -S lsetxattr -S fsetxattr -S removexattr -S lremovexattr -S fremovexattr -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k perm_mod
{% endif %}
{% if rhel9cis_rule_4_1_10 %}
-a always,exit -F arch=b32 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=access
-a always,exit -F arch=b32 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=access
-a always,exit -F arch=b64 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EACCES -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=access
-a always,exit -F arch=b64 -S creat,open,openat,open_by_handle_at,truncate,ftruncate -F exit=-EPERM -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=access
{% endif %}
{% if rhel9cis_rule_4_1_11 %}
-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_12 %}
-a always,exit -F arch=b32 -S mount -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k mounts
-a always,exit -F arch=b64 -S mount -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k mounts
{% endif %}
{% if rhel9cis_rule_4_1_13 %}
{% for proc in priv_procs.stdout_lines -%}
-a always,exit -F path={{ proc }} -F perm=x -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -k privileged
{% endfor %}
{% endif %}
{% if rhel9cis_rule_4_1_14 %}
-a always,exit -F arch=b32 -S rmdir,unlink,unlinkat,rename -S renameat -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=delete
-a always,exit -F arch=b64 -S rmdir,unlink,unlinkat,rename -S renameat -F auid>={{ rhel9cis_int_gid }} -F auid!=4294967295 -F key=delete
{% endif %}
{% if rhel9cis_rule_4_1_15 %}
-w /usr/sbin/insmod -p x -k modules
-w /usr/sbin/rmmod -p x -k modules
-w /usr/sbin/modprobe -p x -k modules
-a always,exit -F arch=b64 -S init_module -S delete_module -k modules
{% endif %}
{% if rhel9cis_rule_4_1_16 %}
-w /var/log/sudo.log -p wa -k actions
{% endif %}
{% if rhel9cis_rule_4_1_17 %}
-e 2
{% endif %}

93
templates/chrony.conf.j2 Normal file
View file

@ -0,0 +1,93 @@
# 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 <jhasler@debian.org> 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.
{% 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/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.
commandkey 1
# I moved the driftfile to /var/lib/chrony to comply with the Debian
# filesystem standard.
driftfile /var/lib/chrony/chrony.drift
# Comment this line out to turn off logging.
log tracking measurements statistics
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

View file

@ -0,0 +1,75 @@
# Setting added via ansible CIS remediation playbook
{% if rhel9cis_rule_1_6_1 %}
# Filesystem sysctl
# CIS 1.6.1
fs.suid_dumpable = 0
{% endif %}
{% if rhel9cis_rule_1_6_2 %}
# Kernel sysctl
# CIS 1.6.2
kernel.randomize_va_space = 2
{% endif %}
# Network sysctl
{% if rhel9cis_rule_3_1_1 %}
# CIS 3.1.1
net.ipv4.ip_forward = 0
{% if rhel9cis_rule_3_1_1 and rhel9cis_ipv6_required %}
net.ipv6.conf.all.forwarding = 0
{% endif %}
{% endif %}
{% if rhel9cis_rule_3_1_2 %}
# CIS 3.1.2
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
{% endif %}
{% if rhel9cis_rule_3_2_1 %}
# CIS 3.2.1
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
{% if rhel9cis_rule_3_2_1 and rhel9cis_ipv6_required %}
net.ipv6.conf.all.accept_source_route = 0
net.ipv6.conf.default.accept_source_route = 0
{% endif %}
{% endif %}
{% if rhel9cis_rule_3_2_2 %}
# CIS 3.2.2
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
{% if rhel9cis_rule_3_2_2 and rhel9cis_ipv6_required %}
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
{% endif %}
{% endif %}
{% if rhel9cis_rule_3_2_3 %}
# CIS 3.2.3
net.ipv4.conf.all.secure_redirects = 0
net.ipv4.conf.default.secure_redirects = 0
{% endif %}
{% if rhel9cis_rule_3_2_4 %}
# CIS 3.2.4
net.ipv4.conf.all.log_martians = 1
net.ipv4.conf.default.log_martians = 1
{% endif %}
{% if rhel9cis_rule_3_2_5 %}
# CIS 3.2.5
net.ipv4.icmp_echo_ignore_broadcasts = 1
{% endif %}
{% if rhel9cis_rule_3_2_6 %}
# CIS 3.2.6
net.ipv4.icmp_ignore_bogus_error_responses = 1
{% endif %}
{% if rhel9cis_rule_3_2_7 %}
# CIS 3.2.7
net.ipv4.conf.default.rp_filter = 1
{% endif %}
{% if rhel9cis_rule_3_2_8 %}
# CIS 3.2.8
net.ipv4.tcp_syncookies = 1
{% endif %}
{% if rhel9cis_rule_3_2_9 %}
# CIS 3.2.9
net.ipv6.conf.all.accept_ra = 0
net.ipv6.conf.default.accept_ra = 0
{% endif %}

1
templates/etc/issue.j2 Normal file
View file

@ -0,0 +1 @@
{{ rhel9cis_warning_banner }}

View file

@ -0,0 +1 @@
{{ rhel9cis_warning_banner }}

1
templates/etc/motd.j2 Normal file
View file

@ -0,0 +1 @@
{{ rhel9cis_warning_banner }}

View file

@ -0,0 +1,28 @@
# SPDX-License-Identifier: LGPL-2.1+
#
# This file is part of systemd.
#
# systemd is free software; you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation; either version 2.1 of the License, or
# (at your option) any later version.
[Unit]
Description=Temporary Directory (/tmp)
Documentation=man:hier(7)
Documentation=https://www.freedesktop.org/wiki/Software/systemd/APIFileSystems
ConditionPathIsSymbolicLink=!/tmp
DefaultDependencies=no
Conflicts=umount.target
Before=local-fs.target umount.target
After=swap.target
[Mount]
What=tmpfs
Where=/tmp
Type=tmpfs
Options=mode=1777,strictatime,{% if rhel9cis_rule_1_1_3 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_4 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_5 %}noexec{% endif %}
# Make 'systemctl enable tmp.mount' work:
[Install]
WantedBy=local-fs.target

11
templates/hosts.allow.j2 Normal file
View file

@ -0,0 +1,11 @@
#
# hosts.allow This file contains access rules which are used to
# allow or deny connections to network services that
# either use the tcp_wrappers library or that have been
# started through a tcp_wrappers-enabled xinetd.
#
# See 'man 5 hosts_options' and 'man 5 hosts_access'
# for information on rule syntax.
# See 'man tcpd' for information on tcp_wrappers
#
ALL: {% for iprange in rhel9cis_host_allow -%}{{ iprange }}{% if not loop.last %}, {% endif %}{% endfor %}

59
templates/ntp.conf.j2 Normal file
View file

@ -0,0 +1,59 @@
# For more information about this file, see the man pages
# ntp.conf(5), ntp_acc(5), ntp_auth(5), ntp_clock(5), ntp_misc(5), ntp_mon(5).
driftfile /var/lib/ntp/drift
# Permit time synchronization with our time source, but do not
# permit the source to query or modify the service on this system.
#restrict default nomodify notrap nopeer noquery
restrict -4 default kod nomodify notrap nopeer noquery
restrict -6 default kod nomodify notrap nopeer noquery
# Permit all access over the loopback interface. This could
# be tightened as well, but to do so would effect some of
# the administrative functions.
restrict 127.0.0.1
restrict ::1
# Hosts on local network are less restricted.
#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
# 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_ntp_server_options }}
{% endfor %}
#broadcast 192.168.1.255 autokey # broadcast server
#broadcastclient # broadcast client
#broadcast 224.0.1.1 autokey # multicast server
#multicastclient 224.0.1.1 # multicast client
#manycastserver 239.255.254.254 # manycast server
#manycastclient 239.255.254.254 autokey # manycast client
# Enable public key cryptography.
#crypto
includefile /etc/ntp/crypto/pw
# Key file containing the keys and key identifiers used when operating
# with symmetric key cryptography.
keys /etc/ntp/keys
# Specify the key identifiers which are trusted.
#trustedkey 4 8 42
# Specify the key identifier to use with the ntpdc utility.
#requestkey 8
# Specify the key identifier to use with the ntpq utility.
#controlkey 8
# Enable writing of statistics records.
#statistics clockstats cryptostats loopstats peerstats
# Disable the monitoring facility to prevent amplification attacks using ntpdc
# monlist command when default restrict does not include the noquery flag. See
# CVE-2013-5211 for more details.
# Note: Monitoring will not be disabled with the limited restriction flag.
disable monitor

5
vars/main.yml Normal file
View file

@ -0,0 +1,5 @@
---
# vars file for RHEL9-CIS
rhel9cis_allowed_crypto_policies:
- 'FUTURE'
- 'FIPS'