4
0
Fork 0

Merge pull request #268 from ansible-lockdown/benchmark_v2.0.0

Benchmark v2.0.0
This commit is contained in:
uk-bolly 2024-12-23 14:09:08 +00:00 committed by GitHub
commit d323305082
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
140 changed files with 10796 additions and 8510 deletions

View file

@ -3,20 +3,7 @@
parseable: true
quiet: true
skip_list:
- 'schema'
- 'no-changed-when'
- 'var-spacing'
- 'experimental'
- 'name[play]'
- 'name[casing]'
- 'name[template]'
- 'key-order[task]'
- '204'
- '305'
- '303'
- '403'
- '306'
- '602'
- '208'
- 'package-latest'
- 'risky-shell-pipe'
use_default_rules: true
verbosity: 0

View file

@ -1,322 +0,0 @@
[
{
"Description": "Generic API Key",
"StartLine": 119,
"EndLine": 119,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\"",
"Secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.853056,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:119"
},
{
"Description": "Generic API Key",
"StartLine": 127,
"EndLine": 127,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"fe96f7cfa2ab2224e7d015067a6f6cc713f7012e\"",
"Secret": "fe96f7cfa2ab2224e7d015067a6f6cc713f7012e",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.6568441,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:127"
},
{
"Description": "Generic API Key",
"StartLine": 135,
"EndLine": 135,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"a415ab5cc17c8c093c015ccdb7e552aee7911aa4\"",
"Secret": "a415ab5cc17c8c093c015ccdb7e552aee7911aa4",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.5221736,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:135"
},
{
"Description": "Generic API Key",
"StartLine": 145,
"EndLine": 145,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"2478fefdceefe2847c3aa36dc731aaad5b3cc2fb\"",
"Secret": "2478fefdceefe2847c3aa36dc731aaad5b3cc2fb",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.6348295,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:145"
},
{
"Description": "Generic API Key",
"StartLine": 153,
"EndLine": 153,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"64411efd0f0561fe4852c6e414071345c9c6432a\"",
"Secret": "64411efd0f0561fe4852c6e414071345c9c6432a",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.646039,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:153"
},
{
"Description": "Generic API Key",
"StartLine": 163,
"EndLine": 163,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360\"",
"Secret": "2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "495f942b7d26ee82690dc16eb4f231c587a57687",
"Entropy": 3.8439426,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-26T15:51:17Z",
"Message": "added pre-commit files\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "495f942b7d26ee82690dc16eb4f231c587a57687:.secrets.baseline:generic-api-key:163"
},
{
"Description": "Generic API Key",
"StartLine": 119,
"EndLine": 119,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8\"",
"Secret": "5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.853056,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:119"
},
{
"Description": "Generic API Key",
"StartLine": 127,
"EndLine": 127,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"fe96f7cfa2ab2224e7d015067a6f6cc713f7012e\"",
"Secret": "fe96f7cfa2ab2224e7d015067a6f6cc713f7012e",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.6568441,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:127"
},
{
"Description": "Generic API Key",
"StartLine": 135,
"EndLine": 135,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"a415ab5cc17c8c093c015ccdb7e552aee7911aa4\"",
"Secret": "a415ab5cc17c8c093c015ccdb7e552aee7911aa4",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.5221736,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:135"
},
{
"Description": "Generic API Key",
"StartLine": 145,
"EndLine": 145,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"2478fefdceefe2847c3aa36dc731aaad5b3cc2fb\"",
"Secret": "2478fefdceefe2847c3aa36dc731aaad5b3cc2fb",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.6348295,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:145"
},
{
"Description": "Generic API Key",
"StartLine": 153,
"EndLine": 153,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"64411efd0f0561fe4852c6e414071345c9c6432a\"",
"Secret": "64411efd0f0561fe4852c6e414071345c9c6432a",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.646039,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:153"
},
{
"Description": "Generic API Key",
"StartLine": 163,
"EndLine": 163,
"StartColumn": 18,
"EndColumn": 68,
"Match": "secret\": \"2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360\"",
"Secret": "2aaf9f2a51d8fe89e48cb9cc7d04a991ceb7f360",
"File": ".secrets.baseline",
"SymlinkFile": "",
"Commit": "7452e78f487c0b2cacfb81ccf582936a6ab09389",
"Entropy": 3.8439426,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-07-04T16:08:02Z",
"Message": "signature new precommits\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "7452e78f487c0b2cacfb81ccf582936a6ab09389:.secrets.baseline:generic-api-key:163"
},
{
"Description": "Generic API Key",
"StartLine": 3,
"EndLine": 4,
"StartColumn": 9,
"EndColumn": 1,
"Match": "key_pubkey_name: gpg-pubkey-8d8b756f-629e59ec",
"Secret": "gpg-pubkey-8d8b756f-629e59ec",
"File": "vars/OracleLinux.yml",
"SymlinkFile": "",
"Commit": "e04da88df42da0108d489f359513c574fbe5c87a",
"Entropy": 3.96772,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2023-03-06T11:22:08Z",
"Message": "Added OracleLinux support\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "e04da88df42da0108d489f359513c574fbe5c87a:vars/OracleLinux.yml:generic-api-key:3"
},
{
"Description": "Generic API Key",
"StartLine": 4,
"EndLine": 5,
"StartColumn": 8,
"EndColumn": 1,
"Match": "key_pubkey_name: gpg-pubkey-fd431d51-4ae0493b",
"Secret": "gpg-pubkey-fd431d51-4ae0493b",
"File": "vars/RedHat.yml",
"SymlinkFile": "",
"Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a",
"Entropy": 3.96772,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2022-07-25T10:26:27Z",
"Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/RedHat.yml:generic-api-key:4"
},
{
"Description": "Generic API Key",
"StartLine": 4,
"EndLine": 5,
"StartColumn": 8,
"EndColumn": 1,
"Match": "key_pubkey_name: gpg-pubkey-b86b3716-61e69f29",
"Secret": "gpg-pubkey-b86b3716-61e69f29",
"File": "vars/AlmaLinux.yml",
"SymlinkFile": "",
"Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a",
"Entropy": 3.824863,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2022-07-25T10:26:27Z",
"Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/AlmaLinux.yml:generic-api-key:4"
},
{
"Description": "Generic API Key",
"StartLine": 4,
"EndLine": 5,
"StartColumn": 8,
"EndColumn": 1,
"Match": "key_pubkey_name: gpg-pubkey-350d275d-6279464b",
"Secret": "gpg-pubkey-350d275d-6279464b",
"File": "vars/Rocky.yml",
"SymlinkFile": "",
"Commit": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a",
"Entropy": 3.9946804,
"Author": "Mark Bolwell",
"Email": "mark.bollyuk@gmail.com",
"Date": "2022-07-25T10:26:27Z",
"Message": "1.2.2 rpm gpg key check\n\nSigned-off-by: Mark Bolwell \u003cmark.bollyuk@gmail.com\u003e",
"Tags": [],
"RuleID": "generic-api-key",
"Fingerprint": "28bbc2ff5f832d150452e9dc4cb6667b876ed09a:vars/Rocky.yml:generic-api-key:4"
}
]

View file

@ -1,119 +0,0 @@
{
"version": "1.4.0",
"plugins_used": [
{
"name": "ArtifactoryDetector"
},
{
"name": "AWSKeyDetector"
},
{
"name": "AzureStorageKeyDetector"
},
{
"name": "Base64HighEntropyString",
"limit": 4.5
},
{
"name": "BasicAuthDetector"
},
{
"name": "CloudantDetector"
},
{
"name": "DiscordBotTokenDetector"
},
{
"name": "GitHubTokenDetector"
},
{
"name": "HexHighEntropyString",
"limit": 3.0
},
{
"name": "IbmCloudIamDetector"
},
{
"name": "IbmCosHmacDetector"
},
{
"name": "JwtTokenDetector"
},
{
"name": "KeywordDetector",
"keyword_exclude": ""
},
{
"name": "MailchimpDetector"
},
{
"name": "NpmDetector"
},
{
"name": "PrivateKeyDetector"
},
{
"name": "SendGridDetector"
},
{
"name": "SlackDetector"
},
{
"name": "SoftlayerDetector"
},
{
"name": "SquareOAuthDetector"
},
{
"name": "StripeDetector"
},
{
"name": "TwilioKeyDetector"
}
],
"filters_used": [
{
"path": "detect_secrets.filters.allowlist.is_line_allowlisted"
},
{
"path": "detect_secrets.filters.common.is_ignored_due_to_verification_policies",
"min_level": 2
},
{
"path": "detect_secrets.filters.heuristic.is_indirect_reference"
},
{
"path": "detect_secrets.filters.heuristic.is_likely_id_string"
},
{
"path": "detect_secrets.filters.heuristic.is_lock_file"
},
{
"path": "detect_secrets.filters.heuristic.is_not_alphanumeric_string"
},
{
"path": "detect_secrets.filters.heuristic.is_potential_uuid"
},
{
"path": "detect_secrets.filters.heuristic.is_prefixed_with_dollar_sign"
},
{
"path": "detect_secrets.filters.heuristic.is_sequential_string"
},
{
"path": "detect_secrets.filters.heuristic.is_swagger_file"
},
{
"path": "detect_secrets.filters.heuristic.is_templated_secret"
},
{
"path": "detect_secrets.filters.regex.should_exclude_file",
"pattern": [
".config/.gitleaks-report.json",
"tasks/parse_etc_password.yml"
]
}
],
"results": {},
"generated_at": "2023-09-21T14:11:05Z"
}

View file

@ -1,4 +0,0 @@
passlib
lxml
xmltodict
yamllint

View file

@ -23,18 +23,6 @@
# A workflow run is made up of one or more jobs
# that can run sequentially or in parallel
jobs:
# This will create messages for first time contributers and direct them to the Discord server
welcome:
runs-on: self-hosted
steps:
- uses: actions/first-interaction@main
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: |-
Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown!
Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well.
# This workflow contains a single job that tests the playbook
playbook-test:
# The type of runner that the job will run on

View file

@ -2,8 +2,8 @@
##### CI for use by github no need for action to be added
##### Inherited
ci:
autofix_prs: false
skip: [detect-aws-credentials, ansible-lint ]
autofix_prs: false
skip: [detect-aws-credentials, ansible-lint ]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
@ -11,12 +11,17 @@ repos:
hooks:
# Safety
- id: detect-aws-credentials
name: Detect AWS Credentials
- id: detect-private-key
name: Detect Private Keys
# git checks
- id: check-merge-conflict
name: Check for merge conflicts
- id: check-added-large-files
name: Check for Large files
- id: check-case-conflict
name: Check case conflict
# General checks
- id: trailing-whitespace
@ -27,20 +32,18 @@ repos:
types: [text]
args: [--markdown-linebreak-ext=md]
- id: end-of-file-fixer
name: Ensure line at end of file
# Scan for passwords
- repo: https://github.com/Yelp/detect-secrets
rev: v1.5.0
hooks:
- id: detect-secrets
args: [ '--baseline', '.config/.secrets.baseline' ]
exclude: .config/.gitleaks-report.json
- repo: https://github.com/gitleaks/gitleaks
rev: v8.21.2
hooks:
- id: gitleaks
args: ['--baseline-path', '.config/.gitleaks-report.json']
- repo: https://github.com/ansible-community/ansible-lint
rev: v24.12.2
@ -54,14 +57,15 @@ repos:
# https://github.com/ansible/ansible-lint/issues/611
pass_filenames: false
always_run: true
additional_dependencies:
# additional_dependencies:
# https://github.com/pre-commit/pre-commit/issues/1526
# If you want to use specific version of ansible-core or ansible, feel
# free to override `additional_dependencies` in your own hook config
# file.
- ansible-core>=2.10.1
# - ansible-core>=2.10.1
- repo: https://github.com/adrienverge/yamllint.git
rev: v1.35.1 # or higher tag
hooks:
- id: yamllint
name: Check YAML Lint

View file

@ -1,33 +1,38 @@
---
extends: default
ignore: |
tests/
molecule/
.github/
.gitlab-ci.yml
*molecule.yml
rules:
indentation:
# Requiring 4 space indentation
spaces: 4
# Requiring consistent indentation within a file, either indented or not
indent-sequences: consistent
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
empty-lines:
max: 1
line-length: disable
key-duplicates: enable
new-line-at-end-of-file: enable
new-lines:
type: unix
trailing-spaces: enable
truthy:
allowed-values: ['true', 'false']
check-keys: true
braces:
max-spaces-inside: 1
level: error
brackets:
max-spaces-inside: 1
level: error
comments:
ignore-shebangs: true
min-spaces-from-content: 1 # prettier compatibility
comments-indentation: enable
empty-lines:
max: 1
indentation:
# Requiring 2 space indentation
spaces: 2
# Requiring consistent indentation within a file, either indented or not
indent-sequences: consistent
key-duplicates: enable
line-length: disable
new-line-at-end-of-file: enable
new-lines:
type: unix
octal-values:
forbid-implicit-octal: true # yamllint defaults to false
forbid-explicit-octal: true
trailing-spaces: enable
truthy:
allowed-values: ['true', 'false']
check-keys: true

121
README.md
View file

@ -2,7 +2,7 @@
## Configure a RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant
### Based on [ CIS RedHat Enterprise Linux 9 Benchmark v1.0.0 - 11-30-2022 ](https://www.cisecurity.org/cis-benchmarks/)
### Based on [CIS RedHat Enterprise Linux 9 Benchmark v2.0.0](https://www.cisecurity.org/cis-benchmarks/)
---
@ -32,38 +32,35 @@
---
## Looking for support?
[Lockdown Enterprise](https://www.lockdownenterprise.com#GH_AL_RH9_cis)
[Ansible support](https://www.mindpointgroup.com/cybersecurity-products/ansible-counselor#GH_AL_RH9_cis)
### Community
Join us on our [Discord Server](https://www.lockdownenterprise.com/discord) to ask questions, discuss features, or just chat with other Ansible-Lockdown users.
### Contributing
Issues and Pull requests are welcome please ensure that all commits are signed-off-by and gpg-signed.
Refer to [Contributing Guide](./CONTRIBUTING.rst)
---
## Caution(s)
This role **will make changes to the system** which may have unintended consequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted.
Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode.
- Testing is the most important thing you can do.
This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed.
- Check Mode is not supported! The role will complete in check mode without errors, but it is not supported and should be used with caution. The RHEL9-CIS-Audit role or a compliance scanner should be used for compliance checking over check mode.
To use the release version, please point to the `main` branch and relevant release for the cis benchmark you wish to work with.
- This role was developed against a clean install of the Operating System. If you are implementing to an existing system please review this role for any site specific changes that are needed.
- To use release version please point to main branch and relevant release/tag for the cis benchmark you wish to work with.
- If moving across major releases e.g. v2.0.0 - v3.0.0 there are significant changes to the benchmarks and controls it is suggested to start as a new standard not to upgrade.
- Containers references vars/is_container.yml this is an example and to be updated for your requirements
- Did we mention testing??
---
## Matching a security Level for CIS
It is possible to only run level 1 or level 2 controls for CIS.
It is possible to to only run level 1 or level 2 controls for CIS.
This is managed using tags:
- level1-server
@ -71,26 +68,46 @@ This is managed using tags:
- level2-server
- level2-workstation
The control found in the `defaults` main also needs to reflect this, as this control is the testing that takes place if you are using the audit component.
The control found in defaults main also need to reflect this as this control the testing thet takes place if you are using the audit component.
## Coming from a previous release
CIS release always contains changes, it is highly recommended to review the new references and available variables. This has changed significantly since the ansible-lockdown initial release.
This is now compatible with python3 if it is found to be the default interpreter. This does come with prerequisites which configure the system accordingly.
CIS release always contains changes, it is highly recommended to review the new references and available variables. This have changed significantly since ansible-lockdown initial release.
This is now compatible with python3 if it is found to be the default interpreter. This does come with pre-requisites which it configures the system accordingly.
Further details can be seen in the [Changelog](./Changelog.md)
## Auditing (new)
This can be turned on or off within the `defaults/main.yml` file with the variables `setup_audit` and `run_audit`. The value is `false` by default. Please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role.
This can be turned on or off within the defaults/main.yml file with the variable run_audit. The value is false by default, please refer to the wiki for more details. The defaults file also populates the goss checks to check only the controls that have been enabled in the ansible role.
This is a much quicker, very lightweight, checking (where possible) config compliance and live/running settings.
A new form of auditing has been developed by using a small (12MB) go binary called [goss](https://github.com/goss-org/goss) along with the relevant configurations to check without the need for infrastructure or other tooling.
This audit will not only check the config has the correct setting but aims to capture if it is running with that configuration also try to remove [false positives](https://www.mindpointgroup.com/blog/is-compliance-scanning-still-relevant/) in the process.
A new form of auditing has been developed, by using a small (12MB) go binary called [goss](https://github.com/goss-org/goss) along with the relevant configurations to check. Without the need for infrastructure or other tooling.
This audit will not only check the config has the correct setting but aims to capture if it is running with that configuration also trying to remove [false positives](https://www.mindpointgroup.com/blog/is-compliance-scanning-still-relevant/) in the process.
Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit).
## Example Audit Summary
This is based on a vagrant image with selections enabled. e.g. No Gui or firewall.
Note: More tests are run during audit as we check config and running state.
```txt
ok: [default] => {
"msg": [
"The pre remediation results are: ['Total Duration: 5.454s', 'Count: 338, Failed: 47, Skipped: 5'].",
"The post remediation results are: ['Total Duration: 5.007s', 'Count: 338, Failed: 46, Skipped: 5'].",
"Full breakdown can be found in /var/tmp",
""
]
}
PLAY RECAP *******************************************************************************************************************************************
default : ok=270 changed=23 unreachable=0 failed=0 skipped=140 rescued=0 ignored=0
```
## Documentation
- [Read The Docs](https://ansible-lockdown.readthedocs.io/en/latest/)
@ -101,19 +118,6 @@ Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit).
## Requirements
RHEL 9
Almalinux 9
Rocky 9
OracleLinux 9
- Access to download or add the goss binary and content to the system if using auditing (other options are available on how to get the content to the system.)
CentOS stream - while this will generally work it is not supported and requires the following variable setting
```sh
os_check: false
```
**General:**
- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible
@ -123,21 +127,22 @@ os_check: false
- [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html)
- [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html)
- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup.
- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consiquences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file.
- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consequences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file.
**Technical Dependencies:**
- Python3
- Ansible 2.12+
- python-def (should be included in RHEL 9)
- libselinux-python
- collections found in collections/requirements.yml
RHEL/AlmaLinux/Rocky/Oracle 9 - Other versions are not supported.
pre-commit is available if installed on your host for pull request testing.
- Access to download or add the goss binary and content to the system if using auditing
(other options are available on how to get the content to the system.)
- Python3.8
- Ansible 2.12+
- python-def
- libselinux-python
## Role Variables
This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done by overriding the required varaibles as found in defaults/main.yml file. e.g. using inventory, group_vars, extra_vars
This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main.yml file or with extra vars within the project, job, workflow, etc.
## Tags
@ -167,10 +172,7 @@ We encourage you (the community) to contribute to this role. Please read the rul
## Known Issues
CIS 1.2.4 - repo_gpgcheck is not carried out for RedHat hosts as the default repos do not have this function. This also affect EPEL(not covered by var).
- Rocky and Alma not affected.
Variable used to unset.
rhel9cis_rhel_default_repo: true # to be set to false if using repo that does have this ability
Almalinux BaseOS, EPEL and many cloud providers repositories, do not allow gpgcheck(rule_1.2.1.2) or repo_gpgcheck (rule_1.2.1.3) this will cause issues during the playbook unless or a workaround is found.
## Pipeline Testing
@ -178,21 +180,32 @@ uses:
- ansible-core 2.12
- ansible collections - pulls in the latest version based on requirements file
- Runs the audit using the devel branch
- Runs the pre-commit setup on the PR to ensure everything is in place as expected.
- runs the audit using the devel branch
- This is an automated test that occurs on pull requests into devel
## Local Testing
- Ansible
Molecule can be used to work on this role and test in distinct _scenarios_.
- ansible-base 2.10.17 - python 3.8
- ansible-core 2.13.4 - python 3.10
- ansible-core 2.15.1 - python 3.11
### examples
```bash
molecule test -s default
molecule converge -s wsl -- --check
molecule verify -s localhost
```
local testing uses:
- ansible 2.13.3
- molecule 4.0.1
- molecule-docker 2.0.0
- molecule-podman 2.0.2
- molecule-vagrant 1.0.0
- molecule-azure 0.5.0
## Added Extras
- makefile - this is there purely for testing and initial setup purposes.
- [pre-commit](https://pre-commit.com) can be tested and can be run from within the directory
```sh

View file

@ -1,14 +1,14 @@
---
collections:
- name: community.general
source: https://github.com/ansible-collections/community.general
type: git
- name: community.general
source: https://github.com/ansible-collections/community.general
type: git
- name: community.crypto
source: https://github.com/ansible-collections/community.crypto
type: git
- name: community.crypto
source: https://github.com/ansible-collections/community.crypto
type: git
- name: ansible.posix
source: https://github.com/ansible-collections/ansible.posix
type: git
- name: ansible.posix
source: https://github.com/ansible-collections/ansible.posix
type: git

File diff suppressed because it is too large Load diff

56
files/fs_with_cves.sh Normal file
View file

@ -0,0 +1,56 @@
#! /usr/bin/env bash
# Based on original Script provided by CIS
# CVEs correct at time of creation - April2024
{
a_output=(); a_output2=(); a_modprope_config=(); a_excluded=(); a_available_modules=()
a_ignore=("xfs" "vfat" "ext2" "ext3" "ext4")
a_cve_exists=("afs" "ceph" "cifs" "exfat" "ext" "fat" "fscache" "fuse" "gfs2" "nfs_common" "nfsd" "smbfs_common")
f_module_chk()
{
l_out2=""; grep -Pq -- "\b$l_mod_name\b" <<< "${a_cve_exists[*]}" && l_out2=" <- CVE exists!"
if ! grep -Pq -- '\bblacklist\h+'"$l_mod_name"'\b' <<< "${a_modprope_config[*]}"; then
a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2")
elif ! grep -Pq -- '\binstall\h+'"$l_mod_name"'\h+\/bin\/(false|true)\b' <<< "${a_modprope_config[*]}"; then
a_output2+=(" - Kernel module: \"$l_mod_name\" is not fully disabled $l_out2")
fi
if lsmod | grep "$l_mod_name" &> /dev/null; then # Check if the module is currently loaded
l_output2+=(" - Kernel module: \"$l_mod_name\" is loaded" "")
fi
}
while IFS= read -r -d $'\0' l_module_dir; do
a_available_modules+=("$(basename "$l_module_dir")")
done < <(find "$(readlink -f /lib/modules/"$(uname -r)"/kernel/fs)" -mindepth 1 -maxdepth 1 -type d ! -empty -print0)
while IFS= read -r l_exclude; do
if grep -Pq -- "\b$l_exclude\b" <<< "${a_cve_exists[*]}"; then
a_output2+=(" - ** WARNING: kernel module: \"$l_exclude\" has a CVE and is currently mounted! **")
elif
grep -Pq -- "\b$l_exclude\b" <<< "${a_available_modules[*]}"; then
a_output+=(" - Kernel module: \"$l_exclude\" is currently mounted - do NOT unload or disable")
fi
! grep -Pq -- "\b$l_exclude\b" <<< "${a_ignore[*]}" && a_ignore+=("$l_exclude")
done < <(findmnt -knD | awk '{print $2}' | sort -u)
while IFS= read -r l_config; do
a_modprope_config+=("$l_config")
done < <(modprobe --showconfig | grep -P '^\h*(blacklist|install)')
for l_mod_name in "${a_available_modules[@]}"; do # Iterate over all filesystem modules
[[ "$l_mod_name" =~ overlay ]] && l_mod_name="${l_mod_name::-2}"
if grep -Pq -- "\b$l_mod_name\b" <<< "${a_ignore[*]}"; then
a_excluded+=(" - Kernel module: \"$l_mod_name\"")
else
f_module_chk
fi
done
# Output findings
echo "### Script can be found at ${BASH_SOURCE} ##"
if [ "${#a_output2[@]}" -le 0 ]; then
printf '%s\n' "" " - No unused filesystem kernel modules are enabled" "${a_output[@]}" ""
else
printf '%s\n' "" "-- Audit Result: --" " ** REVIEW the following **" "${a_output2[@]}"
# Changed return value to capture error
exit 99
#[ "${#a_output[@]}" -gt 0 ] && printf '%s\n' "" "-- Correctly set: --" "${a_output[@]}" ""
fi
}

View file

@ -1,113 +1,264 @@
---
# handlers file for RHEL9-CIS
- name: "Adding options for /tmp"
when: not rhel9cis_tmp_svc
vars:
mount_point: '/tmp'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /tmp"
- name: "Remounting /tmp"
vars:
mount_point: '/tmp'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /tmp"
- name: "Remounting /tmp systemd"
vars:
mount_point: '/tmp'
ansible.builtin.systemd:
name: tmp.mount
state: restarted
daemon_reload: true
listen: "Remount /tmp"
- name: "Adding options for /dev/shm"
vars:
mount_point: '/dev/shm'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /dev/shm"
- name: "Remounting /dev/shm"
vars:
mount_point: '/dev/shm'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /dev/shm"
- name: "Adding options for /home"
vars:
mount_point: '/home'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /home"
- name: "Remounting /home"
vars:
mount_point: '/home'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /home"
- name: "Adding options for /var"
vars:
mount_point: '/var'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /var"
- name: "Remounting /var"
vars:
mount_point: '/var'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /var"
- name: "Adding options for /var/tmp"
vars:
mount_point: '/var/tmp'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /var/tmp"
- name: "Remounting /var/tmp"
vars:
mount_point: '/var/tmp'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /var/tmp"
- name: "Adding options for /var/log"
vars:
mount_point: '/var/log'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /var/log"
- name: "Remounting /var/log"
vars:
mount_point: '/var/log'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /var/log"
- name: "Adding options for /var/log/audit"
vars:
mount_point: '/var/log/audit'
ansible.posix.mount:
path: "{{ mount_point }}"
src: "{{ prelim_mount_point_fs_and_options[mount_point]['src'] }}"
state: present
fstype: "{{ prelim_mount_point_fs_and_options[mount_point]['fs_type'] }}"
opts: "{{ prelim_mount_point_fs_and_options[mount_point]['options'] | unique | join(',') }}"
listen: "Remount /var/log/audit"
- name: "Remounting /var/log/audit"
vars:
mount_point: '/var/log/audit'
ansible.posix.mount:
path: "{{ mount_point }}"
state: remounted
listen: "Remount /var/log/audit"
- name: Reload sysctl
ansible.builtin.shell: sysctl --system
ansible.builtin.command: sysctl --system
changed_when: true
- name: Sysctl flush ipv4 route table
ansible.posix.sysctl:
name: net.ipv4.route.flush
value: '1'
sysctl_set: true
ignore_errors: true # noqa ignore-errors
when:
- rhel9cis_flush_ipv4_route
- not system_is_container
- rhel9cis_flush_ipv4_route
- not system_is_container
ansible.posix.sysctl:
name: net.ipv4.route.flush
value: '1'
sysctl_set: true
ignore_errors: true # noqa ignore-errors
- name: Sysctl flush ipv6 route table
ansible.posix.sysctl:
name: net.ipv6.route.flush
value: '1'
sysctl_set: true
when:
- rhel9cis_flush_ipv6_route
- not system_is_container
- rhel9cis_flush_ipv6_route
- not system_is_container
ansible.posix.sysctl:
name: net.ipv6.route.flush
value: '1'
sysctl_set: true
- name: Systemd restart tmp.mount
ansible.builtin.systemd:
name: tmp.mount
daemon_reload: true
enabled: true
masked: false
state: reloaded
name: tmp.mount
daemon_reload: true
enabled: true
masked: false
state: reloaded
- name: Remount tmp
ansible.posix.mount:
path: /tmp
state: remounted
- name: Update Crypto Policy
ansible.builtin.set_fact:
rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}{{ rhel9cis_crypto_policy_module }}{% endif %}"
notify: Set Crypto Policy
- name: Set Crypto Policy
when: prelim_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy
ansible.builtin.command: update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}"
changed_when: true
notify:
- Change_requires_reboot
- Restart sshd
- name: Restart firewalld
ansible.builtin.systemd:
name: firewalld
state: restarted
name: firewalld
state: restarted
- name: Restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
name: sshd
state: restarted
- name: Restart postfix
ansible.builtin.systemd:
name: postfix
state: restarted
name: postfix
state: restarted
- name: Reload dconf
ansible.builtin.shell: dconf update
ansible.builtin.command: dconf update
changed_when: true
- name: Grub2cfg
ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg"
ansible.builtin.command: "grub2-mkconfig -o /boot/grub2/grub.cfg"
changed_when: true
ignore_errors: true # noqa ignore-errors
- name: Restart rsyslog
ansible.builtin.systemd:
name: rsyslog
state: restarted
name: rsyslog
state: restarted
- name: Restart journald
ansible.builtin.systemd:
name: systemd-journald
state: restarted
name: systemd-journald
state: restarted
- name: Restart systemd_journal_upload
ansible.builtin.systemd:
name: systemd-journal-upload
state: restarted
name: systemd-journal-upload
state: restarted
- name: Systemd daemon reload
ansible.builtin.systemd:
daemon-reload: true
daemon-reload: true
- name: Apply_authselect
ansible.builtin.shell: authselect apply-changes
when: not rhel9cis_rule_5_4_2
- name: Authselect update
ansible.builtin.command: authselect apply-changes
changed_when: true
- name: Apply_authselect
ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force --backup=rhel9cis_commit_{{ ansible_date_time.epoch}}"
when: rhel9cis_rule_5_4_2
## Auditd tasks note order for handlers to run
- name: Auditd immutable check
ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules
ansible.builtin.command: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules
changed_when: false
register: auditd_immutable_check
register: discovered_auditd_immutable_check
- name: Audit immutable fact
when: discovered_auditd_immutable_check.stdout == '1'
ansible.builtin.debug:
msg: "Reboot required for auditd to apply new rules as immutable set"
msg: "Reboot required for auditd to apply new rules as immutable set"
notify: Change_requires_reboot
when:
- auditd_immutable_check.stdout == '1'
- name: Stop auditd process
ansible.builtin.shell: systemctl kill auditd
ansible.builtin.command: systemctl kill auditd
changed_when: true
listen: Restart auditd
- name: Start auditd process
ansible.builtin.systemd_service:
name: auditd
state: started
name: auditd
state: started
listen: Restart auditd
- name: Change_requires_reboot
ansible.builtin.set_fact:
change_requires_reboot: true
change_requires_reboot: true

View file

@ -1,32 +1,32 @@
---
galaxy_info:
author: "MindPoint Group"
description: "Apply the RHEL 9 CIS"
company: "MindPoint Group"
license: MIT
role_name: rhel9_cis
namespace: mindpointgroup
min_ansible_version: 2.10.1
platforms:
- name: EL
versions:
- "9"
galaxy_tags:
- system
- security
- stig
- hardening
- benchmark
- compliance
- redhat
- complianceascode
- disa
- rhel9
- cis
- rocky
- alma
author: "MindPoint Group"
description: "Apply the RHEL 9 CIS"
company: "MindPoint Group"
license: MIT
role_name: rhel9_cis
namespace: mindpointgroup
min_ansible_version: 2.10.1
platforms:
- name: EL
versions:
- "9"
galaxy_tags:
- system
- security
- stig
- hardening
- benchmark
- compliance
- redhat
- complianceascode
- disa
- rhel9
- cis
- rocky
- alma
collections:
- community.general
- community.crypto
- ansible.posix
- community.general
- community.crypto
- ansible.posix
dependencies: []

View file

@ -9,7 +9,7 @@
ansible_user: root
system_is_container: true
rhel9cis_selinux_disable: true
rhel9cis_rule_5_3_4: false
rhel9cis_rule_5_2_4: false
rhel9cis_rule_1_1_10: false
rhel9cis_firewall: "none"
rhel9cis_rule_4_1_1_1: false

View file

@ -8,7 +8,7 @@
vars:
ansible_user: "{{ lookup('env', 'USER') }}"
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
rhel9cis_rule_5_3_4: false
rhel9cis_rule_5_2_4: false
pre_tasks:
tasks:

View file

@ -1,7 +1,7 @@
---
- name: Apply RHEL9 CIS hardening
- name: Apply ansible-lockdown hardening
hosts: all
become: true
roles:
- role: "{{ playbook_dir }}"
- role: "{{ playbook_dir }}"

View file

@ -1,34 +1,31 @@
---
- name: Pre Audit Setup | Set audit package name
block:
- name: Pre Audit Setup | Set audit package name | 64bit
ansible.builtin.set_fact:
audit_pkg_arch_name: AMD64
when: ansible_facts.machine == "x86_64"
- name: Pre Audit Setup | Set audit package name | 64bit
when: ansible_facts.machine == "x86_64"
ansible.builtin.set_fact:
audit_pkg_arch_name: AMD64
- name: Pre Audit Setup | Set audit package name | ARM64
ansible.builtin.set_fact:
audit_pkg_arch_name: ARM64
when: ansible_facts.machine == "aarch64"
- name: Pre Audit Setup | Set audit package name | ARM64
when: ansible_facts.machine == "arm64"
ansible.builtin.set_fact:
audit_pkg_arch_name: ARM64
- name: Pre Audit Setup | Download audit binary
when: get_audit_binary_method == 'download'
ansible.builtin.get_url:
url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}"
dest: "{{ audit_bin }}"
owner: root
group: root
checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}"
mode: '0555'
when:
- get_audit_binary_method == 'download'
url: "{{ audit_bin_url }}{{ audit_pkg_arch_name }}"
dest: "{{ audit_bin }}"
owner: root
group: root
checksum: "{{ audit_bin_version[audit_pkg_arch_name + '_checksum'] }}"
mode: 'u+x,go-w'
- name: Pre Audit Setup | Copy audit binary
when: get_audit_binary_method == 'copy'
ansible.builtin.copy:
src: "{{ audit_bin_copy_location }}"
dest: "{{ audit_bin }}"
mode: '0555'
owner: root
group: root
when:
- get_audit_binary_method == 'copy'
src: "{{ audit_bin_copy_location }}"
dest: "{{ audit_bin }}"
owner: root
group: root
mode: 'u+x,go-w'

View file

@ -1,30 +1,27 @@
---
- name: Audit_Only | Create local Directories for hosts
ansible.builtin.file:
mode: '0755'
path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}"
recurse: true
state: directory
when: fetch_audit_files
ansible.builtin.file:
mode: 'u+x,go-w'
path: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}"
recurse: true
state: directory
delegate_to: localhost
become: false
- name: Audit_only | Get audits from systems and put in group dir
ansible.builtin.fetch:
dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/"
flat: true
mode: '0644'
src: "{{ pre_audit_outfile }}"
when: fetch_audit_files
ansible.builtin.fetch:
dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/"
flat: true
mode: 'go-wx'
src: "{{ pre_audit_outfile }}"
- name: Audit_only | Show Audit Summary
when:
- audit_only
when: audit_only
ansible.builtin.debug:
msg: "{{ audit_results.split('\n') }}"
msg: "{{ audit_results.split('\n') }}"
- name: Audit_only | Stop Playbook Audit Only selected
when:
- audit_only
when: audit_only
ansible.builtin.meta: end_play

View file

@ -2,46 +2,46 @@
- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file
ansible.builtin.stat:
path: /etc/audit/rules.d/99_auditd.rules
register: rhel9cis_auditd_file
path: /etc/audit/rules.d/99_auditd.rules
register: discovered_auditd_rules_file
- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | setup file
ansible.builtin.template:
src: audit/99_auditd.rules.j2
dest: /etc/audit/rules.d/99_auditd.rules
owner: root
group: root
mode: '0640'
diff: "{{ rhel9cis_auditd_file.stat.exists }}" # Only run diff if not a new file
register: rhel9cis_auditd_template_updated
src: audit/99_auditd.rules.j2
dest: /etc/audit/rules.d/99_auditd.rules
owner: root
group: root
mode: '0640'
diff: "{{ discovered_auditd_rules_file.stat.exists }}" # Only run diff if not a new file
register: discovered_auditd_rules_template_updated
notify:
- Auditd immutable check
- Audit immutable fact
- Restart auditd
- Auditd immutable check
- Audit immutable fact
- Restart auditd
- name: POST | AUDITD | Add Warning count for changes to template file | Warn Count # noqa no-handler
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: 'Auditd template updated, validate as expected'
when:
- rhel9cis_auditd_template_updated.changed
- rhel9cis_auditd_file.stat.exists
- discovered_auditd_rules_template_updated.changed
- discovered_auditd_rules_file.stat.exists
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: 'Auditd template updated, validate as expected'
- name: POST | AUDITD | Apply auditd template will for section 4.1.3 - only required rules will be added | stat file
ansible.builtin.stat:
path: /etc/audit/rules.d/98_auditd_exceptions.rules
register: rhel9cis_auditd_exception_file
path: /etc/audit/rules.d/98_auditd_exceptions.rules
register: discovered_auditd_exception_file
- name: POST | Set up auditd user logging exceptions | setup file
ansible.builtin.template:
src: audit/98_auditd_exception.rules.j2
dest: /etc/audit/rules.d/98_auditd_exceptions.rules
owner: root
group: root
mode: '0640'
diff: "{{ rhel9cis_auditd_exception_file.stat.exists }}"
notify: Restart auditd
when:
- rhel9cis_allow_auditd_uid_user_exclusions
- rhel9cis_auditd_uid_exclude | length > 0
- rhel9cis_allow_auditd_uid_user_exclusions
- rhel9cis_auditd_uid_exclude | length > 0
ansible.builtin.template:
src: audit/98_auditd_exception.rules.j2
dest: /etc/audit/rules.d/98_auditd_exceptions.rules
owner: root
group: root
mode: '0640'
diff: "{{ discovered_auditd_exception_file.stat.exists }}"
notify: Restart auditd

View file

@ -1,8 +1,7 @@
---
- name: "PREREQ | If required install libselinux package to manage file changes."
when: '"libselinux-python3" not in ansible_facts.packages'
ansible.builtin.package:
name: libselinux-python3
state: present
when:
- '"libselinux-python3" not in ansible_facts.packages'
name: libselinux-python3
state: present

View file

@ -1,226 +1,230 @@
---
# tasks file for RHEL9-CIS
- name: Check OS version and family
- name: "Check OS version and family"
when: os_check
tags: always
ansible.builtin.assert:
that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==')
fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported."
success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }}"
when:
- os_check
tags:
- always
that: (ansible_facts.distribution != 'CentOS' and ansible_facts.os_family == 'RedHat' or ansible_facts.os_family == "Rocky") and ansible_facts.distribution_major_version is version_compare('9', '==')
fail_msg: "This role can only be run against Supported OSs. {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }} is not supported."
success_msg: "This role is running against a supported OS {{ ansible_facts.distribution }} {{ ansible_facts.distribution_major_version }}"
- name: Check ansible version
- name: "Check ansible version"
tags: always
ansible.builtin.assert:
that: ansible_version.full is version_compare(min_ansible_version, '>=')
fail_msg: "You must use Ansible {{ min_ansible_version }} or greater"
success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}"
that: ansible_version.full is version_compare(min_ansible_version, '>=')
fail_msg: "You must use Ansible {{ min_ansible_version }} or greater"
success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}"
- name: "Setup rules if container"
when:
- ansible_connection == 'docker' or
ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- always
- container_discovery
- always
block:
- name: "Discover and set container variable if required"
ansible.builtin.set_fact:
system_is_container: true
- name: "Load variable for container"
ansible.builtin.include_vars:
file: "{{ container_vars_file }}"
- name: "Output if discovered is a container"
when: system_is_container
ansible.builtin.debug:
msg: system has been discovered as a container
- name: "Check crypto-policy input"
ansible.builtin.assert:
that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies
fail_msg: "Crypto policy is not a permitted version"
success_msg: "Crypto policy is a permitted version"
- name: "Check rhel9cis_bootloader_password_hash variable has been changed"
when:
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
tags: always
ansible.builtin.assert:
that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret
msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly"
- name: "Check crypto-policy module input"
when:
- rhel9cis_rule_1_6_1
- rhel9cis_crypto_policy_module | length > 0
tags:
- rule_1.6.1
- crypto
- NIST800-53R5_SC-6
ansible.builtin.assert:
that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules
fail_msg: "Crypto policy module is not a permitted version"
success_msg: "Crypto policy module is a permitted version"
- name: "Check password set for {{ ansible_env.SUDO_USER }}"
block:
- name: "Check password set for {{ ansible_env.SUDO_USER }} | password state"
ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'"
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_ansible_user_password_set
- name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account"
ansible.builtin.debug:
msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks."
when:
- rhel9cis_ansible_user_password_set.stdout == "not found"
- name: "Check local account"
block:
- name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set"
ansible.builtin.assert:
that:
- rhel9cis_ansible_user_password_set.stdout | length != 0
- rhel9cis_ansible_user_password_set.stdout != "!!"
fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access"
success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user"
- name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked"
ansible.builtin.assert:
that:
- not rhel9cis_ansible_user_password_set.stdout.startswith("!")
fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access"
success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user"
when:
- rhel9cis_ansible_user_password_set.stdout != "not found"
when:
- rhel9cis_rule_5_3_4
- ansible_env.SUDO_USER is defined
- not system_is_ec2
- rhel9cis_rule_5_2_4
- ansible_env.SUDO_USER is defined
- not system_is_ec2
tags:
- user_passwd
- rule_5.3.4
- user_passwd
- rule_5.2.4
vars:
sudo_password_rule: rhel9cis_rule_5_3_4 # pragma: allowlist secret
- name: Ensure root password is set
sudo_password_rule: rhel9cis_rule_5_2_4 # pragma: allowlist secret
block:
- name: Ensure root password is set
ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)"
changed_when: false
register: root_passwd_set
- name: "Check password set for {{ ansible_env.SUDO_USER }} | password state" # noqa name[template]
ansible.builtin.shell: "(grep {{ ansible_env.SUDO_USER }} /etc/shadow || echo 'not found:not found') | awk -F: '{print $2}'"
changed_when: false
failed_when: false
check_mode: false
register: prelim_ansible_user_password_set
- name: Ensure root password is set
ansible.builtin.assert:
that: root_passwd_set.rc == 0
fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set"
success_msg: "You have a root password set"
when:
- rhel9cis_rule_5_6_6
tags:
- level1-server
- level1-workstation
- patch
- accounts
- root
- rule_5.6.6
- name: "Check for local account {{ ansible_env.SUDO_USER }} | Check for local account" # noqa name[template]
when: prelim_ansible_user_password_set.stdout == "not found"
ansible.builtin.debug:
msg: "No local account found for {{ ansible_env.SUDO_USER }} user. Skipping local account checks."
- name: Setup rules if container
- name: "Check local account"
when: prelim_ansible_user_password_set.stdout != "not found"
block:
- name: "Check password set for {{ ansible_env.SUDO_USER }} | Assert local password set" # noqa name[template]
ansible.builtin.assert:
that:
- prelim_ansible_user_password_set.stdout | length != 0
- prelim_ansible_user_password_set.stdout != "!!"
fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} has no password set - It can break access"
success_msg: "You have a password set for the {{ ansible_env.SUDO_USER }} user"
- name: "Check account is not locked for {{ ansible_env.SUDO_USER }} | Assert local account not locked" # noqa name[template]
ansible.builtin.assert:
that:
- not prelim_ansible_user_password_set.stdout.startswith("!")
fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_env.SUDO_USER }} is locked - It can break access"
success_msg: "The local account is not locked for {{ ansible_env.SUDO_USER }} user"
- name: "PRELIM | AUDIT | Check authselect profile is selected"
when: rhel9cis_allow_authselect_updates
tags: always
block:
- name: Discover and set container variable if required
ansible.builtin.set_fact:
system_is_container: true
- name: "PRELIM | AUDIT | Check authselect profile name has been updated"
ansible.builtin.assert:
that: rhel9cis_authselect_custom_profile_name != 'cis_example_profile'
fail_msg: "You still have the default name for your authselect profile"
- name: Load variable for container
ansible.builtin.include_vars:
file: "{{ container_vars_file }}"
- name: "PRELIM | AUDIT | Check authselect profile is selected"
ansible.builtin.shell: authselect current | head -1 | awk '{print $NF}'
changed_when: false
failed_when: prelim_authselect_current_profile.rc not in [ 0, 1 ]
register: prelim_authselect_current_profile
- name: Output if discovered is a container
ansible.builtin.debug:
msg: system has been discovered as a container
when:
- system_is_container
when:
- ansible_connection == 'docker' or
ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
- name: "PRELIM | AUDIT | Check authselect profile is selected"
ansible.builtin.assert:
that: prelim_authselect_current_profile is defined
success_msg: "Authselect is running and profile is selected"
fail_msg: Authselect updates have been selected there are issues with profile selection"
- name: "Ensure root password is set"
when: rhel9cis_rule_5_4_2_4
tags:
- container_discovery
- always
- level1-server
- level1-workstation
- patch
- accounts
- root
- rule_5.4.2.4
block:
- name: "Ensure root password is set"
ansible.builtin.shell: passwd -S root | egrep -e "(Password set, SHA512 crypt|Password locked)"
changed_when: false
register: prelim_root_passwd_set
- name: Check crypto-policy input
ansible.builtin.assert:
that: rhel9cis_crypto_policy in rhel9cis_allowed_crypto_policies
fail_msg: "Crypto policy is not a permitted version"
success_msg: "Crypto policy is a permitted version"
- name: "Ensure root password is set"
ansible.builtin.assert:
that: prelim_root_passwd_set.rc == 0
fail_msg: "You have rule 5.4.2.4 enabled this requires that you have a root password set"
success_msg: "You have a root password set"
- name: Check crypto-policy module input
ansible.builtin.assert:
that: rhel9cis_crypto_policy_module in rhel9cis_allowed_crypto_policies_modules
fail_msg: "Crypto policy module is not a permitted version"
success_msg: "Crypto policy module is a permitted version"
when:
- rhel9cis_rule_1_10
- rhel9cis_crypto_policy_module | length > 0
tags:
- rule_1.10
- name: Check rhel9cis_bootloader_password_hash variable has been changed
ansible.builtin.assert:
that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword' # pragma: allowlist secret
msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly"
when:
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
tags:
- always
- name: Gather the package facts
- name: "Gather the package facts"
tags: always
ansible.builtin.package_facts:
manager: auto
tags:
- always
manager: auto
- name: Include OS specific variables
ansible.builtin.include_vars: "{{ ansible_facts.distribution }}.yml"
tags:
- always
- name: "Include OS specific variables"
tags: always
ansible.builtin.include_vars:
file: "{{ ansible_facts.distribution }}.yml"
- name: Include preliminary steps
- name: "Include preliminary steps"
tags:
- prelim_tasks
- always
ansible.builtin.import_tasks:
file: prelim.yml
tags:
- prelim_tasks
- always
file: prelim.yml
- name: Run Section 1 tasks
ansible.builtin.import_tasks:
file: section_1/main.yml
- name: "Run Section 1 tasks"
when: rhel9cis_section1
tags:
- rhel9cis_section1
- name: Run Section 2 tasks
ansible.builtin.import_tasks:
file: section_2/main.yml
file: section_1/main.yml
- name: "Run Section 2 tasks"
when: rhel9cis_section2
tags:
- rhel9cis_section2
- name: Run Section 3 tasks
ansible.builtin.import_tasks:
file: section_3/main.yml
file: section_2/main.yml
- name: "Run Section 3 tasks"
when: rhel9cis_section3
tags:
- rhel9cis_section3
- name: Run Section 4 tasks
ansible.builtin.import_tasks:
file: section_4/main.yml
file: section_3/main.yml
- name: "Run Section 4 tasks"
when: rhel9cis_section4
tags:
- rhel9cis_section4
- name: Run Section 5 tasks
ansible.builtin.import_tasks:
file: section_5/main.yml
file: section_4/main.yml
- name: "Run Section 5 tasks"
when: rhel9cis_section5
tags:
- rhel9cis_section5
- name: Run Section 6 tasks
ansible.builtin.import_tasks:
file: section_6/main.yml
file: section_5/main.yml
- name: "Run Section 6 tasks"
when: rhel9cis_section6
tags:
- rhel9cis_section6
- name: Run auditd logic
ansible.builtin.import_tasks:
file: auditd.yml
file: section_6/main.yml
- name: "Run Section 7 tasks"
when: rhel9cis_section7
ansible.builtin.import_tasks:
file: section_7/main.yml
- name: "Run auditd logic"
when: update_audit_template
tags:
- always
- name: Run post remediation tasks
tags: always
ansible.builtin.import_tasks:
file: post.yml
file: auditd.yml
- name: "Run post remediation tasks"
tags:
- post_tasks
- always
- name: Run post_remediation audit
- post_tasks
- always
ansible.builtin.import_tasks:
file: post_remediation_audit.yml
when:
- run_audit
file: post.yml
- name: Show Audit Summary
ansible.builtin.debug:
msg: "{{ audit_results.split('\n') }}"
- name: "Run post_remediation audit"
when: run_audit
ansible.builtin.import_tasks:
file: post_remediation_audit.yml
- name: If Warnings found Output count and control IDs affected
- name: "Show Audit Summary"
when: run_audit
ansible.builtin.debug:
msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}"
msg: "{{ audit_results.split('\n') }}"
- name: "If Warnings found Output count and control IDs affected"
when: warn_count != 0
tags:
- always
tags: always
ansible.builtin.debug:
msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}"

View file

@ -1,32 +1,31 @@
---
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd"
tags: always
block:
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd"
ansible.builtin.shell: cat /etc/passwd
changed_when: false
check_mode: false
register: rhel9cis_passwd_file_audit
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd"
ansible.builtin.command: cat /etc/passwd
changed_when: false
check_mode: false
register: prelim_passwd_file_audit
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries"
ansible.builtin.set_fact:
rhel9cis_passwd: "{{ rhel9cis_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}"
loop: "{{ rhel9cis_passwd_file_audit.stdout_lines }}"
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
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries"
ansible.builtin.set_fact:
rhel9cis_passwd: "{{ prelim_passwd_file_audit.stdout_lines | map('regex_replace', ld_passwd_regex, ld_passwd_yaml) | map('from_yaml') | list }}"
loop: "{{ prelim_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: | # pragma: allowlist secret
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>

View file

@ -1,67 +1,49 @@
---
# Post tasks
- name: POST | Gather the package facts after remediation
tags: always
ansible.builtin.package_facts:
manager: auto
tags:
- always
manager: auto
- name: POST | Update sysctl
when:
- rhel9cis_sysctl_update
- not system_is_container
- "'procps-ng' in ansible_facts.packages"
ansible.builtin.template:
src: "etc/sysctl.d/{{ item }}.j2"
dest: "/etc/sysctl.d/{{ item }}"
owner: root
group: root
mode: '0600'
register: sysctl_updated
src: "etc/sysctl.d/{{ item }}.j2"
dest: "/etc/sysctl.d/{{ item }}"
owner: root
group: root
mode: 'go-rwx'
notify: Reload sysctl
loop:
- 60-kernel_sysctl.conf
- 60-disable_ipv6.conf
- 60-netipv4_sysctl.conf
- 60-netipv6_sysctl.conf
when:
- rhel9cis_sysctl_update
- not system_is_container
- "'procps-ng' in ansible_facts.packages"
- 60-kernel_sysctl.conf
- 60-disable_ipv6.conf
- 60-netipv4_sysctl.conf
- 60-netipv6_sysctl.conf
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: POST | reboot system if changes require it and not skipped
block:
- name: POST | Reboot system if changes require it and not skipped
ansible.builtin.reboot:
when:
- change_requires_reboot
- not skip_reboot
- name: POST | Warning a reboot required but skip option set
ansible.builtin.debug:
msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results"
changed_when: true
when:
- change_requires_reboot
- skip_reboot
- name: "POST | Warning a reboot required but skip option set | warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- change_requires_reboot
- skip_reboot
vars:
warn_control_id: Reboot_required
when: change_requires_reboot
tags:
- grub
- level1-server
- level1-workstation
- level2-server
- level2-workstation
- rhel9cis_section1
- rhel9cis_section2
- rhel9cis_section3
- rhel9cis_section4
- rhel9cis_section5
- rhel9cis_section6
- always
vars:
warn_control_id: Reboot_required
block:
- name: POST | Reboot system if changes require it and not skipped
when: not skip_reboot
ansible.builtin.reboot:
- name: POST | Warning a reboot required but skip option set
when: skip_reboot
ansible.builtin.debug:
msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results"
changed_when: true
- name: "POST | Warning a reboot required but skip option set | warning count"
when: skip_reboot
ansible.builtin.import_tasks:
file: warning_facts.yml

View file

@ -1,44 +1,42 @@
---
- name: Post Audit | Run post_remediation {{ benchmark }} audit
ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\""
- name: Post Audit | Run post_remediation {{ benchmark }} audit # noqa name[template]
ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ post_audit_outfile }} -g \"{{ group_names }}\""
changed_when: true
environment:
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}"
AUDIT_FILE: goss.yml
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}"
AUDIT_FILE: goss.yml
- name: Post Audit | ensure audit files readable by users
ansible.builtin.file:
path: "{{ item }}"
mode: '0644'
state: file
path: "{{ item }}"
mode: '0644'
state: file
loop:
- "{{ post_audit_outfile }}"
- "{{ pre_audit_outfile }}"
- "{{ post_audit_outfile }}"
- "{{ pre_audit_outfile }}"
- name: Post Audit | Capture audit data if json format
when:
- audit_format == "json"
when: audit_format == "json"
block:
- name: Post Audit | Capture audit data if json format
ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4
register: post_audit_summary
changed_when: false
- name: Post Audit | Capture audit data if json format
ansible.builtin.shell: grep -E '"summary-line.*Count:.*Failed' "{{ post_audit_outfile }}" | cut -d'"' -f4
changed_when: false
register: post_audit_summary
- name: Post Audit | Set Fact for audit summary
ansible.builtin.set_fact:
post_audit_results: "{{ post_audit_summary.stdout }}"
- name: Post Audit | Set Fact for audit summary
ansible.builtin.set_fact:
post_audit_results: "{{ post_audit_summary.stdout }}"
- name: Post Audit | Capture audit data if documentation format
when:
- audit_format == "documentation"
when: audit_format == "documentation"
block:
- name: Post Audit | Capture audit data if documentation format
ansible.builtin.shell: tail -2 "{{ post_audit_outfile }}" | tac | tr '\n' ' '
register: post_audit_summary
changed_when: false
- name: Post Audit | Capture audit data if documentation format
ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' '
changed_when: false
register: post_audit_summary
- name: Post Audit | Set Fact for audit summary
ansible.builtin.set_fact:
post_audit_results: "{{ post_audit_summary.stdout }}"
- name: Post Audit | Set Fact for audit summary
ansible.builtin.set_fact:
post_audit_results: "{{ post_audit_summary.stdout }}"

View file

@ -1,119 +1,107 @@
---
- name: Pre Audit Setup | Setup the LE audit
when:
- setup_audit
tags:
- setup_audit
when: setup_audit
tags: setup_audit
ansible.builtin.include_tasks:
file: LE_audit_setup.yml
file: LE_audit_setup.yml
- name: Pre Audit Setup | Ensure {{ audit_conf_dir }} exists
- name: Pre Audit Setup | Ensure existence of {{ audit_conf_dir }} # noqa name[template]
ansible.builtin.file:
path: "{{ audit_conf_dir }}"
state: directory
mode: '0755'
path: "{{ audit_conf_dir }}"
mode: 'go-w'
state: directory
- name: Pre Audit Setup | If using git for content set up
when:
- audit_content == 'git'
when: audit_content == 'git'
block:
- name: Pre Audit Setup | Install git
ansible.builtin.package:
name: git
state: present
- name: Pre Audit Setup | Install git
ansible.builtin.package:
name: git
state: present
- name: Pre Audit Setup | Retrieve audit content files from git
ansible.builtin.git:
repo: "{{ audit_file_git }}"
dest: "{{ audit_conf_dir }}"
version: "{{ audit_git_version }}"
- name: Pre Audit Setup | Retrieve audit content files from git
ansible.builtin.git:
repo: "{{ audit_file_git }}"
dest: "{{ audit_conf_dir }}"
version: "{{ audit_git_version }}"
- name: Pre Audit Setup | Copy to audit content files to server
when:
- audit_content == 'copy'
when: audit_content == 'copy'
ansible.builtin.copy:
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}"
mode: preserve
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}"
mode: preserve
- name: Pre Audit Setup | Unarchive audit content files on server
when:
- audit_content == 'archive'
when: audit_content == 'archive'
ansible.builtin.unarchive:
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}"
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}"
- name: Pre Audit Setup | Get audit content from url
when:
- audit_content == 'get_url'
when: audit_content == 'get_url'
ansible.builtin.unarchive:
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit"
remote_src: "{{ ( audit_conf_source is contains ('http'))| ternary(true, false ) }}"
extra_opts: "{{ (audit_conf_source is contains ('github')) | ternary('--strip-components=1', [] ) }}"
src: "{{ audit_conf_source }}"
dest: "{{ audit_conf_dest }}/{{ benchmark }}-Audit"
remote_src: "{{ (audit_conf_source is contains('http')) | ternary(true, false) }}"
extra_opts: "{{ (audit_conf_source is contains('github')) | ternary('--strip-components=1', []) }}"
- name: Pre Audit Setup | Check Goss is available
when:
- run_audit
when: run_audit
block:
- name: Pre Audit Setup | Check for goss file
ansible.builtin.stat:
path: "{{ audit_bin }}"
register: goss_available
- name: Pre Audit Setup | Check for goss file
ansible.builtin.stat:
path: "{{ audit_bin }}"
register: prelim_goss_available
- name: Pre Audit Setup | If audit ensure goss is available
ansible.builtin.assert:
that: goss_available.stat.exists
msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}"
- name: Pre Audit Setup | If audit ensure goss is available
when: not prelim_goss_available.stat.exists
ansible.builtin.assert:
msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}"
- name: Pre Audit Setup | Copy ansible default vars values to test audit
when: run_audit
tags:
- goss_template
- run_audit
when:
- run_audit
- goss_template
- run_audit
ansible.builtin.template:
src: ansible_vars_goss.yml.j2
dest: "{{ audit_vars_path }}"
mode: '0600'
src: ansible_vars_goss.yml.j2
dest: "{{ audit_vars_path }}"
mode: 'go-rwx'
- name: Pre Audit | Run pre_remediation {{ benchmark }} audit
ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\""
- name: Pre Audit | Run pre_remediation audit {{ benchmark }} # noqa name[template]
ansible.builtin.command: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -f {{ audit_format }} -o {{ pre_audit_outfile }} -g \"{{ group_names }}\"" # noqa yaml[line-length]
changed_when: true
environment:
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}"
AUDIT_FILE: goss.yml
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_CONTENT_LOCATION: "{{ audit_conf_dest | default('/opt') }}"
AUDIT_FILE: goss.yml
- name: Pre Audit | Capture audit data if json format
when:
- audit_format == "json"
when: audit_format == "json"
block:
- name: Pre Audit | Capture audit data if json format
ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4
register: pre_audit_summary
changed_when: false
- name: Pre Audit | Capture audit data if json format
ansible.builtin.shell: grep -E '\"summary-line.*Count:.*Failed' "{{ pre_audit_outfile }}" | cut -d'"' -f4
changed_when: false
register: pre_audit_summary
- name: Pre Audit | Set Fact for audit summary
ansible.builtin.set_fact:
pre_audit_results: "{{ pre_audit_summary.stdout }}"
- name: Pre Audit | Set Fact for audit summary
ansible.builtin.set_fact:
pre_audit_results: "{{ pre_audit_summary.stdout }}"
- name: Pre Audit | Capture audit data if documentation format
when:
- audit_format == "documentation"
when: audit_format == "documentation"
block:
- name: Pre Audit | Capture audit data if documentation format
ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' '
register: pre_audit_summary
changed_when: false
- name: Pre Audit | Capture audit data if documentation format
ansible.builtin.shell: tail -2 "{{ pre_audit_outfile }}" | tac | tr '\n' ' '
changed_when: false
register: pre_audit_summary
- name: Pre Audit | Set Fact for audit summary
ansible.builtin.set_fact:
pre_audit_results: "{{ pre_audit_summary.stdout }}"
- name: Pre Audit | Set Fact for audit summary
ansible.builtin.set_fact:
pre_audit_results: "{{ pre_audit_summary.stdout }}"
- name: Audit_Only | Run Audit Only
when:
- audit_only
when: audit_only
ansible.builtin.import_tasks:
file: audit_only.yml
file: audit_only.yml

View file

@ -3,308 +3,336 @@
# Preliminary tasks that should always be run
# List users in order to look files inside each home directory
- name: PRELIM | Include audit specific variables
- name: "PRELIM | Include audit specific variables"
when:
- run_audit or audit_only
- setup_audit
- run_audit or audit_only
- setup_audit
tags:
- setup_audit
- run_audit
ansible.builtin.include_vars: audit.yml
- setup_audit
- run_audit
ansible.builtin.include_vars:
file: audit.yml
- name: PRELIM | Include pre-remediation audit tasks
- name: "PRELIM | Include pre-remediation audit tasks"
when:
- run_audit or audit_only
- setup_audit
tags:
- run_audit
- run_audit or audit_only
- setup_audit
tags: run_audit
ansible.builtin.import_tasks: pre_remediation_audit.yml
- name: "PRELIM | AUDIT | Interactive Users"
tags:
- always
tags: always
ansible.builtin.shell: >
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }'
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false" && $7 != "/dev/null") { print $1 }'
changed_when: false
register: discovered_interactive_usernames
register: prelim_interactive_usernames
- name: "PRELIM | AUDIT | Interactive User accounts home directories"
tags:
- always
tags: always
ansible.builtin.shell: >
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }'
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $6 }'
changed_when: false
register: discovered_interactive_users_home
register: prelim_interactive_users_home
- name: "PRELIM | AUDIT | Interactive UIDs"
tags:
- always
tags: always
ansible.builtin.shell: >
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }'
grep -E -v '^(root|halt|sync|shutdown)' /etc/passwd | awk -F: '(!index($7, "sbin/nologin") && $7 != "/bin/nologin" && $7 != "/bin/false") { print $3 }'
changed_when: false
register: discovered_interactive_uids
register: prelim_interactive_uids
- name: "PRELIM | capture /etc/password variables"
- name: "PRELIM | AUDIT | Capture /etc/password variables"
tags: always
ansible.builtin.include_tasks:
file: parse_etc_password.yml
tags:
- always
file: parse_etc_password.yml
- name: "PRELIM | List users accounts"
ansible.builtin.shell: "awk -F: '{print $1}' /etc/passwd"
changed_when: false
check_mode: false
register: users
tags:
- level1-server
- level1-workstation
- users
- name: "PRELIM | PATCH | Ensure python3-libselinux is installed"
when: '"python3-libselinux" not in ansible_facts.packages'
ansible.builtin.package:
name: python3-libselinux
state: present
- name: "PRELIM | Gather accounts with empty password fields"
ansible.builtin.shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'"
changed_when: false
check_mode: false
register: empty_password_accounts
tags:
- level1-server
- level1-workstation
- passwords
- name: PRELIM | AUDIT | Section 1.1 | Create list of mount points
tags: always
ansible.builtin.set_fact:
prelim_mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}"
- name: "PRELIM | Gather UID 0 accounts other than root"
- name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options
tags: always
block:
- name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - call mount # noqa command-instead-of-module
ansible.builtin.shell: |
mount | awk '{print $1, $3, $5, $6}'
changed_when: false
register: prelim_mount_output
- name: PRELIM | AUDIT | Section 1.1 | Retrieve mount options - build fact # This is inherited and used in mountpoints tasks
ansible.builtin.set_fact:
prelim_mount_point_fs_and_options: >-
{%- set prelim_mount_point_fs_and_options = {} -%}
{%- for line in prelim_mount_output.stdout_lines -%}
{%- set fields = line.split() -%}
{%- set _ = prelim_mount_point_fs_and_options.update({fields[1]: {'src': fields[0], 'fs_type': fields[2], 'original_options': fields[3][1:-1].split(','), 'options': fields[3][1:-1].split(',')}}) -%}
{%- endfor -%}
{{ prelim_mount_point_fs_and_options }}
- name: "PRELIM | AUDIT | Debug of mount variables to assist in troubleshooting"
when: rhel9cis_debug_mount_data
ansible.builtin.debug:
msg: "{{ prelim_mount_point_fs_and_options }}"
- name: "PRELIM | PATCH | Update to latest gpg keys"
when:
- rhel9cis_rule_1_2_1_1
- ansible_facts.distribution != 'RedHat'
- ansible_facts.distribution != 'OracleLinux'
ansible.builtin.package:
name: "{{ gpg_key_package }}"
state: latest
- name: "PRELIM | AUDIT | Import gpg keys | RedHat Only"
when:
- rhel9cis_rule_1_2_1_1
- rhel9cis_force_gpg_key_import
- ansible_facts.distribution == 'RedHat'
block:
- name: "PRELIM | AUDIT | Import gpg keys | get data"
ansible.builtin.command: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' # noqa command-instead-of-module
changed_when: false
failed_when: false
register: prelim_check_gpg_imported
- name: "PRELIM | AUDIT | Import gpg keys | Check Package" # noqa command-instead-of-module
when: "'not installed' in prelim_check_gpg_imported.stdout"
ansible.builtin.shell: rpm -qi redhat-release | grep Signature # noqa command-instead-of-module
changed_when: false
failed_when: false
register: prelim_os_gpg_package_valid
- name: "PRELIM | PATCH | Force keys to be imported" # noqa command-instead-of-module
when:
- "'not installed' in prelim_check_gpg_imported.stdout"
- "'Key ID 199e2f91fd431d51' in prelim_os_gpg_package_valid.stdout"
ansible.builtin.rpm_key:
key: /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
state: present
- name: "PRELIM | AUDIT | Check systemd coredump"
when: rhel9cis_rule_1_5_4
tags:
- level1-server
- level1-workstation
- rule_1.5.4
- systemd
ansible.builtin.stat:
path: /etc/systemd/coredump.conf
register: prelim_systemd_coredump
- name: "PRELIM | PATCH | Setup crypto-policy"
when:
- rhel9cis_rule_1_6_1
tags:
- level1-server
- level1-workstation
- rule_1.6.1
- crypto
block:
- name: "PRELIM | PATCH | Install crypto-policies | pkgs present"
ansible.builtin.package:
name:
- crypto-policies
- crypto-policies-scripts
state: present
- name: "PRELIM | AUDIT | Gather system-wide crypto-policy"
ansible.builtin.command: 'update-crypto-policies --show'
changed_when: false
check_mode: false
register: prelim_system_wide_crypto_policy
- name: "PRELIM | AUDIT | Gather system-wide crypto-policy | set fact system policy"
ansible.builtin.set_fact:
current_crypto_policy: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[0] }}"
- name: "PRELIM | AUDIT | Gather system-wide crypto-policy module | set fact system policy submodule"
when: "':' in prelim_system_wide_crypto_policy.stdout"
ansible.builtin.set_fact:
current_crypto_module: "{{ prelim_system_wide_crypto_policy.stdout.split(':')[1] }}"
- name: "PRELIM | AUDIT | Set facts based on boot type"
block:
- name: "PRELIM | AUDIT | Check whether machine is UEFI-based"
ansible.builtin.stat:
path: /sys/firmware/efi
register: prelim_efi_boot
- name: "PRELIM | AUDIT | Set legacy boot and grub path | Bios"
when: not prelim_efi_boot.stat.exists
ansible.builtin.set_fact:
rhel9cis_legacy_boot: true
grub2_path: /etc/grub2.cfg
- name: "PRELIM | AUDIT | Set grub fact | UEFI"
when: prelim_efi_boot.stat.exists
ansible.builtin.set_fact:
grub2_path: /etc/grub2-efi.cfg
- name: "PRELIM | Discover Gnome Desktop Environment"
tags:
- always
ansible.builtin.stat:
path: /usr/share/gnome/gnome-version.xml
register: prelim_gnome_present
- name: "PRELIM | Install dconf if gui installed"
when:
- rhel9cis_gui
tags:
- always
ansible.builtin.package:
name: dconf
state: present
- name: "PRELIM | AUDIT | Wireless adapter pre-requisites"
when:
- rhel9cis_rule_3_1_2
- not system_is_container
tags:
- always
block:
- name: "PRELIM | AUDIT | Discover is wirelss adapter on system"
ansible.builtin.command: find /sys/class/net/*/ -type d -name wireless
register: discover_wireless_adapters
changed_when: false
failed_when: discover_wireless_adapters.rc not in [ 0, 1 ]
- name: "PRELIM | PATCH | Install Network-Manager | if wireless adapter present"
when:
- discover_wireless_adapters.rc == 0
- "'NetworkManager' not in ansible_facts.packages"
ansible.builtin.package:
name: NetworkManager
state: present
- name: "PRELIM | PATCH | Install Cronie"
when:
- rhel9cis_rule_5_1_1
- '"cronie" not in ansible_facts.packages'
tags:
- level1-server
- level1-workstation
- rule_5.1.1
- cron
ansible.builtin.package:
name: cronie
state: present
# Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config
- name: "PRELIM | PATCH | SSH Config file is not exist"
when:
- rhel9cis_sshd_config_file != '/etc/ssh/sshd_config'
- "'openssh-server' in ansible_facts.packages"
tags:
- always
- level1_server
- level1_workstation
ansible.builtin.file:
path: "{{ rhel9cis_sshd_config_file }}"
owner: root
group: root
mode: 'go-rwx'
state: touch
- name: "PRELIM | AUDIT | Gather UID 0 accounts other than root"
when: rhel9cis_rule_5_4_2_1
tags:
- rule_5.4.2.1
- level1-server
- level1-workstation
- users
ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'"
changed_when: false
check_mode: false
register: rhel9cis_uid_zero_accounts_except_root
tags:
- rule_6.2.9
- level1-server
- level1-workstation
- users
register: prelim_uid_zero_accounts_except_root
- name: "PRELIM | Setup crypto-policy"
block:
- name: "PRELIM | Install crypto-policies | pkgs present"
ansible.builtin.package:
name:
- crypto-policies
- crypto-policies-scripts
state: present
- name: "PRELIM | Gather system-wide crypto-policy"
ansible.builtin.shell: 'update-crypto-policies --show'
changed_when: false
check_mode: false
register: rhel9cis_system_wide_crypto_policy
- name: "PRELIM | Gather system-wide crypto-policy | set fact system policy"
ansible.builtin.set_fact:
current_crypto_policy: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[0] }}"
- name: "PRELIM | Gather system-wide crypto-policy module | set fact system policy submodule"
ansible.builtin.set_fact:
current_crypto_module: "{{ rhel9cis_system_wide_crypto_policy.stdout.split(':')[1] }}"
when: "':' in rhel9cis_system_wide_crypto_policy.stdout"
- name: "PRELIM | PATCH | Create journald config directory"
when:
- rhel9cis_rule_1_10
tags:
- level1-server
- level1-workstation
- rule_1.10
- crypto
- name: "PRELIM | if systemd coredump"
ansible.builtin.stat:
path: /etc/systemd/coredump.conf
register: systemd_coredump
when:
- rhel9cis_rule_1_5_1
tags:
- level1-server
- level1-workstation
- rule_1.5.1
- systemd
- name: "PRELIM | Section 1.1 | Create list of mount points"
ansible.builtin.set_fact:
mount_names: "{{ ansible_facts.mounts | map(attribute='mount') | list }}"
tags:
- level1-server
- level1-workstation
- name: "PRELIM | Ensure python3-libselinux is installed"
ansible.builtin.package:
name: python3-libselinux
state: present
when:
- '"python3-libselinux" not in ansible_facts.packages'
- name: "PRELIM | Set facts based on boot type"
block:
- name: "PRELIM | Check whether machine is UEFI-based"
ansible.builtin.stat:
path: /sys/firmware/efi
register: rhel_09_efi_boot
- name: "PRELIM | set legacy boot and grub path | Bios"
ansible.builtin.set_fact:
rhel9cis_legacy_boot: true
grub2_path: /etc/grub2.cfg
when: not rhel_09_efi_boot.stat.exists
- name: "PRELIM | set grub fact | UEFI"
ansible.builtin.set_fact:
grub2_path: /etc/grub2-efi.cfg
when: rhel_09_efi_boot.stat.exists
- name: "PRELIM | Update to latest gpg keys"
ansible.builtin.package:
name: "{{ gpg_key_package }}"
state: latest
when:
- rhel9cis_rule_1_2_4
- ansible_facts.distribution != 'RedHat'
- ansible_facts.distribution != 'OracleLinux'
- name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not | RedHat Only"
block:
- name: "PRELIM | Check gpg keys are imported will cause 1.2.1 to fail if not"
ansible.builtin.shell: rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n'
changed_when: false
failed_when: false
register: check_gpg_imported
- name: "PRELIM | Check key package matches RedHat"
ansible.builtin.shell: rpm -qi redhat-release | grep Signature
changed_when: false
failed_when: false
register: os_gpg_package_valid
when: "'not installed' in check_gpg_imported.stdout"
- name: "PRELIM | Force keys to be imported"
ansible.builtin.shell: rpm --import /etc/pki/rpm-gpg/RPM-GPG-KEY-redhat-release
when:
- "'not installed' in check_gpg_imported.stdout"
- "'Key ID 199e2f91fd431d51' in os_gpg_package_valid.stdout"
when:
- rhel9cis_rule_1_2_1
- rhel9cis_force_gpg_key_import
- ansible_facts.distribution == 'RedHat'
- name: "PRELIM | Discover Gnome Desktop Environment"
ansible.builtin.stat:
path: /usr/share/gnome/gnome-version.xml
register: prelim_gnome_present
tags:
- always
- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)"
ansible.builtin.package:
name: audit
state: present
become: true
when:
- '"auditd" not in ansible_facts.packages'
- rhel9cis_rule_4_1_1_1
tags:
- level2-server
- level2-workstation
- patch
- rule_4.1.1.1
- auditd
- name: "PRELIM | 4.1.4.5 | Audit conf and rules files | list files"
ansible.builtin.find:
path: /etc/audit
file_type: file
recurse: true
patterns: '*.conf,*.rules'
register: auditd_conf_files
when:
- rhel9cis_rule_4_1_4_5 or
rhel9cis_rule_4_1_4_6 or
rhel9cis_rule_4_1_4_7
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.5
- rule_4.1.4.6
- rule_4.1.4.7
- name: "PRELIM | Section 5.1 | Configure cron"
ansible.builtin.package:
name: cronie
state: present
become: true
when:
- rhel9cis_rule_5_1_1
- '"cronie" not in ansible_facts.packages'
tags:
- level1-server
- level1-workstation
- rule_5.1.1
- cron
# Added to ensure ssh drop in file exists if not default /etc/ssh/sshd_config
- name: "PRELIM | Section 5.2 | SSH"
- rhel9cis_syslog == 'journald'
- rhel9cis_rule_6_2_1_3 or
rhel9cis_rule_6_2_1_4
tags: always
ansible.builtin.file:
path: "{{ rhel9cis_sshd_config_file }}"
owner: root
group: root
mode: '0600'
state: touch
when:
- rhel9cis_sshd_config_file != '/etc/ssh/sshd_config'
- "'openssh-server' in ansible_facts.packages"
tags:
- always
path: /etc/systemd/journald.conf.d
state: directory
mode: 'u+x,g-w,o-rwx'
- name: "PRELIM | 5.3.4 | Find all sudoers files."
ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'"
- name: "PRELIM | PATCH | Configure System Accounting (auditd)"
when:
- '"auditd" not in ansible_facts.packages'
- rhel9cis_rule_6_3_1_1
tags:
- level2-server
- level2-workstation
- patch
- rule_6.3.1.1
- auditd
ansible.builtin.package:
name: audit
state: present
become: true
- name: "PRELIM | AUDIT | Discover audit logfile"
when:
- rhel9cis_rule_6_3_4_1 or
rhel9cis_rule_6_3_4_2 or
rhel9cis_rule_6_3_4_3 or
rhel9cis_rule_6_3_4_4
tags: always
ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_sudoers_files
when:
- rhel9cis_rule_5_3_4 or
rhel9cis_rule_5_3_5
tags:
- rule_5.3.4
- rule_5.3.5
register: prelim_auditd_logfile
- name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def"
- name: "PRELIM | AUDIT | Audit conf and rules files | list files"
when:
- rhel9cis_rule_6_3_4_5 or
rhel9cis_rule_6_3_4_6 or
rhel9cis_rule_6_3_4_7
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_6.3.4.5
- rule_6.3.4.6
- rule_6.3.4.7
ansible.builtin.find:
path: /etc/audit
file_type: file
recurse: true
patterns: '*.conf,*.rules'
register: prelim_auditd_conf_files
- name: "PRELIM | AUDIT | Discover Interactive UID MIN and MIN from logins.def"
when: rhel9cis_discover_int_uid
tags: always
block:
- name: "PRELIM | Capture UID_MIN information from logins.def"
ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: uid_min_id
- name: "PRELIM | AUDIT | Capture UID_MIN information from logins.def"
ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: prelim_uid_min_id
- name: "PRELIM | Capture UID_MAX information from logins.def"
ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: uid_max_id
- name: "PRELIM | AUDIT | Capture UID_MAX information from logins.def"
ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: prelim_uid_max_id
- name: "PRELIM | Capture GID_MIN information from logins.def"
ansible.builtin.shell: grep -w "^GID_MIN" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: gid_min_id
- name: "PRELIM | AUDIT | set_facts for interactive uid/gid"
ansible.builtin.set_fact:
prelim_min_int_uid: "{{ prelim_uid_min_id.stdout }}"
prelim_max_int_uid: "{{ prelim_uid_max_id.stdout }}"
- name: "PRELIM | set_facts for interactive uid/gid"
ansible.builtin.set_fact:
min_int_uid: "{{ uid_min_id.stdout }}"
max_int_uid: "{{ uid_max_id.stdout }}"
min_int_gid: "{{ gid_min_id.stdout }}"
- name: "PRELIM | Output of uid findings"
ansible.builtin.debug:
msg: "{{ min_int_uid }} {{ max_int_uid }}"
when:
- not discover_int_uid
- name: "PRELIM | Gather the package facts after prelim"
ansible.builtin.package_facts:
manager: auto
- name: "PRELIM | AUDIT | Gather the package facts after prelim"
tags:
- always
- always
ansible.builtin.package_facts:
manager: auto

View file

@ -1,66 +1,292 @@
---
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled"
block:
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install squashfs(\\s|$)"
line: "install squashfs /bin/true"
create: true
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist squashfs(\\s|$)"
line: "blacklist squashfs"
create: true
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure mounting of squashfs filesystems is disabled | Disable squashfs"
community.general.modprobe:
name: squashfs
state: absent
when: not system_is_container
when:
- rhel9cis_rule_1_1_1_1
- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available"
when: rhel9cis_rule_1_1_1_1
tags:
- level2-server
- level2-workstation
- patch
- rule_1.1.1.1
- squashfs
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled"
- level1-server
- level1-workstation
- patch
- rule_1.1.1.1
- cramfs
- NIST800-53R5_CM-7
block:
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install udf(\\s|$)"
line: "install udf /bin/true"
create: true
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install cramfs(\\s|$)"
line: "install cramfs /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disabled | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist udf(\\s|$)"
line: "blacklist udf"
create: true
mode: '0600'
- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist cramfs(\\s|$)"
line: "blacklist cramfs"
create: true
mode: 'go-rwx'
- name: "1.1.1.2 | PATCH | Ensure mounting of udf filesystems is disable | Disable udf"
community.general.modprobe:
name: udf
state: absent
when: not system_is_container
when:
- rhel9cis_rule_1_1_1_2
- name: "1.1.1.1 | PATCH | Ensure cramfs kernel module is not available | Disable cramfs"
when:
- not system_is_container
community.general.modprobe:
name: cramfs
state: absent
- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available"
when: rhel9cis_rule_1_1_1_2
tags:
- level2-server
- level2-workstation
- patch
- rule_1.1.1.2
- udf
- level1-server
- level1-workstation
- patch
- rule_1.1.1.2
- freevxfs
- NIST800-53R5_CM-7
block:
- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install freevxfs(\\s|$)"
line: "install freevxfs /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist freevxfs(\\s|$)"
line: "blacklist freevxfs"
create: true
mode: 'go-rwx'
- name: "1.1.1.2 | PATCH | Ensure freevxfs kernel module is not available | Disable freevxfs"
when: not system_is_container
community.general.modprobe:
name: freevxfs
state: absent
- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available"
when: rhel9cis_rule_1_1_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_1.1.1.3
- hfs
- NIST800-53R5_CM-7
block:
- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install hfs(\\s|$)"
line: "install hfs /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist hfs(\\s|$)"
line: "blacklist hfs"
create: true
mode: 'go-rwx'
- name: "1.1.1.3 | PATCH | Ensure hfs kernel module is not available | Disable hfs"
when: not system_is_container
community.general.modprobe:
name: hfs
state: absent
- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available"
when: rhel9cis_rule_1_1_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_1.1.1.4
- hfsplus
- NIST800-53R5_CM-7
block:
- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install hfsplus(\\s|$)"
line: "install hfsplus /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist hfsplus(\\s|$)"
line: "blacklist hfsplus"
create: true
mode: 'go-rwx'
- name: "1.1.1.4 | PATCH | Ensure hfsplus kernel module is not available | Disable hfsplus"
when: not system_is_container
community.general.modprobe:
name: hfsplus
state: absent
- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available"
when: rhel9cis_rule_1_1_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_1.1.1.5
- jffs2
- NIST800-53R5_CM-7
block:
- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install jffs2(\\s|$)"
line: "install jffs2 /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist jffs2(\\s|$)"
line: "blacklist jffs2"
create: true
mode: 'go-rwx'
- name: "1.1.1.5 | PATCH | Ensure jffs2 kernel module is not available | Disable jffs2"
when: not system_is_container
community.general.modprobe:
name: jffs2
state: absent
- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available"
when: rhel9cis_rule_1_1_1_6
tags:
- level2-server
- level2-workstation
- patch
- rule_1.1.1.6
- squashfs
- NIST800-53R5_CM-7
block:
- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install squashfs(\\s|$)"
line: "install squashfs /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist squashfs(\\s|$)"
line: "blacklist squashfs"
create: true
mode: 'go-rwx'
- name: "1.1.1.6 | PATCH | Ensure squashfs kernel module is not available | Disable squashfs"
when: not system_is_container
community.general.modprobe:
name: squashfs
state: absent
- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available"
when: rhel9cis_rule_1_1_1_7
tags:
- level2-server
- level2-workstation
- patch
- rule_1.1.1.7
- udf
- NIST800-53R5_CM-7
block:
- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install udf(\\s|$)"
line: "install udf /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist udf(\\s|$)"
line: "blacklist udf"
create: true
mode: 'go-rwx'
- name: "1.1.1.7 | PATCH | Ensure udf kernel module is not available | Disable udf"
when: not system_is_container
community.general.modprobe:
name: udf
state: absent
- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available"
when: rhel9cis_rule_1_1_1_8
tags:
- level1-server
- level2-workstation
- patch
- rule_1.1.1.8
- usb
- NIST800-53R5_SI-3
block:
- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install usb-storage(\\s|$)"
line: "install usb-storage /bin/true"
create: true
mode: 'go-rwx'
- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist usb-storage(\\s|$)"
line: "blacklist usb-storage"
create: true
mode: 'go-rwx'
- name: "1.1.1.8 | PATCH | Ensure usb-storage kernel module is not available | Disable usb"
when: not system_is_container
community.general.modprobe:
name: usb-storage
state: absent
- name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available"
when: rhel9cis_rule_1_1_1_9
tags:
- level1-server
- level1-workstation
- patch
- rule_1.1.1.9
vars:
warn_control_id: '1.1.1.9'
block:
- name: "1.1.1.9 | PATCH | Ensure unused filesystems kernel modules are not available | Add discovery script"
ansible.builtin.copy:
src: fs_with_cves.sh
dest: /var/fs_with_cves.sh
owner: root
group: root
mode: 'u+x,go-wx'
- name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Run discovery script"
ansible.builtin.command: /var/fs_with_cves.sh
changed_when: false
failed_when: discovered_fs_modules_loaded.rc not in [ 0, 99 ]
register: discovered_fs_modules_loaded
- name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Output Warning"
when: discovered_fs_modules_loaded.stdout | length > 0
ansible.builtin.debug:
msg: "{{ ['Warning!! Discovered loaded Filesystem modules that need attention. This is a manual task'] + discovered_fs_modules_loaded.stdout_lines }}"
- name: "1.1.1.9 | AUDIT | Ensure unused filesystems kernel modules are not available | Capture Warning"
when: discovered_fs_modules_loaded.stdout | length > 0
ansible.builtin.import_tasks:
file: warning_facts.yml

View file

@ -0,0 +1,132 @@
---
- name: "1.1.2.1.1 | PATCH | Ensure /tmp is a separate partition"
when:
- required_mount not in prelim_mount_names
- rhel9cis_rule_1_1_2_1_1
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.1.1
- NIST800-53R5_CM-7
vars:
warn_control_id: "1.1.2.1.1"
required_mount: "/tmp"
block:
- name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_tmp_mount.rc not in [ 0, 1 ]
register: discovered_tmp_mount
- name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Absent"
when: discovered_tmp_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.1.1 | AUDIT | Ensure /tmp is a separate partition | Present"
when: discovered_tmp_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
# via fstab
- name: "1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs"
- rhel9cis_rule_1_1_2_1_2
- not rhel9cis_tmp_svc
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.1.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/tmp"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.1.3 | PATCH | Ensure nosuid option set on /tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs"
- rhel9cis_rule_1_1_2_1_3
- not rhel9cis_tmp_svc
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.1.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/tmp"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
- name: "1.1.2.1.4 | PATCH | Ensure noexec option set on /tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- not prelim_mount_point_fs_and_options[mount_point]['src'] == "tmpfs"
- rhel9cis_rule_1_1_2_1_4
- not rhel9cis_tmp_svc
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.1.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/tmp"
required_option: noexec
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
# via systemd
- name: |
"1.1.2.1.1 | PATCH | Ensure /tmp is configured
1.1.2.1.2 | PATCH | Ensure nodev option set on /tmp partition
1.1.2.1.3 | PATCH | Ensure noexec option set on /tmp partition
1.1.2.1.4 | PATCH | Ensure nosuid option set on /tmp partition"
when:
- rhel9cis_tmp_svc
- rhel9cis_rule_1_1_2_1_1 or rhel9cis_rule_1_1_2_1_2 or rhel9cis_rule_1_1_2_1_3 or rhel9cis_rule_1_1_2_1_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.1.1
- rule_1.1.2.1.2
- rule_1.1.2.1.3
- rule_1.1.2.1.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/tmp"
ansible.builtin.template:
src: etc/systemd/system/tmp.mount.j2
dest: /etc/systemd/system/tmp.mount
owner: root
group: root
mode: 'go-wx'
notify: *mount_option_notify

View file

@ -0,0 +1,95 @@
---
- name: "1.1.2.2.1 | PATCH | Ensure /dev/shm is a separate partition"
when:
- rhel9cis_rule_1_1_2_2_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.2.1
- NIST800-53R5_CM-7
vars:
warn_control_id: "1.1.2.2.1"
required_mount: "/dev/shm"
block:
- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_dev_shm_mount.rc not in [ 0, 1 ]
register: discovered_dev_shm_mount
- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent"
when: discovered_dev_shm_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.2.1 | AUDIT | Ensure /dev/shm is a separate partition | Present"
when: discovered_dev_shm_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.2.2 | PATCH | Ensure nodev option set on /dev/shm partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_2_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.2.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/dev/shm"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.2.3 | PATCH | Ensure nosuid option set on /dev/shm partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_2_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.2.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/dev/shm"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
- name: "1.1.2.2.4 | PATCH | Ensure noexec option set on /dev/shm partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_2_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.2.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/dev/shm"
required_option: noexec
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -0,0 +1,74 @@
---
- name: "1.1.2.3.1 | PATCH | Ensure /home is a separate partition"
when:
- rhel9cis_rule_1_1_2_3_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.3.1
- NIST800-53R5_CM-7
vars:
warn_control_id: "1.1.2.3.1"
required_mount: "/home"
block:
- name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_home_mount.rc not in [ 0, 1 ]
register: discovered_home_mount
- name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Absent"
when: discovered_dev_shm_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.3.1 | AUDIT | Ensure /home is a separate partition | Present"
when: discovered_dev_shm_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.3.2 | PATCH | Ensure nodev option set on /home partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_3_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.3.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/home"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.3.3 | PATCH | Ensure nosuid option set on /home partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_3_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.3.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/home"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -0,0 +1,75 @@
---
- name: "1.1.2.4.1 | PATCH | Ensure /var is a separate partition"
when:
- rhel9cis_rule_1_1_2_4_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.4.1
- NIST800-53R5_CM-7
vars:
warn_control_id: '1.1.2.4.1'
required_mount: '/var'
block:
- name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_var_mount.rc not in [ 0, 1 ]
register: discovered_var_mount
- name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent"
when: discovered_dev_shm_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present"
when: discovered_dev_shm_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.4.2 | PATCH | Ensure nodev option set on /var partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_4_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.4.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.4.3 | PATCH | Ensure nosuid option set on /var partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_4_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.4.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -0,0 +1,95 @@
---
- name: "1.1.2.5.1 | PATCH | Ensure /var/tmp is a separate partition"
when:
- rhel9cis_rule_1_1_2_5_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.5.1
- NIST800-53R5_CM-7
vars:
warn_control_id: '1.1.2.5.1'
required_mount: '/var/tmp'
block:
- name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_var_tmp_mount.rc not in [ 0, 1 ]
register: discovered_var_tmp_mount
- name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Absent"
when: discovered_var_tmp_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.5.1 | AUDIT | Ensure /var/tmp is a separate partition | Present"
when: discovered_var_tmp_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.5.2 | PATCH | Ensure nodev option set on /var/tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_5_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.5.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/tmp"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.5.3 | PATCH | Ensure nosuid option set on /var/tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_5_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.5.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/tmp"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
- name: "1.1.2.5.4 | PATCH | Ensure noexec option set on /var/tmp partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_5_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.5.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/tmp"
required_option: noexec
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -0,0 +1,95 @@
---
- name: "1/.1 | PATCH | Ensure /var/log is a separate partition"
when:
- rhel9cis_rule_1_1_2_6_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.6.1
- NIST800-53R5_CM-7
vars:
warn_control_id: '1.1.2.6.1'
required_mount: '/var/log'
block:
- name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_var_log_mount.rc not in [ 0, 1 ]
register: discovered_var_log_mount
- name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Absent"
when: discovered_var_log_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.6.1 | AUDIT | Ensure /var/log is a separate partition | Present"
when: discovered_var_log_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.6.2 | PATCH | Ensure nodev option set on /var/log partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_6_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.6.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.6.3 | PATCH | Ensure nosuid option set on /var/log partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_6_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.6.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
- name: "1.1.2.6.4 | PATCH | Ensure noexec option set on /var/log partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_6_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.6.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log"
required_option: noexec
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -0,0 +1,95 @@
---
- name: "1/.1 | PATCH | Ensure /var/log/audit is a separate partition"
when:
- rhel9cis_rule_1_1_2_7_1
- required_mount not in prelim_mount_names
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.7.1
- NIST800-53R5_CM-7
vars:
warn_control_id: '1.1.2.7.1'
required_mount: '/var/log/audit'
block:
- name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | check for mount"
ansible.builtin.command: findmnt -kn "{{ required_mount }}"
changed_when: false
failed_when: discovered_var_log_audit_mount.rc not in [ 0, 1 ]
register: discovered_var_log_audit_mount
- name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Absent"
when: discovered_var_log_audit_mount is undefined
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} is not mounted on a separate partition"
- name: "1.1.2.7.1 | AUDIT | Ensure /var/log/audit is a separate partition | Present"
when: discovered_var_log_audit_mount is undefined
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.1.2.7.2 | PATCH | Ensure nodev option set on /var/log/audit partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_7_2
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.7.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log/audit"
required_option: nodev
notify: &mount_option_notify
- "Remount {{ mount_point }}"
ansible.builtin.set_fact: &mount_option_set_fact
prelim_mount_point_fs_and_options: |
{{ prelim_mount_point_fs_and_options | combine({mount_point: {'options': (prelim_mount_point_fs_and_options[mount_point]['options'] + [required_option])}}, recursive=True) }}
changed_when: &mount_option_changed_when
- required_option not in prelim_mount_point_fs_and_options[mount_point]['original_options']
- name: "1.1.2.7.3 | PATCH | Ensure nosuid option set on /var/log/audit partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_7_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.7.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log/audit"
required_option: nosuid
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when
- name: "1.1.2.7.4 | PATCH | Ensure noexec option set on /var/log/audit partition"
when:
- prelim_mount_point_fs_and_options[mount_point] is defined
- rhel9cis_rule_1_1_2_7_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.7.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
mount_point: "/var/log/audit"
required_option: noexec
notify: *mount_option_notify
ansible.builtin.set_fact:
<<: *mount_option_set_fact
changed_when: *mount_option_changed_when

View file

@ -1,82 +0,0 @@
---
- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition"
block:
- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.2.1 | PATCH | Ensure /tmp is a separate partition | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.2.1'
required_mount: '/tmp'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_2_1
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.2.1
# via fstab
- name: |
"1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition"
"1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition"
"1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition"
ansible.posix.mount:
name: /tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_2_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_2_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_2_4) %},nosuid{% endif %}"
notify: Remount tmp
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
when:
- item.mount == "/tmp"
- not rhel9cis_tmp_svc
- rhel9cis_rule_1_1_2_2 or
rhel9cis_rule_1_1_2_3 or
rhel9cis_rule_1_1_2_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.2
- rule_1.1.2.3
- rule_1.1.2.4
# via systemd
- name: |
"1.1.2.1 | PATCH | Ensure /tmp is configured"
"1.1.2.2 | PATCH | Ensure nodev option set on /tmp partition"
"1.1.2.3 | PATCH | Ensure noexec option set on /tmp partition"
"1.1.2.4 | PATCH | Ensure nosuid option set on /tmp partition"
ansible.builtin.template:
src: etc/systemd/system/tmp.mount.j2
dest: /etc/systemd/system/tmp.mount
owner: root
group: root
mode: '0644'
notify: Systemd restart tmp.mount
when:
- rhel9cis_tmp_svc
- rhel9cis_rule_1_1_2_1 or
rhel9cis_rule_1_1_2_2 or
rhel9cis_rule_1_1_2_3 or
rhel9cis_rule_1_1_2_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.2.1
- rule_1.1.2.2
- rule_1.1.2.3
- rule_1.1.2.4

View file

@ -1,49 +0,0 @@
---
- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var"
block:
- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.3.1 | AUDIT | Ensure separate partition exists for /var | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.3.1'
required_mount: '/var'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_3_1
tags:
- level2-server
- level2-workstation
- patch
- mounts
- rule_1.1.3.1
# skips if mount is absent
- name: |
"1.1.3.2 | PATCH | Ensure nodev option set on /var partition"
"1.1.3.3 | PATCH | Ensure nosuid option set on /var partition"
ansible.builtin.mount:
name: /var
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_3_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_3_3) %},nosuid{% endif %}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var"
- rhel9cis_rule_1_1_3_2 or
rhel9cis_rule_1_1_3_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.3.2
- rule_1.1.3.3

View file

@ -1,53 +0,0 @@
---
# Skips if mount is absent
- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp"
block:
- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.4.1 | AUDIT | Ensure separate partition exists for /var/tmp | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.4.1'
required_mount: '/var/tmp'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_4_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.4.1
# skips if mount is absent
- name: |
"1.1.4.2 | PATCH | Ensure noexec option set on /var/tmp partition"
"1.1.4.3 | PATCH | Ensure nosuid option set on /var/tmp partition"
"1.1.4.4 | PATCH | Ensure nodev option set on /var/tmp partition"
ansible.builtin.mount:
name: /var/tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_4_2) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_4_3) %},nosuid{% endif %}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_4_4) %},nodev{% endif %}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/tmp"
- rhel9cis_rule_1_1_4_2 or
rhel9cis_rule_1_1_4_3 or
rhel9cis_rule_1_1_4_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.4.2
- rule_1.1.4.3
- rule_1.1.4.4

View file

@ -1,52 +0,0 @@
---
- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log"
block:
- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.5.1 | AUDIT | Ensure separate partition exists for /var/log | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.5.1'
required_mount: '/var/log'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_5_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.5.1
- name: |
"1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition"
"1.1.5.3 | PATCH | Ensure noexec option set on /var/log partition"
"1.1.5.4 | PATCH | Ensure nosuid option set on /var/log partition"
ansible.builtin.mount:
name: /var/log
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_5_2) %},nodev{% endif %}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_5_3) %},noexec{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_5_4) %},nosuid{% endif %}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/log"
- rhel9cis_rule_1_1_5_2 or
rhel9cis_rule_1_1_5_3 or
rhel9cis_rule_1_1_5_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.5.2
- rule_1.1.5.3
- rule_1.1.5.4

View file

@ -1,52 +0,0 @@
---
- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit"
block:
- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.6.1 | AUDIT | Ensure separate partition exists for /var/log/audit | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.6.1'
required_mount: '/var/log/audit'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_6_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.6.1
- name: |
"1.1.6.2 | PATCH | Ensure noexec option set on /var/log/audit partition"
"1.1.6.3 | PATCH | Ensure nodev option set on /var/log/audit partition"
"1.1.6.4 | PATCH | Ensure nosuid option set on /var/log/audit partition"
ansible.builtin.mount:
name: /var/log/audit
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('noexec' not in item.options and rhel9cis_rule_1_1_6_2) %},noexec{% endif %}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_6_3) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_6_4) %},nosuid{% endif %}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/log/audit"
- rhel9cis_rule_1_1_6_2 or
rhel9cis_rule_1_1_6_3 or
rhel9cis_rule_1_1_6_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.6.2
- rule_1.1.6.3
- rule_1.1.6.4

View file

@ -1,49 +0,0 @@
---
- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home"
block:
- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.7.1 | AUDIT | Ensure separate partition exists for /home | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.1.7.1'
required_mount: '/home'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_7_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.7.1
- name: |
"1.1.7.2 | PATCH | Ensure nodev option set on /home partition
1.1.7.3 | PATCH | Ensure nosuid option set on /home partition"
ansible.builtin.mount:
name: /home
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: "{{ item.options }}{% if ('nodev' not in item.options and rhel9cis_rule_1_1_7_2) %},nodev{% endif %}{% if ('nosuid' not in item.options and rhel9cis_rule_1_1_7_3) %},nosuid{% endif %}"
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/home"
- rhel9cis_rule_1_1_7_2 or
rhel9cis_rule_1_1_7_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.7.2
- rule_1.1.7.3

View file

@ -1,55 +0,0 @@
---
# Skips if mount is absent
- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition"
block:
- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | check exists"
ansible.builtin.shell: mount -l | grep -w /dev/shm
changed_when: false
register: rhel9cis_1_8_1_1_mount_check
- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition"
block:
- name: "1.1.8.1 | AUDIT | Ensure /dev/shm is a separate partition | Absent"
ansible.builtin.debug:
msg: "Warning!! {{ required_mount }} doesn't exist. This is a manual task"
- name: "1.1.8.1 | AUDIT | Ensure separate partition exists for /home | Present"
ansible.builtin.import_tasks:
file: warning_facts.yml
when: rhel9cis_1_8_1_1_mount_check.rc == 1
vars:
warn_control_id: '1.1.8.1'
when:
- rhel9cis_rule_1_1_8_1
tags:
- level1-server
- level1-workstation
- audit
- mounts
- rule_1.1.8.1
- name: |
"1.1.8.2 | PATCH | Ensure nodev option set on /dev/shm partition | Set nodev option
1.1.8.3 | PATCH | Ensure noexec option set on /dev/shm partition | Set nosuid option
1.1.8.4 | PATCH | Ensure nosuid option set on /dev/shm partition | Set noexec option"
ansible.posix.mount:
name: /dev/shm
src: tmpfs
fstype: tmpfs
state: mounted
opts: defaults,{% if rhel9cis_rule_1_1_8_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_8_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_8_4 %}nosuid{% endif %}
notify: Change_requires_reboot
when:
- rhel9cis_rule_1_1_8_2 or
rhel9cis_rule_1_1_8_3 or
rhel9cis_rule_1_1_8_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.8.2
- rule_1.1.8.3
- rule_1.1.8.4

View file

@ -1,36 +0,0 @@
---
- name: "1.1.9 | PATCH | Disable USB Storage"
block:
- name: "1.1.9 | PATCH | Disable USB Storage | Edit modprobe config"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install usb-storage(\\s|$)"
line: "install usb-storage /bin/true"
create: true
owner: root
group: root
mode: '0600'
- name: "1.1.9 | PATCH | Disable USB Storage | Edit modprobe config"
community.general.modprobe:
name: usb-storage
state: absent
when: not system_is_container
- name: "1.1.9 | PATCH | Disable USB Storage | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist usb-storage(\\s|$)"
line: "blacklist usb-storage"
create: true
mode: '0600'
when:
- rhel9cis_rule_1_1_9
tags:
- level1-server
- level2-workstation
- patch
- mounts
- removable_storage
- rule_1.1.9

View file

@ -1,25 +0,0 @@
---
- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy"
block:
- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy | set_fact"
ansible.builtin.set_fact:
rhel9cis_full_crypto_policy: "{{ rhel9cis_crypto_policy }}{% if rhel9cis_crypto_policy_module | length > 0 %}:{{ rhel9cis_crypto_policy_module }}{% endif %}"
- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy"
ansible.builtin.shell: |
update-crypto-policies --set "{{ rhel9cis_full_crypto_policy }}"
update-crypto-policies
notify: Change_requires_reboot
when:
- rhel9cis_system_wide_crypto_policy.stdout != rhel9cis_full_crypto_policy
when:
- rhel9cis_rule_1_10
tags:
- level1-server
- level1-workstation
- automated
- no system_is_ec2
- patch
- rule_1.10

View file

@ -0,0 +1,122 @@
---
- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured"
when:
- rhel9cis_rule_1_2_1_1
- ansible_facts.distribution == "RedHat" or
ansible_facts.distribution == "Rocky" or
ansible_facts.distribution == "AlmaLinux"
tags:
- level1-server
- level1-workstation
- manual
- patch
- rule_1.2.1.1
- NIST800-53R5_SI-2
block:
- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | List installed pubkey keys"
ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}" # noqa command-instead-of-module
changed_when: false
failed_when: false
register: discovered_os_installed_pub_keys
- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | Query found keys"
ansible.builtin.shell: |
'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"'
changed_when: false
failed_when: false
register: discovered_os_gpg_key_check
- name: "1.2.1.1 | AUDIT | Ensure GPG keys are configured | If expected keys fail"
when:
- discovered_os_installed_pub_keys.rc == 1 or
discovered_os_gpg_key_check.rc == 1
ansible.builtin.fail:
msg: Installed GPG Keys do not meet expected values or expected keys are not installed
- name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated"
when: rhel9cis_rule_1_2_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.2.1.2
- NIST800-53R5_SI-2
block:
- name: "1.2.1.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: discovered_yum_repos
- name: "1.2.1.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos"
ansible.builtin.replace:
name: "{{ item.path }}"
regexp: ^gpgcheck\s*=\s*0
replace: "gpgcheck=1"
loop: "{{ discovered_yum_repos.files }}"
loop_control:
label: "{{ item.path }}"
- name: "1.2.1.3 | AUDIT | Ensure repo_gpgcheck is globally activated"
when:
- rhel9cis_rule_1_2_1_3
- rhel9cis_rule_enable_repogpg
- not rhel9cis_rhel_default_repo
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_1.2.1.3
- NIST800-53R5_SI-2
block:
- name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf"
ansible.builtin.lineinfile:
path: /etc/dnf/dnf.conf
regexp: '^repo_gpgcheck'
line: repo_gpgcheck=1
- name: "1.2.1.3 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: discovered_repo_files
- name: "1.2.1.3 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files"
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: ^repo_gpgcheck\s*=s*0
replace: repo_gpgcheck=1
loop: "{{ discovered_repo_files.files }}"
loop_control:
label: "{{ item.path }}"
- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured"
when: rhel9cis_rule_1_2_1_4
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_1.2.1.4
- NIST800-53R5_SI-2
vars:
warn_control_id: '1.2.1.4'
block:
- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Get repo list"
ansible.builtin.command: dnf repolist
changed_when: false
failed_when: false
check_mode: false
register: discovered_dnf_configured
- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Display repo list"
ansible.builtin.debug:
msg:
- "Warning!! Below are the configured repos. Please review and make sure all align with site policy"
- "{{ discovered_dnf_configured.stdout_lines }}"
- name: "1.2.1.4 | AUDIT | Ensure package manager repositories are configured | Warn Count"
ansible.builtin.import_tasks:
file: warning_facts.yml

View file

@ -0,0 +1,16 @@
---
- name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installed"
when:
- rhel9cis_rule_1_2_2_1
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.2.2.1
- NIST800-53R5_SI-2
ansible.builtin.package:
name: "*"
state: latest
notify: Change_requires_reboot

View file

@ -1,121 +0,0 @@
---
- name: "1.2.1 | AUDIT | Ensure GPG keys are configured"
block:
- name: "1.2.1 | AUDIT | Ensure GPG keys are configured | list installed pubkey keys"
ansible.builtin.shell: "rpm -qa | grep {{ os_gpg_key_pubkey_name }}"
changed_when: false
failed_when: false
register: os_installed_pub_keys
- name: "1.2.1 | AUDIT | Ensure GPG keys are configured | Query found keys"
ansible.builtin.shell: 'rpm -q --queryformat "%{PACKAGER} %{VERSION}\\n" {{ os_gpg_key_pubkey_name }} | grep "{{ os_gpg_key_pubkey_content }}"'
changed_when: false
failed_when: false
register: os_gpg_key_check
when: os_installed_pub_keys.rc == 0
- name: "1.2.1 | AUDIT | Ensure GPG keys are configured | expected keys fail"
ansible.builtin.fail:
msg: Installed GPG Keys do not meet expected values or expected keys are not installed
when:
- os_installed_pub_keys.rc == 1 or
os_gpg_key_check.rc == 1
when:
- rhel9cis_rule_1_2_1
- ansible_facts.distribution == "RedHat" or
ansible_facts.distribution == "Rocky" or
ansible_facts.distribution == "AlmaLinux"
tags:
- level1-server
- level1-workstation
- manual
- patch
- rule_1.2.1
- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated"
block:
- name: "1.2.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: yum_repos
- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos"
ansible.builtin.replace:
name: "{{ item.path }}"
regexp: ^gpgcheck\s*=\s*0
replace: "gpgcheck=1"
loop: "{{ yum_repos.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_1_2_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.2.2
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured"
block:
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Get repo list"
ansible.builtin.shell: dnf repolist
changed_when: false
failed_when: false
register: dnf_configured
check_mode: false
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Display repo list"
ansible.builtin.debug:
msg:
- "Warning!! Below are the configured repos. Please review and make sure all align with site policy"
- "{{ dnf_configured.stdout_lines }}"
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Warn Count"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '1.2.3'
when:
- rhel9cis_rule_1_2_3
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_1.2.3
- name: "1.2.4 | AUDIT | Ensure repo_gpgcheck is globally activated"
block:
- name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf"
ansible.builtin.lineinfile:
path: /etc/dnf/dnf.conf
regexp: '^repo_gpgcheck'
line: repo_gpgcheck=1
- name: "1.2.4 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: repo_files
- name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files"
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: ^repo_gpgcheck\s*=\s*0
replace: repo_gpgcheck=1
loop: "{{ repo_files.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_1_2_4
- rhel9cis_rule_enable_repogpg
- not rhel9cis_rhel_default_repo
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_1.2.4

View file

@ -0,0 +1,150 @@
---
- name: "1.3.1.1 | PATCH | Ensure SELinux is installed"
when:
- rhel9cis_rule_1_3_1_1
- not rhel9cis_selinux_disable
tags:
- level1-server
- level1-workstation
- patch
- rule_1.3.1.1
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.package:
name: libselinux
state: present
- name: "1.3.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration"
when:
- rhel9cis_rule_1_3_1_2
- not rhel9cis_selinux_disable
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.3.1.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.replace:
path: /etc/default/grub
regexp: '{{ item }}'
replace: ''
loop:
- selinux=0
- enforcing=0
ignore_errors: true # noqa ignore-errors
notify: Grub2cfg
# State set to enforcing because control 1.3.1.5 requires enforcing to be set
- name: "1.3.1.3 | PATCH | Ensure SELinux policy is configured"
when:
- rhel9cis_rule_1_3_1_3
- not rhel9cis_selinux_disable
tags:
- level1-server
- level1-workstation
- selinux
- patch
- rule_1.3.1.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
- name: "1.3.1.4 | PATCH | Ensure the SELinux state is not disabled"
when:
- rhel9cis_rule_1_3_1_4
- not rhel9cis_selinux_disable
tags:
- level1-server
- level1-workstation
- selinux
- patch
- rule_1.3.1.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
- name: "1.3.1.5 | PATCH | Ensure the SELinux state is enforcing"
when:
- rhel9cis_selinux_enforce == 'enforcing'
- rhel9cis_rule_1_3_1_5
- not rhel9cis_selinux_disable
tags:
- level2-server
- level2-workstation
- selinux
- patch
- rule_1.3.1.5
- NIST800-53R4_AC-3
- NIST800-53R4_SI-6
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: enforcing
- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist"
when:
- rhel9cis_rule_1_3_1_6
- not rhel9cis_selinux_disable
tags:
- level1-server
- level1-workstation
- audit
- services
- rule_1.3.1.6
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
vars:
warn_control_id: '1.3.1.6'
block:
- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services"
ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }'
register: discovered_unconf_services
failed_when: false
changed_when: false
- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services"
when: discovered_unconf_services.stdout | length > 0
ansible.builtin.debug:
msg: "Warning!! You have unconfined services: {{ discovered_unconf_services.stdout_lines }}"
- name: "1.3.1.6 | AUDIT | Ensure no unconfined services exist | warning count"
when: discovered_unconf_services.stdout | length > 0
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "1.3.1.7 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed"
when: rhel9cis_rule_1_3_1_7
tags:
- level1-server
- level1-workstation
- patch
- rule_1.3.1.7
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.package:
name: mcstrans
state: absent
- name: "1.3.1.8 | PATCH | Ensure SETroubleshoot is not installed"
when:
- rhel9cis_rule_1_3_1_8
- "'setroubleshoot' in ansible_facts.packages"
tags:
- level1-server
- selinux
- patch
- rule_1.3.1.8
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.package:
name: setroubleshoot
state: absent

View file

@ -1,78 +0,0 @@
---
- name: "1.3.1 | PATCH | Ensure AIDE is installed"
block:
- name: "1.3.1 | PATCH | Ensure AIDE is installed | Install AIDE"
ansible.builtin.package:
name: aide
state: present
- name: "1.3.1 | PATCH | Ensure AIDE is installed | Build AIDE DB"
ansible.builtin.shell: /usr/sbin/aide --init
args:
creates: /var/lib/aide/aide.db.new.gz
when: not ansible_check_mode
- name: "1.3.1 | PATCH | Ensure AIDE is installed | Wait for file before continuing"
ansible.builtin.wait_for:
path: /var/lib/aide/aide.db.new.gz
- name: "1.3.1 | PATCH | Ensure AIDE is installed | copy AIDE DB"
ansible.builtin.copy:
src: /var/lib/aide/aide.db.new.gz
dest: /var/lib/aide/aide.db.gz
remote_src: true
when:
- rhel9cis_config_aide
- rhel9cis_rule_1_3_1
tags:
- level1-server
- level1-workstation
- aide
- patch
- rule_1.3.1
- name: "1.3.2 | PATCH | Ensure filesystem integrity is regularly checked"
ansible.builtin.cron:
name: Run AIDE integrity check
cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}"
user: "{{ rhel9cis_aide_cron['cron_user'] }}"
minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}"
hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}"
day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}"
month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}"
weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}"
job: "{{ rhel9cis_aide_cron['aide_job'] }}"
when:
- rhel9cis_rule_1_3_2
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- aide
- file_integrity
- patch
- rule_1.3.2
- name: "1.3.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools"
ansible.builtin.blockinfile:
path: /etc/aide.conf
marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown"
block: |
/usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
validate: aide -D --config %s
when:
- rhel9cis_rule_1_3_3
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- aide
- file_integrity
- patch
- rule_1.3.3

View file

@ -1,44 +1,44 @@
---
- name: "1.4.1 | PATCH | Ensure bootloader password is set"
ansible.builtin.copy:
dest: /boot/grub2/user.cfg
content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy
owner: root
group: root
mode: '0600'
notify: Grub2cfg
when:
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
tags:
- level1-server
- level1-workstation
- grub
- patch
- rule_1.4.1
- level1-server
- level1-workstation
- grub
- patch
- rule_1.4.1
- NIST800-53R5_AC-3
ansible.builtin.copy:
dest: /boot/grub2/user.cfg
content: "GRUB2_PASSWORD={{ rhel9cis_bootloader_password_hash }}" # noqa template-instead-of-copy
owner: root
group: root
mode: 'go-rwx'
notify: Grub2cfg
- name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured"
block:
- name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured"
ansible.builtin.file:
path: "/boot/grub2/{{ item.path }}"
owner: root
group: root
mode: "{{ item.mode }}"
state: touch
modification_time: preserve
access_time: preserve
loop:
- { path: 'grub.cfg', mode: '0700' }
- { path: 'grubenv', mode: '0600' }
- { path: 'user.cfg', mode: '0600' }
when:
- rhel9cis_rule_1_4_2
when: rhel9cis_rule_1_4_2
tags:
- level1-server
- level1-workstation
- grub
- patch
- rule_1.4.2
- level1-server
- level1-workstation
- grub
- patch
- rule_1.4.2
- NIST800-53R5_AC-3
block:
- name: "1.4.2 | PATCH | Ensure permissions on bootloader config are configured"
ansible.builtin.file:
path: "/boot/grub2/{{ item.path }}"
owner: root
group: root
mode: "{{ item.mode }}"
state: touch
modification_time: preserve
access_time: preserve
loop:
- { path: 'grub.cfg', mode: '0700' }
- { path: 'grubenv', mode: 'go-rwx' }
- { path: 'user.cfg', mode: 'go-rwx' }

View file

@ -1,48 +1,66 @@
---
- name: "1.5.1 | PATCH | Ensure core dump storage is disabled"
ansible.builtin.lineinfile:
path: /etc/systemd/coredump.conf
regexp: '^Storage\s*=\s*(?!none).*'
line: 'Storage=none'
notify: Systemd daemon reload
when:
- rhel9cis_rule_1_5_1
- systemd_coredump.stat.exists
- name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
when: rhel9cis_rule_1_5_1
tags:
- level1-server
- level1-workstation
- patch
- rule_1.5.1
- name: "1.5.2 | PATCH | Ensure core dump backtraces are disabled"
ansible.builtin.lineinfile:
path: /etc/systemd/coredump.conf
regexp: '^ProcessSizeMax\s*=\s*.*[1-9].*'
line: 'ProcessSizeMax=0'
when:
- rhel9cis_rule_1_5_2
tags:
- level1-server
- level1-workstation
- patch
- sysctl
- rule_1.5.2
- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
- level1-server
- level1-workstation
- patch
- sysctl
- rule_1.5.1
- NIST800-53R5_CM-6
- NIST800-53R5_CM-6.1
block:
- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
- name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
- name: "1.5.3 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf"
when:
- rhel9cis_rule_1_5_3
- name: "1.5.1 | PATCH | Ensure address space layout randomization (ASLR) is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf"
- name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted"
when: rhel9cis_rule_1_5_2
tags:
- level1-server
- level1-workstation
- patch
- sysctl
- rule_1.5.3
- level1-server
- level1-workstation
- patch
- sysctl
- rule_1.5.2
block:
- name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
- name: "1.5.2 | PATCH | Ensure ptrace_scope is restricted"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-kernel_sysctl.conf"
- name: "1.5.3 | PATCH | Ensure core dump backtraces are disabled"
when: rhel9cis_rule_1_5_3
tags:
- level1-server
- level1-workstation
- patch
- sysctl
- rule_1.5.3
- NIST800-53R5_CM-6b
ansible.builtin.lineinfile:
path: /etc/systemd/coredump.conf
regexp: '(?#)^ProcessSizeMax\s*=\s*.*[1-9].*$'
line: 'ProcessSizeMax=0'
- name: "1.5.4 | PATCH | Ensure core dump storage is disabled"
when:
- rhel9cis_rule_1_5_4
- prelim_systemd_coredump.stat.exists
tags:
- level1-server
- level1-workstation
- patch
- rule_1.5.4
ansible.builtin.lineinfile:
path: /etc/systemd/coredump.conf
regexp: '^Storage\s*=\s*(?!none).*'
line: 'Storage=none'
notify: Systemd daemon reload

View file

@ -1,130 +0,0 @@
---
- name: "1.6.1.1 | PATCH | Ensure SELinux is installed"
ansible.builtin.package:
name: libselinux
state: present
when:
- rhel9cis_rule_1_6_1_1
tags:
- level1-server
- level1-workstation
- patch
- rule_1.6.1.1
- name: "1.6.1.2 | PATCH | Ensure SELinux is not disabled in bootloader configuration"
ansible.builtin.replace:
path: /etc/default/grub
regexp: '{{ item }}'
replace: ''
loop:
- selinux=0
- enforcing=0
register: selinux_grub_patch
ignore_errors: true # noqa ignore-errors
notify: Grub2cfg
when:
- rhel9cis_rule_1_6_1_2
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.6.1.2
# State set to enforcing because control 1.6.1.5 requires enforcing to be set
- name: "1.6.1.3 | PATCH | Ensure SELinux policy is configured"
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
when:
- rhel9cis_rule_1_6_1_3
tags:
- level1-server
- level1-workstation
- selinux
- patch
- rule_1.6.1.3
- name: "1.6.1.4 | PATCH | Ensure the SELinux state is not disabled"
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: "{{ rhel9cis_selinux_enforce }}"
when:
- rhel9cis_rule_1_6_1_4
tags:
- level1-server
- level1-workstation
- selinux
- patch
- rule_1.6.1.4
- name: "1.6.1.5 | PATCH | Ensure the SELinux state is enforcing"
ansible.posix.selinux:
conf: /etc/selinux/config
policy: "{{ rhel9cis_selinux_pol }}"
state: enforcing
when:
- rhel9cis_selinux_enforce == 'enforcing'
- rhel9cis_rule_1_6_1_5
tags:
- level2-server
- level2-workstation
- selinux
- patch
- rule_1.6.1.5
- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist"
block:
- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Find the unconfined services"
ansible.builtin.shell: ps -eZ | grep unconfined_service_t | egrep -vw "tr|ps|egrep|bash|awk" | tr ':' ' ' | awk '{ print $NF }'
register: rhelcis_1_6_1_6_unconf_services
failed_when: false
changed_when: false
- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | Message on unconfined services"
ansible.builtin.debug:
msg: "Warning!! You have unconfined services: {{ rhelcis_1_6_1_6_unconf_services.stdout_lines }}"
when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0
- name: "1.6.1.6 | AUDIT | Ensure no unconfined services exist | warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
when: rhelcis_1_6_1_6_unconf_services.stdout | length > 0
vars:
warn_control_id: '1.6.1.6'
when:
- rhel9cis_rule_1_6_1_6
tags:
- level1-server
- level1-workstation
- audit
- services
- rule_1.6.1.6
- name: "1.6.1.7 | PATCH | Ensure SETroubleshoot is not installed"
ansible.builtin.package:
name: setroubleshoot
state: absent
when:
- rhel9cis_rule_1_6_1_7
- "'setroubleshoot' in ansible_facts.packages"
tags:
- level1-server
- selinux
- patch
- rule_1.6.1.7
- name: "1.6.1.8 | PATCH | Ensure the MCS Translation Service (mcstrans) is not installed"
ansible.builtin.package:
name: mcstrans
state: absent
when:
- rhel9cis_rule_1_6_1_8
tags:
- level1-server
- level1-workstation
- patch
- rule_1.6.1.8

View file

@ -0,0 +1,185 @@
---
- name: "1.6.1 | AUDIT | Ensure system-wide crypto policy is not legacy"
when: rhel9cis_rule_1_6_1
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.1
- NIST800-53R5_SC-6
ansible.builtin.debug:
msg: "Captured in prelim to ensure not LEGACY. Runs handler to update"
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "1.6.2 | PATCH | Ensure system wide crypto policy is not set in sshd configuration"
when: rhel9cis_rule_1_6_2
tags:
- level1-server
- level1-workstation
- automated
- patch
- rule_1.6.2
- NIST800-53R5_SC-8
- NIST800-53R5_IA-5
- NIST800-53R5_AC-17- NIST800-53R5_SC-6
ansible.builtin.lineinfile:
path: /etc/sysconfig/sshd
regexp: ^CRYPTO_POLICY\s*=
state: absent
notify: Restart sshd
- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | Add submodule exclusion"
when:
- rhel9cis_rule_1_6_3
- "'NO-SHA1' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.3
- NIST800-53R5_SC-6
block:
- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
register: discovered_no_sha1_template
- name: "1.6.3 | PATCH | Ensure system wide crypto policy disables sha1 hash and signature support | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SHA1' }}"
changed_when: discovered_no_sha1_template is changed # noqa: no-handler
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits"
when:
- rhel9cis_rule_1_6_4
- "'NO-WEAKMAC' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.4
- NIST800-53R5_SC-6
block:
- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-WEAKMAC.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
register: discovered_no_weakmac_template
- name: "1.6.4 | PATCH | Ensure system wide crypto policy disables macs less than 128 bits | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-WEAKMAC' }}"
changed_when: discovered_no_weakmac_template is changed # noqa: no-handler
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh"
when:
- rhel9cis_rule_1_6_5
- "'NO-SSHCBC' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.5
- NIST800-53R5_SC-6
block:
- name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SSHCBC.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SSHCBC.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
register: discovered_no_sshcbc_template
- name: "1.6.5 | PATCH | Ensure system wide crypto policy disables cbc for ssh | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHCBC' }}"
changed_when: discovered_no_sshcbc_template is changed # noqa: no-handler
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh"
when:
- rhel9cis_rule_1_6_6
- "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.6
- NIST800-53R5_SC-6
block:
- name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
register: discovered_no_sshweakciphers_template
- name: "1.6.6 | PATCH | Ensure system wide crypto policy disables chacha20-poly1305 for ssh | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKCIPHERS' }}"
changed_when: discovered_no_sshweakciphers_template is changed # noqa: no-handler
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh"
when:
- rhel9cis_rule_1_6_7
- "'NO-SSHETM' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_1.6.7
- NIST800-53R5_SC-6
block:
- name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SSHETM.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SSHETM.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
register: discovered_no_sshetm_template
- name: "1.6.7 | PATCH | Ensure system wide crypto policy disables EtM for ssh | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHETM' }}"
changed_when: discovered_no_sshetm_template is changed # noqa: no-handler
notify:
- Update Crypto Policy
- Set Crypto Policy

View file

@ -1,93 +1,102 @@
---
- name: "1.7.1 | PATCH | Ensure message of the day is configured properly"
ansible.builtin.template:
src: etc/motd.j2
dest: /etc/motd
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_1
when: rhel9cis_rule_1_7_1
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.7.1
- level1-server
- level1-workstation
- banner
- patch
- rule_1.7.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-3
- NIST800-53R5_CM-6
ansible.builtin.template:
src: etc/motd.j2
dest: /etc/motd
owner: root
group: root
mode: 'u-x,go-wx'
- name: "1.7.2 | PATCH | Ensure local login warning banner is configured properly"
ansible.builtin.template:
src: etc/issue.j2
dest: /etc/issue
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_2
when: rhel9cis_rule_1_7_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.7.2
- level1-server
- level1-workstation
- patch
- rule_1.7.2
- NIST800-53R5_CM-1
- NIST800-53R5_CM-3
- NIST800-53R5_CM-6
ansible.builtin.template:
src: etc/issue.j2
dest: /etc/issue
owner: root
group: root
mode: 'go-wx'
- name: "1.7.3 | PATCH | Ensure remote login warning banner is configured properly"
ansible.builtin.template:
src: etc/issue.net.j2
dest: /etc/issue.net
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_3
when: rhel9cis_rule_1_7_3
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.7.3
- level1-server
- level1-workstation
- banner
- patch
- rule_1.7.3
- NIST800-53R5_CM-1
- NIST800-53R5_CM-3
- NIST800-53R5_CM-6
ansible.builtin.template:
src: etc/issue.net.j2
dest: /etc/issue.net
owner: root
group: root
mode: 'go-wx'
- name: "1.7.4 | PATCH | Ensure permissions on /etc/motd are configured"
ansible.builtin.file:
path: /etc/motd
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_4
when: rhel9cis_rule_1_7_4
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.4
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.4
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/motd
owner: root
group: root
mode: 'go-wx'
- name: "1.7.5 | PATCH | Ensure permissions on /etc/issue are configured"
ansible.builtin.file:
path: /etc/issue
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_5
when: rhel9cis_rule_1_7_5
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.5
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.5
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/issue
owner: root
group: root
mode: 'go-wx'
- name: "1.7.6 | PATCH | Ensure permissions on /etc/issue.net are configured"
ansible.builtin.file:
path: /etc/issue.net
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_1_7_6
when: rhel9cis_rule_1_7_6
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.6
- level1-server
- level1-workstation
- perms
- patch
- rule_1.7.6
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/issue.net
owner: root
group: root
mode: 'go-wx'

View file

@ -1,264 +1,264 @@
---
- name: "1.8.1 | PATCH | Ensure GNOME Display Manager is removed"
ansible.builtin.package:
name: gdm
state: absent
when:
- rhel9cis_rule_1_8_1
- "'gdm' in ansible_facts.packages"
- not rhel9cis_gui
- rhel9cis_rule_1_8_1
- "'gdm' in ansible_facts.packages"
- not rhel9cis_gui
tags:
- level2-server
- patch
- gui
- gdm
- rule_1.8.1
- level2-server
- patch
- gui
- gdm
- rule_1.8.1
ansible.builtin.package:
name: gdm
state: absent
- name: "1.8.2 | PATCH | Ensure GDM login banner is configured"
block:
- name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile"
ansible.builtin.lineinfile:
path: /etc/dconf/profile/gdm
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: '0644'
notify: Reload dconf
loop:
- { regexp: 'user-db', line: 'user-db:user' }
- { regexp: 'system-db', line: 'system-db:gdm' }
- { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' }
- name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile"
ansible.builtin.template:
src: etc/dconf/db/gdm.d/01-banner-message.j2
dest: /etc/dconf/db/gdm.d/01-banner-message
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_2
- rhel9cis_gui
- rhel9cis_rule_1_8_2
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- gdm
- rule_1.8.2
- level1-server
- level1-workstation
- patch
- gui
- gdm
- rule_1.8.2
block:
- name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile"
ansible.builtin.lineinfile:
path: /etc/dconf/profile/gdm
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
loop:
- { regexp: 'user-db', line: 'user-db:user' }
- { regexp: 'system-db', line: 'system-db:gdm' }
- { regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults' }
- name: "1.8.2 | PATCH | Ensure GDM login banner is configured | gdm profile"
ansible.builtin.template:
src: etc/dconf/db/gdm.d/01-banner-message.j2
dest: /etc/dconf/db/gdm.d/01-banner-message
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled"
when:
- rhel9cis_rule_1_8_3
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.3
ansible.builtin.lineinfile:
path: "{{ item.file }}"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: '0644'
path: "{{ item.file }}"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
loop:
- { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' }
- { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' }
- { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'}
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' }
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' }
when:
- rhel9cis_rule_1_8_3
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.3
- { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' }
- { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' }
- { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'}
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' }
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' }
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle"
block:
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile"
ansible.builtin.lineinfile:
path: /etc/dconf/profile/user
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: '0644'
loop:
- { regexp: '^user-db', line: 'user-db:user' }
- { regexp: '^system-db', line: 'system-db:local' }
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: '0755'
state: directory
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file"
ansible.builtin.template:
src: etc/dconf/db/00-screensaver.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-screensaver"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_4
- rhel9cis_gui
- rhel9cis_rule_1_8_4
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.4
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.4
block:
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | User profile"
ansible.builtin.lineinfile:
path: /etc/dconf/profile/user
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: 'go-wx'
loop:
- { regexp: '^user-db', line: 'user-db:user' }
- { regexp: '^system-db', line: 'system-db:local' }
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make db directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: 'go-w'
state: directory
- name: "1.8.4 | PATCH | Ensure GDM screen locks when the user is idle | Make conf file"
ansible.builtin.template:
src: etc/dconf/db/00-screensaver.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-screensaver"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden"
block:
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: '0755'
state: directory
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file"
ansible.builtin.template:
src: etc/dconf/db/00-screensaver_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver_lock"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_5
- rhel9cis_gui
- rhel9cis_rule_1_8_5
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.5
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.5
block:
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 'go-w'
state: directory
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file"
ansible.builtin.template:
src: etc/dconf/db/00-screensaver_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver_lock"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.6 | PATCH | Ensure GDM automatic mounting of removable media is disabled"
ansible.builtin.template:
src: etc/dconf/db/00-media-automount.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_6
- rhel9cis_gui
- rhel9cis_rule_1_8_6
- rhel9cis_gui
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.6
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.6
ansible.builtin.template:
src: etc/dconf/db/00-media-automount.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-automount"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden"
block:
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: '0755'
state: directory
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file"
ansible.builtin.template:
src: etc/dconf/db/00-automount_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_7
- rhel9cis_gui
- rhel9cis_rule_1_8_7
- rhel9cis_gui
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.7
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.7
block:
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 'go-w'
state: directory
- name: "1.8.7 | PATCH | Ensure GDM disabling automatic mounting of removable media is not overridden | Make lock file"
ansible.builtin.template:
src: etc/dconf/db/00-automount_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-automount_lock"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled"
block:
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: '0755'
state: directory
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file"
ansible.builtin.template:
src: etc/dconf/db/00-media-autorun.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_8
- rhel9cis_gui
- rhel9cis_rule_1_8_8
- rhel9cis_gui
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.8
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.8
block:
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d"
owner: root
group: root
mode: 'go-w'
state: directory
- name: "1.8.8 | PATCH | Ensure GDM autorun-never is enabled | Make conf file"
ansible.builtin.template:
src: etc/dconf/db/00-media-autorun.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/00-media-autorun"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden"
block:
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: '0755'
state: directory
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile"
ansible.builtin.template:
src: etc/dconf/db/00-autorun_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock"
owner: root
group: root
mode: '0644'
notify: Reload dconf
when:
- rhel9cis_rule_1_8_9
- rhel9cis_gui
- rhel9cis_rule_1_8_9
- rhel9cis_gui
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.9
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.9
block:
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 'go-w'
state: directory
- name: "1.8.9 | PATCH | Ensure GDM autorun-never is not overridden | Make lockfile"
ansible.builtin.template:
src: etc/dconf/db/00-autorun_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-autorun_lock"
owner: root
group: root
mode: 'go-wx'
notify: Reload dconf
- name: "1.8.10 | PATCH | Ensure XDMCP is not enabled"
ansible.builtin.lineinfile:
path: /etc/gdm/custom.conf
regexp: 'Enable=true'
state: absent
when:
- rhel9cis_rule_1_8_10
- rhel9cis_gui
- rhel9cis_rule_1_8_10
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.10
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.10
ansible.builtin.lineinfile:
path: /etc/gdm/custom.conf
regexp: 'Enable=true'
state: absent

View file

@ -1,14 +0,0 @@
---
- name: "1.9 | PATCH | Ensure updates, patches, and additional security software are installed"
ansible.builtin.package:
name: "*"
state: latest
notify: Change_requires_reboot
when:
- rhel9cis_rule_1_9
tags:
- level1-server
- level1-workstation
- patch
- rule_1.9

View file

@ -2,76 +2,64 @@
- name: "SECTION | 1.1.1.x | Disable unused filesystems"
ansible.builtin.import_tasks:
file: cis_1.1.1.x.yml
file: cis_1.1.1.x.yml
- name: "SECTION | 1.1.2.x | Configure /tmp"
- name: "SECTION | 1.1.2.1.x | Configure /tmp"
ansible.builtin.import_tasks:
file: cis_1.1.2.x.yml
file: cis_1.1.2.1.x.yml
- name: "SECTION | 1.1.3.x | Configure /var"
- name: "SECTION | 1.1.2.2.x | Configure /dev/shm"
ansible.builtin.import_tasks:
file: cis_1.1.3.x.yml
file: cis_1.1.2.2.x.yml
- name: "SECTION | 1.1.4.x | Configure /var/tmp"
- name: "SECTION | 1.1.2.3.x | Configure /home"
ansible.builtin.import_tasks:
file: cis_1.1.4.x.yml
file: cis_1.1.2.3.x.yml
- name: "SECTION | 1.1.5.x | Configure /var/log"
- name: "SECTION | 1.1.2.4.x | Configure /var"
ansible.builtin.import_tasks:
file: cis_1.1.5.x.yml
file: cis_1.1.2.4.x.yml
- name: "SECTION | 1.1.6.x | Configure /var/log/audit"
- name: "SECTION | 1.1.2.5.x | Configure /var/tmp"
ansible.builtin.import_tasks:
file: cis_1.1.6.x.yml
file: cis_1.1.2.5.x.yml
- name: "SECTION | 1.1.7.x | Configure /home"
- name: "SECTION | 1.1.2.6.x | Configure /var/log"
ansible.builtin.import_tasks:
file: cis_1.1.7.x.yml
file: cis_1.1.2.6.x.yml
- name: "SECTION | 1.1.8.x | Configure /dev/shm"
- name: "SECTION | 1.1.2.7.x | Configure /var/log/audit"
ansible.builtin.import_tasks:
file: cis_1.1.8.x.yml
file: cis_1.1.2.7.x.yml
- name: "SECTION | 1.1.x | Disable various mounting"
- name: "SECTION | 1.2.1.x | Configure Package Repositories"
ansible.builtin.import_tasks:
file: cis_1.1.x.yml
file: cis_1.2.1.x.yml
- name: "SECTION | 1.2 | Configure Software Updates"
- name: "SECTION | 1.2.2.x | Configure Package Updates"
ansible.builtin.import_tasks:
file: cis_1.2.x.yml
file: cis_1.2.2.x.yml
- name: "SECTION | 1.3 | Filesystem Integrity Checking"
ansible.builtin.import_tasks:
file: cis_1.3.x.yml
when: rhel9cis_config_aide
- name: "SECTION | 1.3.1 | Configure SELinux"
ansible.builtin.include_tasks:
file: cis_1.3.1.x.yml
- name: "SECTION | 1.4 | Secure Boot Settings"
- name: "SECTION | 1.4 | Configure Bootloader"
ansible.builtin.import_tasks:
file: cis_1.4.x.yml
file: cis_1.4.x.yml
- name: "SECTION | 1.5 | Additional Process Hardening"
ansible.builtin.import_tasks:
file: cis_1.5.x.yml
file: cis_1.5.x.yml
- name: "SECTION | 1.6 | Mandatory Access Control"
ansible.builtin.include_tasks:
file: cis_1.6.1.x.yml
when: not rhel9cis_selinux_disable
- name: "SECTION | 1.6 | Configure system wide crypto policy"
ansible.builtin.import_tasks:
file: cis_1.6.x.yml
- name: "SECTION | 1.7 | Command Line Warning Banners"
ansible.builtin.import_tasks:
file: cis_1.7.x.yml
file: cis_1.7.x.yml
- name: "SECTION | 1.8 | Gnome Display Manager"
ansible.builtin.import_tasks:
file: cis_1.8.x.yml
- name: "SECTION | 1.9 | Updates and Patches"
ansible.builtin.import_tasks:
file: cis_1.9.yml
- name: "SECTION | 1.10 | Crypto policies"
ansible.builtin.include_tasks:
file: cis_1.10.yml
when:
- not system_is_ec2
file: cis_1.8.x.yml

View file

@ -1,40 +1,695 @@
---
- name: "2.1.1 | PATCH | Ensure time synchronization is in use"
ansible.builtin.package:
name: chrony
state: present
- name: "2.1.1 | PATCH | Ensure autofs services are not in use"
when:
- rhel9cis_rule_2_1_1
- not system_is_container
- rhel9cis_rule_2_1_1
- "'autofs' in ansible_facts.packages"
tags:
- level1-server
- level1-workstation
- patch
- rule_2.1.1
- name: "2.1.2 | PATCH | Ensure chrony is configured"
- level1-server
- level2-workstation
- automated
- patch
- NIST800-53R5_SI-3
- NIST800-53R5_MP-7
- rule_2.1.1
block:
- name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration"
ansible.builtin.template:
src: etc/chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: '0644'
- name: "2.1.1 | PATCH | Ensure autofs services are not in use | Remove Package"
when:
- not rhel9cis_autofs_services
- not rhel9cis_autofs_mask
ansible.builtin.package:
name: autofs
state: absent
- name: "2.1.2 | PATCH | Ensure chrony is configured | modify /etc/sysconfig/chronyd | 1"
ansible.builtin.lineinfile:
path: /etc/sysconfig/chronyd
regexp: "^(#)?OPTIONS"
line: "OPTIONS=\"-u chrony\""
create: true
mode: '0644'
when:
- rhel9cis_rule_2_1_2
- not system_is_container
- name: "2.1.1 | PATCH | Ensure autofs services are not in use | Mask service"
when:
- not rhel9cis_autofs_services
- rhel9cis_autofs_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: autofs
enabled: false
state: stopped
masked: true
- name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use"
when: rhel9cis_rule_2_1_2
tags:
- level1-server
- level1-workstation
- patch
- rule_2.1.2
- level1-server
- level2-workstation
- automated
- patch
- avahi
- NIST800-53R5_SI-4
- rule_2.1.2
block:
- name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use | Remove package"
when:
- not rhel9cis_avahi_server
- not rhel9cis_avahi_mask
ansible.builtin.package:
name:
- avahi-autoipd
- avahi
state: absent
- name: "2.1.2 | PATCH | Ensure avahi daemon services are not in use | Mask service"
when:
- not rhel9cis_avahi_server
- rhel9cis_avahi_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- avahi-daemon.socket
- avahi-daemon.service
- name: "2.1.3 | PATCH | Ensure dhcp server services are not in use"
when: rhel9cis_rule_2_1_3
tags:
- level1-server
- level1-workstation
- automated
- patch
- dhcp
- NIST800-53R5_CM-7
- rule_2.1.3
block:
- name: "2.1.3 | PATCH | Ensure dhcp server services are not in use | Remove package"
when:
- not rhel9cis_dhcp_server
- not rhel9cis_dhcp_mask
ansible.builtin.package:
name: dhcp-server
state: absent
- name: "2.1.3 | PATCH | Ensure dhcp server services are not in use | Mask service"
when:
- not rhel9cis_dhcp_server
- rhel9cis_dhcp_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- dhcpd.service
- dhcpd6.service
- name: "2.1.4 | PATCH | Ensure dns server services are not in use"
when: rhel9cis_rule_2_1_4
tags:
- level1-server
- level1-workstation
- automated
- patch
- dns
- NIST800-53R5_CM-7
- rule_2.1.4
block:
- name: "2.1.4 | PATCH | Ensure dns server services are not in use | Remove package"
when:
- not rhel9cis_dns_server
- not rhel9cis_dns_mask
ansible.builtin.package:
name: bind
state: absent
- name: "2.1.4 | PATCH | Ensure dns server services are not in use | Mask service"
when:
- not rhel9cis_dns_server
- rhel9cis_dns_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: named.service
enabled: false
state: stopped
masked: true
- name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use"
when: rhel9cis_rule_2_1_5
tags:
- level1-server
- level1-workstation
- automated
- patch
- dns
- NIST800-53R5_CM-7
- rule_2.1.5
block:
- name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use | Remove package"
when:
- not rhel9cis_dnsmasq_server
- not rhel9cis_dnsmasq_mask
ansible.builtin.package:
name: dnsmasq
state: absent
- name: "2.1.5 | PATCH | Ensure dnsmasq server services are not in use | Mask service"
when:
- not rhel9cis_dnsmasq_server
- rhel9cis_dnsmasq_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: dnsmasq.service
enabled: false
state: stopped
masked: true
- name: "2.1.6 | PATCH | Ensure samba file server services are not in use"
when: rhel9cis_rule_2_1_6
tags:
- level1-server
- level1-workstation
- automated
- patch
- samba
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.6
block:
- name: "2.1.6 | PATCH | Ensure samba file server services are not in use | Remove package"
when:
- not rhel9cis_samba_server
- not rhel9cis_samba_mask
ansible.builtin.package:
name: samba
state: absent
- name: "2.1.6 | PATCH | Ensure samba file server services are not in use | Mask service"
when:
- not rhel9cis_samba_server
- rhel9cis_samba_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: smb.service
enabled: false
state: stopped
masked: true
- name: "2.1.7 | PATCH | Ensure ftp server services are not in use"
when: rhel9cis_rule_2_1_7
tags:
- level1-server
- level1-workstation
- automation
- patch
- ftp
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.7
block:
- name: "2.1.7 | PATCH | Ensure ftp server services are not in use | Remove package"
when:
- not rhel9cis_ftp_server
- not rhel9cis_ftp_mask
ansible.builtin.package:
name: vsftpd
state: absent
- name: "2.1.7 | PATCH | Ensure ftp server services are not in use | Mask service"
when:
- not rhel9cis_ftp_server
- rhel9cis_ftp_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: vsftpd.service
enabled: false
state: stopped
masked: true
- name: "2.1.8 | PATCH | Ensure message access server services are not in use"
when: rhel9cis_rule_2_1_8
tags:
- level1-server
- level1-workstation
- automated
- patch
- dovecot
- imap
- pop3
- NIST800-53R5_CM-7
- rule_2.1.8
block:
- name: "2.1.8 | PATCH | Ensure message access server services are not in use | Remove package"
when:
- not rhel9cis_message_server
- not rhel9cis_message_mask
ansible.builtin.package:
name:
- dovecot
- cyrus-imapd
state: absent
- name: "2.1.8 | PATCH | Ensure message access server services are not in use | Mask service"
when:
- not rhel9cis_message_server
- rhel9cis_message_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- "dovecot.socket"
- "dovecot.service"
- "cyrus-imapd.service"
- name: "2.1.9 | PATCH | Ensure network file system services are not in use"
when: rhel9cis_rule_2_1_9
tags:
- level1-server
- level1-workstation
- automated
- patch
- nfs
- services
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.9
block:
- name: "2.1.9 | PATCH | Ensure network file system services are not in use | Remove package"
when:
- not rhel9cis_nfs_server
- not rhel9cis_nfs_mask
ansible.builtin.package:
name: nfs-utils
state: absent
- name: "2.1.9 | PATCH | Ensure network file system services are not in use | Mask service"
when:
- not rhel9cis_nfs_server
- rhel9cis_nfs_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: nfs-server.service
enabled: false
state: stopped
masked: true
- name: "2.1.10 | PATCH | Ensure nis server services are not in use"
when: rhel9cis_rule_2_1_10
tags:
- level1-server
- level1-workstation
- automated
- patch
- nis
- NIST800-53R5_CM-7
- rule_2.1.10
notify: Systemd_daemon_reload
block:
- name: "2.1.10 | PATCH | Ensure nis server services are not in use | Remove package"
when:
- not rhel9cis_nis_server
- not rhel9cis_nis_mask
ansible.builtin.package:
name: ypserv
state: absent
- name: "2.1.10 | PATCH | Ensure nis server services are not in use | Mask service"
when:
- not rhel9cis_nis_server
- rhel9cis_nis_mask
ansible.builtin.systemd:
name: ypserv.service
enabled: false
state: stopped
masked: true
- name: "2.1.11 | PATCH | Ensure print server services are not in use"
when: rhel9cis_rule_2_1_11
tags:
- level1-server
- automated
- patch
- cups
- NIST800-53R5_CM-7
- rule_2.1.11
block:
- name: "2.1.11 | PATCH | Ensure print server services are not in use | Remove package"
when:
- not rhel9cis_print_server
- not rhel9cis_print_mask
ansible.builtin.package:
name: cups
state: absent
- name: "2.1.11 | PATCH | Ensure print server services are not in use | Mask service"
when:
- not rhel9cis_print_server
- rhel9cis_print_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- "cups.socket"
- "cups.service"
- name: "2.1.12 | PATCH | Ensure rpcbind services are not in use"
when: rhel9cis_rule_2_1_12
tags:
- level1-server
- level1-workstation
- automated
- patch
- rpc
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.12
block:
- name: "2.1.12 | PATCH | Ensure rpcbind services are not in use | Remove package"
when:
- not rhel9cis_rpc_server
- not rhel9cis_rpc_mask
ansible.builtin.package:
name: rpcbind
state: absent
- name: "2.1.12 | PATCH | Ensure rpcbind services are not in use | Mask service"
when:
- not rhel9cis_rpc_server
- rhel9cis_rpc_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- rpcbind.service
- rpcbind.socket
- name: "2.1.13 | PATCH | Ensure rsync services are not in use"
when: rhel9cis_rule_2_1_13
tags:
- level1-server
- level1-workstation
- automated
- patch
- rsync
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.13
block:
- name: "2.1.13 | PATCH | Ensure rsync services are not in use | Remove package"
when:
- not rhel9cis_rsync_server
- not rhel9cis_rsync_mask
ansible.builtin.package:
name: rsync-daemon
state: absent
- name: "2.1.13 | PATCH | Ensure rsync services are not in use | Mask service"
when:
- not rhel9cis_rsync_server
- rhel9cis_rsync_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- 'rsyncd.socket'
- 'rsyncd.service'
- name: "2.1.14 | PATCH | Ensure snmp services are not in use"
when: rhel9cis_rule_2_1_14
tags:
- level1-server
- level1-workstation
- automation
- patch
- snmp
- NIST800-53R5_CM-7
- rule_2.1.14
block:
- name: "2.1.14 | PATCH | Ensure snmp services are not in use | Remove package"
when:
- not rhel9cis_snmp_server
- not rhel9cis_snmp_mask
ansible.builtin.package:
name: net-snmp
state: absent
- name: "2.1.14 | PATCH | Ensure snmp services are not in use | Mask service"
when:
- not rhel9cis_snmp_server
- rhel9cis_snmp_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: snmpd.service
enabled: false
state: stopped
masked: true
- name: "2.1.15 | PATCH | Ensure telnet server services are not in use"
when: rhel9cis_rule_2_1_15
tags:
- level1-server
- level1-workstation
- automated
- patch
- telnet
- NIST800-53R5_CM-7
- NIST800-53R5_CM-11
- rule_2.1.15
block:
- name: "2.1.15 | PATCH | Ensure telnet server services are not in use | Remove package"
when:
- not rhel9cis_telnet_server
- not rhel9cis_telnet_mask
ansible.builtin.package:
name: telnet-server
state: absent
- name: "2.1.15 | PATCH | Ensure telnet server services are not in use | Mask service"
when:
- not rhel9cis_telnet_server
- rhel9cis_telnet_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: telnet.socket
enabled: false
state: stopped
masked: true
- name: "2.1.16 | PATCH | Ensure tftp server services are not in use"
when: rhel9cis_rule_2_1_16
tags:
- level1-server
- level1-workstation
- automated
- patch
- tftp
- NIST800-53R5_CM-7
- rule_2.1.16
block:
- name: "2.1.16 | PATCH | Ensure tftp server services are not in use | Remove package"
when:
- not rhel9cis_tftp_server
- not rhel9cis_tftp_mask
ansible.builtin.package:
name: tftp-server
state: absent
- name: "2.1.16 | PATCH | Ensure tftp server services are not in use | Mask service"
when:
- not rhel9cis_tftp_server
- rhel9cis_tftp_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: "{{ item }}"
enabled: false
state: stopped
masked: true
loop:
- 'tftp.socket'
- 'tftp.service'
- name: "2.1.17 | PATCH | Ensure web proxy server services are not in use"
when: rhel9cis_rule_2_1_17
tags:
- level1-server
- level1-workstation
- automation
- patch
- squid
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- rule_2.1.17
block:
- name: "2.1.17 | PATCH | Ensure web proxy server services are not in use | Remove package"
when:
- not rhel9cis_squid_server
- not rhel9cis_squid_mask
ansible.builtin.package:
name: squid
state: absent
- name: "2.1.17 | PATCH | Ensure web proxy server services are not in use | Mask service"
when:
- not rhel9cis_squid_server
- rhel9cis_squid_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: squid.service
enabled: false
state: stopped
masked: true
- name: "2.1.18 | PATCH | Ensure web server services are not in use"
when: rhel9cis_rule_2_1_18
tags:
- level1-server
- level1-workstation
- automated
- patch
- httpd
- nginx
- webserver
- NIST800-53R5_CM-7
- rule_2.1.18
block:
- name: "2.1.18 | PATCH | Ensure web server services are not in use | Remove httpd server"
when:
- not rhel9cis_httpd_server
- not rhel9cis_httpd_mask
ansible.builtin.package:
name: httpd
state: absent
- name: "2.1.18 | PATCH | Ensure web server services are not in use | Remove nginx server"
when:
- not rhel9cis_nginx_server
- not rhel9cis_nginx_mask
ansible.builtin.package:
name: nginx
state: absent
- name: "2.1.18 | PATCH | Ensure web server services are not in use | Mask httpd service"
when:
- not rhel9cis_httpd_server
- rhel9cis_httpd_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: httpd.service
enabled: false
state: stopped
masked: true
- name: "2.1.18 | PATCH | Ensure web server services are not in use | Mask nginx service"
when:
- not rhel9cis_nginx_server
- rhel9cis_nginx_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: ngnix.service
enabled: false
state: stopped
masked: true
- name: "2.1.19 | PATCH | Ensure xinetd services are not in use"
when: rhel9cis_rule_2_1_19
tags:
- level1-server
- level1-workstation
- automated
- patch
- xinetd
- NIST800-53R5_CM-7
- rule_2.1.19
block:
- name: "2.1.19 | PATCH | Ensure xinetd services are not in use | Remove package"
when:
- not rhel9cis_xinetd_server
- not rhel9cis_xinetd_mask
ansible.builtin.package:
name: xinetd
state: absent
- name: "2.1.19 | PATCH | Ensure xinetd services are not in use | Mask service"
when:
- not rhel9cis_xinetd_server
- rhel9cis_xinetd_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: xinetd.service
enabled: false
state: stopped
masked: true
- name: "2.1.20 | PATCH | Ensure X window server services are not in use"
when:
- not rhel9cis_xwindow_server
- rhel9cis_rule_2_1_20
tags:
- level1-server
- level1-workstation
- automated
- patch
- xwindow
- NIST800-53R5_CM-11
- rule_2.1.20
ansible.builtin.package:
name: xorg-x11-server-common
state: absent
- name: "2.1.21 | PATCH | Ensure mail transfer agents are configured for local-only mode"
when:
- not rhel9cis_is_mail_server
- "'postfix' in ansible_facts.packages"
- rhel9cis_rule_2_1_21
tags:
- level1-server
- level1-workstation
- automated
- patch
- postfix
- NIST800-53R5_CM-7
- rule_2.1.21
notify: Restart_postfix
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: "^(#)?inet_interfaces"
line: "inet_interfaces = loopback-only"
- name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface"
when: rhel9cis_rule_2_1_22
tags:
- level1-server
- level1-workstation
- manual
- audit
- services
- NIST800-53R5_CM-7
- rule_2.1.22
vars:
warn_control_id: '2.1.22'
block:
- name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Get list of services"
ansible.builtin.command: systemctl list-units --type=service # noqa command-instead-of-module
changed_when: false
failed_when: discovered_running_services.rc not in [ 0, 1 ]
check_mode: false
register: discovered_running_services
- name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Display list of services"
ansible.builtin.debug:
msg:
- "Warning!! Below are the list of services, both active and inactive"
- "Please review to make sure all are essential"
- "{{ discovered_running_services.stdout_lines }}"
- name: "2.1.22 | AUDIT | Ensure only approved services are listening on a network interface | Warn Count"
ansible.builtin.import_tasks:
file: warning_facts.yml

View file

@ -1,348 +1,81 @@
---
- name: "2.2.1 | PATCH | Ensure xorg-x11-server-common is not installed"
- name: "2.2.1 | PATCH | Ensure ftp client is not installed"
when:
- not rhel9cis_ftp_client
- rhel9cis_rule_2_2_1
tags:
- level1-server
- level1-workstation
- automated
- patch
- ftp
- NIST800-53R5_CM-7
- rule_2.2.1
ansible.builtin.package:
name: xorg-x11-server-common
state: absent
when:
- rhel9cis_rule_2_2_1
- "'xorg-x11-server-common' in ansible_facts.packages"
- not rhel9cis_gui
tags:
- level1-server
- patch
- x11
- rule_2.2.1
name: ftp
state: absent
- name: "2.2.2 | PATCH | Ensure Avahi Server is not installed"
- name: "2.2.2 | PATCH | Ensure ldap client is not installed"
when:
- not rhel9cis_openldap_clients_required
- rhel9cis_rule_2_2_2
tags:
- level2-server
- level2-workstation
- automated
- patch
- ldap
- NIST800-53R5_CM-7
- rule_2.2.2
ansible.builtin.package:
name:
- avahi-autoipd
- avahi
state: absent
when:
- rhel9cis_rule_2_2_2
- not rhel9cis_avahi_server
- "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages"
tags:
- level1-server
- level2-workstation
- patch
- avahi
- rule_2.2.2
name: openldap-clients
state: absent
- name: "2.2.3 | PATCH | Ensure CUPS is not installed"
- name: "2.2.3 | PATCH | Ensure nis client is not installed"
when:
- not rhel9cis_ypbind_required
- rhel9cis_rule_2_2_3
tags:
- level1-server
- level1-workstation
- automated
- patch
- nis
- NIST800-53R5_CM-7
- rule_2.2.3
ansible.builtin.package:
name: cups
state: absent
when:
- not rhel9cis_cups_server
- "'cups' in ansible_facts.packages"
- rhel9cis_rule_2_2_3
tags:
- level1-server
- patch
- cups
- rule_2.2.3
name: ypbind
state: absent
- name: "2.2.4 | PATCH | Ensure DHCP Server is not installed"
- name: "2.2.4 | PATCH | Ensure telnet client is not installed"
when:
- not rhel9cis_telnet_required
- rhel9cis_rule_2_2_4
tags:
- level1-server
- level1-workstation
- automated
- patch
- telnet
- NIST800-53R5_CM-7
- rule_2.2.4
ansible.builtin.package:
name: dhcp-server
state: absent
when:
- not rhel9cis_dhcp_server
- "'dhcp-server' in ansible_facts.packages"
- rhel9cis_rule_2_2_4
tags:
- level1-server
- level1-workstation
- patch
- dhcp
- rule_2.2.4
name: telnet
state: absent
- name: "2.2.5 | PATCH | Ensure DNS Server is not installed"
- name: "2.2.5 | PATCH | Ensure TFTP client is not installed"
when:
- not rhel9cis_tftp_client
- rhel9cis_rule_2_2_5
tags:
- level1-server
- level1-workstation
- automated
- patch
- tftp
- NIST800-53R5_CM-7
- rule_2.2.5
ansible.builtin.package:
name: bind
state: absent
when:
- not rhel9cis_dns_server
- "'bind' in ansible_facts.packages"
- rhel9cis_rule_2_2_5
tags:
- level1-server
- level1-workstation
- patch
- dns
- rule_2.2.5
- name: "2.2.6 | PATCH | Ensure VSFTP Server is not installed"
ansible.builtin.package:
name: vsftpd
state: absent
when:
- not rhel9cis_vsftpd_server
- "'vsftpd' in ansible_facts.packages"
- rhel9cis_rule_2_2_6
tags:
- level1-server
- level1-workstation
- patch
- vsftpd
- rule_2.2.6
- name: "2.2.7 | PACH | Ensure TFTP Server is not installed"
ansible.builtin.package:
name: tftp-server
state: absent
when:
- not rhel9cis_tftp_server
- "'tftp-server' in ansible_facts.packages"
- rhel9cis_rule_2_2_7
tags:
- level1-server
- level1-workstation
- patch
- tftp
- rule_2.2.7
- name: "2.2.8 | PATCH | Ensure a web server is not installed"
block:
- name: "2.2.8 | PATCH | Ensure a web server is not installed | Remove httpd server"
ansible.builtin.package:
name: httpd
state: absent
when:
- not rhel9cis_httpd_server
- "'httpd' in ansible_facts.packages"
- name: "2.2.8 | PATCH | Ensure a web server is not installed | Remove nginx server"
ansible.builtin.package:
name: nginx
state: absent
when:
- not rhel9cis_nginx_server
- "'nginx' in ansible_facts.packages"
when:
- rhel9cis_rule_2_2_8
tags:
- level1-server
- level1-workstation
- patch
- httpd
- nginx
- webserver
- rule_2.2.8
- name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed"
block:
- name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed"
ansible.builtin.package:
name:
- dovecot
state: absent
when:
- not rhel9cis_dovecot_server
- "'dovecot' in ansible_facts.packages"
- name: "2.2.9 | PATCH | Ensure IMAP and POP3 server is not installed"
ansible.builtin.package:
name:
- cyrus-imapd
state: absent
when:
- not rhel9cis_imap_server
- "'cyrus-imapd' in ansible_facts.packages"
when:
- rhel9cis_rule_2_2_9
tags:
- level1-server
- level1-workstation
- patch
- dovecot
- imap
- pop3
- rule_2.2.9
- name: "2.2.10 | PATCH | Ensure Samba is not enabled"
ansible.builtin.package:
name: samba
state: absent
when:
- not rhel9cis_samba_server
- "'samba' in ansible_facts.packages"
- rhel9cis_rule_2_2_10
tags:
- level1-server
- level1-workstation
- patch
- samba
- rule_2.2.10
- name: "2.2.11 | PATCH | Ensure HTTP Proxy Server is not installed"
ansible.builtin.package:
name: squid
state: absent
when:
- not rhel9cis_squid_server
- "'squid' in ansible_facts.packages"
- rhel9cis_rule_2_2_11
tags:
- level1-server
- level1-workstation
- patch
- squid
- rule_2.2.11
- name: "2.2.12 | PATCH | Ensure net-snmp is not installed"
ansible.builtin.package:
name: net-snmp
state: absent
when:
- not rhel9cis_snmp_server
- "'net-snmp' in ansible_facts.packages"
- rhel9cis_rule_2_2_12
tags:
- level1-server
- level1-workstation
- patch
- snmp
- rule_2.2.12
- name: "2.2.13 | PATCH | Ensure telnet-server is not installed"
ansible.builtin.package:
name: telnet-server
state: absent
when:
- not rhel9cis_telnet_server
- "'telnet-server' in ansible_facts.packages"
- rhel9cis_rule_2_2_13
tags:
- level1-server
- level1-workstation
- patch
- telnet
- rule_2.2.13
- name: "2.2.14 | PATCH | Ensure dnsmasq is not installed"
ansible.builtin.package:
name: dnsmasq
state: absent
when:
- not rhel9cis_dnsmasq_server
- "'dnsmasq' in ansible_facts.packages"
- rhel9cis_rule_2_2_14
tags:
- level1-server
- level1-workstation
- patch
- dnsmasq
- rule_2.2.14
- name: "2.2.15 | PATCH | Ensure mail transfer agent is configured for local-only mode"
ansible.builtin.lineinfile:
path: /etc/postfix/main.cf
regexp: "^(#)?inet_interfaces"
line: "inet_interfaces = loopback-only"
notify: Restart postfix
when:
- not rhel9cis_is_mail_server
- "'postfix' in ansible_facts.packages"
- rhel9cis_rule_2_2_15
tags:
- level1-server
- level1-workstation
- patch
- postfix
- rule_2.2.15
# The name title of the service says mask the service, but the fix allows for both options
# Options available in default/main if to remove the package default is false just mask the server service
- name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked"
block:
- name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | remove package"
ansible.builtin.package:
name: nfs-utils
state: absent
when:
- not rhel9cis_use_nfs_server
- not rhel9cis_use_nfs_service
- name: "2.2.16 | PATCH | Ensure nfs-utils is not installed or the nfs-server service is masked | mask service"
ansible.builtin.systemd:
name: nfs-server
masked: true
state: stopped
when:
- rhel9cis_use_nfs_server
- not rhel9cis_use_nfs_service
when:
- "'nfs-utils' in ansible_facts.packages"
- rhel9cis_rule_2_2_16
tags:
- level1-server
- level1-workstation
- patch
- nfs
- services
- rule_2.2.16
# The name title of the service says mask the service, but the fix allows for both options
# Options available in default/main if to remove the package default is false just mask the server service
- name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked"
block:
- name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | remove package"
ansible.builtin.package:
name: rpcbind
state: absent
when:
- not rhel9cis_use_rpc_server
- not rhel9cis_use_rpc_service
- name: "2.2.17 | PATCH | Ensure rpcbind is not installed or the rpcbind services are masked | mask service"
ansible.builtin.systemd:
name: rpcbind.socket
masked: true
state: stopped
when:
- rhel9cis_use_rpc_server
- not rhel9cis_use_rpc_service
when:
- "'rpcbind' in ansible_facts.packages"
- rhel9cis_rule_2_2_17
tags:
- level1-server
- level1-workstation
- patch
- rpc
- rule_2.2.17
# The name title of the service says mask the service, but the fix allows for both options
# Options available in default/main if to remove the package default is false just mask the server service
- name: "2.2.18 | PATCH | Ensure rsync service is not enabled "
block:
- name: "2.2.18 | PATCH | Ensure rsync-daemon is not installed or the rsync service is masked | remove package"
ansible.builtin.package:
name: rsync-daemon
state: absent
when:
- not rhel9cis_use_rsync_server
- not rhel9cis_use_rsync_service
- name: "2.2.18 | PATCH | Ensure rsync service is not enabled | mask service"
ansible.builtin.systemd:
name: rsyncd
masked: true
state: stopped
when:
- rhel9cis_use_rsync_server
- not rhel9cis_use_rsync_service
when:
- "'rsync' in ansible_facts.packages"
- rhel9cis_rule_2_2_18
tags:
- level1-server
- level1-workstation
- patch
- rsync
- rule_2.2.18
name: tftp
state: absent

View file

@ -1,61 +1,51 @@
---
- name: "2.3.1 | PATCH | Ensure telnet client is not installed"
ansible.builtin.package:
name: telnet
state: absent
- name: "2.3.1 | PATCH | Ensure time synchronization is in use"
when:
- not rhel9cis_telnet_required
- "'telnet' in ansible_facts.packages"
- rhel9cis_rule_2_3_1
- rhel9cis_rule_2_3_1
- not system_is_container
tags:
- level1-server
- level1-workstation
- patch
- telnet
- rule_2.3.1
- level1-server
- level1-workstation
- patch
- NIST800-53R5_AU-3
- NIST800-53R5_AU-12
- rule_2.3.1
ansible.builtin.package:
name: chrony
state: present
- name: "2.3.2 | PATCH | Ensure LDAP client is not installed"
ansible.builtin.package:
name: openldap-clients
state: absent
- name: "2.3.2 | PATCH | Ensure chrony is configured"
when:
- not rhel9cis_openldap_clients_required
- "'openldap-clients' in ansible_facts.packages"
- rhel9cis_rule_2_3_2
- rhel9cis_rule_2_3_2
- not system_is_container
tags:
- level1-server
- level1-workstation
- patch
- ldap
- rule_2.3.2
- level1-server
- level1-workstation
- patch
- rule_2.3.2
- NIST800-53R5_AU-3
- NIST800-53R5_AU-12
ansible.builtin.template:
src: etc/chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: 'go-wx'
- name: "2.3.3 | PATCH | Ensure TFTP client is not installed"
ansible.builtin.package:
name: tftp
state: absent
- name: "2.3.3 | PATCH | Ensure chrony is not run as the root user"
when:
- not rhel9cis_tftp_client
- "'tftp' in ansible_facts.packages"
- rhel9cis_rule_2_3_3
- rhel9cis_rule_2_3_3
- not system_is_container
tags:
- level1-server
- level1-workstation
- patch
- tftp
- rule_2.3.3
- name: "2.3.4 | PATCH | Ensure FTP client is not installed"
ansible.builtin.package:
name: ftp
state: absent
when:
- not rhel9cis_ftp_client
- "'ftp' in ansible_facts.packages"
- rhel9cis_rule_2_3_4
tags:
- level1-server
- level1-workstation
- patch
- ftp
- rule_2.3.4
- level1-server
- level1-workstation
- patch
- rule_2.3.3
ansible.builtin.lineinfile:
path: /etc/sysconfig/chronyd
regexp: '^OPTIONS="(?!.* -u chrony.*)(.*)"'
line: OPTIONS="\1 -u chrony"
create: true
backrefs: true
mode: 'go-wx'

View file

@ -0,0 +1,173 @@
---
- name: "2.4.1.1 | PATCH | Ensure cron daemon is enabled"
when: rhel9cis_rule_2_4_1_1
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.service:
name: crond
enabled: true
- name: "2.4.1.2 | PATCH | Ensure permissions on /etc/crontab are configured"
when: rhel9cis_rule_2_4_1_2
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/crontab
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured"
when: rhel9cis_rule_2_4_1_3
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/cron.hourly
state: directory
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured"
when: rhel9cis_rule_2_4_1_4
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.4
ansible.builtin.file:
path: /etc/cron.daily
state: directory
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured"
when: rhel9cis_rule_2_4_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_2.4.1.5
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/cron.weekly
state: directory
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured"
when: rhel9cis_rule_2_4_1_6
tags:
- level1-server
- level1-workstation
- patch
- rule_2.4.1.6
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/cron.monthly
state: directory
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured"
when: rhel9cis_rule_2_4_1_7
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.7
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/cron.d
state: directory
owner: root
group: root
mode: 'og-rwx'
- name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users"
when: rhel9cis_rule_2_4_1_8
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.1.8
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Remove cron.deny"
ansible.builtin.file:
path: /etc/cron.deny
state: absent
- name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Check if cron.allow exists"
ansible.builtin.stat:
path: "/etc/cron.allow"
register: discovered_cron_allow_state
- name: "2.4.1.8 | PATCH | Ensure crontab is restricted to authorized users | Ensure cron.allow is restricted to authorized users"
ansible.builtin.file:
path: /etc/cron.allow
state: '{{ "file" if discovered_cron_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: 'u-x,g-wx,o-rwx'
- name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users"
when: rhel9cis_rule_2_4_2_1
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_2.4.2.1
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Remove at.deny"
ansible.builtin.file:
path: /etc/at.deny
state: absent
- name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists"
ansible.builtin.stat:
path: "/etc/at.allow"
register: discovered_at_allow_state
- name: "2.4.2.1 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users"
ansible.builtin.file:
path: /etc/at.allow
state: '{{ "file" if discovered_at_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: 'u-x,g-wx,o-rwx'

View file

@ -1,40 +0,0 @@
---
- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked"
block:
- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Get list of services"
ansible.builtin.shell: systemctl list-units --type=service
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_2_4_services
- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Get list of sockets"
ansible.builtin.shell: systemctl list-units --type=socket
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_2_4_sockets
- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Display list of services"
ansible.builtin.debug:
msg:
- "Warning!! Below are the list of services and sockets, both active and inactive"
- "Please review to make sure all are essential"
- "{{ rhel9cis_2_4_services.stdout_lines }}"
- "{{ rhel9cis_2_4_sockets.stdout_lines }}"
- name: "2.4 | AUDIT | Ensure nonessential services listening on the system are removed or masked | Warn Count"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '2.4'
when:
- rhel9cis_rule_2_4
tags:
- level1-server
- level1-workstation
- manual
- audit
- services
- rule_2.4

View file

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

View file

@ -3,82 +3,92 @@
# The CIS Control wants IPv6 disabled if not in use.
# We are using the rhel9cis_ipv6_required to specify if you have IPv6 in use
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified"
block:
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv6_route: true
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf"
when:
- not rhel9cis_ipv6_required
- rhel9cis_rule_3_1_1
- not rhel9cis_ipv6_required
- rhel9cis_rule_3_1_1
tags:
- level1-server
- level1-workstation
- manual
- patch
- ipv6
- networking
- rule_3.1.1
- level1-server
- level1-workstation
- manual
- patch
- ipv6
- networking
- rule_3.1.1
- NIST800-53R5_CM-7
block:
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv6_route: true
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified | disable"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-disable_ipv6.conf"
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled"
block:
- name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if nmcli command is available | if wlan exists"
ansible.builtin.shell: rpm -q NetworkManager
changed_when: false
failed_when: false
check_mode: false
register: rhel_09_nmcli_available
- name: "3.1.2 | AUDIT | Ensure wireless interfaces are disabled | Check if wifi is enabled"
ansible.builtin.shell: nmcli radio wifi
register: rhel_09_wifi_enabled
changed_when: rhel_09_wifi_enabled.stdout != "disabled"
failed_when: false
when: rhel_09_nmcli_available.rc == 0
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wifi if enabled"
ansible.builtin.shell: nmcli radio all off
changed_when: false
failed_when: false
when: rhel_09_wifi_enabled is changed # noqa no-handler
when:
- rhel9cis_rule_3_1_2
- "'wlan' in ansible_facts.interfaces"
- rhel9cis_rule_3_1_2
- discover_wireless_adapters.rc == 0
tags:
- level1-server
- patch
- wireless
- rule_3.1.2
- name: "3.1.3 | PATCH | Ensure TIPC is disabled"
- level1-server
- patch
- rule_3.1.2
- wireless
- NIST800-53R5_CM-7
vars:
warn_control_id: '3.1.2'
block:
- name: "3.1.3 | PATCH | Ensure TIPC is disabled"
ansible.builtin.template:
src: "etc/modprobe.d/modprobe.conf.j2"
dest: "/etc/modprobe.d/{{ item }}.conf"
mode: '0600'
owner: root
group: root
loop:
- tipc
# note the item used in the template
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Check for network-manager tool"
when: "'network-manager' in ansible_facts.packages"
ansible.builtin.command: nmcli radio wifi
changed_when: false
failed_when: false
check_mode: false
register: discovered_wifi_status
- name: "3.1.3 | PATCH | Ensure TIPC is disabled | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist tipc(\\s|$)"
line: "blacklist tipc"
create: true
mode: '0600'
when:
- rhel9cis_rule_3_1_3
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Disable wireless if network-manager installed"
when:
- "'network-manager' in ansible_facts.packages"
- "'enabled' in discovered_wifi_status.stdout"
ansible.builtin.command: nmcli radio all off
changed_when: discovered_nmcli_radio_off.rc == 0
register: discovered_nmcli_radio_off
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Warn about wireless if network-manager not installed"
when: "'network-manager' not in ansible_facts.packages"
ansible.builtin.debug:
msg: "Warning!! You need to disable wireless interfaces manually since network-manager is not installed"
- name: "3.1.2 | PATCH | Ensure wireless interfaces are disabled | Set warning count"
when: "'network-manager' not in ansible_facts.packages"
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use"
when: rhel9cis_rule_3_1_3
tags:
- level2-server
- level2-workstation
- patch
- tipc
- rule_3.1.3
- level1-server
- level2-workstation
- patch
- bluetooth
- rule_3.1.3
- NIST800-53R5_CM-7
block:
- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | pkg"
when:
- not rhel9cis_bluetooth_service
- not rhel9cis_bluetooth_mask
ansible.builtin.package:
name: bluez
state: absent
- name: "3.1.3 | PATCH | Ensure bluetooth services are not in use | mask"
when:
- not rhel9cis_bluetooth_service
- rhel9cis_bluetooth_mask
notify: Systemd_daemon_reload
ansible.builtin.systemd:
name: bluetooth.service
enabled: false
state: stopped
masked: true

View file

@ -1,52 +1,121 @@
---
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled"
block:
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | IPv6"
block:
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.2.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
when: rhel9cis_ipv6_required
when:
- not rhel9cis_is_router
- rhel9cis_rule_3_2_1
- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available"
when: rhel9cis_rule_3_2_1
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.2.1
- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled"
- level2-server
- level2-workstation
- patch
- rule_3.2.1
- dccp
- NIST800-53R5_CM-7
- NIST800-53R5_SI-4
block:
- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.2.2 | PATCH | Ensure packet redirect sending is disabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- not rhel9cis_is_router
- rhel9cis_rule_3_2_2
- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | modprobe"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/dccp.conf
regexp: '^(#)?install dccp(\\s|$)'
line: "{{ item }}"
create: true
mode: 'u-x,go-rwx'
loop:
- install dccp /bin/true
- blacklist dccp
- name: "3.2.1 | PATCH | Ensure dccp kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist cramfs(\\s|$)"
line: "blacklist cramfs"
create: true
mode: 'u-x,go-rwx'
- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available"
when: rhel9cis_rule_3_2_2
tags:
- level1-server
- level1-workstation
- patch
- sysctl
- rule_3.2.2
- level2-server
- level2-workstation
- patch
- rule_3.2.2
- tipc
- NIST800-53R5_CM-7
- NIST800-53R5_SI-4
block:
- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | modprobe"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/tipc.conf
regexp: '^(#)?install tipc(\\s|$)'
line: "{{ item }}"
create: true
mode: 'u-x,go-rwx'
loop:
- install tipc /bin/true
- blacklist tipc
- name: "3.2.2 | PATCH | Ensure tipc kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist tipc(\\s|$)"
line: "blacklist tipc"
create: true
mode: 'u-x,go-rwx'
- name: "3.2.3 | PATCH | Ensure rds kernel module is not available"
when: rhel9cis_rule_3_2_3
tags:
- level2-server
- level2-workstation
- patch
- rule_3.2.3
- rds
- NIST800-53R5_CM-7
- NIST800-53R5_SI-4
block:
- name: "3.2.3 | PATCH | Ensure rds kernel module is not available | modprobe"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/rds.conf
regexp: '^(#)?install rds(\\s|$)'
line: "{{ item }}"
create: true
mode: 'u-x,go-rwx'
loop:
- install rds /bin/true
- blacklist rds
- name: "3.2.3 | PATCH | Ensure rds kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist rds(\\s|$)"
line: "blacklist rds"
create: true
mode: 'u-x,go-rwx'
- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available"
when: rhel9cis_rule_3_2_4
tags:
- level2-server
- level2-workstation
- patch
- rule_3.2.4
- sctp
- NIST800-53R5_CM-7
- NIST800-53R5_SI-4
block:
- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | modprobe"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/sctp.conf
regexp: '^(#)?install sctp(\\s|$)'
line: "{{ item }}"
create: true
mode: 'u-x,go-rwx'
loop:
- install sctp /bin/true
- blacklist sctp
- name: "3.2.4 | PATCH | Ensure sctp kernel module is not available | blacklist"
ansible.builtin.lineinfile:
path: /etc/modprobe.d/blacklist.conf
regexp: "^(#)?blacklist sctp(\\s|$)"
line: "blacklist sctp"
create: true
mode: 'u-x,go-rwx'

View file

@ -1,194 +1,298 @@
---
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted"
block:
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv4 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv4"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6"
block:
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.1 | PATCH | Ensure source routed packets are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
when: rhel9cis_ipv6_required
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled"
when:
- rhel9cis_rule_3_3_1
- not rhel9cis_is_router
- rhel9cis_rule_3_3_1
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.1
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted"
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv4"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv4 forwarding"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6"
block:
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
when: rhel9cis_ipv6_required
when:
- rhel9cis_rule_3_3_2
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.2
- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted"
block:
- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.3 | PATCH | Ensure secure ICMP redirects are not accepted"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_3
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.3
- name: "3.3.4 | PATCH | Ensure suspicious packets are logged"
block:
- name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.4 | PATCH | Ensure suspicious packets are logged"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_4
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.4
- name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored"
block:
- name: "3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: 3.3.5 | PATCH | Ensure broadcast ICMP requests are ignored"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_5
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.5
- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored"
block:
- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.6 | PATCH | Ensure bogus ICMP responses are ignored"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_6
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.6
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled"
block:
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_7
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.7
- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled"
block:
- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.8 | PATCH | Ensure TCP SYN Cookies is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
when:
- rhel9cis_rule_3_3_8
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.8
- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted"
block:
- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | IPv6"
when: rhel9cis_ipv6_required
block:
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.9 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl"
- name: "3.3.1 | PATCH | Ensure IP forwarding is disabled | Disable IPv6 forwarding"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled"
when:
- rhel9cis_ipv6_required
- rhel9cis_rule_3_3_9
- not rhel9cis_is_router
- rhel9cis_rule_3_3_2
tags:
- level2-server
- level2-workstation
- sysctl
- patch
- rule_3.3.9
- level1-server
- level1-workstation
- patch
- sysctl
- rule_3.3.2
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.2 | PATCH | Ensure packet redirect sending is disabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored"
when: rhel9cis_rule_3_3_3
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.3
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.3 | PATCH | Ensure bogus ICMP responses are ignored"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored"
when: rhel9cis_rule_3_3_4
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.4
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: 3.3.4 | PATCH | Ensure broadcast ICMP requests are ignored"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted"
when: rhel9cis_rule_3_3_5
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.5
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6"
when: rhel9cis_ipv6_required
block:
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.5 | PATCH | Ensure ICMP redirects are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted"
when: rhel9cis_rule_3_3_6
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.6
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv4 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv4"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6"
when: rhel9cis_ipv6_required
block:
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.6 | PATCH | Ensure secure ICMP redirects are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled"
when: rhel9cis_rule_3_3_7
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.7
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.7 | PATCH | Ensure Reverse Path Filtering is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted"
when: rhel9cis_rule_3_3_8
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.8
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv4 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv4"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6"
when: rhel9cis_ipv6_required
block:
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_flush_ipv6_route: true
- name: "3.3.8 | PATCH | Ensure source routed packets are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl.conf"
- name: "3.3.9 | PATCH | Ensure suspicious packets are logged"
when: rhel9cis_rule_3_3_9
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.9
- NIST800-53R5_AU-3
block:
- name: "3.3.4 | PATCH | Ensure suspicious packets are logged | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.4 | PATCH | Ensure suspicious packets are logged"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled"
when: rhel9cis_rule_3_3_10
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.10
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv4_route: true
- name: "3.3.10 | PATCH | Ensure TCP SYN Cookies is enabled"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv4_sysctl.conf"
- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted"
when:
- rhel9cis_ipv6_required
- rhel9cis_rule_3_3_11
tags:
- level2-server
- level2-workstation
- sysctl
- patch
- rule_3.3.11
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6 | Set Fact"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv6_route: true
- name: "3.3.11 | PATCH | Ensure IPv6 router advertisements are not accepted | IPv6"
ansible.builtin.debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/60-netipv6_sysctl"

View file

@ -1,59 +0,0 @@
---
- name: "3.4.1.1 | PATCH | Ensure nftables is installed"
ansible.builtin.package:
name:
- nftables
state: present
when:
- rhel9cis_rule_3_4_1_1
- rhel9cis_firewall == 'nftables'
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.1.1
- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use"
block:
- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables"
ansible.builtin.systemd:
name: "{{ item }}"
masked: true
loop:
- firewalld
when:
- item in ansible_facts.packages
- rhel9cis_firewall == 'nftables'
- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld"
ansible.builtin.systemd:
name: "{{ item }}"
masked: true
loop:
- nftables
when:
- item in ansible_facts.packages
- rhel9cis_firewall == 'firewalld'
- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | package installed"
ansible.builtin.package:
name: "{{ rhel9cis_firewall }}"
state: installed
- name: "3.4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled"
ansible.builtin.systemd:
name: "{{ rhel9cis_firewall }}"
enabled: true
state: started
when:
- rhel9cis_rule_3_4_1_2
tags:
- level1-server
- level1-workstation
- patch
- firewalld
- nftables
- rule_3.4.1.2

View file

@ -1,301 +0,0 @@
---
- name: "3.4.2.1 | PATCH | Ensure firewalld default zone is set"
block:
- name: "3.4.2.1 | AUDIT | Ensure firewalld default zone is set"
ansible.builtin.shell: "firewall-cmd --get-default-zone | grep {{ rhel9cis_default_zone }}"
changed_when: false
failed_when: ( firewalld_zone_set.rc not in [ 0, 1 ] )
register: firewalld_zone_set
- name: "3.4.2.1 | AUDIT | Ensure firewalld default zone is set"
ansible.builtin.command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}"
when: firewalld_zone_set.rc != 0
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_1
tags:
- level1-server
- level1-workstation
- patch
- firewalld
- rule_3.4.2.1
- name: "3.4.2.2 | AUDIT | Ensure at least one nftables table exists"
block:
- name: "3.4.2.2 | AUDIT | Ensure a table exists | Check for tables"
ansible.builtin.command: nft list tables
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_2_nft_tables
- name: "3.4.2.2 | AUDIT | Ensure an nftables table exists | Show existing tables"
ansible.builtin.debug:
msg:
- "Below are the current nft tables, please review"
- "{{ rhel9cis_3_4_2_2_nft_tables.stdout_lines }}"
when: rhel9cis_3_4_2_2_nft_tables.stdout | length > 0
- name: "3.4.2.2 | AUDIT | Ensure an nftables table exists | Alert on no tables"
ansible.builtin.debug:
msg:
- "Warning!! You currently have no nft tables, please review your setup"
- 'Use the command "nft create table inet <table name>" to create a new table'
when:
- rhel9cis_3_4_2_2_nft_tables.stdout | length == 0
- not rhel9cis_nft_tables_autonewtable
- name: "3.4.2.2 | AUDIT | Ensure an nftables table exists | Alert on no tables | warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- rhel9cis_3_4_2_2_nft_tables.stdout | length == 0
- not rhel9cis_nft_tables_autonewtable
- name: "3.4.2.2 | PATCH | Ensure a table exists | Create table if needed"
ansible.builtin.command: nft create table inet "{{ rhel9cis_nft_tables_tablename }}"
failed_when: false
when: rhel9cis_nft_tables_autonewtable
vars:
warn_control_id: '3.4.2.2'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_2
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.2
- name: "3.4.2.3 | PATCH | Ensure nftables base chains exist"
block:
- name: "3.4.2.3 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT"
ansible.builtin.shell: nft list ruleset | grep 'hook input'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_3_input_chains
- name: "3.4.2.3 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD"
ansible.builtin.shell: nft list ruleset | grep 'hook forward'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_3_forward_chains
- name: "3.4.2.3 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT"
ansible.builtin.shell: nft list ruleset | grep 'hook output'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_3_output_chains
- name: "3.4.2.3 | AUDIT | Ensure nftables base chains exist | Display chains for review"
ansible.builtin.debug:
msg:
- "Below are the current INPUT chains"
- "{{ rhel9cis_3_4_2_3_input_chains.stdout_lines }}"
- "Below are the current FORWARD chains"
- "{{ rhel9cis_3_4_2_3_forward_chains.stdout_lines }}"
- "Below are teh current OUTPUT chains"
- "{{ rhel9cis_3_4_2_3_output_chains.stdout_lines }}"
when: not rhel9cis_nft_tables_autochaincreate
- name: "3.4.2.3 | PATCH | Ensure nftables base chains exist | Create chains if needed"
ansible.builtin.shell: "{{ item }}"
failed_when: false
loop:
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; }
when: rhel9cis_nft_tables_autochaincreate
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.3
- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured"
block:
- name: "3.4.2.4 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather iif lo accept existence | nftables"
ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_4_iiflo
- name: "3.4.2.4 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip saddr existence | nftables"
ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_4_ipsaddr
- name: "3.4.2.4 | AUDIT | Ensure host based firewall loopback traffic is configured | Gather ip6 saddr existence | nftables"
ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_4_ip6saddr
- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set iif lo accept rule | nftables"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept
when: '"iif \"lo\" accept" not in rhel9cis_3_4_2_4_iiflo.stdout'
- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip sddr rule | nftables"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop
when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_2_4_ipsaddr.stdout'
- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | Set ip6 saddr rule | nftables"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop
when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_2_4_ip6saddr.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_4
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.4
- name: "3.4.2.4 | PATCH | Ensure host based firewall loopback traffic is configured | firewalld"
ansible.posix.firewalld:
rich_rule: "{{ item }}"
zone: "{{ rhel9cis_default_zone }}"
permanent: true
immediate: true
state: enabled
loop:
- rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop
- rule family="ipv6" source address="::1" destination not address="::1" drop
when:
- rhel9cis_firewall == "firewalld"
- rhel9cis_rule_3_4_2_4
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.4
- name: "3.4.2.5 | AUDIT | Ensure firewalld drops unnecessary services and ports"
block:
- name: "3.4.2.5 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports"
ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done"
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_3_4_2_5_servicesport
- name: "3.4.2.5 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports"
ansible.builtin.debug:
msg:
- "The items below are the services and ports that are accepted, please correct as needed"
- "{{ rhel9cis_3_4_2_5_servicesport.stdout_lines }}"
when:
- rhel9cis_rule_3_4_2_5
- rhel9cis_firewall == "firewalld"
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_3.4.2.5
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured"
block:
- name: "3.4.2.6 | AUDIT | Ensure nftables established connections are configured | Gather incoming connection rules"
ansible.builtin.shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_6_inconnectionrule
- name: "3.4.2.6| AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules"
ansible.builtin.shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: rhel9cis_3_4_2_6_outconnectionrule
- name: "3.4.2.6| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept
when: '"ip protocol tcp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout'
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept
when: '"ip protocol udp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout'
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept
when: '"ip protocol icmp ct state established accept" not in rhel9cis_3_4_2_6_inconnectionrule.stdout'
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept
when: '"ip protocol tcp ct state established,related,new accept" not in rhel9cis_3_4_2_6_outconnectionrule.stdout'
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept
when: '"ip protocol udp ct state established,related,new accept" not in rhel9cis_3_4_2_6_outconnectionrule.stdout'
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept
when: '"ip protocol icmp ct state established,related,new accept" not in rhel9cis_3_4_2_6_outconnectionrule.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_6
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.6
- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy"
block:
- name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy"
ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input'
failed_when: false
changed_when: false
register: rhel9cis_3_4_2_7_inputpolicy
- name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy"
ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward'
failed_when: false
changed_when: false
register: rhel9cis_3_4_2_7_forwardpolicy
- name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy"
ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output'
failed_when: false
changed_when: false
register: rhel9cis_3_4_2_7_outputpolicy
- name: "3.4.2.7 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow"
ansible.builtin.shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh'
failed_when: false
changed_when: false
register: rhel9cis_3_4_2_7_sshallowcheck
- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic"
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept
when: '"tcp dport ssh accept" not in rhel9cis_3_4_2_7_sshallowcheck.stdout'
- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy"
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; }
when: '"type filter hook input priority 0; policy drop;" not in rhel9cis_3_4_2_7_inputpolicy.stdout'
- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy"
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; }
when: '"type filter hook forward priority 0; policy drop;" not in rhel9cis_3_4_2_7_forwardpolicy.stdout'
- name: "3.4.2.7 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy"
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; }
when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_3_4_2_7_outputpolicy.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_7
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.7

View file

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

View file

@ -1,101 +0,0 @@
---
- name: "4.1.1.1 | PATCH | Ensure auditd is installed"
block:
- name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd packages"
ansible.builtin.package:
name: audit
state: present
when: '"auditd" not in ansible_facts.packages'
- name: "4.1.1.1 | PATCH | Ensure auditd is installed | Install auditd-lib packages"
ansible.builtin.package:
name: audit-libs
state: present
when: '"auditd-lib" not in ansible_facts.packages'
when:
- rhel9cis_rule_4_1_1_1
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.1.1
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled"
block:
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby existence of current value"
ansible.builtin.shell: grubby --info=ALL | grep args | sed -n 's/.*audit=\([[:alnum:]]\+\).*/\1/p'
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_4_1_1_2_grubby_curr_value_audit_linux
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Grubby update, if needed"
ansible.builtin.shell: grubby --update-kernel=ALL --args="audit=1"
when:
- rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout == '' or
'0' in rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout or
'off' in rhel9cis_4_1_1_2_grubby_curr_value_audit_linux.stdout|lower
when:
- rhel9cis_rule_4_1_1_2
tags:
- level2-server
- level2-workstation
- patch
- auditd
- grub
- rule_4.1.1.2
- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient"
block:
- name: "4.1.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby existence of current value"
ansible.builtin.shell:
cmd: 'grubby --info=ALL | grep args | grep -o -E "audit_backlog_limit=([[:digit:]])+" | grep -o -E "([[:digit:]])+"'
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux
- name: "4.1.1.3 | AUDIT | Check to see if limits are set"
ansible.builtin.set_fact:
rhel9cis_4_1_1_3_reset_backlog_limits: true
when:
- rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux is not defined or
rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux.stdout_lines == []
- name: "4.1.1.3 | AUDIT | Check to see if any limits are too low"
ansible.builtin.set_fact:
rhel9cis_4_1_1_3_reset_backlog_limits: true
when:
- (item | int < rhel9cis_audit_back_log_limit)
loop: "{{ rhel9cis_4_1_1_3_grubby_curr_value_backlog_linux.stdout_lines }}"
- name: "4.1.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Grubby update applied"
ansible.builtin.shell:
cmd: 'grubby --update-kernel=ALL --args="audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"'
when:
- rhel9cis_4_1_1_3_reset_backlog_limits is defined
when:
- rhel9cis_rule_4_1_1_3
tags:
- level2-server
- level2-workstation
- patch
- auditd
- grub
- rule_4.1.1.3
- name: "4.1.1.4 | PATCH | Ensure auditd service is enabled"
ansible.builtin.systemd:
name: auditd
state: started
enabled: true
when:
- rhel9cis_rule_4_1_1_4
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.1.4

View file

@ -1,66 +0,0 @@
---
- name: "4.1.2.1 | PATCH | Ensure audit log storage size is configured"
ansible.builtin.lineinfile:
path: /etc/audit/auditd.conf
regexp: "^max_log_file( |=)"
line: "max_log_file = {{ rhel9cis_auditd['max_log_file'] }}"
notify: Restart auditd
when:
- rhel9cis_rule_4_1_2_1
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.2.1
- name: "4.1.2.2 | PATCH | Ensure audit logs are not automatically deleted"
ansible.builtin.lineinfile:
path: /etc/audit/auditd.conf
regexp: "^max_log_file_action"
line: "max_log_file_action = {{ rhel9cis_auditd['max_log_file_action'] }}"
notify: Restart auditd
when:
- rhel9cis_rule_4_1_2_2
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.2.2
- name: "4.1.2.3 | PATCH | Ensure system is disabled when audit logs are full"
ansible.builtin.lineinfile:
path: /etc/audit/auditd.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
notify: Restart auditd
loop:
- { regexp: '^admin_space_left_action', line: 'admin_space_left_action = {{ rhel9cis_auditd.admin_space_left_action }}' }
- { regexp: '^action_mail_acct', line: 'action_mail_acct = {{ rhel9cis_auditd.action_mail_acct }}' }
- { regexp: '^space_left_action', line: 'space_left_action = {{ rhel9cis_auditd.space_left_action }}' }
when:
- rhel9cis_rule_4_1_2_3
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.2.3
- name: PATCH | Configure other keys for auditd.conf
ansible.builtin.lineinfile:
path: /etc/audit/auditd.conf
regexp: "^{{ item }}( |=)"
line: "{{ item }} = {{ rhel9cis_auditd_extra_conf[item] }}"
loop: "{{ rhel9cis_auditd_extra_conf.keys() }}"
notify: Restart auditd
when:
- rhel9cis_auditd_extra_conf.keys() | length > 0
- rhel9cis_auditd_extra_conf_usage
tags:
- level2-server
- level2-workstation
- patch
- auditd

View file

@ -1,292 +0,0 @@
---
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.1 | PATCH | Ensure changes to system administration scope (sudoers) is collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_1
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.1
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.2 | PATCH | Ensure actions as another user are always logged"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_2
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.2
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.3 | PATCH | Ensure events that modify the sudo log file are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_3
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.3
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.4 | PATCH | Ensure events that modify date and time information are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_4
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.4
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.5 | PATCH | Ensure events that modify the system's network environment are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_5
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.5
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected"
block:
- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected"
ansible.builtin.shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm /6000 2>/dev/null; done
changed_when: false
failed_when: false
check_mode: false
register: priv_procs
- name: "4.1.3.6 | PATCH | Ensure use of privileged commands is collected"
ansible.builtin.set_fact:
update_audit_template: true
notify: update auditd
when:
- rhel9cis_rule_4_1_3_6
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.6
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.7 | PATCH | Ensure unsuccessful unauthorized file access attempts are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_7
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.7
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.8 | PATCH | Ensure events that modify user/group information are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_8
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.8
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.9 | PATCH | Ensure discretionary access control permission modification events are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_9
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.9
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.10 | PATCH | Ensure successful file system mounts are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_10
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.10
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.11 | PATCH | Ensure session initiation information is collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_11
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.11
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.12 | PATCH | Ensure login and logout events are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_12
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.12
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.13 | PATCH | Ensure file deletion events by users are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_13
tags:
- level2-server
- level2-workstation
- auditd
- patch
- rule_4.1.3.13
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.14 | PATCH | Ensure events that modify the system's Mandatory Access Controls are collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_14
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.14
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.15 | PATCH | Ensure successful and unsuccessful attempts to use the chcon command are recorded"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_15
tags:
- level2-server
- level2- workstation
- patch
- auditd
- rule_4.1.3.15
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.16 | PATCH | Ensure successful and unsuccessful attempts to use the setfacl command are recorded"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_16
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.16
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.17 | PATCH | Ensure successful and unsuccessful attempts to use the chacl command are recorded"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_17
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.17
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.18 | PATCH | Ensure successful and unsuccessful attempts to use the usermod command are recorded"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_18
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.18
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.19 | PATCH | Ensure kernel module loading and unloading is collected"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_19
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.19
# All changes selected are managed by the POST audit and handlers to update
- name: "4.1.3.20 | PATCH | Ensure the audit configuration is immutable"
ansible.builtin.set_fact:
update_audit_template: true
when:
- rhel9cis_rule_4_1_3_20
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.3.20
- name: "4.1.3.21 | AUDIT | Ensure the running and on disk configuration is the same"
ansible.builtin.debug:
msg:
- "Please run augenrules --load if you suspect there is a configuration that is not active"
when:
- rhel9cis_rule_4_1_3_21
tags:
- level2-server
- level2-workstation
- manual
- patch
- auditd
- rule_4.1.3.21
- name: Auditd | 4.1.3 | Auditd controls updated
ansible.builtin.debug:
msg: "Auditd Controls handled in POST using template - updating /etc/auditd/rules.d/99_auditd.rules"
changed_when: false
when:
- update_audit_template

View file

@ -1,188 +0,0 @@
---
- name: |
"4.1.4.1 | PATCH | Ensure audit log files are mode 0640 or less permissive"
"4.1.4.2 | PATCH | Ensure only authorized users own audit log files"
"4.1.4.3 | PATCH | Ensure only authorized groups are assigned ownership of audit log files"
block:
- name: "4.1.4.1 | AUDIT | Ensure audit log files are mode 0640 or less permissive | discover file"
ansible.builtin.shell: grep ^log_file /etc/audit/auditd.conf | awk '{ print $NF }'
changed_when: false
register: audit_discovered_logfile
- name: "4.1.4.1 | AUDIT | Ensure audit log files are mode 0640 or less permissive | stat file"
ansible.builtin.stat:
path: "{{ audit_discovered_logfile.stdout }}"
changed_when: false
register: auditd_logfile
- name: |
"4.1.4.1 | PATCH | Ensure audit log files are mode 0640 or less permissive"
"4.1.4.2 | PATCH | Ensure only authorized users own audit log files"
"4.1.4.3 | PATCH | Ensure only authorized groups are assigned ownership of audit log files"
ansible.builtin.file:
path: "{{ audit_discovered_logfile.stdout }}"
mode: 'u-x,g-rw,o-rwx'
owner: root
group: root
when:
- rhel9cis_rule_4_1_4_1 or
rhel9cis_rule_4_1_4_2 or
rhel9cis_rule_4_1_4_3
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.1
- rule_4.1.4.2
- rule_4.1.4.3
- name: "4.1.4.4 | PATCH | Ensure the audit log directory is 0750 or more restrictive"
block:
- name: "4.1.4.4 | AUDIT | Ensure the audit log directory is 0750 or more restrictive | get current permissions"
ansible.builtin.stat:
path: "{{ audit_discovered_logfile.stdout | dirname }}"
register: auditlog_dir
- name: "4.1.4.4 | PATCH | Ensure the audit log directory is 0750 or more restrictive | set"
ansible.builtin.file:
path: "{{ audit_discovered_logfile.stdout | dirname }}"
state: directory
mode: 'g-w,o-rwx'
when: not auditlog_dir.stat.mode is match('07(0|5)0')
when:
- rhel9cis_rule_4_1_4_4
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.4
- name: "4.1.4.5 | PATCH | Ensure audit configuration files are 640 or more restrictive"
ansible.builtin.file:
path: "{{ item.path }}"
mode: 'u-x,g-wx,o-rwx'
failed_when: rhel9cis_4_1_4_5_file_list.state not in '[ file, absent ]'
register: rhel9cis_4_1_4_5_file_list
loop: "{{ auditd_conf_files.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_4_1_4_5
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.5
- name: "4.1.4.6 | PATCH | Ensure audit configuration files are owned by root"
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
failed_when: rhel9cis_4_1_4_6_file_list.state not in '[ file, absent ]'
register: rhel9cis_4_1_4_6_file_list
loop: "{{ auditd_conf_files.files | default([]) }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_4_1_4_6
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.6
- name: "4.1.4.7 | PATCH | Ensure audit configuration files belong to group root"
ansible.builtin.file:
path: "{{ item.path }}"
group: root
failed_when: rhel9cis_4_1_4_7_file_list.state not in '[ file, absent ]'
register: rhel9cis_4_1_4_7_file_list
loop: "{{ auditd_conf_files.files | default([]) }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_4_1_4_7
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.7
- name: "4.1.4.8 | PATCH | Ensure audit tools are 755 or more restrictive"
block:
- name: "4.1.4.8 | AUDIT | Get audit binary file stat | get current mode"
ansible.builtin.stat:
path: "{{ item }}"
register: "audit_bins"
loop:
- /sbin/auditctl
- /sbin/aureport
- /sbin/ausearch
- /sbin/autrace
- /sbin/auditd
- /sbin/augenrules
- name: "4.1.4.8 | PATCH | Ensure audit tools are 755 or more restrictive | set if required"
ansible.builtin.file:
path: "{{ item.item }}"
mode: 'go-w'
loop: "{{ audit_bins.results }}"
loop_control:
label: "{{ item.item }}"
when: not item.stat.mode is match('07(0|5)0')
when:
- rhel9cis_rule_4_1_4_8
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.8
- name: "4.1.4.9 | PATCH | Ensure audit tools are owned by root"
ansible.builtin.file:
path: "{{ item }}"
owner: root
group: root
loop:
- /sbin/auditctl
- /sbin/aureport
- /sbin/ausearch
- /sbin/autrace
- /sbin/auditd
- /sbin/augenrules
when:
- rhel9cis_rule_4_1_4_9
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.9
- name: "4.1.4.10 | PATCH | Ensure audit tools belong to group root"
ansible.builtin.file:
path: "{{ item }}"
group: root
loop:
- /sbin/auditctl
- /sbin/aureport
- /sbin/ausearch
- /sbin/autrace
- /sbin/auditd
- /sbin/augenrules
when:
- rhel9cis_rule_4_1_4_10
tags:
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.4.10

View file

@ -0,0 +1,58 @@
---
- name: "4.1.1 | PATCH | Ensure nftables is installed"
when:
- rhel9cis_rule_4_1_1
- rhel9cis_firewall == 'nftables'
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.1.1
- NIST800-53R5_CA-9
ansible.builtin.package:
name:
- nftables
state: present
- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use"
when: rhel9cis_rule_4_1_2
tags:
- level1-server
- level1-workstation
- patch
- firewalld
- nftables
- rule_4.1.2
block:
- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | nftables"
when:
- item in ansible_facts.packages
- rhel9cis_firewall == 'nftables'
ansible.builtin.systemd:
name: "{{ item }}"
masked: true
loop:
- firewalld
- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | firewalld"
when:
- item in ansible_facts.packages
- rhel9cis_firewall == 'firewalld'
ansible.builtin.systemd:
name: "{{ item }}"
masked: true
loop:
- nftables
- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | package installed"
ansible.builtin.package:
name: "{{ rhel9cis_firewall }}"
state: installed
- name: "4.1.2 | PATCH | Ensure a single firewall configuration utility is in use | {{ rhel9cis_firewall }} started and enabled" # noqa name[template]
ansible.builtin.systemd:
name: "{{ rhel9cis_firewall }}"
enabled: true
state: started

View file

@ -1,215 +0,0 @@
---
- name: "4.2.1.1 | PATCH | Ensure rsyslog installed"
ansible.builtin.package:
name: rsyslog
state: present
when:
- "'rsyslog' not in ansible_facts.packages"
- rhel9cis_rule_4_2_1_1
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.1
- name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled"
ansible.builtin.systemd:
name: rsyslog
enabled: true
when:
- rhel9cis_rule_4_2_1_2
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.2
- name: "4.2.1.3 | PATCH | Ensure journald is configured to send logs to rsyslog"
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: "^#ForwardToSyslog=|^ForwardToSyslog="
line: ForwardToSyslog=yes
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_3
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.3
- name: "4.2.1.4 | PATCH | Ensure rsyslog default file permissions configured"
ansible.builtin.lineinfile:
path: /etc/rsyslog.conf
regexp: '^\$FileCreateMode'
line: '$FileCreateMode 0640'
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_4
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.4
- name: "4.2.1.5 | PATCH | Ensure logging is configured"
block:
- name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out"
ansible.builtin.shell: cat /etc/rsyslog.conf | grep -Ev "^#|^$"
changed_when: false
failed_when: false
check_mode: false
register: rhel_09_4_2_1_5_audit
- name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out"
ansible.builtin.debug:
msg:
- "These are the current logging configurations for rsyslog, please review:"
- "{{ rhel_09_4_2_1_5_audit.stdout_lines }}"
- name: "4.2.1.5 | PATCH | Ensure logging is configured | mail.* log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# mail logging additions to meet CIS standards
mail.* -/var/log/mail
mail.info -/var/log/mail.info
mail.warning -/var/log/mail.warning
mail.err /var/log/mail.err
insertafter: '# Log all the mail messages in one place.'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | news.crit log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} NEWS LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# news logging additions to meet CIS standards
news.crit -/var/log/news/news.crit
news.notice -/var/log/news/news.crit
insertafter: '# Save news errors of level crit and higher in a special file.'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Misc. log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MISC. LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# misc. logging additions to meet CIS standards
*.=warning;*.=err -/var/log/warn
*.crit /var/log/warn
*.*;mail.none;news.none /var/log/messages
insertafter: '#### RULES ####'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Local log settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# local log settings to meet CIS standards
local0,local1.* -/var/log/localmessages
local2,local3.* -/var/log/localmessages
local4,local5.* -/var/log/localmessages
local6,local7.* -/var/log/localmessages
*.emerg :omusrmsg:*
insertafter: '#### RULES ####'
notify: Restart rsyslog
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Auth Settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# Private settings to meet CIS standards
auth,authpriv.* /var/log/secure
insertafter: '#### RULES ####'
notify: Restart rsyslog
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Cron Settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} Cron SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# Cron settings to meet CIS standards
cron.* /var/log/cron
insertafter: '#### RULES ####'
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_5
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.5
- name: "4.2.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
block: |
# target can be IP or FQDN
*.* action(type="omfwd" target="{{ rhel9cis_remote_log_host }}" port="{{ rhel9cis_remote_log_port }}" protocol="{{ rhel9cis_remote_log_protocol }}" action.resumeRetryCount="{{ rhel9cis_remote_log_retrycount }}" queue.type="LinkedList" queue.size="{{ rhel9cis_remote_log_queuesize }}")
insertafter: EOF
register: result
failed_when:
- result is failed
- result.rc != 257
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_6
- rhel9cis_remote_log_server
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.6
- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client"
block:
- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client. | When not log host"
ansible.builtin.replace:
path: /etc/rsyslog.conf
regexp: '{{ item }}'
replace: '#\1'
notify: Restart rsyslog
loop:
- '^(\$ModLoad imtcp)'
- '^(\$InputTCPServerRun)'
- '^(module\(load="imtcp"\))'
- '^(input\(type="imtcp")'
when: not rhel9cis_system_is_log_server
- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote clients. | When log host"
ansible.builtin.replace:
path: /etc/rsyslog.conf
regexp: '^#(.*{{ item }}.*)'
replace: '\1'
notify: Restart rsyslog
loop:
- 'ModLoad imtcp'
- 'InputTCPServerRun'
when: rhel9cis_system_is_log_server
when:
- rhel9cis_rule_4_2_1_7
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.7

View file

@ -1,200 +0,0 @@
---
- name: "4.2.2.1.1 | PATCH | Ensure systemd-journal-remote is installed"
ansible.builtin.package:
name: systemd-journal-remote
state: present
when:
- rhel9cis_rule_4_2_2_1_1
tags:
- level1-server
- level1-workstation
- manual
- patch
- journald
- rule_4.2.2.1.1
- name: "4.2.2.1.2 | PATCH | Ensure systemd-journal-remote is configured"
ansible.builtin.lineinfile:
path: /etc/systemd/journal-upload.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
notify: Restart journald
loop:
- { regexp: 'URL=', line: 'URL={{ rhel9cis_journal_upload_url }}'}
- { regexp: 'ServerKeyFile=', line: 'ServerKeyFile={{ rhel9cis_journal_upload_serverkeyfile }}'}
- { regexp: 'ServerCertificateFile=', line: 'ServerCertificateFile={{ rhel9cis_journal_servercertificatefile }}'}
- { regexp: 'TrustedCertificateFile=', line: 'TrustedCertificateFile={{ rhel9cis_journal_trustedcertificatefile }}'}
when:
- rhel9cis_rule_4_2_2_1_2
tags:
- level1-server
- level1-workstation
- manual
- patch
- journald
- rule_4.2.2.1.2
- name: "4.2.2.1.3 | PATCH | Ensure systemd-journal-remote is enabled"
ansible.builtin.systemd:
name: systemd-journal-upload
state: started
enabled: true
when:
- rhel9cis_system_is_log_server
- rhel9cis_rule_4_2_2_1_3
tags:
- level1-server
- level1-workstation
- manual
- patch
- journald
- rule_4.2.2.1.3
- name: "4.2.2.1.4 | PATCH | Ensure journald is not configured to recieve logs from a remote client"
ansible.builtin.systemd:
name: systemd-journal-remote.socket
state: stopped
enabled: false
masked: true
when:
- not rhel9cis_system_is_log_server
- rhel9cis_rule_4_2_2_1_4
tags:
- level1-server
- level1-workstation
- patch
- journald
- rule_4.2.2.1.4
- name: "4.2.2.2 | PATCH | Ensure journald service is enabled"
block:
- name: "4.2.2.2 | PATCH | Ensure journald service is enabled | Enable service"
ansible.builtin.systemd:
name: systemd-journald
state: started
enabled: true
- name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Capture status"
ansible.builtin.shell: systemctl is-enabled systemd-journald.service
changed_when: false
failed_when: false
register: rhel9cis_4_2_2_2_status
- name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Alert on bad status"
ansible.builtin.debug:
msg:
- "Warning!! The status of systemd-journald should be static and it is not. Please investigate"
when: "'static' not in rhel9cis_4_2_2_2_status.stdout"
- name: "4.2.2.2 | AUDIT | Ensure journald service is enabled | Warn Count"
ansible.builtin.import_tasks:
file: warning_facts.yml
when: "'static' not in rhel9cis_4_2_2_2_status.stdout"
vars:
warn_control_id: '4.2.2.2'
when:
- rhel9cis_rule_4_2_2_2
tags:
- level1-server
- level1-workstation
- audit
- journald
- rule_4.2.2.2
- name: "4.2.2.3 | PATCH | Ensure journald is configured to compress large log files"
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: "^#Compress=|^Compress="
line: Compress=yes
notify: Restart journald
when:
- rhel9cis_rule_4_2_2_3
tags:
- level1-server
- level1-workstation
- patch
- journald
- rule_4.2.2.3
- name: "4.2.2.4 | PATCH | Ensure journald is configured to write logfiles to persistent disk"
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: "^#Storage=|^Storage="
line: Storage=persistent
notify: Restart journald
when:
- rhel9cis_rule_4_2_2_4
tags:
- level1-server
- level1-workstation
- patch
- journald
- rule_4.2.2.4
# This is counter to control 4.2.1.3??
- name: "4.2.2.5 | PATCH | Ensure journald is not configured to send logs to rsyslog"
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: "^ForwardToSyslog="
line: "#ForwardToSyslog=yes"
notify: Restart journald
when:
- rhel9cis_rule_4_2_2_5
tags:
- level1-server
- level2-workstation
- manual
- patch
- journald
- rule_4.2.2.5
- name: "4.2.2.6 | PATCH | Ensure journald log rotation is configured per site policy"
ansible.builtin.lineinfile:
path: /etc/systemd/journald.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
notify: Restart journald
loop:
- { regexp: '^#SystemMaxUse=|^SystemMaxUse=', line: 'SystemMaxUse={{ rhel9cis_journald_systemmaxuse }}'}
- { regexp: '^#SystemKeepFree=|^SystemKeepFree=', line: 'SystemKeepFree={{ rhel9cis_journald_systemkeepfree }}' }
- { regexp: '^#RuntimeMaxUse=|^RuntimeMaxUse=', line: 'RuntimeMaxUse={{ rhel9cis_journald_runtimemaxuse }}'}
- { regexp: '^#RuntimeKeepFree=|^RuntimeKeepFree=', line: 'RuntimeKeepFree={{ rhel9cis_journald_runtimekeepfree }}'}
- { regexp: '^#MaxFileSec=|^MaxFileSec=', line: 'MaxFileSec={{ rhel9cis_journald_maxfilesec }}'}
when:
- rhel9cis_rule_4_2_2_6
tags:
- level1-server
- level1-workstation
- manual
- patch
- journald
- rule_4.2.2.6
- name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured"
block:
- name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Check for override file"
ansible.builtin.stat:
path: /etc/tmpfiles.d/systemd.conf
register: rhel9cis_4_2_2_7_override
- name: "4.2.2.7 | AUDIT | Ensure journald default file permissions configured | Set live file"
ansible.builtin.set_fact:
systemd_conf_file: /etc/tmpfiles.d/systemd.conf
when: rhel9cis_4_2_2_7_override.stat.exists
- name: "4.2.2.7 | PATCH | Ensure journald default file permissions configured | Set permission"
ansible.builtin.lineinfile:
path: "{{ systemd_conf_file | default('/usr/lib/tmpfiles.d/systemd.conf') }}"
regexp: '^z \/var\/log\/journal\/%m\/system.journal (!?06(0|4)0) root'
line: 'z /var/log/journal/%m/system.journal 0640 root systemd-journal - -'
when:
- rhel9cis_rule_4_2_2_7
tags:
- level1-server
- level1-workstation
- manual
- patch
- journald
- rule_4.2.2.7

View file

@ -1,33 +0,0 @@
---
- name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured"
block:
- name: "4.2.3 | AUDIT | Ensure permissions on all logfiles are configured | find files"
ansible.builtin.find:
paths: "/var/log"
file_type: file
recurse: true
hidden: true
register: logfiles
- name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured | change permissions"
ansible.builtin.file:
path: "{{ item.path }}"
mode: "{{ '0600' if item.mode == '0600' else '0640' }}"
failed_when: rhel9cis_4_2_3_file_list.state not in '[ file, absent ]'
register: rhel9cis_4_2_3_file_list
loop: "{{ logfiles.files }}"
loop_control:
label: "{{ item.path }}"
when:
- item.path != "/var/log/btmp"
- item.path != "/var/log/utmp"
- item.path != "/var/log/wtmp"
when:
- rhel9cis_rule_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- logfiles
- rule_4.2.3

View file

@ -0,0 +1,43 @@
---
- name: "4.2.1 | AUDIT | Ensure firewalld drops unnecessary services and ports"
when: rhel9cis_rule_4_2_1
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_4.2.1
- NIST800-55_CA-9
block:
- name: "4.2.1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports"
ansible.builtin.shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done"
changed_when: false
failed_when: false
check_mode: false
register: discovered_services_and_ports
- name: "4.2.1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports"
ansible.builtin.debug:
msg:
- "The items below are the services and ports that are accepted, please correct as needed"
- "{{ discovered_services_and_ports.stdout_lines }}"
- name: "4.2.2 | PATCH | Ensure firewalld loopback traffic is configured | firewalld"
when: rhel9cis_rule_4_2_2
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.2.2
- NIST800-55_CA-9
ansible.posix.firewalld:
rich_rule: "{{ item }}"
zone: "{{ rhel9cis_default_zone }}"
permanent: true
immediate: true
state: enabled
loop:
- rule family="ipv4" source address="127.0.0.1" destination not address="127.0.0.1" drop
- rule family="ipv6" source address="::1" destination not address="::1" drop

View file

@ -0,0 +1,221 @@
---
- name: "OPTIONAL | PATCH | Create Table if doesn't exist and required"
when:
- rhel9cis_nft_tables_autonewtable
- rhel9cis_rule_4_3_1
- rhel9cis_rule_4_3_2
- rhel9cis_rule_4_3_3
- rhel9cis_rule_4_3_4
tags: always
ansible.builtin.command: "nft add table inet {{ rhel9cis_nft_tables_tablename }}"
changed_when: true
- name: "4.3.1 | PATCH | Ensure nftables base chains exist"
when: rhel9cis_rule_4_3_1
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.3.1
- NIST800-55_CA-9
block:
- name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for INPUT"
ansible.builtin.shell: |
nft list ruleset | grep 'hook input'
changed_when: false
failed_when: false
register: discovered_nftables_input_chains
- name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD"
ansible.builtin.shell: |
nft list ruleset | grep 'hook forward'
changed_when: false
failed_when: false
register: discovered_nftables_forward_chains
- name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT"
ansible.builtin.shell: |
nft list ruleset | grep 'hook output'
changed_when: false
failed_when: false
register: discovered_nftables_output_chains
- name: "4.3.1 | AUDIT | Ensure nftables base chains exist | Display chains for review"
when: not rhel9cis_nft_tables_autochaincreate
ansible.builtin.debug:
msg:
- "Below are the current INPUT chains"
- "{{ discovered_nftables_input_chains.stdout_lines }}"
- "Below are the current FORWARD chains"
- "{{ discovered_nftables_forward_chains.stdout_lines }}"
- "Below are teh current OUTPUT chains"
- "{{ discovered_nftables_output_chains.stdout_lines }}"
- name: "4.3.1 | PATCH | Ensure nftables base chains exist | Create chains if needed"
when: rhel9cis_nft_tables_autochaincreate
ansible.builtin.command: "{{ item }}"
changed_when: true
failed_when: false
loop:
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; }
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured"
when: rhel9cis_rule_4_3_2
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.3.2
- NIST800-55_CA-9
block:
- name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather incoming connection rules"
ansible.builtin.shell: |
nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: discovered_nftables_inconnectionrule
- name: "4.3.2 | AUDIT | Ensure nftables established connections are configured | Gather outbound connection rules"
ansible.builtin.command: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: discovered_nftables_outconnectionrule
- name: "4.3.2| PATCH | Ensure nftables established connections are configured | Add input tcp established accept policy"
when: '"ip protocol tcp ct state established accept" not in discovered_nftables_inconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept
changed_when: true
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input udp established accept policy"
when: '"ip protocol udp ct state established accept" not in discovered_nftables_inconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept
changed_when: true
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add input icmp established accept policy"
when: '"ip protocol icmp ct state established accept" not in discovered_nftables_inconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept
changed_when: true
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output tcp new, related, established accept policy"
when: '"ip protocol tcp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept
changed_when: true
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output udp new, related, established accept policy"
when: '"ip protocol udp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept
changed_when: true
- name: "4.3.2 | PATCH | Ensure nftables established connections are configured | Add output icmp new, related, established accept policy"
when: '"ip protocol icmp ct state established,related,new accept" not in discovered_nftables_outconnectionrule.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept
changed_when: true
- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy"
when: rhel9cis_rule_4_3_3
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.3.3
- NIST800-55_CA-9
block:
- name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy"
ansible.builtin.shell: |
nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input'
failed_when: false
changed_when: false
register: discovered_nftables_inputpolicy
- name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy"
ansible.builtin.shell: |
nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward'
failed_when: false
changed_when: false
register: discovered_nftables_forwardpolicy
- name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy"
ansible.builtin.shell: |
nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output'
failed_when: false
changed_when: false
register: discovered_nftables_outputpolicy
- name: "4.3.3 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow"
ansible.builtin.shell: |
nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh'
failed_when: false
changed_when: false
register: discovered_nftables_sshallowcheck
- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic"
when: '"tcp dport ssh accept" not in discovered_nftables_sshallowcheck.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept
changed_when: true
- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy"
when: '"type filter hook input priority 0; policy drop;" not in discovered_nftables_inputpolicy.stdout'
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; }
changed_when: true
- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy"
when: '"type filter hook forward priority 0; policy drop;" not in discovered_nftables_forwardpolicy.stdout'
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; }
changed_when: true
- name: "4.3.3 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy"
when: '"type filter hook output priority 0; policy drop;" not in discovered_nftables_outputpolicy.stdout'
ansible.builtin.command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; }
changed_when: true
- name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured"
when: rhel9cis_rule_4_3_4
tags:
- level1-server
- level1-workstation
- patch
- nftables
- rule_4.3.4
- NIST800-55_CA-9
block:
- name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence | nftables"
ansible.builtin.shell: |
nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept'
changed_when: false
failed_when: false
register: discovered_nftables_iiflo
- name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence | nftables"
ansible.builtin.shell: |
nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr'
changed_when: false
failed_when: false
register: discovered_nftables_ipsaddr
- name: "4.3.4 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence | nftables"
ansible.builtin.shell: |
nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr'
changed_when: false
failed_when: false
register: discovered_nftables_ip6saddr
- name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule | nftables"
when: '"iif \"lo\" accept" not in discovered_nftables_iiflo.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept
changed_when: true
- name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule | nftables"
when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in discovered_nftables_ipsaddr.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop
changed_when: true
- name: "4.3.4 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule | nftables"
when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in discovered_nftables_ip6saddr.stdout'
ansible.builtin.command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop
changed_when: true

View file

@ -1,56 +0,0 @@
---
- name: "4.3 | PATCH | Ensure logrotate is configured"
block:
- name: "4.3 | PATCH | Ensure logrotate is configured | installed"
ansible.builtin.package:
name: rsyslog-logrotate
state: present
- name: "4.3 | PATCH | Ensure logrotate is configured | scheduled"
ansible.builtin.systemd:
name: logrotate.timer
state: started
enabled: true
- name: "4.3 | PATCH | Ensure logrotate is configured | set default conf"
ansible.builtin.replace:
path: "/etc/logrotate.conf"
regexp: '^(\s*)(daily|weekly|monthly|yearly)$'
replace: "\\1{{ rhel9cis_logrotate }}"
- name: "4.3 | AUDIT | Ensure logrotate is configured | Get non default logrotate settings"
ansible.builtin.find:
paths: /etc/logrotate.d/
contains: '^(\s*)(?!{{ rhel9cis_logrotate }})(daily|weekly|monthly|yearly)$'
register: log_rotates
- name: "4.3 | AUDIT | Ensure logrotate is configured"
block:
- name: "4.3 | AUDIT | Ensure logrotate is configured | generate file list"
ansible.builtin.set_fact:
logrotate_non_def_conf: "{{ log_rotates.files | map(attribute='path') | join (', ') }}"
- name: "4.3 | AUDIT | Ensure logrotate is configured | List configured files"
ansible.builtin.debug:
msg: |
"Warning!! The following files are not covered by default logrotate settings ensure they match site policy"
"{{ logrotate_non_def_conf }}"
loop: "{{ log_rotates.files }}"
- name: "4.3 | AUDIT | Ensure logrotate is configured | Warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '4.3'
when: log_rotates.matched > 0
when:
- rhel9cis_rule_4_3
tags:
- level1-server
- level1-workstation
- manual
- patch
- logrotate
- rule_4.3

View file

@ -1,37 +1,15 @@
---
- name: "SECTION | 4.1 | Configure System Accounting (auditd)"
- name: "SECTION | 4.1.x | Configure a firewall"
ansible.builtin.import_tasks:
file: cis_4.1.1.x.yml
when:
- not system_is_container
file: cis_4.1.x.yml
- name: "SECTION | 4.1.2 | Configure Data Retention"
- name: "SECTION | 4.2.x | Configure FirewallD"
when: rhel9cis_firewall == "firewalld"
ansible.builtin.import_tasks:
file: cis_4.1.2.x.yml
file: cis_4.2.x.yml
- name: "SECTION | 4.1.3 | Configure Auditd rules"
- name: "SECTION | 4.3.x | Configure nftables"
when: rhel9cis_firewall == "nftables"
ansible.builtin.import_tasks:
file: cis_4.1.3.x.yml
- name: "SECTION | 4.1.4 | Configure Audit files"
ansible.builtin.import_tasks:
file: cis_4.1.4.x.yml
- name: "SECTION | 4.2.1 | Configure rsyslog"
ansible.builtin.import_tasks:
file: cis_4.2.1.x.yml
when: rhel9cis_syslog == 'rsyslog'
- name: "SECTION | 4.2.2 | Configure journald"
ansible.builtin.import_tasks:
file: cis_4.2.2.x.yml
when: rhel9cis_syslog == 'journald'
- name: "SECTION | 4.2.3 | Configure logile perms"
ansible.builtin.import_tasks:
file: cis_4.2.3.yml
- name: "SECTION | 4.3 | Configure logrotate"
ansible.builtin.import_tasks:
file: cis_4.3.yml
file: cis_4.3.x.yml

View file

@ -1,163 +1,526 @@
---
- name: "5.1.1 | PATCH | Ensure cron daemon is enabled"
ansible.builtin.service:
name: crond
enabled: true
when:
- rhel9cis_rule_5_1_1
- name: "5.1.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured"
when: rhel9cis_rule_5_1_1
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.1
- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured"
- level1-server
- level1-workstation
- patch
- ssh
- permissions
- rule_5.1.1
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.file:
path: /etc/crontab
owner: root
group: root
mode: '0600'
when:
- rhel9cis_rule_5_1_2
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.2
path: "/etc/ssh/sshd_config"
owner: root
group: root
mode: 'go-rwx'
- name: "5.1.3 | PATCH | Ensure permissions on /etc/cron.hourly are configured"
ansible.builtin.file:
path: /etc/cron.hourly
state: directory
owner: root
group: root
mode: '0700'
when:
- rhel9cis_rule_5_1_3
- name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured"
when: rhel9cis_rule_5_1_2
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.3
- name: "5.1.4 | PATCH | Ensure permissions on /etc/cron.daily are configured"
ansible.builtin.file:
path: /etc/cron.daily
state: directory
owner: root
group: root
mode: '0700'
when:
- rhel9cis_rule_5_1_4
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.4
- name: "5.1.5 | PATCH | Ensure permissions on /etc/cron.weekly are configured"
ansible.builtin.file:
path: /etc/cron.weekly
state: directory
owner: root
group: root
mode: '0700'
when:
- rhel9cis_rule_5_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.5
- name: "5.1.6 | PATCH | Ensure permissions on /etc/cron.monthly are configured"
ansible.builtin.file:
path: /etc/cron.monthly
state: directory
owner: root
group: root
mode: '0700'
when:
- rhel9cis_rule_5_1_6
tags:
- level1-server
- level1-workstation
- patch
- rule_5.1.6
- name: "5.1.7 | PATCH | Ensure permissions on /etc/cron.d are configured"
ansible.builtin.file:
path: /etc/cron.d
state: directory
owner: root
group: root
mode: '0700'
when:
- rhel9cis_rule_5_1_7
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.7
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users"
- level1-server
- level1-workstation
- patch
- ssh
- permissions
- rule_5.1.2
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny"
ansible.builtin.file:
path: /etc/cron.deny
state: absent
- name: "5.1.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys"
ansible.builtin.find:
paths: /etc/ssh
patterns: 'ssh_host_*_key'
recurse: true
file_type: any
register: discovered_ssh_private_host_key
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Check if cron.allow exists"
ansible.builtin.stat:
path: "/etc/cron.allow"
register: rhel9cis_5_1_8_cron_allow_state
- name: "5.1.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys"
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
group: root
mode: 'u-x,go-rwx'
loop: "{{ discovered_ssh_private_host_key.files }}"
loop_control:
label: "{{ item.path }}"
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users"
ansible.builtin.file:
path: /etc/cron.allow
state: '{{ "file" if rhel9cis_5_1_8_cron_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: '0600'
when:
- rhel9cis_rule_5_1_8
- name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured"
when: rhel9cis_rule_5_1_3
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.8
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users"
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Remove at.deny"
ansible.builtin.file:
path: /etc/at.deny
state: absent
- name: "5.1.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys"
ansible.builtin.find:
paths: /etc/ssh
patterns: 'ssh_host_*_key.pub'
recurse: true
file_type: any
register: discovered_ssh_public_host_key
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists"
ansible.builtin.stat:
path: "/etc/at.allow"
register: rhel9cis_5_1_9_at_allow_state
- name: "5.1.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys"
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
group: root
mode: 'u-x,go-wx'
loop: "{{ discovered_ssh_public_host_key.files }}"
loop_control:
label: "{{ item.path }}"
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users"
ansible.builtin.file:
path: /etc/at.allow
state: '{{ "file" if rhel9cis_5_1_9_at_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: '0600'
- name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured"
when:
- rhel9cis_rule_5_1_9
- rhel9cis_rule_5_1_4
- "'NO-SSHWEAKCIPHERS' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.9
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_5.1.4
- NIST800-53R5_SC-8
block:
- name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKCIPHERS.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "5.1.4 | PATCH | Ensure sshd Ciphers are configured | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SSHWEAKCIPHERS' }}"
- name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured"
when:
- rhel9cis_rule_5_1_5
- "'NO-SHA1' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_5.1.5
- NIST800-53R5_SC-6
block:
- name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SHA1.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SHA1.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "5.1.5 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':NO-SHA1' }}"
- name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured"
when:
- rhel9cis_rule_5_1_6
- "'NO-SSHWEAKMACS' not in rhel9cis_crypto_policy_module"
tags:
- level1-server
- level1-workstation
- automated
- patch
- crypto
- rule_5.1.6
- NIST800-53R5_SC-6
block:
- name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | Add submodule exclusion"
ansible.builtin.template:
src: etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod.j2
dest: /etc/crypto-policies/policies/modules/NO-SSHWEAKMACS.pmod
owner: root
group: root
mode: 'g-wx,o-rwx'
notify:
- Update Crypto Policy
- Set Crypto Policy
- name: "5.1.6 | PATCH | Ensure sshd KexAlgorithms is configured | submodule to crypto policy modules"
ansible.builtin.set_fact:
rhel9cis_crypto_policy_module: "{{ rhel9cis_crypto_policy_module + ':' + 'NO-SSHWEAKMACS' }}"
- name: "5.1.7 | PATCH | Ensure sshd access is configured"
when: rhel9cis_rule_5_1_7
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.7
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowusers"
when: "rhel9cis_sshd_allowusers | length > 0"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^AllowUsers"
line: "AllowUsers {{ rhel9cis_sshd_allowusers }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for allowgroups"
when: "rhel9cis_sshd_allowgroups | length > 0"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^AllowGroups"
line: "AllowGroups {{ rhel9cis_sshd_allowgroups }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denyusers"
when: "rhel9cis_sshd_denyusers | length > 0"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^DenyUsers"
line: "DenyUsers {{ rhel9cis_sshd_denyusers }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.7 | PATCH | Ensure sshd access is configured | Add line to sshd_config for denygroups"
when: "rhel9cis_sshd_denygroups | length > 0"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^DenyGroups"
line: "DenyGroups {{ rhel9cis_sshd_denygroups }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.8 | PATCH | Ensure sshd Banner is configured"
when: rhel9cis_rule_5_1_8
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.8
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^Banner'
line: 'Banner /etc/issue.net'
- name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured"
when: rhel9cis_rule_5_1_9
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.9
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Add line in sshd_config for ClientAliveInterval"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^ClientAliveInterval'
line: "ClientAliveInterval {{ rhel9cis_sshd_clientaliveinterval }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.9 | PATCH | Ensure sshd ClientAliveInterval and ClientAliveCountMax are configured | Ensure SSH ClientAliveCountMax set to <= 3"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^ClientAliveCountMax'
line: "ClientAliveCountMax {{ rhel9cis_sshd_clientalivecountmax }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled"
when: rhel9cis_rule_5_1_10
tags:
- level2-server
- level1-workstation
- patch
- ssh
- rule_5.1.10
- NIST800-53R5_CM-7
block:
- name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | config file"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(#|)\s*DisableForwarding
line: 'DisableForwarding yes'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.10 | PATCH | Ensure sshd DisableForwarding is enabled | override"
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/50-redhat.conf
regexp: ^(?i)(#|)\s*X11Forwarding
line: 'X11Forwarding {{ rhel9cis_sshd_x11forwarding }}'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled"
when: rhel9cis_rule_5_1_11
tags:
- level1-server
- level1-workstation
- patch
- sshs
- rule_5.1.11
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | redhat file"
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/50-redhat.conf
regexp: ^(?i)(#|)\s*GSSAPIAuthentication
line: GSSAPIAuthentication no
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.11 | PATCH | Ensure sshd GSSAPIAuthentication is disabled | ssh config"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*GSSAPIAuthentication
line: GSSAPIAuthentication no
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.12 | PATCH | Ensure sshd HostbasedAuthentication is disabled"
when: rhel9cis_rule_5_1_12
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.12
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*HostbasedAuthentication
line: 'HostbasedAuthentication no'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.13 | PATCH | Ensure sshd IgnoreRhosts is enabled"
when: rhel9cis_rule_5_1_13
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.13
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*IgnoreRhosts
line: 'IgnoreRhosts yes'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.14 | PATCH | Ensure sshd LoginGraceTime is set to one minute or less"
when: rhel9cis_rule_5_1_14
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.14
- NIST800-53R5_CM-6
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*LoginGraceTime
line: "LoginGraceTime {{ rhel9cis_sshd_logingracetime }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.15 | PATCH | Ensure sshd LogLevel is appropriate"
when: rhel9cis_rule_5_1_15
tags:
- level1-server
- level1-workstation
- patch
- sshs
- rule_5.1.15
- NIST800-53R5_AU-3
- NIST800-53R5_AU-12
- NIST800-53R5_SI-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*LogLevel
line: 'LogLevel {{ rhel9cis_ssh_loglevel }}'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.16 | PATCH | Ensure sshd MaxAuthTries is set to 4 or less"
when: rhel9cis_rule_5_1_16
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.16
- NIST800-53R5_AU-3
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^(#)?MaxAuthTries \d'
line: 'MaxAuthTries {{ rhel9cis_ssh_maxauthtries }}'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.17 | PATCH | Ensure sshd MaxStartups is configured"
when: rhel9cis_rule_5_1_17
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.17
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*MaxStartups
line: 'MaxStartups {{ rhel9cis_ssh_maxstartups }}'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less"
when: rhel9cis_rule_5_1_18
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.18
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*MaxSessions
line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.19 | PATCH | Ensure sshd PermitEmptyPasswords is disabled"
when: rhel9cis_rule_5_1_19
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.19
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*PermitEmptyPasswords
line: 'PermitEmptyPasswords no'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled"
when: rhel9cis_rule_5_1_20
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.20
- NIST800-53R5_AC-6
block:
- name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | config file"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*PermitRootLogin
line: 'PermitRootLogin no'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.20 | PATCH | Ensure sshd PermitRootLogin is disabled | override file"
ansible.builtin.file:
path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf
state: absent
notify: Restart sshd
- name: "5.1.21 | PATCH | Ensure sshd PermitUserEnvironment is disabled"
when: rhel9cis_rule_5_1_21
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.21
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*PermitUserEnvironment
line: 'PermitUserEnvironment no'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.1.22 | PATCH | Ensure SSH PAM is enabled"
when: rhel9cis_rule_5_1_22
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.1.22
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: ^(?i)(#|)\s*UsePAM
line: 'UsePAM yes'
validate: sshd -t -f %s
notify: Restart sshd

View file

@ -1,408 +1,158 @@
---
- name: "5.2.1 | PATCH | Ensure permissions on /etc/ssh/sshd_config are configured"
ansible.builtin.file:
path: "/etc/ssh/sshd_config"
owner: root
group: root
mode: '0600'
when:
- rhel9cis_rule_5_2_1
- name: "5.2.1 | PATCH | Ensure sudo is installed"
when: rhel9cis_rule_5_2_1
tags:
- level1-server
- level1-workstation
- patch
- ssh
- permissions
- rule_5.2.1
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.1
- NIST800-53R5_AC-6
ansible.builtin.package:
name: sudo
state: present
- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured"
- name: "5.2.2 | PATCH | Ensure sudo commands use pty"
when: rhel9cis_rule_5_2_2
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.2
- NIST800-53R5_AC-6
ansible.builtin.lineinfile:
path: /etc/sudoers
line: "Defaults use_pty"
validate: '/usr/sbin/visudo -cf %s'
- name: "5.2.3 | PATCH | Ensure sudo log file exists"
when: rhel9cis_rule_5_2_3
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.3
- NIST800-53R5_AU-3
- NIST800-53R5_AU-12
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: '^Defaults logfile='
line: 'Defaults logfile="{{ rhel9cis_sudolog_location }}"'
validate: '/usr/sbin/visudo -cf %s'
- name: "5.2.4 | PATCH | Ensure users must provide password for escalation"
when: rhel9cis_rule_5_2_4
tags:
- level2-server
- level2-workstation
- patch
- sudo
- rule_5.2.4
- NIST800-53R5_AC-6
block:
- name: "5.2.2 | AUDIT | Ensure permissions on SSH private host key files are configured | Find the SSH private host keys"
ansible.builtin.find:
paths: /etc/ssh
patterns: 'ssh_host_*_key'
recurse: true
file_type: any
register: rhel9cis_5_2_2_ssh_private_host_key
- name: "5.2.4 | AUDIT | Ensure users must provide password for escalation | Discover accts with NOPASSWD"
ansible.builtin.shell: grep -Ei '(nopasswd)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1
become: true
changed_when: false
failed_when: false
register: discovered_nopasswd_sudoers
- name: "5.2.2 | PATCH | Ensure permissions on SSH private host key files are configured | Set permissions on SSH private host keys"
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
group: root
mode: '0600'
loop: "{{ rhel9cis_5_2_2_ssh_private_host_key.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_5_2_2
- name: "5.2.4 | PATCH | Ensure users must provide password for escalation | Remove nopasswd for accounts not excluded"
when: discovered_nopasswd_sudoers.stdout | length > 0
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^((?!#|{% for name in rhel9cis_sudoers_exclude_nopasswd_list %}{{ name }}{% if not loop.last -%}|{%- endif -%}{% endfor %}).*)NOPASSWD(.*)'
replace: '\1PASSWD\2'
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ discovered_nopasswd_sudoers.stdout_lines }}"
- name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally"
when: rhel9cis_rule_5_2_5
tags:
- level1-server
- level1-workstation
- patch
- ssh
- permissions
- rule_5.2.2
- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured"
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.5
- NIST800-53R5_AC-6
block:
- name: "5.2.3 | AUDIT | Ensure permissions on SSH public host key files are configured | Find the SSH public host keys"
ansible.builtin.find:
paths: /etc/ssh
patterns: 'ssh_host_*_key.pub'
recurse: true
file_type: any
register: rhel9cis_5_2_3_ssh_public_host_key
- name: "5.2.5 | AUDIT | Ensure re-authentication for privilege escalation is not disabled globally"
ansible.builtin.shell: grep -Ei '(!authenticate)' /etc/sudoers /etc/sudoers.d/* | cut -d':' -f1
become: true
changed_when: false
failed_when: false
register: discovered_priv_reauth
- name: "5.2.3 | PATCH | Ensure permissions on SSH public host key files are configured | Set permissions on SSH public host keys"
ansible.builtin.file:
path: "{{ item.path }}"
owner: root
group: root
mode: '0644'
loop: "{{ rhel9cis_5_2_3_ssh_public_host_key.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_5_2_3
- name: "5.2.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally"
when: discovered_priv_reauth.stdout | length > 0
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^([^#].*)!authenticate(.*)'
replace: '\1authenticate\2'
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ discovered_priv_reauth.stdout_lines }}"
- name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly"
when: rhel9cis_rule_5_2_6
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.3
- name: "5.2.4 | PATCH | Ensure SSH access is limited"
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.6
block:
- name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowusers"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^AllowUsers"
line: "AllowUsers {{ rhel9cis_sshd['allowusers'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when: "rhel9cis_sshd['allowusers']|default('') | length > 0"
- name: "5.2.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set"
ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort
changed_when: false
failed_when: false
register: discovered_sudo_timeout_files
- name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for allowgroups"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^AllowGroups"
line: "AllowGroups {{ rhel9cis_sshd['allowgroups'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when: "rhel9cis_sshd['allowgroups']|default('') | length > 0"
- name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results"
when: discovered_sudo_timeout_files.stdout | length == 0
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: 'Defaults timestamp_timeout='
line: "Defaults timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}"
validate: '/usr/sbin/visudo -cf %s'
- name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denyusers"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^DenyUsers"
line: "DenyUsers {{ rhel9cis_sshd['denyusers'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when: "rhel9cis_sshd['denyusers']|default('') | length > 0"
- name: "5.2.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results"
when: discovered_sudo_timeout_files.stdout | length > 0
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'timestamp_timeout=(\d+)'
replace: "timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}"
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ discovered_sudo_timeout_files.stdout_lines }}"
- name: "5.2.4 | PATCH | Ensure SSH access is limited | Add line to sshd_config for denygroups"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^DenyGroups"
line: "DenyGroups {{ rhel9cis_sshd['denygroups'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when: "rhel9cis_sshd['denygroups']|default('') | length > 0"
when:
- rhel9cis_rule_5_2_4
- name: "5.2.7 | PATCH | Ensure access to the su command is restricted"
when: rhel9cis_rule_5_2_7
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.4
- name: "5.2.5 | PATCH | Ensure SSH LogLevel is appropriate"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#LogLevel|^LogLevel"
line: 'LogLevel {{ rhel9cis_ssh_loglevel }}'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_5
tags:
- level1-server
- level1-workstation
- patch
- sshs
- rule_5.2.5
- name: "5.2.6 | PATCH | Ensure SSH PAM is enabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#UsePAM|^UsePAM"
line: 'UsePAM yes'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_6
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.6
- name: "5.2.7 | PATCH | Ensure SSH root login is disabled"
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.2.7
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
block:
- name: "5.2.7 | PATCH | Ensure SSH root login is disabled | config file"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#PermitRootLogin|^PermitRootLogin"
line: 'PermitRootLogin no'
validate: sshd -t -f %s
- name: "5.2.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists"
ansible.builtin.group:
name: "{{ rhel9cis_sugroup }}"
state: present
register: discovered_sugroup
- name: "5.2.7 | PATCH | Ensure SSH root login is disabled | override file"
ansible.builtin.file:
path: /etc/ssh/sshd_config.d/01-permitrootlogin.conf
state: absent
notify: Restart sshd
when:
- rhel9cis_rule_5_2_7
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.7
- name: "5.2.7 | PATCH | Ensure access to the su command is restricted | remove users from group"
ansible.builtin.lineinfile:
path: /etc/group
regexp: '^{{ rhel9cis_sugroup }}(:.:.*:).*$'
line: '{{ rhel9cis_sugroup }}\g<1>'
backrefs: true
- name: "5.2.8 | PATCH | Ensure SSH HostbasedAuthentication is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#HostbasedAuthentication|^HostbasedAuthentication"
line: 'HostbasedAuthentication no'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_8
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.8
- name: "5.2.9 | PATCH | Ensure SSH PermitEmptyPasswords is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#PermitEmptyPasswords|^PermitEmptyPasswords"
line: 'PermitEmptyPasswords no'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_9
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.9
- name: "5.2.10 | PATCH | Ensure SSH PermitUserEnvironment is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#PermitUserEnvironment|^PermitUserEnvironment"
line: 'PermitUserEnvironment no'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_10
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.10
- name: "5.2.11 | PATCH | Ensure SSH IgnoreRhosts is enabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#IgnoreRhosts|^IgnoreRhosts"
line: 'IgnoreRhosts yes'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_11
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.11
- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled"
block:
- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | config file"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#X11Forwarding|^X11Forwarding"
line: 'X11Forwarding no'
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.2.12 | PATCH | Ensure SSH X11 forwarding is disabled | override"
ansible.builtin.lineinfile:
path: /etc/ssh/sshd_config.d/50-redhat.conf
regexp: "^#X11Forwarding|^X11Forwarding"
line: 'X11Forwarding no'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_12
tags:
- level2-server
- level1-workstation
- patch
- ssh
- rule_5.2.12
- name: "5.2.13 | PATCH | Ensure SSH AllowTcpForwarding is disabled"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#AllowTcpForwarding|^AllowTcpForwarding"
line: 'AllowTcpForwarding no'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_13
tags:
- level2-server
- level2-workstation
- patch
- ssh
- rule_5.2.13
- name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden"
block:
- name: "5.2.14 | AUDIT | Ensure system-wide crypto policy is not over-ridden"
ansible.builtin.shell: grep -i '^\s*CRYPTO_POLICY=' /etc/sysconfig/sshd
changed_when: false
failed_when: ( ssh_crypto_discovery.rc not in [ 0, 1 ] )
register: ssh_crypto_discovery
- name: "5.2.14 | PATCH | Ensure system-wide crypto policy is not over-ridden"
ansible.builtin.shell: sed -ri "s/^\s*(CRYPTO_POLICY\s*=.*)$/# \1/" /etc/sysconfig/sshd
notify: Restart sshd
when: ssh_crypto_discovery.stdout | length > 0
when:
- rhel9cis_rule_5_2_14
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.14
- name: "5.2.15 | PATCH | Ensure SSH warning banner is configured"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^Banner'
line: 'Banner /etc/issue.net'
notify: Restart sshd
when:
- rhel9cis_rule_5_2_15
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.15
- name: "5.2.16 | PATCH | Ensure SSH MaxAuthTries is set to 4 or less"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^(#)?MaxAuthTries \d'
line: 'MaxAuthTries 4'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_16
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.16
- name: "5.2.17 | PATCH | Ensure SSH MaxStartups is configured"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#MaxStartups|^MaxStartups"
line: 'MaxStartups 10:30:60'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_17
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.17
- name: "5.2.18 | PATCH | Ensure SSH MaxSessions is set to 10 or less"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#MaxSessions|^MaxSessions"
line: 'MaxSessions {{ rhel9cis_ssh_maxsessions }}'
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_18
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.18
- name: "5.2.19 | PATCH | Ensure SSH LoginGraceTime is set to one minute or less"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: "^#LoginGraceTime|^LoginGraceTime"
line: "LoginGraceTime {{ rhel9cis_sshd['logingracetime'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_19
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.19
- name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured"
block:
- name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Add line in sshd_config for ClientAliveInterval"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^ClientAliveInterval'
line: "ClientAliveInterval {{ rhel9cis_sshd['clientaliveinterval'] }}"
validate: sshd -t -f %s
notify: Restart sshd
- name: "5.2.20 | PATCH | Ensure SSH Idle Timeout Interval is configured | Ensure SSH ClientAliveCountMax set to <= 3"
ansible.builtin.lineinfile:
path: "{{ rhel9cis_sshd_config_file }}"
regexp: '^ClientAliveCountMax'
line: "ClientAliveCountMax {{ rhel9cis_sshd['clientalivecountmax'] }}"
validate: sshd -t -f %s
notify: Restart sshd
when:
- rhel9cis_rule_5_2_20
tags:
- level1-server
- level1-workstation
- patch
- ssh
- rule_5.2.20
- name: "5.2.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid"
ansible.builtin.lineinfile:
path: /etc/pam.d/su
regexp: '^(#)?auth\s+required\s+pam_wheel\.so'
line: 'auth required pam_wheel.so use_uid group={{ rhel9cis_sugroup }}'

View file

@ -0,0 +1,55 @@
---
- name: "5.3.1.1 | PATCH | Ensure latest version of pam is installed"
when:
- rhel9cis_rule_5_3_1_1
- ansible_facts.packages['pam'][0]['version'] is version('1.5.1-19', '<') or
"'pam' not in ansible_facts.packages"
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.1.1
ansible.builtin.package:
name: pam
state: latest
- name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed"
when:
- rhel9cis_rule_5_3_1_2
- rhel9cis_authselect_pkg_update
- ansible_facts.packages['authselect'][0]['version'] is version('1.2.6-2', '<') or
"'authselect' not in ansible_facts.packages"
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.1.2
block:
- name: "5.3.1.2 | PATCH | Ensure latest version of authselect is installed | Patch"
ansible.builtin.package:
name: authselect
state: latest
register: discovered_authselect_updated
- name: "5.3.1.2 | AUDIT | Ensure latest version of authselect is installed | Patch"
when: discovered_authselect_updated.changed # noqa no-handler
ansible.builtin.set_fact:
authselect_update: OK
- name: "5.3.1.3 | PATCH | Ensure libpwquality is installed"
when:
- rhel9cis_rule_5_3_1_3
- ansible_facts.packages['libpwquality'][0]['version'] is version('1.4.4-8', '<') or
"'libpwquality' not in ansible_facts.packages"
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.1.3
ansible.builtin.package:
name: libpwquality
state: latest

View file

@ -0,0 +1,175 @@
---
- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules"
when:
- rhel9cis_rule_5_3_2_1
- rhel9cis_disruption_high
- rhel9cis_allow_authselect_updates
tags:
- level1-server
- level1-workstation
- manual
- patch
- authselect
- rule_5.3.2.1
block:
- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Create custom profiles"
when:
- rhel9cis_authselect_custom_profile_name not in prelim_authselect_current_profile.stdout or
prelim_authselect_current_profile.stdout is not defined
ansible.builtin.command: "/usr/bin/authselect create-profile {{ rhel9cis_authselect_custom_profile_name }} -b {{ rhel9cis_authselect_default_profile_to_copy }}"
changed_when: false
args:
creates: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}"
- name: "5.3.2.1 | AUDIT | Ensure active authselect profile includes pam modules | get profile features"
ansible.builtin.command: "/usr/bin/authselect list-features custom/{{ rhel9cis_authselect_custom_profile_name }}"
changed_when: false
register: discovered_authselect_profile_features
- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Add missing pam modules to config | pwquality"
when: "'with-pwquality' not in discovered_authselect_profile_features.stdout_lines"
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^password\s*requisite\s*pam_pwquality.so.*
line: password requisite pam_pwquality.so local_users_only {include if "with-pwquality"}
loop:
- system
- password
- name: "5.3.2.1 | PATCH | Ensure active authselect profile includes pam modules | Backup and Add pam modules"
ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %} --force --backup=rhel9cis-preremediate-{{ lookup('pipe', 'date +%Y-%m-%d-%H%M') }}"
changed_when: true
- name: "5.3.2.2 | PATCH | Ensure pam_faillock module is enabled"
when:
- rhel9cis_rule_5_3_2_2
- rhel9cis_disruption_high
- rhel9cis_allow_authselect_updates
tags:
- level1-server
- level1-workstation
- automated
- patch
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
- authselect
- rule_5.3.2.2
notify: Authselect update
block:
- name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Get current config"
ansible.builtin.shell: |
authselect current | grep faillock
changed_when: false
failed_when: discovered_authselect_current_faillock.rc not in [ 0, 1 ]
register: discovered_authselect_current_faillock
- name: "5.3.2.2 | AUDIT | Ensure pam_faillock module is enabled | Add feature if missing" # noqa syntax-check[specific]"
when: discovered_authselect_current_faillock.rc != 0
ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}"
changed_when: true
- name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled"
when:
- rhel9cis_rule_5_3_2_3
- rhel9cis_disruption_high
- rhel9cis_allow_authselect_updates
tags:
- level1-server
- level1-workstation
- automated
- patch
- NIST800-53R5_IA-5
- authselect
- rule_5.3.2.3
block:
- name: "5.3.2.3 | AUDIT | Ensure pam_pwquality module is enabled | Get current config"
ansible.builtin.shell: |
authselect current | grep quality
changed_when: false
failed_when: discovered_authselect_current_quality.rc not in [ 0, 1 ]
register: discovered_authselect_current_quality
- name: "5.3.2.3 | PATCH | Ensure pam_pwquality module is enabled | Add feature if missing"
when: discovered_authselect_current_quality.rc != 0
ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}"
changed_when: true
notify: Authselect update
- name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled"
when:
- rhel9cis_rule_5_3_2_4
- rhel9cis_disruption_high
- rhel9cis_allow_authselect_updates
tags:
- level1-server
- level1-workstation
- automated
- patch
- NIST800-53R5_IA-5
- authselect
- rule_5.3.2.4
block:
- name: "5.3.2.4 | AUDIT | Ensure pam_pwhistory module is enabled | Get current config"
ansible.builtin.shell: |
authselect current | grep pwhistory
changed_when: false
failed_when: discovered_authselect_current_history.rc not in [ 0, 1 ]
register: discovered_authselect_current_history
- name: "5.3.2.4 | PATCH | Ensure pam_pwhistory module is enabled | enable feature"
when: discovered_authselect_current_history.rc != 0
ansible.builtin.command: "/usr/bin/authselect select custom/{{ rhel9cis_authselect_custom_profile_name }}{% if rhel9cis_rule_5_3_2_2 %} with-faillock{% endif %}{% if rhel9cis_rule_5_3_2_3 %} with-pwquality{% endif %}{% if rhel9cis_rule_5_3_2_4 %} with-pwhistory{% endif %}{% if rhel9cis_rule_5_3_3_4_1 %} without-nullok{% endif %}"
changed_when: true
notify: Authselect update
- name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled"
when:
- rhel9cis_rule_5_3_2_5
- rhel9cis_disruption_high
- rhel9cis_allow_authselect_updates
tags:
- level1-server
- level1-workstation
- automated
- patch
- NIST800-53R5_IA-5
- authselect
- rule_5.3.2.5
block:
- name: "5.3.2.5 | AUDIT | Ensure pam_unix module is enabled"
ansible.builtin.command: grep -P -- '\b(pam_unix\.so)\b' /etc/authselect/"$(head -1 /etc/authselect/authselect.conf)"/{system,password}-auth
changed_when: false
failed_when: discovered_discovered_authselect_pam_unix.rc not in [ 0, 1 ]
register: discovered_discovered_authselect_pam_unix
- name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | system-auth"
when: "'system-auth:password' not in discovered_authselect_pam_unix.stdout"
ansible.builtin.lineinfile:
path: /etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/system-auth
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
backrefs: true
insertafter: "{{ item.after | default(omit) }}"
insertbefore: "{{ item.before | default(omit) }}"
loop:
- { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', after: '^auth.*pam_faillock.*preauth' }
- { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' }
notify: Authselect update
- name: "5.3.2.5 | PATCH | Ensure pam_unix module is enabled | password-auth"
when: "'password-auth:password' not in discovered_authselect_pam_unix.stdout"
ansible.builtin.lineinfile:
path: /etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/password-auth
line: "{{ item.line }}"
regexp: "{{ item.regexp }}"
backrefs: true
insertafter: "{{ item.after | default(omit) }}"
insertbefore: "{{ item.before | default(omit) }}"
loop:
- { regexp: '^(auth\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\2', after: '^auth.*pam_faillock.*preauth' }
- { regexp: '^(password\s+)sufficient(\s+pam_unix.so.*)(.*)', line: '\1sufficient\2\3', before: '^password.*pam_deny.so' }
notify: Authselect update

View file

@ -0,0 +1,129 @@
---
- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured"
when: rhel9cis_rule_5_3_3_1_1
tags:
- level1-server
- level1-workstation
- automated
- patch
- pam
- rule_5.3.3.1.1
block:
- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | faillock.conf"
ansible.builtin.lineinfile:
path: /etc/security/faillock.conf
state: present
regexp: '^(#|)\s*deny\s*=\s*\d'
line: "deny = {{ rhel9cis_pam_faillock_deny }}"
- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | remove deny from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | remove deny from AuthSelect config"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+deny\s*=\s*\S+(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured"
when: rhel9cis_rule_5_3_3_1_2
tags:
- level1-server
- level1-workstation
- automated
- patch
- pam
- rule_5.3.3.1.2
block:
- name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | faillock.conf"
ansible.builtin.lineinfile:
path: /etc/security/faillock.conf
state: present
regexp: '^(#|)\s*unlock_time\s*=\s*\d'
line: "unlock_time = {{ rhel9cis_pam_faillock_unlock_time }}"
- name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | remove unlock from pam files NOT AuthSelect"
when:
- rhel9cis_disruption_high
- not rhel9cis_allow_authselect_updates
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | remove unlock from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s+unlock_time\s*=\s*\S+(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account"
when: rhel9cis_rule_5_3_3_1_3
tags:
- level1-server
- level1-workstation
- automated
- patch
- pam
- rule_5.3.3.1.3
block:
- name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | configure faillock.conf"
ansible.builtin.lineinfile:
path: /etc/security/faillock.conf
regexp: '^{{ rhel9cis_pamroot_lock_option }}'
line: "{{ rhel9cis_pamroot_lock_option }}"
insertafter: '^# end of pam-auth-update config'
create: true
mode: 'u-x,go-wx'
- name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files NOT AuthSelect"
when:
- rhel9cis_disruption_high
- not rhel9cis_allow_authselect_updates
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$)
replace: \1\2\4
loop:
- password
- system
- name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | remove lockout from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*auth\s+(requisite|required|sufficient)\s+pam_faillock\.so)(.*)\s(even_deny_root|root_unlock_time=\d*)"(\s*=\s*\d|.*)\S+(.*$)
replace: \1\2\4
loop:
- password
- system
notify: Authselect update

View file

@ -0,0 +1,351 @@
---
- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured"
when: rhel9cis_rule_5_3_3_2_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.1
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from conf files except expected file"
when:
- item != rhel9cis_passwd_difok_file
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'difok\s*=\s*\d+\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- /etc/pam.d/*-auth
- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_difok_file }}.j2"
dest: "/{{ rhel9cis_passwd_difok_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from pam files Not AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdifok=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdifok=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.2 | PATCH | Ensure password length is configured"
when: rhel9cis_rule_5_3_3_2_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.2
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from conf files except expected file"
when:
- item != rhel9cis_passwd_minlen_file
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'minlen\s*=\s*\d+\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- '/etc/pam.d/*-auth'
- name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_minlen_file }}.j2"
dest: "/{{ rhel9cis_passwd_minlen_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sminlen=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sminlen=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured"
when: rhel9cis_rule_5_3_3_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.3
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove pwd complex settings from conf files except expected file"
when:
- item != rhel9cis_passwd_complex_file
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "{{ item }}"
regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- '/etc/pam.d/*-auth'
- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_complex_file }}.j2"
dest: "/{{ rhel9cis_passwd_complex_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove complexity from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s(minclass=[0-3]|[dulo]credit=[^-]\d*)(.*$)
replace: \1\2\4
loop:
- password
- system
- name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove complexity from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\s(minclass=[0-3]|[dulo]credit=[^-]\d*)(.*$)
replace: \1\2\4
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured"
when: rhel9cis_rule_5_3_3_2_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.4
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file"
when: item != rhel9cis_passwd_maxrepeat_file
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'maxrepeat\s*=\s*\d+\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- '/etc/pam.d/*-auth'
- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_maxrepeat_file }}.j2"
dest: "/{{ rhel9cis_passwd_maxrepeat_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxrepeat\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxrepeat\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is is configured"
when: rhel9cis_rule_5_3_3_2_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.5
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence settings from conf files except expected file"
when:
- item != rhel9cis_passwd_maxsequence_file
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'maxsequence\s*=\s*\d+\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- '/etc/pam.d/*-auth'
- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_maxsequence_file }}.j2"
dest: "/{{ rhel9cis_passwd_maxsequence_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxsequence\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\smaxsequence\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled"
when: rhel9cis_rule_5_3_3_2_6
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.6
- NIST800-53R5_IA-5
- pam
block:
- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck settings from conf files except expected file"
when:
- item != rhel9cis_passwd_dictcheck_file
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'dictcheck\s*=\s*\d+\b'
replace: ''
with_fileglob:
- '/etc/security/pwquality.conf'
- '/etc/security/pwquality.conf.d/*.conf'
- '/etc/pam.d/*-auth'
- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists"
ansible.builtin.template:
src: "{{ rhel9cis_passwd_dictcheck_file }}.j2"
dest: "/{{ rhel9cis_passwd_dictcheck_file }}"
owner: root
group: root
mode: 'go-rwx'
- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdictcheck\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwquality\.so)(.*)\sdictcheck\s*=\s*\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.2.7 | PATCH | Ensure password quality is enforced for the root user"
when: rhel9cis_rule_5_3_3_2_7
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.2.7
- NIST800-53R5_IA-5
- pam
ansible.builtin.template:
src: "{{ rhel9cis_passwd_quality_enforce_root_file }}.j2"
dest: "/{{ rhel9cis_passwd_quality_enforce_root_file }}"
owner: root
group: root
mode: 'o-rwx'

View file

@ -0,0 +1,140 @@
---
- name: "5.3.3.3.1 | PATCH | Ensure password history remember is configured"
when: rhel9cis_rule_5_3_3_3_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.3.1
- pam
block:
- name: "5.3.3.3.1 | AUDIT | Ensure password history remember is configured | Check existing files"
ansible.builtin.shell: grep -Psi -- '^\h*password\s+[^#\n\r]+\h+pam_pwhistory\.so\s+([^#\n\r]+\s+)?remember=\d+\b' /etc/pam.d/password-auth /etc/pam.d/system-auth
changed_when: false
failed_when: discovered_pwhistory_remember.rc not in [0, 1]
register: discovered_pwhistory_remember
- name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Ensure remember is set pwhistory file"
ansible.builtin.lineinfile:
path: "/etc/security/pwhistory.conf"
regexp: remember\s*=\s*\d*
line: remember = {{ rhel9cis_pamd_pwhistory_remember }}
- name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files NOT AuthSelect"
when:
- not rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\sremember=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
- name: "5.3.3.3.1 | PATCH | Ensure password number of changed characters is configured | Remove remember from pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\sremember=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user"
when: rhel9cis_rule_5_3_3_3_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.3.2
- pam
block:
- name: "5.3.3.3.2 | AUDIT | Ensure password history is enforced for the root user | Check existing files"
ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?enforce_for_root\b' /etc/pam.d/{system,password}-auth
register: discovered_pwhistory_enforce_for_root
changed_when: false
failed_when: discovered_pwhistory_enforce_for_root.rc not in [0, 1]
- name: "5.3.3.3.2 | PATCH| Ensure password history is enforced for the root user | Ensure enforce_for_root is set pwhistory file"
ansible.builtin.lineinfile:
path: "/etc/security/pwhistory.conf"
regexp: ^\s*(?#)enforce_for_root
line: enforce_for_root
- name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set"
when:
- not rhel9cis_allow_authselect_updates
- discovered_pwhistory_enforce_for_root.stdout | length == 0
- rhel9cis_disruption_high
ansible.builtin.lineinfile:
path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}"
regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(enforce_for_root)
line: '\1\2\3 enforce_for_root'
backrefs: true
- name: "5.3.3.3.2 | PATCH | Ensure password history is enforced for the root user | Ensure enforce_for_root is set"
when:
- rhel9cis_allow_authselect_updates
- discovered_pwhistory_enforce_for_root.stdout | length == 0
- rhel9cis_disruption_high
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\senforce_for_root(.*$)
replace: \1\2enforce_for_root\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok"
when: rhel9cis_rule_5_3_3_3_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.3.3
- pam
block:
- name: "5.3.3.3.3 | AUDIT | Ensure pam_pwhistory includes use_authtok | Check existing files"
ansible.builtin.shell: grep -Psi -- '^\h*password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+([^#\n\r]+\h+)?use_authtok\b' /etc/pam.d/{system,password}-auth
register: discovered_pwhistory_use_authtok
changed_when: false
failed_when: discovered_pwhistory_use_authtok.rc not in [0, 1]
- name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Update pwhistory for use_authtok"
ansible.builtin.lineinfile:
path: "/etc/security/pwhistory.conf"
regexp: ^\s*(?#)use_authtok
line: use_authtok
- name: "5.3.3.3.3 | PATCH | Ensure pam_pwhistory includes use_authtok | Ensure use_authtok is set"
when:
- not rhel9cis_allow_authselect_updates
- discovered_pwhistory_use_authtok.stdout | length == 0
- rhel9cis_disruption_high
ansible.builtin.lineinfile:
path: "/{{ rhel9cis_pam_confd_dir }}{{ rhel9cis_pam_pwhistory_file }}"
regexp: ^(password\h+[^#\n\r]+\h+pam_pwhistory\.so\h+)(.*)(use_authtok)
line: '\1\2 use_authtok'
backrefs: true
- name: "PATCH | Ensure pam_pwhistory includes use_authtok | add authtok to pam files AuthSelect"
when:
- rhel9cis_allow_authselect_updates
- discovered_pwhistory_use_authtok.stdout | length == 0
- rhel9cis_disruption_high
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_pwhistory\.so)(.*)\suse_authtok(.*$)
line: \1\2 use_authtok\3
backrefs: true
loop:
- password
- system
notify: Authselect update

View file

@ -0,0 +1,159 @@
---
- name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok"
when:
- rhel9cis_rule_5_3_3_4_1
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- rule_5.3.3.4.1
- pam
block:
- name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | capture state"
ansible.builtin.shell: grep -E "pam_unix.so.*nullok" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq
changed_when: false
failed_when: discovered_pam_nullok.rc not in [ 0, 1 ]
register: discovered_pam_nullok
- name: "5.3.3.4.1 | PATCH | Ensure pam_unix does not include nullok | Ensure nullok removed"
when:
- discovered_pam_nullok.stdout | length > 0
- not rhel9cis_allow_authselect_updates
ansible.builtin.replace:
path: "{{ item }}"
regexp: nullok
replace: ''
loop: "{{ discovered_pam_nullok.stdout_lines }}"
- name: "5.3.3.4.1 | PATCH | Ensure password number of changed characters is configured | Remove nullok from pam files AuthSelect"
when: rhel9cis_allow_authselect_updates
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\snullok(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember"
when:
- rhel9cis_rule_5_3_3_4_2
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.3.4.2
block:
- name: "5.3.3.4.2 | AUDIT | Ensure pam_unix does not include remember | capture state"
ansible.builtin.shell: grep -E "password.*pam_unix.so.*remember" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq
changed_when: false
failed_when: discovered_pam_remember.rc not in [ 0, 1 ]
register: discovered_pam_remember
- name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Ensure remember removed"
when:
- not rhel9cis_allow_authselect_updates
- discovered_pam_remember.stdout | length > 0
ansible.builtin.replace:
path: "{{ item }}"
regexp: remember
replace: ''
loop: "{{ discovered_pam_remember.stdout_lines }}"
- name: "5.3.3.4.2 | PATCH | Ensure pam_unix does not include remember | Remove remember from pam files AuthSelect"
when: rhel9cis_allow_authselect_updates
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+(requisite|required|sufficient)\s+pam_unix\.so)(.*)\sremember\s*=\s*=\d*(.*$)
replace: \1\2\3
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm"
when:
- rhel9cis_rule_5_3_3_4_3
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.3.4.3
- NIST800-53R5_IA-5
block:
- name: "5.3.3.4.3 | AUDIT | Ensure pam_unix includes a strong password hashing algorithm | capture state"
ansible.builtin.shell: grep -E "password.*pam_unix.so.*(sha512|yescrypt)" /etc/pam.d/*-auth | cut -d ':' -f1 | uniq
changed_when: false
failed_when: discovered_pam_pwhash.rc not in [ 0, 1 ]
register: discovered_pam_pwhash
- name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Ensure hash algorithm set"
when:
- not rhel9cis_allow_authselect_updates
- discovered_pam_remember.stdout | length > 0
ansible.builtin.replace:
path: "{{ item }}"
regexp: "(md5|bigcrypt|sha256|blowfish|gost_yescrypt|sha512|yescrypt)"
replace: '{{ rhel9cis_passwd_hash_algo }}'
loop: "{{ discovered_pam_remember.stdout_lines }}"
- name: "5.3.3.4.3 | PATCH | Ensure pam_unix includes a strong password hashing algorithm | Add hash algorithm to pam files AuthSelect"
when: rhel9cis_allow_authselect_updates
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)(sha512|yescrypt)(.*$)
line: \1\2\3\4{{ rhel9cis_passwd_hash_algo }}\6
backrefs: true
loop:
- password
- system
notify: Authselect update
- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok"
when:
- rhel9cis_rule_5_3_3_4_4
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- pam
- rule_5.3.3.4.4
- NIST800-53R5_IA-5
block:
- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | capture state"
ansible.builtin.shell: grep -PH -- '^\h*^password\h*[^#\n\r]+\h+pam_unix.so\b' /etc/pam.d/{password,system}-auth | grep -Pv -- '\buse_authtok\b'
changed_when: false
failed_when: discovered_pam_authtok.rc not in [ 0, 1 ]
register: discovered_pam_authtok
- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | pam_files"
when:
- not rhel9cis_allow_authselect_updates
- discovered_pam_authtok is defined
- discovered_pam_authtok.stdout | length > 0
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$)
line: \1\2\3\4use_authtok \5
backrefs: true
loop: "{{ discovered_pam_authtok.stdout_lines }}"
- name: "5.3.3.4.4 | PATCH | Ensure pam_unix includes use_authtok | Add use_authtok pam files AuthSelect"
when: rhel9cis_allow_authselect_updates
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect_custom_profile_name }}/{{ item }}-auth"
regexp: ^(\s*password\s+)(requisite|required|sufficient)(\s+pam_unix.so\s)(.*)use_authtok(.*$)
line: \1\2\3\4use_authtok\5
backrefs: true
loop:
- password
- system
notify: Authselect update

View file

@ -1,138 +0,0 @@
---
- name: "5.3.1 | PATCH | Ensure sudo is installed"
ansible.builtin.package:
name: sudo
state: present
when:
- rhel9cis_rule_5_3_1
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.1
- name: "5.3.2 | PATCH | Ensure sudo commands use pty"
ansible.builtin.lineinfile:
path: /etc/sudoers
line: "Defaults use_pty"
validate: '/usr/sbin/visudo -cf %s'
when:
- rhel9cis_rule_5_3_2
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.2
- name: "5.3.3 | PATCH | Ensure sudo log file exists"
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: '^Defaults logfile='
line: 'Defaults logfile="{{ rhel9cis_sudolog_location }}"'
validate: '/usr/sbin/visudo -cf %s'
when:
- rhel9cis_rule_5_3_3
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.3
- name: "5.3.4 | PATCH | Ensure users must provide password for escalation"
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^([^#|{% if system_is_ec2 %}ec2-user{% endif %}].*)NOPASSWD(.*)'
replace: '\1PASSWD\2'
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ rhel9cis_sudoers_files.stdout_lines }}"
when:
- rhel9cis_rule_5_3_4
tags:
- level2-server
- level2-workstation
- patch
- sudo
- rule_5.3.4
- name: "5.3.5 | PATCH | Ensure re-authentication for privilege escalation is not disabled globally"
ansible.builtin.replace:
path: "{{ item }}"
regexp: '^([^#].*)!authenticate(.*)'
replace: '\1authenticate\2'
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ rhel9cis_sudoers_files.stdout_lines }}"
when:
- rhel9cis_rule_5_3_5
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.5
- name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly"
block:
- name: "5.3.6 | AUDIT | Ensure sudo authentication timeout is configured correctly | Get files with timeout set"
ansible.builtin.shell: grep -is 'timestamp_timeout' /etc/sudoers /etc/sudoers.d/* | cut -d":" -f1 | uniq | sort
changed_when: false
failed_when: false
register: rhel9cis_5_3_6_timeout_files
- name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if no results"
ansible.builtin.lineinfile:
path: /etc/sudoers
regexp: 'Defaults timestamp_timeout='
line: "Defaults timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}"
validate: '/usr/sbin/visudo -cf %s'
when: rhel9cis_5_3_6_timeout_files.stdout | length == 0
- name: "5.3.6 | PATCH | Ensure sudo authentication timeout is configured correctly | Set value if has results"
ansible.builtin.replace:
path: "{{ item }}"
regexp: 'timestamp_timeout=(\d+)'
replace: "timestamp_timeout={{ rhel9cis_sudo_timestamp_timeout }}"
validate: '/usr/sbin/visudo -cf %s'
loop: "{{ rhel9cis_5_3_6_timeout_files.stdout_lines }}"
when: rhel9cis_5_3_6_timeout_files.stdout | length > 0
when:
- rhel9cis_rule_5_3_6
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.6
- name: "5.3.7 | PATCH | Ensure access to the su command is restricted"
block:
- name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Ensure sugroup exists"
ansible.builtin.group:
name: "{{ rhel9cis_sugroup }}"
state: present
register: rhel9cis_5_3_7_sugroup
- name: "5.3.7 | PATCH | Ensure access to the su command is restricted | remove users from group"
ansible.builtin.lineinfile:
path: /etc/group
regexp: '^{{ rhel9cis_sugroup }}(:.:.*:).*$'
line: '{{ rhel9cis_sugroup }}\g<1>'
backrefs: true
- name: "5.3.7 | PATCH | Ensure access to the su command is restricted | Setting pam_wheel to use_uid"
ansible.builtin.lineinfile:
path: /etc/pam.d/su
regexp: '^(#)?auth\s+required\s+pam_wheel\.so'
line: 'auth required pam_wheel.so use_uid group={{ rhel9cis_sugroup }}'
when:
- rhel9cis_rule_5_3_7
tags:
- level1-server
- level1-workstation
- patch
- sudo
- rule_5.3.7

View file

@ -0,0 +1,192 @@
---
- name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less"
when: rhel9cis_rule_5_4_1_1
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.4.1.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_MAX_DAYS'
line: "PASS_MAX_DAYS {{ rhel9cis_pass_max_days }}"
- name: "5.4.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS"
ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass_max_days }} || $5< {{ rhel9cis_pass_max_days }} || $5 == -1)){print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_max_days
- name: "5.4.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS"
when:
- discovered_max_days.stdout_lines | length > 0
- item in prelim_interactive_usernames.stdout
- rhel9cis_force_user_maxdays
ansible.builtin.user:
name: "{{ item }}"
password_expire_max: "{{ rhel9cis_pass_max_days }}"
loop: "{{ discovered_max_days.stdout_lines }}"
- name: "5.4.1.2 | PATCH | Ensure minimum password days is configured"
when: rhel9cis_rule_5_4_1_2
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.4.1.2
block:
- name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | set login.defs"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_MIN_DAYS'
line: "PASS_MIN_DAYS {{ rhel9cis_pass_min_days }}"
- name: "5.4.1.2 | AUDIT | Ensure minimum password days is configured | Get existing users PASS_MIN_DAYS"
ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass_min_days }} {print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_min_days
- name: "5.4.1.2 | PATCH | Ensure minimum password days is configured | Set existing users PASS_MIN_DAYS"
when:
- discovered_min_days.stdout_lines | length > 0
- item in prelim_interactive_usernames.stdout
- rhel9cis_force_user_mindays
ansible.builtin.user:
name: "{{ item }}"
password_expire_max: "{{ rhel9cis_pass_min_days }}"
loop: "{{ discovered_min_days.stdout_lines }}"
- name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured"
when: rhel9cis_rule_5_4_1_3
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.4.1.3
block:
- name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | set login.defs"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_WARN_AGE'
line: "PASS_WARN_AGE {{ rhel9cis_pass_warn_age }}"
- name: "5.4.1.3 | AUDIT | Ensure password expiration warning days is configured | Get existing users WARN_DAYS"
ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass_warn_age }} {print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_warn_days
- name: "5.4.1.3 | PATCH | Ensure password expiration warning days is configured | Set existing users WARN_DAYS"
when:
- discovered_warn_days.stdout_lines | length > 0
- item in prelim_interactive_usernames.stdout
- rhel9cis_force_user_warnage
ansible.builtin.command: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}"
changed_when: true
loop: "{{ discovered_warn_days.stdout_lines }}"
- name: "5.4.1.4 | PATCH | Ensure strong password hashing algorithm is configured"
when: rhel9cis_rule_5_4_1_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.4.1.4
- pam
- NIST800-53R5_IA-5
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^ENCRYPT_METHOD'
line: 'ENCRYPT_METHOD {{ rhel9cis_passwd_hash_algo | upper }}'
- name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured"
when: rhel9cis_rule_5_4_1_5
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.4.1.5
block:
- name: "5.4.1.5 | AUDIT | Ensure inactive password lock is configured | Check current settings"
ansible.builtin.shell: |
useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d=
changed_when: false
failed_when: false
check_mode: false
register: discovered_passwdlck_inactive_settings
- name: "5.4.1.5 | PATCH | Ensure inactive password lock is configured | Set default inactive setting"
when: discovered_passwdlck_inactive_settings.stdout | length == 0
ansible.builtin.command: useradd -D -f {{ rhel9cis_inactivelock.lock_days }}
changed_when: true
- name: "5.4.1.5 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list"
ansible.builtin.command: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow"
changed_when: false
check_mode: false
register: discovered_passwdlck_user_list
- name: "5.4.1.5 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts"
when: item in prelim_interactive_usernames.stdout
ansible.builtin.command: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}"
changed_when: true
loop: "{{ discovered_passwdlck_user_list.stdout_lines }}"
- name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past"
when: rhel9cis_rule_5_4_1_6
tags:
- level1-server
- level1-workstation
- patch
- rule_5.4.1.6
vars:
warn_control_id: '5.4.1.6'
block:
- name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time"
ansible.builtin.shell: echo $(($(date --utc --date "$1" +%s)/86400))
changed_when: false
failed_when: false
check_mode: false
register: discovered_passwdlck_currentunixtime
- name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future"
ansible.builtin.shell: "cat /etc/shadow | awk -F: '{if($3>{{ discovered_passwdlck_currentunixtime.stdout }})print$1}'"
changed_when: false
failed_when: false
check_mode: false
register: discovered_passwdlck_user_future
- name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future"
when:
- discovered_passwdlck_user_future.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
ansible.builtin.debug:
msg: "Warning!! The following accounts have the last PW change date in the future: {{ discovered_passwdlck_user_future.stdout_lines }}"
- name: "5.4.1.6 | AUDIT | Ensure all users last password change date is in the past | warning count"
when:
- discovered_passwdlck_user_future.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
ansible.builtin.import_tasks:
file: warning_facts.yml
- name: "5.4.1.6 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future"
when:
- discovered_passwdlck_user_future.stdout | length > 0
- rhel9cis_futurepwchgdate_autofix
ansible.builtin.command: passwd --expire {{ item }}
changed_when: true
loop: "{{ discovered_passwdlck_user_future.stdout_lines }}"

View file

@ -0,0 +1,240 @@
---
- name: "5.4.2.1 | PATCH | Ensure root is the only UID 0 account"
when:
- rhel9cis_rule_5_4_2_1
- prelim_uid_zero_accounts_except_root.rc
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- accounts
- users
- rule_5.4.2.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.command: passwd -l {{ item }}
changed_when: false
failed_when: false
loop: "{{ prelim_uid_zero_accounts_except_root.stdout_lines }}"
- name: "5.4.2.2 | PATCH | Ensure root is the only GID 0 account"
when:
- rhel9cis_rule_5_4_2_2
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- rule_5.4.2.2
- user
- system
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.4.2.2 | AUDIT | Ensure root is the only GID 0 account | Get members of gid 0"
ansible.builtin.shell: "awk -F: '($1 !~ /^(sync|shutdown|halt|operator)/ && $4==\"0\") {print $1}' /etc/passwd | grep -wv 'root'"
register: discovered_gid0_members
changed_when: false
failed_when: discovered_gid0_members.rc not in [ 0, 1 ]
- name: "5.4.2.2 | PATCH | Ensure root is the only GID 0 account | Remove users not root from gid 0"
when:
- discovered_gid0_members is defined
- discovered_gid0_members.stdout | length > 0
ansible.builtin.user:
name: "{{ item }}"
group: root
state: absent
loop: "{{ discovered_gid0_members.stdout_lines }}"
- name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group"
when: rhel9cis_rule_5_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.4.2.2
- user
- system
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group | Get groups with gid 0"
ansible.builtin.shell: "awk -F: '$3==\"0\"{print $1}' /etc/group | grep -vw 'root'"
register: discovered_gid0_groups
changed_when: false
failed_when: discovered_gid0_groups.rc not in [ 0, 1 ]
- name: "5.4.2.3 | AUDIT | Ensure group root is the only GID 0 group | Warning if others gid 0 groups"
when:
- discovered_gid0_groups is defined
- discovered_gid0_groups.stdout | length > 0
ansible.builtin.debug:
msg:
- "Warning!! You have other groups assigned to GID 0 - Please resolve"
- "{{ discovered_gid0_groups.stdout_lines }}"
- name: "5.4.2.3 | WARN | Ensure group root is the only GID 0 group | warn_count"
when:
- discovered_gid0_groups is defined
- discovered_gid0_groups.stdout | length > 0
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '5.4.2.3'
- name: "5.4.2.4 | PATCH | Ensure root account access is controlled "
when: rhel9cis_rule_5_4_2_4
tags:
- level1-server
- level1-workstation
- patch
- shadow_suite
- rule_5.4.2.4
ansible.builtin.debug:
msg: "This is set as an assert in tasks/main"
- name: "5.4.2.5 | PATCH | Ensure root PATH Integrity"
when: rhel9cis_rule_5_4_2_5
tags:
- level1-server
- level1-workstation
- patch
- paths
- rule_5.4.2.5
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
block:
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Get root paths"
ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2
changed_when: false
register: discovered_root_paths
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Get root paths"
when: discovered_root_paths is defined
ansible.builtin.shell: sudo -Hiu root env | grep '^PATH' | cut -d= -f2 | tr ":" "\n"
changed_when: false
register: discovered_root_paths_split
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Set fact"
when: discovered_root_paths is defined
ansible.builtin.set_fact:
root_paths: "{{ discovered_root_paths.stdout }}"
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for empty dirs"
when: discovered_root_paths is defined
ansible.builtin.shell: 'echo {{ root_paths }} | grep -q "::" && echo "roots path contains a empty directory (::)"'
changed_when: false
failed_when: discovered_root_path_empty_dir.rc not in [ 0, 1 ]
register: discovered_root_path_empty_dir
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for trailing ':'"
when: discovered_root_paths is defined
ansible.builtin.shell: '{{ root_paths }} | cut -d= -f2 | grep -q ":$" && echo "roots path contains a trailing (:)"'
changed_when: false
failed_when: discovered_root_path_trailing_colon.rc not in [ 0, 1 ]
register: discovered_root_path_trailing_colon
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions"
when: discovered_root_paths is defined
block:
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Check for owner and permissions"
ansible.builtin.stat:
path: "{{ item }}"
register: discovered_root_path_perms
loop: "{{ discovered_root_paths_split.stdout_lines }}"
- name: "5.4.2.5 | AUDIT | Ensure root PATH Integrity | Set permissions"
when:
- item.stat.exists
- item.stat.isdir
- item.stat.pw_name != 'root' or item.stat.gr_name != 'root' or item.stat.woth or item.stat.wgrp
- (item != 'root') and (not rhel9cis_uses_root)
ansible.builtin.file:
path: "{{ item.stat.path }}"
state: directory
owner: root
group: root
mode: 'go-w'
follow: false
loop: "{{ discovered_root_path_perms.results }}"
loop_control:
label: "{{ item }}"
- name: "5.4.2.6 | PATCH | Ensure root user umask is configured"
when: rhel9cis_rule_5_4_2_6
tags:
- level1-server
- level1-workstation
- patch
- shadow_suite
- rule_5.4.2.6
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.lineinfile:
path: /root/.bash_profile
regexp: \s*umask
line: "umask {{ rhel9cis_root_umask }}"
create: true
mode: 'u+x,go-rwx'
- name: "5.4.2.7 | PATCH | Ensure system accounts do not have a valid login shell"
when:
- rhel9cis_rule_5_4_2_7
- "item.id not in prelim_interactive_usernames.stdout"
- item.id not in rhel9cis_system_users_shell
- "'root' not in item.id"
- rhel9cis_disruption_high
tags:
- level1-server
- level1-workstation
- patch
- shadow_suite
- rule_5.4.2.7
- NIST800-53R5_AC-2
- NIST800-53R5_AC-3
- NIST800-53R5_AC-11
- NIST800-53R5_MP-2
ansible.builtin.user:
name: "{{ item.id }}"
shell: /usr/sbin/nologin
loop: "{{ rhel9cis_passwd }}"
loop_control:
label: "{{ item.id }}"
- name: "5.4.2.8 | PATCH | Ensure accounts without a valid login shell are locked | Lock accounts"
when:
- rhel9cis_rule_5_4_2_8
- rhel9cis_disruption_high
- "item.id not in prelim_interactive_usernames.stdout"
- "'root' not in item.id"
tags:
- level1-server
- level1-workstation
- patch
- shadow_suite
- rule_5.4.2.8
- NIST800-53R5_AC-2
- NIST800-53R5_AC-3
- NIST800-53R5_AC-11
- NIST800-53R5_MP-2
ansible.builtin.user:
name: "{{ item.id }}"
password_lock: true
loop: "{{ rhel9cis_passwd }}"
loop_control:
label: "{{ item.id }}"

View file

@ -0,0 +1,59 @@
---
- name: "5.4.3.1 | PATCH | Ensure nologin is not listed in /etc/shells"
when: rhel9cis_rule_5_4_3_1
tags:
- level2-server
- level2-workstation
- patch
- shells
- rule_5.4.3.1
- NIST800-53R5_CM-1
- NIST800-53R5_CM-2
- NIST800-53R5_CM-6
- NIST800-53R5_CM-7
- NIST800-53R5_IA-5
ansible.builtin.replace:
path: /etc/shells
regexp: nologin
replace: ""
- name: "5.4.3.2 | PATCH | Ensure default user shell timeout is configured"
when: rhel9cis_rule_5_4_3_2
tags:
- level1-server
- level1-workstation
- patch
- shell
- rule_5.4.3.2
ansible.builtin.blockinfile:
path: "{{ item.path }}"
state: "{{ item.state }}"
marker: "# {mark} - CIS benchmark - Ansible-lockdown"
create: true
mode: 'go-wx'
block: |
TMOUT={{ rhel9cis_shell_session_timeout }}
readonly TMOUT
export TMOUT
loop:
- { path: "{{ rhel9cis_shell_session_file }}", state: present }
- { path: /etc/profile, state: "{{ (rhel9cis_shell_session_file == '/etc/profile') | ternary('present', 'absent') }}" }
- name: "5.4.3.3 | PATCH | Ensure default user umask is configured"
when: rhel9cis_rule_5_4_3_3
tags:
- level1-server
- level1-workstation
- patch
- umask
- rule_5.4.3.3
- NIST800-53R5_AC-3
- NIST800-53R5_MP-2
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: (?i)(umask\s+\d*)
replace: '{{ item.line }} {{ rhel9cis_bash_umask }}'
loop:
- { path: '/etc/profile', line: 'umask' }
- { path: '/etc/login.defs', line: 'UMASK' }

View file

@ -1,89 +0,0 @@
---
- name: "5.4.1 | PATCH | Ensure custom authselect profile is used"
block:
- name: "5.4.1 | AUDIT | Ensure custom authselect profile is used | Gather profiles"
ansible.builtin.shell: 'authselect list | grep custom'
failed_when: false
changed_when: false
check_mode: false
register: rhel9cis_5_4_1_current_profile
- name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Create custom profiles"
ansible.builtin.shell: authselect create-profile {{ rhel9cis_authselect['custom_profile_name'] }} -b {{ rhel9cis_authselect['default_file_to_copy'] }}
when:
- rhel9cis_authselect_custom_profile_create
- "rhel9cis_authselect.custom_profile_name not in rhel9cis_5_4_1_current_profile.stdout"
- name: "5.4.1 | PATCH | Ensure custom authselect profile is used | Force custom profile creates backup"
ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} --force --backup=rhel9cis_5_4_1_{{ ansible_date_time.epoch}}"
register: authselect_5_4_1_select
when:
- rhel9cis_authselect_custom_profile_create
- "rhel9cis_authselect.custom_profile_name not in rhel9cis_5_4_1_current_profile.stdout"
when:
- rhel9cis_rule_5_4_1
tags:
- level1-server
- level1-workstation
- manual
- patch
- authselect
- rule_5.4.1
- name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Get Authselect profile options"
block:
- name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock | Gather profiles and enabled features"
ansible.builtin.shell: "authselect current | grep with-faillock"
failed_when: false
changed_when: false
check_mode: false
register: rhel9cis_5_4_2_profiles_faillock
- name: "5.4.2 | AUDIT | Ensure authselect includes with-faillock | Show profiles"
ansible.builtin.debug:
msg:
- "Below are the current custom profiles"
- "{{ rhel9cis_5_4_2_profiles_faillock.stdout_lines }}"
- name: "5.4.2 | PATCH | Ensure authselect includes with-faillock | Authselect add options"
ansible.builtin.shell: "authselect select custom/{{ rhel9cis_authselect['custom_profile_name'] }} {{ rhel9cis_authselect['options'] }} --force"
when: rhel9cis_authselect_custom_profile_select
- name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not Authselect profile"
ansible.builtin.lineinfile:
path: "/etc/pam.d/password-auth"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertbefore: "{{ item.before }}"
loop:
- { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so preauth silent deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'}
- { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', 'before':'^auth\s+required\s+pam_deny.so'}
- { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'}
when:
- rhel9cis_add_faillock_without_authselect
- rhel9cis_5_4_2_risks == 'ACCEPT'
- name: 5.4.2 | PATCH | Ensure authselect includes with-faillock | not Authselect profile"
ansible.builtin.lineinfile:
path: "/etc/pam.d/system-auth"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertbefore: "{{ item.before | default(omit)}}"
insertafter: "{{ item.after | default(omit)}}"
loop:
- { 'regexp': '^auth\s+required\s+pam_faillock.so preauth silent deny=.*unlock_time=.*', 'line':'auth required pam_faillock.so preauth silent deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', 'before':'^auth\s+sufficient\s+pam_unix.so try_first_pass'}
- { 'regexp': '^auth\s+required\s+pam_faillock.so authfail deny=.*unlock_time=.*', 'line': 'auth required pam_faillock.so authfail deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time }}', 'before':'^auth\s+required\s+pam_deny.so'}
- { 'regexp': '^account\s+required\s+pam_faillock.so', 'line': 'account required pam_faillock.so', 'before':'^account required pam_unix.so'}
when:
- rhel9cis_add_faillock_without_authselect
- rhel9cis_5_4_2_risks == 'ACCEPT'
when:
- rhel9cis_rule_5_4_2
tags:
- level1-server
- level1-workstation
- patch
- authselect
- rule_5.4.2

View file

@ -1,135 +0,0 @@
---
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured"
block:
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set pwquality config settings"
ansible.builtin.lineinfile:
path: /etc/security/pwquality.conf
regexp: ^{{ item.name }}
line: "{{ item.name }} = {{ item.value }}"
loop:
- { name: minlen, value: "{{ rhel9cis_pam_password.minlen }}" }
- { name: minclass, value: "{{ rhel9cis_pam_password.minclass }}" }
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings | not Authselect"
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
regexp: '^password\s*requisite\s*pam_pwquality.so'
line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3"
insertbefore: '^#?password ?'
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set password-auth retry settings | not Authselect"
ansible.builtin.lineinfile:
path: /etc/pam.d/password-auth
regexp: '^password\s*requisite\s*pam_pwquality.so'
line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3"
insertbefore: '^#?password ?'
when:
- rhel9cis_rule_5_5_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured"
block:
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set faillock.conf configs"
ansible.builtin.lineinfile:
path: /etc/security/faillock.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = {{ rhel9cis_pam_faillock.deny }}' }
- { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = {{ rhel9cis_pam_faillock.unlock_time }}' }
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set preauth"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*preauth(.*)'
line: "auth required pam_faillock.so preauth silent audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}"
insertafter: 'auth\s*(sufficient|required)\s*pam_env.so$'
loop:
- "/etc/pam.d/system-auth"
- "/etc/pam.d/password-auth"
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set authfail"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*authfail(.*)'
line: "auth required pam_faillock.so authfail audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}"
insertbefore: 'auth\s*(sufficient|required)\s*pam_deny.so$'
loop:
- "/etc/pam.d/system-auth"
- "/etc/pam.d/password-auth"
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Load account faillock.so"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^account\s*(sufficient|required)\s*pam_faillock.so$'
line: "account required pam_faillock.so"
insertbefore: '^account\s*(sufficient|required)\s*pam_unix.so$'
loop:
- "/etc/pam.d/system-auth"
- "/etc/pam.d/password-auth"
when:
- rhel9cis_rule_5_5_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.2
- name: "5.5.3 | PATCH | Ensure password reuse is limited | pwquality"
block:
- name: "5.5.3 | PATCH | Ensure password reuse is limited | Set system-auth remember Settings"
ansible.builtin.lineinfile:
path: /etc/pam.d/system-auth
line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}"
insertafter: '^password\s*requisite\s*pam_pwquality.so'
- name: "5.5.3 | PATCH | Ensure password reuse is limited | Set password-auth remember Settings"
ansible.builtin.lineinfile:
path: /etc/pam.d/password-auth
line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}"
insertafter: '^password\s*requisite\s*pam_pwquality.so'
when:
- rhel9cis_rule_5_5_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.3
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 or yescrypt"
block:
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf"
ansible.builtin.replace:
path: /etc/libuser.conf
regexp: '^crypt_style\s*=\s*.*$'
replace: 'crypt_style = sha512'
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | login.defs"
ansible.builtin.replace:
path: /etc/login.defs
regexp: '^ENCRYPT_METHOD.*'
replace: 'ENCRYPT_METHOD SHA512'
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | password-auth"
ansible.builtin.replace:
path: /etc/pam.d/password-auth
regexp: '^password\s*sufficient\s*pam_unix.so.*$'
replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}'
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | system-auth"
ansible.builtin.replace:
path: /etc/pam.d/system-auth
regexp: '^password\s*sufficient\s*pam_unix.so.*$'
replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}'
when:
- rhel9cis_rule_5_5_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.4

View file

@ -1,144 +0,0 @@
---
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured"
block:
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set pwquality config settings"
ansible.builtin.lineinfile:
path: /etc/security/pwquality.conf
regexp: ^{{ item.name }}
line: "{{ item.name }} = {{ item.value }}"
loop:
- { name: minlen, value: "{{ rhel9cis_pam_password.minlen }}" }
- { name: minclass, value: "{{ rhel9cis_pam_password.minclass }}" }
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set system-auth retry settings | not Authselect"
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
regexp: '^password\s*requisite\s*pam_pwquality.so'
line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3"
insertbefore: '^#?password ?'
notify: Apply_authselect
- name: "5.5.1 | PATCH | Ensure password creation requirements are configured | Set password-auth retry settings | not Authselect"
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
regexp: '^password\s*requisite\s*pam_pwquality.so'
line: "password requisite pam_pwquality.so try_first_pass local_users_only enforce_for_root retry=3"
insertbefore: '^#?password ?'
notify: Apply_authselect
when:
- rhel9cis_rule_5_5_1
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.1
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured"
block:
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set faillock.conf configs"
ansible.builtin.lineinfile:
path: /etc/security/faillock.conf
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
loop:
- { regexp: '^\s*deny\s*=\s*[1-5]\b', line: 'deny = {{ rhel9cis_pam_faillock.deny }}' }
- { regexp: '^\s*unlock_time\s*=\s*(0|9[0-9][0-9]|[1-9][0-9][0-9][0-9]+)\b', line: 'unlock_time = {{ rhel9cis_pam_faillock.unlock_time }}' }
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set preauth"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*preauth(.*)'
line: "auth required pam_faillock.so preauth silent audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}"
insertafter: 'auth\s*(sufficient|required)\s*pam_env.so$'
loop:
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
notify: Apply_authselect
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Set authfail"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^auth\s*(sufficient|required)\s*pam_faillock.so\s*authfail(.*)'
line: "auth required pam_faillock.so authfail audit deny={{ rhel9cis_pam_faillock.deny }} unlock_time={{ rhel9cis_pam_faillock.unlock_time}}"
insertbefore: 'auth\s*(sufficient|required)\s*pam_deny.so$'
loop:
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
notify: Apply_authselect
- name: "5.5.2 | PATCH | Ensure lockout for failed password attempts is configured | Load account faillock.so"
ansible.builtin.lineinfile:
path: "{{ item }}"
regexp: '^account\s*(sufficient|required)\s*pam_faillock.so$'
line: "account required pam_faillock.so"
insertbefore: '^account\s*(sufficient|required)\s*pam_unix.so$'
loop:
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
- "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
notify: Apply_authselect
when:
- rhel9cis_rule_5_5_2
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.2
- name: "5.5.3 | PATCH | Ensure password reuse is limited | pwquality"
block:
- name: "5.5.3 | PATCH | Ensure password reuse is limited | Set system-auth remember Settings"
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}"
insertafter: '^password\s*requisite\s*pam_pwquality.so'
notify: Apply_authselect
- name: "5.5.3 | PATCH | Ensure password reuse is limited | Set password-auth remember Settings"
ansible.builtin.lineinfile:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
line: "password requisite pam_pwhistory.so try_first_pass enforce_for_root retry=3 remember={{ rhel9cis_pam_faillock.remember }}"
insertafter: '^password\s*requisite\s*pam_pwquality.so'
notify: Apply_authselect
when:
- rhel9cis_rule_5_5_3
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.3
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 or yescrypt"
block:
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | libuser.conf"
ansible.builtin.replace:
path: /etc/libuser.conf
regexp: '^crypt_style\s*=\s*.*$'
replace: 'crypt_style = sha512'
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | login.defs"
ansible.builtin.replace:
path: /etc/login.defs
regexp: '^ENCRYPT_METHOD.*'
replace: 'ENCRYPT_METHOD SHA512'
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | password-auth"
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/password-auth"
regexp: '^password\s*sufficient\s*pam_unix.so.*$'
replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}'
notify: Apply_authselect
- name: "5.5.4 | PATCH | Ensure password hashing algorithm is SHA-512 | system-auth"
ansible.builtin.replace:
path: "/etc/authselect/custom/{{ rhel9cis_authselect['custom_profile_name'] }}/system-auth"
regexp: '^password\s*sufficient\s*pam_unix.so.*$'
replace: 'password sufficient pam_unix.so sha512 shadow try_first_pass use_authtok remember={{ rhel9cis_pam_faillock.remember }}'
notify: Apply_authselect
when:
- rhel9cis_rule_5_5_4
tags:
- level1-server
- level1-workstation
- patch
- rule_5.5.4

View file

@ -1,173 +0,0 @@
---
- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less"
block:
- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_MAX_DAYS'
line: "PASS_MAX_DAYS {{ rhel9cis_pass['max_days'] }}"
- name: "5.6.1.1 | AUDIT | Ensure password expiration is 365 days or less | Get existing users PASS_MAX_DAYS"
ansible.builtin.shell: "awk -F: '(/^[^:]+:[^!*]/ && ($5> {{ rhel9cis_pass['max_days'] }} || $5< {{ rhel9cis_pass['max_days'] }} || $5 == -1)){print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_max_days
- name: "5.6.1.1 | PATCH | Ensure password expiration is 365 days or less | Set existing users PASS_MAX_DAYS"
ansible.builtin.user:
name: "{{ item }}"
password_expire_max: "{{ rhel9cis_pass['max_days'] }}"
loop: "{{ discovered_max_days.stdout_lines }}"
when:
- discovered_max_days.stdout_lines | length > 0
- item in discovered_interactive_usernames.stdout
- rhel9cis_force_user_maxdays
when:
- rhel9cis_rule_5_6_1_1
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.6.1.1
- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is 7 or more"
block:
- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is configured | set login.defs"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_MIN_DAYS'
line: "PASS_MIN_DAYS {{ rhel9cis_pass['min_days'] }}"
- name: "5.6.1.2 | AUDIT | Ensure minimum days between password changes is configured | Get existing users PASS_MIN_DAYS"
ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $4< {{ rhel9cis_pass['min_days'] }} {print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_min_days
- name: "5.6.1.2 | PATCH | Ensure minimum days between password changes is configured | Set existing users PASS_MIN_DAYS"
ansible.builtin.user:
name: "{{ item }}"
password_expire_max: "{{ rhel9cis_pass['min_days'] }}"
loop: "{{ discovered_min_days.stdout_lines }}"
when:
- discovered_min_days.stdout_lines | length > 0
- item in discovered_interactive_usernames.stdout
- rhel9cis_force_user_mindays
when:
- rhel9cis_rule_5_6_1_2
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.6.1.2
- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more"
block:
- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | set login.defs"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^PASS_WARN_AGE'
line: "PASS_WARN_AGE {{ rhel9cis_pass['warn_age'] }}"
- name: "5.6.1.3 | AUDIT | Ensure password expiration warning days is 7 or more | Get existing users WARN_DAYS"
ansible.builtin.shell: "awk -F: '/^[^:]+:[^!*]/ && $6< {{ rhel9cis_pass['warn_age'] }} {print $1}' /etc/shadow"
changed_when: false
failed_when: false
register: discovered_warn_days
- name: "5.6.1.3 | PATCH | Ensure password expiration warning days is 7 or more | Set existing users WARN_DAYS"
ansible.builtin.shell: "chage --warndays {{ rhel9cis_pass['warn_age'] }} {{ item }}"
loop: "{{ discovered_warn_days.stdout_lines }}"
when:
- discovered_warn_days.stdout_lines | length > 0
- item in discovered_interactive_usernames.stdout
- rhel9cis_force_user_warnage
when:
- rhel9cis_rule_5_6_1_3
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.6.1.3
- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less"
block:
- name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Check current settings"
ansible.builtin.shell: useradd -D | grep INACTIVE={{ rhel9cis_inactivelock.lock_days }} | cut -f2 -d=
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_5_6_1_4_inactive_settings
- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Set default inactive setting"
ansible.builtin.shell: useradd -D -f {{ rhel9cis_inactivelock.lock_days }}
when: rhel9cis_5_6_1_4_inactive_settings.stdout | length == 0
- name: "5.6.1.4 | AUDIT | Ensure inactive password lock is 30 days or less | Getting user list"
ansible.builtin.shell: "awk -F: '/^[^#:]+:[^\\!\\*:]*:[^:]*:[^:]*:[^:]*:[^:]*:(\\s*|-1|3[1-9]|[4-9][0-9]|[1-9][0-9][0-9]+):[^:]*:[^:]*\\s*$/ {print $1}' /etc/shadow"
changed_when: false
check_mode: false
register: rhel9cis_5_6_1_4_user_list
- name: "5.6.1.4 | PATCH | Ensure inactive password lock is 30 days or less | Apply Inactive setting to existing accounts"
ansible.builtin.shell: chage --inactive {{ rhel9cis_inactivelock.lock_days }} "{{ item }}"
loop: "{{ rhel9cis_5_6_1_4_user_list.stdout_lines }}"
when: item in discovered_interactive_usernames.stdout
when:
- rhel9cis_rule_5_6_1_4
tags:
- level1-server
- level1-workstation
- patch
- password
- rule_5.6.1.4
- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past"
block:
- name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get current date in Unix Time"
ansible.builtin.shell: echo $(($(date --utc --date "$1" +%s)/86400))
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_5_6_1_5_currentut
- name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Get list of users with last changed pw date in the future"
ansible.builtin.shell: "cat /etc/shadow | awk -F: '{if($3>{{ rhel9cis_5_6_1_5_currentut.stdout }})print$1}'"
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_5_6_1_5_user_list
- name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | Alert on accounts with pw change in the future"
ansible.builtin.debug:
msg: "Warning!! The following accounts have the last PW change date in the future: {{ rhel9cis_5_6_1_5_user_list.stdout_lines }}"
when:
- rhel9cis_5_6_1_5_user_list.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
- name: "5.6.1.5 | AUDIT | Ensure all users last password change date is in the past | warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
when:
- rhel9cis_5_6_1_5_user_list.stdout | length > 0
- not rhel9cis_futurepwchgdate_autofix
- name: "5.6.1.5 | PATCH | Ensure all users last password change date is in the past | Fix accounts with pw change in the future"
ansible.builtin.shell: passwd --expire {{ item }}
when:
- rhel9cis_5_6_1_5_user_list.stdout | length > 0
- rhel9cis_futurepwchgdate_autofix
loop: "{{ rhel9cis_5_6_1_5_user_list.stdout_lines }}"
vars:
warn_control_id: '5.6.1.5'
when:
- rhel9cis_rule_5_6_1_5
tags:
- level1-server
- level1-workstation
- patch
- rule_5.6.1.5

View file

@ -1,150 +0,0 @@
---
- name: "5.6.2 | PATCH | Ensure system accounts are secured"
block:
- name: "5.6.2 | PATCH | Ensure system accounts are secured | Set nologin"
ansible.builtin.user:
name: "{{ item.id }}"
shell: /usr/sbin/nologin
loop: "{{ rhel9cis_passwd }}"
when:
- item.id != "root"
- item.id != "sync"
- item.id != "shutdown"
- item.id != "halt"
- item.id != "nfsnobody"
- item.id not in rhel9cis_system_users_shell
- item.uid < min_int_uid | int
- item.shell != "/bin/false"
- item.shell != "/usr/sbin/nologin"
- item.shell != "/sbin/nologin"
- item.shell != "/dev/null"
loop_control:
label: "{{ item.id }}"
- name: "5.6.2 | PATCH | Ensure system accounts are secured | Lock accounts"
ansible.builtin.user:
name: "{{ item.id }}"
password_lock: true
loop: "{{ rhel9cis_passwd }}"
when:
- item.id != "halt"
- item.id != "shutdown"
- item.id != "sync"
- item.id != "root"
- item.id != "nfsnobody"
- item.uid < min_int_uid | int
- item.shell != "/bin/false"
- item.shell != "/usr/sbin/nologin"
- item.shell != "/sbin/nologin"
- item.shell != "/dev/null"
loop_control:
label: "{{ item.id }}"
when:
- rhel9cis_rule_5_6_2
tags:
- level1-server
- level1-workstation
- patch
- accounts
- rule_5.6.2
- name: "5.6.3 | PATCH | Ensure default user shell timeout is 900 seconds or less"
ansible.builtin.blockinfile:
path: "{{ item.path }}"
state: "{{ item.state }}"
marker: "# {mark} - CIS benchmark - Ansible-lockdown"
create: true
mode: '0644'
block: |
TMOUT={{ rhel9cis_shell_session_timeout.timeout }}
export TMOUT
readonly TMOUT
loop:
- { path: "{{ rhel9cis_shell_session_timeout.file }}", state: present }
- { path: /etc/profile, state: "{{ (rhel9cis_shell_session_timeout.file == '/etc/profile') | ternary('present', 'absent') }}" }
when:
- rhel9cis_rule_5_6_3
tags:
- level1-server
- level1-workstation
- patch
- accounts
- rule_5.6.3
- name: "5.6.4 | PATCH | Ensure default group for the root account is GID 0"
ansible.builtin.user:
name: root
group: 0
when:
- rhel9cis_rule_5_6_4
tags:
- level1-server
- level1-workstation
- patch
- accounts
- rule_5.6.4
- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive"
block:
- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/login.defs pam_umask settings"
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: (?i)(umask\s+\d\d\d)
replace: '{{ item.line }} 027'
with_items:
- { path: '/etc/bashrc', line: 'umask' }
- { path: '/etc/profile', line: 'umask' }
- { path: '/etc/login.defs', line: 'UMASK' }
- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Set umask for /etc/bashrc"
ansible.builtin.lineinfile:
path: /etc/login.defs
regexp: '^USERGROUPS_ENAB'
line: USERGROUPS_ENAB no
- name: "5.6.5 | PATCH | Ensure default user umask is 027 or more restrictive | Add umask sessions for pamd"
community.general.pamd:
name: "{{ item }}"
type: session
control: required
module_path: pam_limits.so
new_type: session
new_module_path: pam_umask.so
new_control: optional
state: before
register: rhel9cis_pamd_umask_added
loop:
- system-auth
- password-auth
- name: "5.6.5 | AUDIT | Ensure default user umask is 027 or more restrictive | update umask settings if required"
ansible.builtin.replace:
path: "/etc/pam.d/{{ item }}"
regexp: ^(session\s+)(requisite|required)(\s+pam_umask.so)$
replace: \1optional\3
loop:
- system-auth
- password-auth
when:
- rhel9cis_rule_5_6_5
tags:
- level1-server
- level1-workstation
- patch
- accounts
- rule_5.6.5
- name: "5.6.6 | PATCH | Ensure root password is set"
ansible.builtin.debug:
msg: "The root password has been set as per the assert in early stages"
when:
- rhel9cis_rule_5_6_6
tags:
- level1-server
- level1-workstation
- patch
- accounts
- root
- rule_5.6.6

View file

@ -2,38 +2,48 @@
# Access, Authentication, and Authorization
- name: "SECTION | 5.1 | Configure time-based job schedulers"
ansible.builtin.import_tasks:
file: cis_5.1.x.yml
- name: "SECTION | 5.2 | Configure SSH Server"
ansible.builtin.import_tasks:
file: cis_5.2.x.yml
- name: "SECTION | 5.1 | Configure SSH Server"
when:
- "'openssh-server' in ansible_facts.packages"
- name: "SECTION | 5.3 | Configure privilege escalation"
- "'openssh-server' in ansible_facts.packages"
ansible.builtin.import_tasks:
file: cis_5.3.x.yml
file: cis_5.1.x.yml
- name: "SECTION | 5.4 | Configure authselect"
- name: "SECTION | 5.2 | Configure privilege escalation"
ansible.builtin.import_tasks:
file: cis_5.4.x.yml
file: cis_5.2.x.yml
- name: "SECTION | 5.5 | Configure PAM | not authselect"
- name: "SECTION | 5.3.1.x | Configure PAM software packages"
ansible.builtin.import_tasks:
file: cis_5.5.x.yml
when: not rhel9cis_authselect_custom_profile_select
file: cis_5.3.1.x.yml
- name: "SECTION | 5.5 | Configure PAM | authselect"
- name: "SECTION | 5.3.2.x | Configure authselect"
ansible.builtin.import_tasks:
file: cis_5.5.x_authselect.yml
when: rhel9cis_authselect_custom_profile_select
file: cis_5.3.2.x.yml
- name: "SECTION | 5.6.1.x | Shadow Password Suite Parameters"
- name: "SECTION | 5.3.3.1.x | Configure pam_faillock module"
ansible.builtin.import_tasks:
file: cis_5.6.1.x.yml
file: cis_5.3.3.1.x.yml
- name: "SECTION | 5.6.x | Misc. User Account Settings"
- name: "SECTION | 5.3.3.2.x | Configure pam_pwquality module"
ansible.builtin.import_tasks:
file: cis_5.6.x.yml
file: cis_5.3.3.2.x.yml
- name: "SECTION | 5.3.3.3.x | Configure pam_pwhistory module"
ansible.builtin.import_tasks:
file: cis_5.3.3.3.x.yml
- name: "SECTION | 5.3.3.4.x | Configure pam_unix module"
ansible.builtin.import_tasks:
file: cis_5.3.3.4.x.yml
- name: "SECTION | 5.4.1.x | Configure shadow password suite parameters"
ansible.builtin.import_tasks:
file: cis_5.4.1.x.yml
- name: "SECTION | 5.4.2.x | Configure root and system accounts and environment"
ansible.builtin.import_tasks:
file: cis_5.4.2.x.yml
- name: "SECTION | 5.4.3.x | Configure user default environment"
ansible.builtin.import_tasks:
file: cis_5.4.3.x.yml

View file

@ -1,352 +1,122 @@
---
- name: "6.1.1 | PATCH | Ensure permissions on /etc/passwd are configured"
ansible.builtin.file:
path: /etc/passwd
owner: root
group: root
mode: '0644'
- name: "6.1.1 | PATCH | Ensure AIDE is installed"
when:
- rhel9cis_rule_6_1_1
- rhel9cis_config_aide
- rhel9cis_rule_6_1_1
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.1
- name: "6.1.2 | PATCH | Ensure permissions on /etc/passwd- are configured"
ansible.builtin.file:
path: /etc/passwd-
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_6_1_2
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.2
- name: "6.1.3 | PATCH | Ensure permissions on /etc/group are configured"
ansible.builtin.file:
path: /etc/group
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_6_1_3
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.3
- name: "6.1.4 | PATCH | Ensure permissions on /etc/group- are configured"
ansible.builtin.file:
path: /etc/group-
owner: root
group: root
mode: '0644'
when:
- rhel9cis_rule_6_1_4
tags:
- level1-server
- level1-workstation
- patch
- permissionss
- rule_6.1.4
- name: "6.1.5 | PATCH | Ensure permissions on /etc/shadow are configured"
ansible.builtin.file:
path: /etc/shadow
owner: root
group: root
mode: '0000'
when:
- rhel9cis_rule_6_1_5
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.5
- name: "6.1.6 | PATCH | Ensure permissions on /etc/shadow- are configured"
ansible.builtin.file:
path: /etc/shadow-
owner: root
group: root
mode: '0000'
when:
- rhel9cis_rule_6_1_6
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.6
- name: "6.1.7 | PATCH | Ensure permissions on /etc/gshadow are configured"
ansible.builtin.file:
path: /etc/gshadow
owner: root
group: root
mode: '0000'
when:
- rhel9cis_rule_6_1_7
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.7
- name: "6.1.8 | PATCH | Ensure permissions on /etc/gshadow- are configured"
ansible.builtin.file:
path: /etc/gshadow-
owner: root
group: root
mode: '0000'
when:
- rhel9cis_rule_6_1_8
tags:
- level1-server
- level1-workstation
- patch
- permissions
- rule_6.1.8
- name: "6.1.9 | PATCH | Ensure no world writable files exist"
- level1-server
- level1-workstation
- aide
- patch
- rule_6.1.1
- NIST800-53R5_AU-2
block:
- name: "6.1.9 | AUDIT | Ensure no world writable files exist | Get list of world-writable files"
ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -0002
failed_when: false
changed_when: false
register: rhel_09_6_1_9_perms_results
- name: "6.1.1 | PATCH | Ensure AIDE is installed"
ansible.builtin.package:
name: "{{ aide_packages }}"
state: present
update_cache: true
register: discovered_aide_pkg_added
- name: "6.1.9 | PATCH | Ensure no world writable files exist | Adjust world-writable files if they exist (Configurable)"
ansible.builtin.file:
path: '{{ item }}'
mode: o-w
state: touch
loop: "{{ rhel_09_6_1_9_perms_results.stdout_lines }}"
when:
- rhel_09_6_1_9_perms_results.stdout_lines is defined
- rhel9cis_no_world_write_adjust
- name: "6.1.1 | PATCH | Ensure AIDE is installed | Recapture packages"
when: discovered_aide_pkg_added.skipped is not defined
ansible.builtin.package_facts:
manager: auto
- name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check file exists"
ansible.builtin.stat:
path: "{{ rhel9cis_aide_db_file }}"
register: discovered_aide_db_file
- name: "6.1.1 | AUDIT | Ensure AIDE is installed | Check current db file age"
when: discovered_aide_db_file.stat.exists
ansible.builtin.find:
path: "{{ rhel9cis_aide_db_file | dirname }}"
pattern: "{{ rhel9cis_aide_db_file | basename }}"
age: "{{ rhel9cis_aide_db_file_age }}"
register: discovered_aide_db_age
- name: "6.1.1 | PATCH | Ensure AIDE is installed | Configure AIDE"
when:
- not ansible_check_mode
- not discovered_aide_db_file.stat.exists or
(discovered_aide_db_age.files | length > 0) or
rhel9cis_aide_db_recreate
block:
- name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB"
ansible.builtin.command: "{{ aide_initiate_command }}"
changed_when: true
- name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB | Wait for file before continuing"
ansible.builtin.wait_for:
path: /var/lib/aide/aide.db.new.gz
- name: "6.1.1 | PATCH | Ensure AIDE is installed | Build AIDE DB |copy AIDE DB"
ansible.builtin.copy:
src: /var/lib/aide/aide.db.new.gz
dest: /var/lib/aide/aide.db.gz
remote_src: true
mode: 'ug-wx,o-rwx'
- name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked"
when:
- rhel9cis_rule_6_1_9
- rhel9cis_rule_6_1_2
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- patch
- files
- permissions
- rule_6.1.9
- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist"
- level1-server
- level1-workstation
- aide
- file_integrity
- patch
- rule_6.1.2
- NIST800-53R5_AU-2
block:
- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Finding all unowned files or directories"
ansible.builtin.shell: find "{{ item.mount }}" -xdev -nouser -not -fstype nfs
changed_when: false
failed_when: false
check_mode: false
register: rhel_09_6_1_10_audit
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
when:
- item['device'].startswith('/dev')
- not 'bind' in item['options']
- name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked"
when: rhel9cis_aide_scan == "cron"
ansible.builtin.cron:
name: Run AIDE integrity check
cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}"
user: "{{ rhel9cis_aide_cron['cron_user'] }}"
minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}"
hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}"
day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}"
month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}"
weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}"
job: "{{ rhel9cis_aide_cron['aide_job'] }}"
- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Flatten no_user_items results for easier use"
ansible.builtin.set_fact:
discovered_unowned_files_flatten: "{{ rhel_09_6_1_10_audit.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}"
- name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service"
when: rhel9cis_aide_scan == "timer"
ansible.builtin.systemd_service:
name: aidecheck.service
enabled: true
- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | Displaying any unowned files or directories"
ansible.builtin.debug:
msg: "Warning!! Missing owner on items in {{ discovered_unowned_files_flatten }}"
when: discovered_unowned_files_flatten | length > 0
- name: "6.1.2 | PATCH | Ensure filesystem integrity is regularly checked | aide service"
when: rhel9cis_aide_scan == "timer"
ansible.builtin.systemd_service:
name: aidecheck.timer
state: started
enabled: true
- name: "6.1.10 | AUDIT | Ensure no unowned files or directories exist | warning"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.10'
when: discovered_unowned_files_flatten | length > 0
- name: "6.1.3 | PATCH | Ensure cryptographic mechanisms are used to protect the integrity of audit tools"
when:
- rhel9cis_rule_6_1_10
- rhel9cis_rule_6_1_3
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- audit
- files
- permissions
- rule_6.1.10
- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist"
block:
- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Finding all ungrouped files or directories"
ansible.builtin.shell: find "{{ item.mount }}" -xdev -nogroup
check_mode: false
failed_when: false
changed_when: false
register: rhel_09_6_1_11_audit
loop: "{{ ansible_facts.mounts }}"
loop_control:
label: "{{ item.mount }}"
when:
- item['device'].startswith('/dev')
- not 'bind' in item['options']
- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Flatten no_user_items results for easier use"
ansible.builtin.set_fact:
discovered_ungrouped_files_flatten: "{{ rhel_09_6_1_11_audit.results | selectattr('stdout_lines', 'defined') | map(attribute='stdout_lines') | flatten }}"
- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | Displaying all ungrouped files or directories"
ansible.builtin.debug:
msg: "Warning!! Missing group on items in {{ discovered_ungrouped_files_flatten }}"
when: discovered_ungrouped_files_flatten | length > 0
- name: "6.1.11 | AUDIT | Ensure no ungrouped files or directories exist | warning"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.11'
when: discovered_ungrouped_files_flatten | length > 0
when:
- rhel9cis_rule_6_1_11
tags:
- level1-server
- level1-workstation
- audit
- files
- permissions
- rule_6.1.11
- name: "6.1.12 | PATCH | Ensure sticky bit is set on all world-writable directories"
ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type d -perm -0002 2>/dev/null | xargs chmod a+t
changed_when: false
failed_when: false
when:
- rhel9cis_rule_6_1_12
tags:
- level1-server
- level1-workstation
- patch
- stickybits
- permissons
- rule_6.1.12
- name: "6.1.13 | AUDIT | Audit SUID executables"
block:
- name: "6.1.13 | AUDIT | Audit SUID executables | Find all SUID executables"
ansible.builtin.shell: "df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -4000"
failed_when: false
changed_when: false
register: rhel_09_6_1_13_suid_perms
- name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist"
ansible.builtin.debug:
msg: "Warning!! SUID set on items in {{ rhel_09_6_1_13_suid_perms.stdout_lines }}"
when:
- rhel_09_6_1_13_suid_perms.stdout is defined
- rhel_09_6_1_13_suid_perms.stdout | length > 0
- name: "6.1.13 | AUDIT | Audit SUID executables | Alert SUID executables exist | warning"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.13'
when:
- rhel_09_6_1_13_suid_perms.stdout is defined
- rhel_09_6_1_13_suid_perms.stdout | length > 0
vars:
rhel9_6_1_13_suid_found: false
when:
- rhel9cis_rule_6_1_13
tags:
- level1-server
- level1-workstation
- manual
- audit
- files
- rule_6.1.13
- name: "6.1.14 | AUDIT | Audit SGID executables"
block:
- name: "6.1.14 | AUDIT | Audit SGID executables | Find all SGID executables"
ansible.builtin.shell: df --local -P | awk {'if (NR!=1) print $6'} | xargs -I '{}' find '{}' -xdev -type f -perm -2000
failed_when: false
changed_when: false
register: rhel_09_6_1_14_sgid_perms
- name: "6.1.14 | AUDIT | Audit SGID executables | Alert SGID executables exist"
ansible.builtin.debug:
msg: "Warning!! SGID set on items in {{ rhel_09_6_1_14_sgid_perms.stdout_lines }}"
when:
- rhel_09_6_1_14_sgid_perms.stdout is defined
- rhel_09_6_1_14_sgid_perms.stdout | length > 0
- name: "6.1.14 | AUDIT | Audit SGID executables| warning"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.14'
when:
- rhel_09_6_1_14_sgid_perms.stdout is defined
- rhel_09_6_1_14_sgid_perms.stdout | length > 0
vars:
rhel9_6_1_14_sgid_found: false
when:
- rhel9cis_rule_6_1_14
tags:
- level1-server
- level1-workstation
- manual
- audit
- files
- rule_6.1.14
- name: "6.1.15 | AUDIT | Audit system file permissions"
block:
- name: "6.1.15 | AUDIT | Audit system file permissions | Audit the packages"
ansible.builtin.shell: rpm -Va --nomtime --nosize --nomd5 --nolinkto
changed_when: false
failed_when: false
register: rhel9cis_6_1_15_packages_rpm
- name: "6.1.15 | AUDIT | Audit system file permissions | Create list and warning"
block:
- name: "6.1.15 | AUDIT | Audit system file permissions | Add file discrepancy list to system"
ansible.builtin.copy:
dest: "{{ rhel9cis_rpm_audit_file }}" # noqa template-instead-of-copy
content: "{{ rhel9cis_6_1_15_packages_rpm.stdout }}"
owner: root
group: root
mode: '0640'
- name: "6.1.15 | AUDIT | Audit system file permissions | Message out alert for package descrepancies"
ansible.builtin.debug:
msg: |
"Warning!! You have some package descrepancies issues.
The file list can be found in {{ rhel9cis_rpm_audit_file }}"
- name: "6.1.15 | AUDIT | Audit system file permissions | warning count"
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.1.15'
when: rhel9cis_6_1_15_packages_rpm.stdout|length > 0
when:
- rhel9cis_rule_6_1_15
tags:
- level2-server
- level2-workstation
- manual
- audit
- permissions
- rule_6.1.15
- level1-server
- level1-workstation
- aide
- file_integrity
- patch
- rule_6.1.3
ansible.builtin.blockinfile:
path: /etc/aide.conf
marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown"
block: |
/usr/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/usr/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
validate: aide -D --config %s

View file

@ -0,0 +1,110 @@
---
- name: "6.2.1.1 | PATCH | Ensure journald service is enabled and active"
when: rhel9cis_rule_6_2_1_1
tags:
- level1-server
- level1-workstation
- audit
- journald
- rule_6.2.1.1
ansible.builtin.systemd:
name: systemd-journald.service
masked: false
state: started
- name: "6.2.1.2 | PATCH | Ensure journald log file access is configured"
when: rhel9cis_rule_6_2_1_2
tags:
- level1-server
- level1-workstation
- audit
- journald
- rule_6.2.1.2
block:
- name: "6.2.1.2 | PATCH | Ensure journald log file access is configured | Default file permissions"
ansible.builtin.file:
path: /usr/lib/tmpfiles.d/systemd.conf
mode: 'g-wx,o-rwx'
- name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Check for override file"
ansible.builtin.stat:
path: /etc/tmpfiles.d/systemd.conf
register: discovered_tmpfile_override
- name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | If override file check for journal"
when: discovered_tmpfile_override.stat.exists
ansible.builtin.shell: grep -E 'z /var/log/journal/%m/system.journal \d*' /usr/lib/tmpfiles.d/systemd.conf
register: discovered_journald_fileperms_override
changed_when: false
failed_when: discovered_journald_fileperms_override.rc not in [ 0, 1 ]
- name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found"
when:
- discovered_tmpfile_override.stat.exists
- discovered_journald_fileperms_override.stdout | length > 0
ansible.builtin.debug:
msg: "Warning!! - tmpfiles override found /usr/lib/tmpfiles.d/systemd.conf affecting journald files please confirm matches site policy"
- name: "6.2.1.2 | AUDIT | Ensure journald log file access is configured | Warning if override found"
when:
- discovered_tmpfile_override.stat.exists
- discovered_journald_fileperms_override.stdout | length > 0
ansible.builtin.import_tasks:
file: warning_facts.yml
vars:
warn_control_id: '6.2.1.2'
- name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured"
when: rhel9cis_rule_6_2_1_3
tags:
- level1-server
- level1-workstation
- patch
- journald
- rule_6.2.1.3
notify: Restart journald
block:
- name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured | Add file"
ansible.builtin.template:
src: etc/systemd/journald.conf.d/rotation.conf.j2
dest: /etc/systemd/journald.conf.d/rotation.conf
owner: root
group: root
mode: 'g-wx,o-rwx'
- name: "6.2.1.3 | PATCH | Ensure journald log file rotation is configured | comment out current entries"
ansible.builtin.replace:
path: /etc/systemd/journald.conf
regexp: "{{ item }}"
replace: '#\1'
loop:
- '^(\s*SystemMaxUse\s*=.*)'
- '^(\s*SystemKeepFree\s*=.*)'
- '^(\s*RuntimeMaxUse\s*=)'
- '^(\s*RuntimeKeepFree\s*=.*)'
- '^(\s*MaxFileSec\s*=.*)'
- name: "6.2.1.4 | PATCH | Ensure only one logging system is in use"
when: rhel9cis_rule_6_2_1_4
tags:
- level1-server
- level1-workstation
- patch
- journald
- syslog
- rule_6.2.1.4
block:
- name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when rsyslog"
when: rhel9cis_syslog == "rsyslog"
ansible.builtin.systemd:
name: systemd-journald
state: stopped
enabled: false
- name: "6.2.1.4 | PATCH | Ensure only one logging system is in use | when journald"
when: rhel9cis_syslog == "journald"
ansible.builtin.systemd:
name: rsyslog
state: stopped
enabled: false

Some files were not shown because too many files have changed in this diff Show more