Merge pull request #45 from ansible-lockdown/devel

Initial 1.0 release CIS 1.0
This commit is contained in:
uk-bolly 2023-03-21 15:39:53 +00:00 committed by GitHub
commit beaeb3a181
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
142 changed files with 6834 additions and 4963 deletions

View file

@ -1,11 +1,23 @@
---
parseable: true
quiet: true
skip_list:
- '204'
- '305'
- '303'
- '403'
- '306'
- '602'
- 'schema'
- 'no-changed-when'
- 'var-spacing'
- 'fqcn-builtins'
- 'experimental'
- 'name[play]'
- 'name[casing]'
- 'name[template]'
- 'fqcn[action]'
- '204'
- '305'
- '303'
- '403'
- '306'
- '602'
- '208'
use_default_rules: true
verbosity: 0

34
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,34 @@
---
name: Report Issue
about: Create a bug issue ticket to help us improve
title: ''
labels: bug
assignees: ''
---
**Describe the Issue**
A clear and concise description of what the bug is.
**Expected Behavior**
A clear and concise description of what you expected to happen.
**Actual Behavior**
A clear and concise description of what's happening.
**Control(s) Affected**
What controls are being affected by the issue
**Environment (please complete the following information):**
- branch being used: [e.g. devel]
- Ansible Version: [e.g. 2.10]
- Host Python Version: [e.g. Python 3.7.6]
- Ansible Server Python Version: [e.g. Python 3.7.6]
- Additional Details:
**Additional Notes**
Anything additional goes here
**Possible Solution**
Enter a suggested fix here

View file

@ -0,0 +1,22 @@
---
name: Feature Request or Enhancement
about: Suggest an idea for this project
title: ''
labels: enhancement
assignees: ''
---
## Feature Request or Enhancement
- Feature []
- Enhancement []
**Summary of Request**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Suggested Code**
Please provide any code you have in mind to fulfill the request

18
.github/ISSUE_TEMPLATE/question.md vendored Normal file
View file

@ -0,0 +1,18 @@
---
name: Question
about: Ask away.......
title: ''
labels: question
assignees: ''
---
**Question**
Pose question here.
**Environment (please complete the following information):**
- Ansible Version: [e.g. 2.10]
- Host Python Version: [e.g. Python 3.7.6]
- Ansible Server Python Version: [e.g. Python 3.7.6]
- Additional Details:

12
.github/pull_request_template.md vendored Normal file
View file

@ -0,0 +1,12 @@
**Overall Review of Changes:**
A general description of the changes made that are being requested for merge
**Issue Fixes:**
Please list (using linking) any open issues this PR addresses
**Enhancements:**
Please list any enhancements/features that are not open issue tickets
**How has this been tested?:**
Please give an overview of how these changes were tested. If they were not please use N/A

9
.github/workflows/OS.tfvars vendored Normal file
View file

@ -0,0 +1,9 @@
#Ami Alma 9
ami_id = "ami-0845395779540e3cb"
ami_os = "rhel9"
ami_username = "ec2-user"
ami_user_home = "/home/ec2-user"
instance_tags = {
Name = "RHEL9-CIS"
Environment = "lockdown_github_repo_workflow"
}

53
.github/workflows/github_networks.tf vendored Normal file
View file

@ -0,0 +1,53 @@
resource "aws_vpc" "Main" {
cidr_block = var.main_vpc_cidr
instance_tenancy = "default"
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-VPC"
}
}
resource "aws_internet_gateway" "IGW" {
vpc_id = aws_vpc.Main.id
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-IGW"
}
}
resource "aws_subnet" "publicsubnets" {
vpc_id = aws_vpc.Main.id
cidr_block = var.public_subnets
availability_zone = var.availability_zone
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-pubsub"
}
}
resource "aws_subnet" "Main" {
vpc_id = aws_vpc.Main.id
cidr_block = var.private_subnets
availability_zone = var.availability_zone
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-prvsub"
}
}
resource "aws_route_table" "PublicRT" {
vpc_id = aws_vpc.Main.id
route {
cidr_block = "0.0.0.0/0"
gateway_id = aws_internet_gateway.IGW.id
}
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-publicRT"
}
}
resource "aws_route_table_association" "rt_associate_public" {
subnet_id = aws_subnet.Main.id
route_table_id = aws_route_table.PublicRT.id
}

14
.github/workflows/github_vars.tfvars vendored Normal file
View file

@ -0,0 +1,14 @@
// github_actions variables
// Resourced in github_networks.tf
// Declared in variables.tf
//
namespace = "github_actions"
environment = "lockdown_github_repo_workflow"
// Matching pair name found in AWS for keypairs PEM key
ami_key_pair_name = "github_actions"
private_key = ".ssh/github_actions.pem"
main_vpc_cidr = "172.22.0.0/24"
public_subnets = "172.22.0.128/26"
private_subnets = "172.22.0.192/26"

View file

@ -0,0 +1,111 @@
# This is a basic workflow to help you get started with Actions
name: linux_benchmark_pipeline
# Controls when the action will run.
# Triggers the workflow on push or pull request
# events but only for the devel branch
on:
pull_request_target:
types: [opened, reopened, synchronize]
branches:
- devel
- main
paths:
- '**.yml'
- '**.sh'
- '**.j2'
- '**.ps1'
- '**.cfg'
# A workflow run is made up of one or more jobs
# that can run sequentially or in parallel
jobs:
# This will create messages for first time contributers and direct them to the Discord server
welcome:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@main
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
pr-message: |-
Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown!
Please join in the conversation happening on the [Discord Server](https://discord.io/ansible-lockdown) as well.
# This workflow contains a single job called "build"
build:
# The type of runner that the job will run on
runs-on: ubuntu-latest
env:
ENABLE_DEBUG: false
# Steps represent a sequence of tasks that will be executed as part of the job
steps:
# Checks-out your repository under $GITHUB_WORKSPACE,
# so your job can access it
- uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Add_ssh_key
working-directory: .github/workflows
env:
SSH_AUTH_SOCK: /tmp/ssh_agent.sock
PRIVATE_KEY: "${{ secrets.SSH_PRV_KEY }}"
run: |
mkdir .ssh
chmod 700 .ssh
echo $PRIVATE_KEY > .ssh/github_actions.pem
chmod 600 .ssh/github_actions.pem
### Build out the server
- name: Terraform_Init
working-directory: .github/workflows
run: terraform init
- name: Terraform_Validate
working-directory: .github/workflows
run: terraform validate
- name: Terraform_Apply
working-directory: .github/workflows
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: terraform apply -var-file "github_vars.tfvars" -var-file "OS.tfvars" --auto-approve -input=false
## Debug Section
- name: DEBUG - Show Ansible hostfile
if: env.ENABLE_DEBUG == 'true'
working-directory: .github/workflows
run: cat hosts.yml
# Aws deployments taking a while to come up insert sleep or playbook fails
- name: Sleep for 60 seconds
run: sleep 60s
shell: bash
# Run the ansible playbook
- name: Run_Ansible_Playbook
uses: arillso/action.playbook@master
with:
playbook: site.yml
inventory: .github/workflows/hosts.yml
galaxy_file: collections/requirements.yml
private_key: ${{ secrets.SSH_PRV_KEY }}
# verbose: 3
env:
ANSIBLE_HOST_KEY_CHECKING: "false"
ANSIBLE_DEPRECATION_WARNINGS: "false"
# Remove test system - User secrets to keep if necessary
- name: Terraform_Destroy
working-directory: .github/workflows
if: always() && env.ENABLE_DEBUG == 'false'
env:
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
run: terraform destroy -var-file "github_vars.tfvars" -var-file "OS.tfvars" --auto-approve -input=false

84
.github/workflows/main.tf vendored Normal file
View file

@ -0,0 +1,84 @@
provider "aws" {
profile = ""
region = var.aws_region
}
// Create a security group with access to port 22 and port 80 open to serve HTTP traffic
resource "random_id" "server" {
keepers = {
# Generate a new id each time we switch to a new AMI id
ami_id = "${var.ami_id}"
}
byte_length = 8
}
resource "aws_security_group" "github_actions" {
name = "${var.namespace}-${random_id.server.hex}-SG"
vpc_id = aws_vpc.Main.id
ingress {
from_port = 22
to_port = 22
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
tags = {
Environment = "${var.environment}"
Name = "${var.namespace}-SG"
}
}
// instance setup
resource "aws_instance" "testing_vm" {
ami = var.ami_id
availability_zone = var.availability_zone
associate_public_ip_address = true
key_name = var.ami_key_pair_name # This is the key as known in the ec2 key_pairs
instance_type = var.instance_type
tags = var.instance_tags
vpc_security_group_ids = [aws_security_group.github_actions.id]
subnet_id = aws_subnet.Main.id
root_block_device {
delete_on_termination = true
}
}
// generate inventory file
resource "local_file" "inventory" {
filename = "./hosts.yml"
directory_permission = "0755"
file_permission = "0644"
content = <<EOF
# benchmark host
all:
hosts:
${var.ami_os}:
ansible_host: ${aws_instance.testing_vm.public_ip}
ansible_user: ${var.ami_username}
vars:
setup_audit: true
run_audit: true
system_is_ec2: true
skip_reboot: false
rhel9cis_rule_5_6_6: false # skip root passwd check and keys only
EOF
}

6
.github/workflows/terraform.tfvars vendored Normal file
View file

@ -0,0 +1,6 @@
// vars should be loaded by OSname.tfvars
availability_zone = "us-east-1b"
aws_region = "us-east-1"
ami_os = var.ami_os
ami_username = var.ami_username
instance_tags = var.instance_tags

81
.github/workflows/variables.tf vendored Normal file
View file

@ -0,0 +1,81 @@
// Taken from the OSname.tfvars
variable "aws_region" {
description = "AWS region"
default = "us-east-1"
type = string
}
variable "availability_zone" {
description = "List of availability zone in the region"
default = "us-east-1b"
type = string
}
variable "instance_type" {
description = "EC2 Instance Type"
default = "t3.micro"
type = string
}
variable "instance_tags" {
description = "Tags to set for instances"
type = map(string)
}
variable "ami_key_pair_name" {
description = "Name of key pair in AWS thats used"
type = string
}
variable "private_key" {
description = "path to private key for ssh"
type = string
}
variable "ami_os" {
description = "AMI OS Type"
type = string
}
variable "ami_id" {
description = "AMI ID reference"
type = string
}
variable "ami_username" {
description = "Username for the ami id"
type = string
}
variable "ami_user_home" {
description = "home dir for the username"
type = string
}
variable "namespace" {
description = "Name used across all tags"
type = string
}
variable "environment" {
description = "Env Name used across all tags"
type = string
}
// taken from github_vars.tfvars &
variable "main_vpc_cidr" {
description = "Private cidr block to be used for vpc"
type = string
}
variable "public_subnets" {
description = "public subnet cidr block"
type = string
}
variable "private_subnets" {
description = "private subnet cidr block"
type = string
}

2
.gitignore vendored
View file

@ -11,6 +11,8 @@ packer_cache
delete*
ignore*
test_inv
# temp remove doc while this is built up
doc/
# VSCode
.vscode

View file

@ -1,23 +1,33 @@
---
ignore: |
tests/
molecule/
.gitlab-ci.yml
*molecule.yml
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
truthy: disable
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: false

View file

@ -1,93 +1,144 @@
# Changes to rhel9CIS
## 1.3.3
## 1.0.5
- update to audit script
- variable for audit OS agnostic
- removal of included library module (not required)
updated yamllint
removed empty lines after lint
initial molecule added
galaxy workflow updated
- Issues included
- #135 - running levels - upadted tags
- #138 - auditd immutable
- #139 - 5.2.13 valus updated
- #140
- #141 - check mode update
- #142
- #143 - labels added
- #144
- #146 - undefined variable added
- #147 - removed warn statement
- #149 - shell timeout
## 1.0.4
## 1.3.2
#40 tmp systemd file variable naming update
#41 5.3.7 logic and rewrite - tidy up prelim for sugroup work - audit updated
- issues with crypto policies on ec2 - added skip for rules if system_is_ec2 variable
- cis_1.10 ## Change crypto breaks installing products
- cis_1.11 ## Change crypto breaks installing products
## 1.0.3
## 1.3.1
Update to auditd components improve idempotency and tidy up
Added a warning to check diff if any changes to template file (if template file exists) else its new.
workflow update to remove the urandom update
skip 5.6.6 root password check
variable naming
OracleLinux support added
#38 journald restart amendment thanks to @bdwyertech
- CIS 1.0.1 updates
- Added Issue and PR templates
- Added better reboot logic
- Added options to ensure idempotence
- Enhanced flush handlers
- Typo fixes
- mount check improvements
- Linting fixes
- Added systemd tmp mount
- Added systemd tmpfs block
- #110 tmp.mount support
- thanks to @erpadmin
## 1.0.2
## 1.3
thanks to @smatterchew
#30 ability to change sshd config file to use dropin file instead.
- extentions to LE audit capability
- more lint and layout changes
- sugroup assertion added 5.7
- added extra logic variable to authselect/config section 5.3 related
- AlmaLinux and Rocky tested (comments in readme - also rsyslog installed at build or will fail)
- section 1.1 mount work has been rewritten and systemd tmp mount options added
thanks to @I-am-MoS
#34 create user.cfg if not present
## 1.2.3
Aligned benchmark audit version with remediate release
- #117 sugroup enhancements
- thanks to @ihotz
- #112 use of dnf module not shell
- thanks to @wolskie
## 1.0.1
## 1.2.2
Control 6_2_16 new variable added thanks to @dulin_gnet on rhel8
Will not follow ynlink in hoe directoris and amend permissions.
- #33 mkgrub missing variable issues - efi and bios path resolution
- thanks to @mrampant & @mickey1928geo
- #102 2.2.2 xorg pkg removal extended
- thanks to @RosarioVinoth
- #104 5.4.1 pwquality logic
- thanks to @RosarioVinoth
- #107 Idempotence improvement for 4.1.1.3 and 4.1.1.4
- thanks to @andreyzher
- lint changes and updates to sync with ansible-galaxy
- rhel_09_6_2_16_home_follow_symlink: false
## v1.2.1
## Initial CIS v1.0.0 - released Dec 2022
- bootloader and default variables
- empty strings lint updates
- #87
- rule 6.1.1 - audit only - outputs file discrepancies to {{ rhel9cis_rpm_audit_file }}
- #88
- checkmode_improvements added to relevant tasks
- PR #96
- crypto policy idempotency
### Official CIS release
## v1.2.0
Jan-2023 release
- #86
- Adding on the goss auditing tool
- remove deprecated warnings
- format and layout
- general improvements
- readme updates
- use ansible package_facts
- #90
- cis fix - nfs-server not nfs
- Thanks to danderemer
- updated ansible minimum to 2.10
- Lint file updates and improvements
- auditd now shows diff ater initial template added
- many control rewritten
- Many controls moved ID references
- Audit updates aligned
- Command warn arg removed
- Ansible 2.14 now supported
- makefile added (hopefully help some)
- fqcn added to all controls
- some controls rewritten using module rather than shell
- typo fixes from rhel_08 inheritance
- workflow update for 5.6.6 to set random root password to allow for testing
- incorporates issues
- #23
- #24
- New option to add faillock for users without authselect - defaults/main 5.4.2
## 0.5
- audit path updated and output file name
### Taken from RHEL8-CIS issues and PRs
- #209 5.6.5 rewrite umask settings
- #220 tidy up and align variables
- #226 Thanks to Thulium-Drake
-Extended the auditd config required value for auditd space left percentage (not part of CIS Benchmark but required fopr auditd to run correctly in some cases)
- #227 thanks to OscarElits
- chrony files now RH expected locations
- #228 Thanks to benbulll
- audit binary copy var missing
## 0.4
- Added assertion that ansible_user has password set for rule 5.3.4
- RockyLinux now supported - release since initial branches
- gpg check updates
- audit out dir now /opt
- lint updates and improvements
- workflow updates and improvements moved to rocky image
- selinux regexp improvements
- warning summary now at end of play
- advanced auditd options to exclude users in POST section
- Issues fixed thanks to fgierlinger
- [#21](https://github.com/ansible-lockdown/RHEL9-CIS/issues/21)
- [#22](https://github.com/ansible-lockdown/RHEL9-CIS/issues/22)
## 0.3
- update to auditd template
- uses facts and template new variable
- update_audit_template (default false)
- sysctl template updates and idempotency improvements
- container discovery usage improvements
- 3.4.1.5 discovery improvement
- 5.6.1.4 discovery improvement
- logrotate process logrotate.timer
- tidy up become:
- logic improvements
## 0.2
- not all controls work with rhel8 releases any longer
- selinux disabled 1.6.1.4
- logrotate - 4.3.x
- updated to rhel8cis v2.0 benchamrk requirements
- removed iptables firewall controls (not valid on rhel9)
- added more to logrotate 4.3.x - sure to logrotate now a seperate package
- grub path now standard to /boot/grub2/grub.cfg
- 1.6.1.4 from rh8 removed as selinux.cfg doesnt disable selinux any longer
- workflow update
- removed doc update
## 0.1
- change to include statements
- prelim and package facts discovery
- commands module removed and moved to shell
- added
```yml
args:
warn: false
```
- update boolean values to true/false
- 3.4.2 improved checks for p[ackage presence
- changed to assert for OS/release and ansible version
## Initial
- based on RHEL8 currently as RH or CIS not GA
- Changes to systctl, auditd, aide cron changes to utilise templates - see issue #1
- Collection statement added to meta/main.yml using only community-general
- aide crontab moved to template due to module change

View file

@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases
Copyright (c) 2022 Mindpoint Group / Lockdown Enterprise / Lockdown Enterprise Releases
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

32
Makefile Executable file
View file

@ -0,0 +1,32 @@
.PHONY: all help galaxy-install ansible-list yamllint pip-requirements
GALAXY=ansible-galaxy
ANSIBLE_LINT='/usr/local/bin/ansible-lint'
ANSIBLE_FILE=site.yml
all: help
help:
@echo "Make command examples for Ansible"
@echo "Command for assisting with ansible setup"
@echo " galaxy-install to install roles using ansible-galaxy"
@echo " ansible-lint to lint playbook files"
@echo " yamllint to lint playbook files"
@echo " pip-requirements add pip required file"
galaxy-install:
$(GALAXY) install -r ./collections/requirements.yml
ansible-lint:
$(ANSIBLE_LINT) $(ANSIBLE_FILE)
yamllint:
git ls-files "*.yml"|xargs yamllint
pip-requirements:
@echo 'Python dependencies:'
@cat requirements.txt
pip3 install -r requirements.txt

View file

@ -1,22 +1,23 @@
# Development Only
## RHEL 9 CIS (predicted) - ALPHA - CIS baselines or OS not yet GA
# RHEL 9 CIS
## Testing if you have access to the RH developer branches
### This should work on RHEL8 and derivatives currently
## v1.0.0 - released Dec 2022
![Build Status](https://img.shields.io/github/workflow/status/ansible-lockdown/RHEL9-CIS/CommunityToDevel?label=Devel%20Build%20Status&style=plastic)
![Build Status](https://img.shields.io/github/workflow/status/ansible-lockdown/RHEL9-CIS/DevelToMain?label=Main%20Build%20Status&style=plastic)
![Release](https://img.shields.io/github/v/release/ansible-lockdown/RHEL9-CIS?style=plastic)
Configure RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/) compliant with RHEL8 settings (RHEL9 not yet released)
Configure RHEL 9 machine to be [CIS](https://www.cisecurity.org/cis-benchmarks/)
Based on [CIS RedHat Enterprise Linux 8 Benchmark v1.0.1 - 05-19-2021 ](https://www.cisecurity.org/cis-benchmarks/)
Based on [CIS RedHat Enterprise Linux 9 Benchmark v1.0.0. - 11-30-2022 ](https://www.cisecurity.org/cis-benchmarks/)
## Join us
On our [Discord Server](https://discord.io/ansible-lockdown) to ask questions, discuss features, or just chat with other Ansible-Lockdown users
## Caution(s)
This role **will make changes to the system** which may have unintended concequences. This is not an auditing tool but rather a remediation tool to be used after an audit has been conducted.
This role **will make changes to the system** which may have unintended concequences.
This role was developed against a clean install of the Operating System. If you are implimenting to an existing system please review this role for any site specific changes that are needed.
@ -24,39 +25,43 @@ To use release version please point to main branch
## Documentation
- [Readthedocs](https://ansible-lockdown.readthedocs.io/en/latest/)
- [Getting Started](https://www.lockdownenterprise.com/docs/getting-started-with-lockdown)
- [Customizing Roles](https://www.lockdownenterprise.com/docs/customizing-lockdown-enterprise)
- [Per-Host Configuration](https://www.lockdownenterprise.com/docs/per-host-lockdown-enterprise-configuration)
- [Getting the Most Out of the Role](https://www.lockdownenterprise.com/docs/get-the-most-out-of-lockdown-enterprise)
- [Wiki](https://github.com/ansible-lockdown/RHEL9-CIS/wiki)
- [Repo GitHub Page](https://ansible-lockdown.github.io/RHEL9-CIS/)
## Auditing (new)
This can be turned on or off within the defaults/main.yml file with the variable rhel9cis_run_audit. The value is false by default, please refer to the wiki for more details.
This is a much quicker, very lightweight, checking (where possible) config compliance and live/running settings.
A new form of auditing has been develeoped, by using a small (12MB) go binary called [goss](https://github.com/aelsabbahy/goss) along with the relevant configurations to check. Without the need for infrastructure or other tooling.
This audit will not only check the config has the correct setting but aims to capture if it is running with that configuration also trying to remove [false positives](https://www.mindpointgroup.com/blog/is-compliance-scanning-still-relevant/) in the process.
Refer to [RHEL9-CIS-Audit](https://github.com/ansible-lockdown/RHEL9-CIS-Audit).
## Requirements
RHEL 9 - Other versions are not supported.
RHEL 9
Almalinux 9
Rocky 9
OracleLinux 9
ansible 2.10
jmespath
relevant collections
- Access to download or add the goss binary and content to the system if using auditing (other options are available on how to get the content to the system.)
**General:**
## Tested with
ansible-base 2.10.17 - python 3.8
ansible-core 2.13.4 - python 3.10
- makefile - this is there purely for testing and initial setup purposes.
## General
- Basic knowledge of Ansible, below are some links to the Ansible documentation to help get started if you are unfamiliar with Ansible
- [Main Ansible documentation page](https://docs.ansible.com)
- [Ansible Getting Started](https://docs.ansible.com/ansible/latest/user_guide/intro_getting_started.html)
- [Tower User Guide](https://docs.ansible.com/ansible-tower/latest/html/userguide/index.html)
- [Ansible Community Info](https://docs.ansible.com/ansible/latest/community/index.html)
- Functioning Ansible and/or Tower Installed, configured, and running. This includes all of the base Ansible/Tower configurations, needed packages installed, and infrastructure setup.
- Please read through the tasks in this role to gain an understanding of what each control is doing. Some of the tasks are disruptive and can have unintended consiquences in a live production system. Also familiarize yourself with the variables in the defaults/main.yml file or the [Main Variables Wiki Page](https://github.com/ansible-lockdown/RHEL9-CIS/wiki/Main-Variables).
- 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
## Dependencies
@ -64,10 +69,13 @@ RHEL 9 - Other versions are not supported.
- Ansible 2.9+
- python-def (should be included in RHEL 9)
- libselinux-python
- pip packages
- jmespath ( complete list found in requirements.txt)
- collections found in collections/requirememnts.yml
## Role Variables
This role is designed that the end user should not have to edit the tasks themselves. All customizing should be done via the defaults/main.yml file or with extra vars within the project, job, workflow, etc. These variables can be found [here](https://github.com/ansible-lockdown/RHEL9-CIS/wiki/Main-Variables) in the Main Variables Wiki page. All variables are listed there along with descriptions.
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
## Tags
@ -86,38 +94,9 @@ Below is an example of the tag section from a control within this role. Using th
- rule_2.2.4
```
## Example Audit Summary
### Known Issues
This is based on a vagrant image with selections enabled. e.g. No Gui or firewall.
Note: More tests are run during audit as we check config and running state.
```txt
ok: [default] => {
"msg": [
"The pre remediation results are: ['Total Duration: 5.454s', 'Count: 338, Failed: 47, Skipped: 5'].",
"The post remediation results are: ['Total Duration: 5.007s', 'Count: 338, Failed: 46, Skipped: 5'].",
"Full breakdown can be found in /var/tmp",
""
]
}
PLAY RECAP *******************************************************************************************************************************************
default : ok=270 changed=23 unreachable=0 failed=0 skipped=140 rescued=0 ignored=0
```
## Branches
- devel - This is the default branch and the working development branch. Community pull requests will pull into this branch
- main - This is the release branch
- reports - This is a protected branch for our scoring reports, no code should ever go here
- all other branches** - Individual community member branches
## Community Contribution
We encourage you (the community) to contribute to this role. Please read the rules below.
- Your work is done in your own individual branch. Make sure to Signed-off and GPG sign all commits you intend to merge.
- All community Pull Requests are pulled into the devel branch
- Pull Requests into devel will confirm your commits have a GPG signature, Signed-off, and a functional test before being approved
- Once your changes are merged and a more detailed review is complete, an authorized member will merge your changes into the main branch for a new release
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

View file

@ -5,7 +5,13 @@ system_warnings=False
command_warnings=False
nocows=1
retry_files_save_path=/dev/null
library=~/.ansible/plugins/modules:/usr/share/ansible/plugins/modules:./library
pipelining=true
# Use the YAML callback plugin.
stdout_callback = yaml
# Use the stdout_callback when running ad-hoc commands.
bin_ansible_callbacks = True
[privilege_escalation]
@ -14,6 +20,7 @@ record_host_keys=False
[ssh_connection]
transfer_method=scp
ssh_args = -o ControlMaster=auto -o ControlPersist=60s
[accelerate]

View file

@ -0,0 +1,5 @@
---
collections:
- name: community.general
- name: community.crypto
- name: ansible.posix

View file

@ -1,13 +1,15 @@
---
# defaults file for rhel9-cis
rhel9cis_skip_for_travis: false
rhel9cis_system_is_container: false
system_is_container: false
container_vars_file: is_container.yml
# rhel9cis is left off the front of this var for consistency in testing pipeline
# system_is_ec2 toggle will disable tasks that fail on Amazon EC2 instances. Set true to skip and false to run tasks
system_is_ec2: false
rhel9cis_notauto: false
# Run the OS validation check
os_check: true
rhel9cis_section1: true
rhel9cis_section2: true
rhel9cis_section3: true
@ -15,6 +17,10 @@ rhel9cis_section4: true
rhel9cis_section5: true
rhel9cis_section6: true
# This is used for audit purposes to run only specifc level use the tags
# e.g.
# - level1-server
# - level2-workstation
rhel9cis_level_1: true
rhel9cis_level_2: true
@ -27,10 +33,16 @@ python2_bin: /bin/python2.7
## Benchmark name used by audting control role
# The audit variable found at the base
## metadata for Audit benchmark
benchmark_version: 'v1.0.0'
benchmark: RHEL9-CIS
# Whether to skip the reboot
rhel9cis_skip_reboot: true
skip_reboot: true
# default value will change to true but wont reboot if not enabled but will error
change_requires_reboot: false
#### Basic external goss audit enablement settings ####
#### Precise details - per setting can be found at the bottom of this file ####
@ -50,7 +62,7 @@ audit_content: git
run_audit: false
# Timeout for those cmds that take longer to run where timeout set
audit_cmd_timeout: 30000
audit_cmd_timeout: 60000
### End Goss enablements ####
#### Detailed settings found at the end of this document ####
@ -62,36 +74,41 @@ audit_cmd_timeout: 30000
# Section 1 rules
rhel9cis_rule_1_1_1_1: true
rhel9cis_rule_1_1_1_2: true
rhel9cis_rule_1_1_1_3: true
rhel9cis_rule_1_1_1_4: true
rhel9cis_rule_1_1_1_5: true
rhel9cis_rule_1_1_2: true
rhel9cis_rule_1_1_3: true
rhel9cis_rule_1_1_4: true
rhel9cis_rule_1_1_5: true
rhel9cis_rule_1_1_6: true
rhel9cis_rule_1_1_7: true
rhel9cis_rule_1_1_8: true
rhel9cis_rule_1_1_9: true
rhel9cis_rule_1_1_10: true
rhel9cis_rule_1_1_11: true
rhel9cis_rule_1_1_12: true
rhel9cis_rule_1_1_13: true
rhel9cis_rule_1_1_14: true
rhel9cis_rule_1_1_15: true
rhel9cis_rule_1_1_16: true
rhel9cis_rule_1_1_17: true
rhel9cis_rule_1_1_2_1: true
rhel9cis_rule_1_1_2_2: true
rhel9cis_rule_1_1_2_3: true
rhel9cis_rule_1_1_2_4: true
rhel9cis_rule_1_1_3_1: true
rhel9cis_rule_1_1_3_2: true
rhel9cis_rule_1_1_3_3: true
rhel9cis_rule_1_1_4_1: true
rhel9cis_rule_1_1_4_2: true
rhel9cis_rule_1_1_4_3: true
rhel9cis_rule_1_1_4_4: true
rhel9cis_rule_1_1_5_1: true
rhel9cis_rule_1_1_5_2: true
rhel9cis_rule_1_1_5_3: true
rhel9cis_rule_1_1_5_4: true
rhel9cis_rule_1_1_6_1: true
rhel9cis_rule_1_1_6_2: true
rhel9cis_rule_1_1_6_3: true
rhel9cis_rule_1_1_6_4: true
rhel9cis_rule_1_1_7_1: true
rhel9cis_rule_1_1_7_2: true
rhel9cis_rule_1_1_7_3: true
rhel9cis_rule_1_1_8_1: true
rhel9cis_rule_1_1_8_2: true
rhel9cis_rule_1_1_8_3: true
rhel9cis_rule_1_1_8_4: true
rhel9cis_rule_1_1_18: true
rhel9cis_rule_1_1_19: true
rhel9cis_rule_1_1_20: true
rhel9cis_rule_1_1_21: true
rhel9cis_rule_1_1_22: true
rhel9cis_rule_1_1_23: true
rhel9cis_rule_1_1_9: true
rhel9cis_rule_1_2_1: true
rhel9cis_rule_1_2_2: true
rhel9cis_rule_1_2_3: true
rhel9cis_rule_1_2_4: true
rhel9cis_rule_1_2_5: true
rhel9cis_rule_1_3_1: true
rhel9cis_rule_1_3_2: true
rhel9cis_rule_1_3_3: true
@ -100,37 +117,37 @@ rhel9cis_rule_1_4_2: true
rhel9cis_rule_1_5_1: true
rhel9cis_rule_1_5_2: true
rhel9cis_rule_1_5_3: true
rhel9cis_rule_1_6_1: true
rhel9cis_rule_1_6_2: true
rhel9cis_rule_1_7_1_1: true
rhel9cis_rule_1_7_1_2: true
rhel9cis_rule_1_7_1_3: true
rhel9cis_rule_1_7_1_4: true
rhel9cis_rule_1_7_1_5: true
rhel9cis_rule_1_7_1_6: true
rhel9cis_rule_1_7_1_7: true
rhel9cis_rule_1_8_1_1: true
rhel9cis_rule_1_8_1_2: true
rhel9cis_rule_1_8_1_3: true
rhel9cis_rule_1_8_1_4: true
rhel9cis_rule_1_8_1_5: true
rhel9cis_rule_1_8_1_6: true
rhel9cis_rule_1_6_1_1: true
rhel9cis_rule_1_6_1_2: true
rhel9cis_rule_1_6_1_3: true
rhel9cis_rule_1_6_1_4: true
rhel9cis_rule_1_6_1_5: true
rhel9cis_rule_1_6_1_6: true
rhel9cis_rule_1_6_1_7: true
rhel9cis_rule_1_6_1_8: true
rhel9cis_rule_1_7_1: true
rhel9cis_rule_1_7_2: true
rhel9cis_rule_1_7_3: true
rhel9cis_rule_1_7_4: true
rhel9cis_rule_1_7_5: true
rhel9cis_rule_1_7_6: true
rhel9cis_rule_1_8_1: true
rhel9cis_rule_1_8_2: true
rhel9cis_rule_1_8_3: true
rhel9cis_rule_1_8_4: true
rhel9cis_rule_1_8_5: true
rhel9cis_rule_1_8_6: true
rhel9cis_rule_1_8_7: true
rhel9cis_rule_1_8_8: true
rhel9cis_rule_1_8_9: true
rhel9cis_rule_1_8_10: true
rhel9cis_rule_1_9: true
rhel9cis_rule_1_10: true
rhel9cis_rule_1_11: true
# Section 2 rules
rhel9cis_rule_2_1_1: true
rhel9cis_rule_2_1_2: true
rhel9cis_rule_2_1_3: true
rhel9cis_rule_2_1_4: true
rhel9cis_rule_2_1_5: true
rhel9cis_rule_2_1_6: true
rhel9cis_rule_2_1_7: true
rhel9cis_rule_2_2_1_1: true
rhel9cis_rule_2_2_1_2: true
rhel9cis_rule_2_2_1_3: true
rhel9cis_rule_2_2_1: true
rhel9cis_rule_2_2_2: true
rhel9cis_rule_2_2_3: true
rhel9cis_rule_2_2_4: true
@ -151,50 +168,33 @@ rhel9cis_rule_2_2_18: true
rhel9cis_rule_2_3_1: true
rhel9cis_rule_2_3_2: true
rhel9cis_rule_2_3_3: true
rhel9cis_rule_2_3_4: true
rhel9cis_rule_2_4: true
# Section 3 rules
rhel9cis_rule_3_1_1: true
rhel9cis_rule_3_1_2: true
rhel9cis_rule_3_1_3: true
rhel9cis_rule_3_2_1: true
rhel9cis_rule_3_2_2: true
rhel9cis_rule_3_2_3: true
rhel9cis_rule_3_2_4: true
rhel9cis_rule_3_2_5: true
rhel9cis_rule_3_2_6: true
rhel9cis_rule_3_2_7: true
rhel9cis_rule_3_2_8: true
rhel9cis_rule_3_2_9: true
rhel9cis_rule_3_3_1: true
rhel9cis_rule_3_3_2: true
rhel9cis_rule_3_3_3: true
rhel9cis_rule_3_3_4: true
rhel9cis_rule_3_3_5: true
rhel9cis_rule_3_3_6: true
rhel9cis_rule_3_3_7: true
rhel9cis_rule_3_3_8: true
rhel9cis_rule_3_3_9: true
rhel9cis_rule_3_4_1_1: true
rhel9cis_rule_3_4_1_2: true
rhel9cis_rule_3_4_2_1: true
rhel9cis_rule_3_4_2_2: true
rhel9cis_rule_3_4_2_3: true
rhel9cis_rule_3_4_2_4: true
rhel9cis_rule_3_4_2_5: true
rhel9cis_rule_3_4_2_6: true
rhel9cis_rule_3_4_3_1: true
rhel9cis_rule_3_4_3_2: true
rhel9cis_rule_3_4_3_3: true
rhel9cis_rule_3_4_3_4: true
rhel9cis_rule_3_4_3_5: true
rhel9cis_rule_3_4_3_6: true
rhel9cis_rule_3_4_3_7: true
rhel9cis_rule_3_4_3_8: true
rhel9cis_rule_3_4_4_1_1: true
rhel9cis_rule_3_4_4_1_2: true
rhel9cis_rule_3_4_4_1_3: true
rhel9cis_rule_3_4_4_1_4: true
rhel9cis_rule_3_4_4_1_5: true
rhel9cis_rule_3_4_4_2_1: true
rhel9cis_rule_3_4_4_2_2: true
rhel9cis_rule_3_4_4_2_3: true
rhel9cis_rule_3_4_4_2_4: true
rhel9cis_rule_3_4_4_2_5: true
rhel9cis_rule_3_5: true
rhel9cis_rule_3_6: true
rhel9cis_rule_3_4_2_7: true
# Section 4 rules
rhel9cis_rule_4_1_1_1: true
@ -204,30 +204,54 @@ rhel9cis_rule_4_1_1_4: true
rhel9cis_rule_4_1_2_1: true
rhel9cis_rule_4_1_2_2: true
rhel9cis_rule_4_1_2_3: true
rhel9cis_rule_4_1_3: true
rhel9cis_rule_4_1_4: true
rhel9cis_rule_4_1_5: true
rhel9cis_rule_4_1_6: true
rhel9cis_rule_4_1_7: true
rhel9cis_rule_4_1_8: true
rhel9cis_rule_4_1_9: true
rhel9cis_rule_4_1_10: true
rhel9cis_rule_4_1_11: true
rhel9cis_rule_4_1_12: true
rhel9cis_rule_4_1_13: true
rhel9cis_rule_4_1_14: true
rhel9cis_rule_4_1_15: true
rhel9cis_rule_4_1_16: true
rhel9cis_rule_4_1_17: true
rhel9cis_rule_4_1_3_1: true
rhel9cis_rule_4_1_3_2: true
rhel9cis_rule_4_1_3_3: true
rhel9cis_rule_4_1_3_4: true
rhel9cis_rule_4_1_3_5: true
rhel9cis_rule_4_1_3_6: true
rhel9cis_rule_4_1_3_7: true
rhel9cis_rule_4_1_3_8: true
rhel9cis_rule_4_1_3_9: true
rhel9cis_rule_4_1_3_10: true
rhel9cis_rule_4_1_3_11: true
rhel9cis_rule_4_1_3_12: true
rhel9cis_rule_4_1_3_13: true
rhel9cis_rule_4_1_3_14: true
rhel9cis_rule_4_1_3_15: true
rhel9cis_rule_4_1_3_16: true
rhel9cis_rule_4_1_3_17: true
rhel9cis_rule_4_1_3_18: true
rhel9cis_rule_4_1_3_19: true
rhel9cis_rule_4_1_3_20: true
rhel9cis_rule_4_1_3_21: true
rhel9cis_rule_4_1_4_1: true
rhel9cis_rule_4_1_4_2: true
rhel9cis_rule_4_1_4_3: true
rhel9cis_rule_4_1_4_4: true
rhel9cis_rule_4_1_4_5: true
rhel9cis_rule_4_1_4_6: true
rhel9cis_rule_4_1_4_7: true
rhel9cis_rule_4_1_4_8: true
rhel9cis_rule_4_1_4_9: true
rhel9cis_rule_4_1_4_10: true
rhel9cis_rule_4_2_1_1: true
rhel9cis_rule_4_2_1_2: true
rhel9cis_rule_4_2_1_3: true
rhel9cis_rule_4_2_1_4: true
rhel9cis_rule_4_2_1_5: true
rhel9cis_rule_4_2_1_6: true
rhel9cis_rule_4_2_2_1: true
rhel9cis_rule_4_2_1_7: true
rhel9cis_rule_4_2_2_1_1: true
rhel9cis_rule_4_2_2_1_2: true
rhel9cis_rule_4_2_2_1_3: true
rhel9cis_rule_4_2_2_1_4: true
rhel9cis_rule_4_2_2_2: true
rhel9cis_rule_4_2_2_3: true
rhel9cis_rule_4_2_2_4: true
rhel9cis_rule_4_2_2_5: true
rhel9cis_rule_4_2_2_6: true
rhel9cis_rule_4_2_2_7: true
rhel9cis_rule_4_2_3: true
rhel9cis_rule_4_3: true
@ -240,6 +264,7 @@ rhel9cis_rule_5_1_5: true
rhel9cis_rule_5_1_6: true
rhel9cis_rule_5_1_7: true
rhel9cis_rule_5_1_8: true
rhel9cis_rule_5_1_9: true
rhel9cis_rule_5_2_1: true
rhel9cis_rule_5_2_2: true
rhel9cis_rule_5_2_3: true
@ -263,21 +288,27 @@ rhel9cis_rule_5_2_20: true
rhel9cis_rule_5_3_1: true
rhel9cis_rule_5_3_2: true
rhel9cis_rule_5_3_3: true
rhel9cis_rule_5_3_4: true
rhel9cis_rule_5_3_5: true
rhel9cis_rule_5_3_6: true
rhel9cis_rule_5_3_7: true
rhel9cis_rule_5_4_1: true
rhel9cis_rule_5_4_2: true
rhel9cis_rule_5_4_3: true
rhel9cis_rule_5_4_4: true
rhel9cis_rule_5_5_1_1: true
rhel9cis_rule_5_5_1_2: true
rhel9cis_rule_5_5_1_3: true
rhel9cis_rule_5_5_1_4: true
rhel9cis_rule_5_5_1_5: true
rhel9cis_rule_5_5_1: true
rhel9cis_rule_5_5_2: true
rhel9cis_rule_5_5_3: true
rhel9cis_rule_5_5_4: true
rhel9cis_rule_5_5_5: true
rhel9cis_rule_5_6: true
rhel9cis_rule_5_7: true
rhel9cis_rule_5_6_1_1: true
rhel9cis_rule_5_6_1_2: true
rhel9cis_rule_5_6_1_3: true
rhel9cis_rule_5_6_1_4: true
rhel9cis_rule_5_6_1_5: true
rhel9cis_rule_5_6_2: true
rhel9cis_rule_5_6_3: true
rhel9cis_rule_5_6_4: true
rhel9cis_rule_5_6_5: true
rhel9cis_rule_5_6_6: true
# Section 6 rules
rhel9cis_rule_6_1_1: true
@ -294,6 +325,7 @@ rhel9cis_rule_6_1_11: true
rhel9cis_rule_6_1_12: true
rhel9cis_rule_6_1_13: true
rhel9cis_rule_6_1_14: true
rhel9cis_rule_6_1_15: true
rhel9cis_rule_6_2_1: true
rhel9cis_rule_6_2_2: true
rhel9cis_rule_6_2_3: true
@ -301,7 +333,7 @@ rhel9cis_rule_6_2_4: true
rhel9cis_rule_6_2_5: true
rhel9cis_rule_6_2_6: true
rhel9cis_rule_6_2_7: true
rhel9cis_rule_6_2_8: false
rhel9cis_rule_6_2_8: true
rhel9cis_rule_6_2_9: true
rhel9cis_rule_6_2_10: true
rhel9cis_rule_6_2_11: true
@ -310,51 +342,19 @@ rhel9cis_rule_6_2_13: true
rhel9cis_rule_6_2_14: true
rhel9cis_rule_6_2_15: true
rhel9cis_rule_6_2_16: true
rhel9cis_rule_6_2_17: true
rhel9cis_rule_6_2_18: true
rhel9cis_rule_6_2_19: true
rhel9cis_rule_6_2_20: true
# Service configuration booleans set true to keep service
rhel9cis_avahi_server: false
rhel9cis_cups_server: false
rhel9cis_dhcp_server: false
rhel9cis_ldap_server: false
rhel9cis_telnet_server: false
rhel9cis_nfs_server: false
rhel9cis_rpc_server: false
rhel9cis_ntalk_server: false
rhel9cis_rsyncd_server: false
rhel9cis_tftp_server: false
rhel9cis_rsh_server: false
rhel9cis_nis_server: false
rhel9cis_snmp_server: false
rhel9cis_squid_server: false
rhel9cis_smb_server: false
rhel9cis_dovecot_server: false
rhel9cis_httpd_server: false
rhel9cis_vsftpd_server: false
rhel9cis_named_server: false
rhel9cis_nfs_rpc_server: false
rhel9cis_is_mail_server: false
rhel9cis_bind: false
rhel9cis_vsftpd: false
rhel9cis_httpd: false
rhel9cis_dovecot: false
rhel9cis_samba: false
rhel9cis_squid: false
rhel9cis_net_snmp: false
rhel9cis_allow_autofs: false
## Section 1 vars
# 1.1.2
#### 1.1.2
# These settings go into the /etc/fstab file for the /tmp mount settings
# The value must contain nosuid,nodev,noexec to conform to CIS standards
# rhel9cis_tmp_tmpfs_settings: "defaults,rw,nosuid,nodev,noexec,relatime 0 0"
# If set true uses the tmp.mount service else using fstab configuration
rhel9cis_tmp_svc: false
#### 1.1.9
rhel9cis_allow_autofs: false
# 1.2.1
# This is the login information for your RedHat Subscription
# DO NOT USE PLAIN TEXT PASSWORDS!!!!!
@ -367,20 +367,22 @@ rhel9cis_rh_sub_password: password
# RedHat Satellite Subscription items
rhel9cis_rhnsd_required: false
# 1.3.3 var log location variable
rhel9cis_varlog_location: "/var/log/sudo.log"
# xinetd required
rhel9cis_xinetd_required: false
# 1.2.4 repo_gpgcheck
rhel9cis_rhel_default_repo: true
# 1.4.2 Bootloader password
rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.changethispassword'
rhel9cis_bootloader_password_hash: 'grub.pbkdf2.sha512.10000.9306A36764A7BEA3BF492D1784396B27F52A71812E9955A58709F94EE70697F9BD5366F36E07DEC41B52279A056E2862A93E42069D7BBB08F5DFC2679CD43812.6C32ADA5449303AD5E67A4C150558592A05381331DE6B33463469A236871FA8E70738C6F9066091D877EF88A213C86825E093117F30E9E1BF158D0DB75E7581B'
rhel9cis_bootloader_password: random
rhel9cis_set_boot_pass: false
rhel9cis_set_boot_pass: true
# 1.10/1.11 Set crypto policy (LEGACY, DEFAULT, FUTURE, FIPS)
# Control 1.10 sates not ot use LEGACY and control 1.11 says to use FUTURE or FIPS.
rhel9cis_crypto_policy: "FUTURE"
# 1.8 Gnome Desktop
rhel9cis_dconf_db_name: local
rhel9cis_screensaver_idle_delay: 900 # Set max value for idle-delay in seconds (between 1 and 900)
rhel9cis_screensaver_lock_delay: 5 # Set max value for lock-delay in seconds (between 0 and 5)
# 1.10 Set crypto policy DEFAULT
# Control 1.10 states not to use LEGACY
rhel9cis_crypto_policy: "DEFAULT"
# System network parameters (host only OR host and router)
rhel9cis_is_router: false
@ -393,7 +395,7 @@ rhel9cis_config_aide: true
# AIDE cron settings
rhel9cis_aide_cron:
cron_user: root
cron_file: /etc/crontab
cron_file: /etc/cron.d/aide_cron
aide_job: '/usr/sbin/aide --check'
aide_minute: 0
aide_hour: 5
@ -403,107 +405,170 @@ rhel9cis_aide_cron:
# SELinux policy
rhel9cis_selinux_pol: targeted
# chose onf or enfocing or permissive
rhel9cis_selinux_enforce: enforcing
# Whether or not to run tasks related to auditing/patching the desktop environment
rhel9cis_gui: no
# Set to 'true' if X Windows is needed in your environment
rhel9cis_xwindows_required: false
## 2. Services
rhel9cis_openldap_clients_required: false
rhel9cis_telnet_required: false
rhel9cis_talk_required: false
rhel9cis_rsh_required: false
rhel9cis_ypbind_required: false
# 2.2.1.1 Time Synchronization - Either chrony or ntp
rhel9cis_time_synchronization: chrony
# 2.2.1.2 Time Synchronization servers - used in template file chrony.conf.j2
### 2.1 Time Synchronization
#### 2.1.2 Time Synchronization servers - used in template file chrony.conf.j2
rhel9cis_time_synchronization_servers:
- 0.pool.ntp.org
- 1.pool.ntp.org
- 2.pool.ntp.org
- 3.pool.ntp.org
rhel9cis_chrony_server_options: "minpoll 8"
rhel9cis_ntp_server_options: "iburst"
### 2.2 Special Purposes
##### Service configuration booleans set true to keep service
rhel9cis_gui: false
rhel9cis_avahi_server: false
rhel9cis_cups_server: false
rhel9cis_dhcp_server: false
rhel9cis_dns_server: false
rhel9cis_dnsmasq_server: false
rhel9cis_vsftpd_server: false
rhel9cis_tftp_server: false
rhel9cis_httpd_server: false
rhel9cis_nginx_server: false
rhel9cis_dovecot_server: false
rhel9cis_imap_server: false
rhel9cis_samba_server: false
rhel9cis_squid_server: false
rhel9cis_snmp_server: false
rhel9cis_telnet_server: false
rhel9cis_is_mail_server: false
# Note the options
# Packages are used for client services and Server- only remove if you dont use the client service
#
rhel9cis_use_nfs_server: false
rhel9cis_use_nfs_service: false
rhel9cis_use_rpc_server: false
rhel9cis_use_rpc_service: false
rhel9cis_use_rsync_server: false
rhel9cis_use_rsync_service: false
#### 2.3 Service clients
rhel9cis_telnet_required: false
rhel9cis_openldap_clients_required: false
rhel9cis_tftp_client: false
rhel9cis_ftp_client: false
## Section3 vars
# 3.4.2 | PATCH | Ensure /etc/hosts.allow is configured
rhel9cis_host_allow:
- "10.0.0.0/255.0.0.0"
- "172.16.0.0/255.240.0.0"
- "192.168.0.0/255.255.0.0"
## Sysctl
rhel9cis_sysctl_update: false
rhel9cis_flush_ipv4_route: false
rhel9cis_flush_ipv6_route: false
# Firewall Service - either firewalld, iptables, or nftables
### Firewall Service - either firewalld, iptables, or nftables
#### Some control allow for services to be removed or masked
#### The options are under each heading
#### absent = remove the package
#### masked = leave package if installed and mask the service
rhel9cis_firewall: firewalld
# 3.4.2.4 Default zone setting
##### firewalld
rhel9cis_default_zone: public
# 3.4.2.5 Zone and Interface setting
rhel9cis_int_zone: customezone
rhel9cis_interface: eth0
# These are added to demonstrate how this can be done
rhel9cis_firewalld_ports:
- number: 80
protocol: tcp
rhel9cis_firewall_services:
- ssh
- dhcpv6-client
# 3.4.3.2 Set nftables new table create
#### nftables
rhel9cis_nft_tables_autonewtable: true
rhel9cis_nft_tables_tablename: filter
# 3.4.3.3 Set nftables new chain create
rhel9cis_nft_tables_autochaincreate: true
# Warning Banner Content (issue, issue.net, motd)
rhel9cis_warning_banner: |
Authorized uses only. All activity may be monitored and reported.
rhel9cis_warning_banner: Authorized uses only. All activity may be monitored and reported.
# End Banner
## Section4 vars
### 4.1 Configure System Accounting
#### 4.1.2 Configure Data Retention
rhel9cis_auditd:
space_left_action: email
action_mail_acct: root
admin_space_left_action: halt
max_log_file_action: keep_logs
rhel9cis_logrotate: "daily"
# The audit_back_log_limit value should never be below 8192
rhel9cis_audit_back_log_limit: 8192
# The max_log_file parameter should be based on your sites policy
rhel9cis_max_log_file_size: 10
# RHEL-09-4.2.1.4/4.2.1.5 remote and destation log server name
rhel9cis_remote_log_server: logagg.example.com
### 4.1.3.x audit template
update_audit_template: false
# RHEL-09-4.2.1.5
## Advanced option found in auditd post
rhel9cis_allow_auditd_uid_user_exclusions: false
# This can be used to configure other keys in auditd.conf
rhel9cis_auditd_extra_conf: {}
# Example:
# rhel9cis_auditd_extra_conf:
# admin_space_left: '10%'
## Preferred method of logging
## Whether rsyslog or journald preferred method for local logging
## Affects rsyslog cis 4.2.1.3 and journald cis 4.2.2.5
rhel9cis_syslog: rsyslog
rhel9cis_rsyslog_ansiblemanaged: true
#### 4.2.1.6 remote and destation log server name
rhel9cis_remote_log_server: false
rhel9cis_remote_log_host: logagg.example.com
rhel9cis_remote_log_port: 514
rhel9cis_remote_log_protocol: tcp
rhel9cis_remote_log_retrycount: 100
rhel9cis_remote_log_queuesize: 1000
#### 4.2.1.7
rhel9cis_system_is_log_server: false
# 4.2.2.1.2
# rhel9cis_journal_upload_url is the ip address to upload the journal entries to
rhel9cis_journal_upload_url: 192.168.50.42
# The paths below have the default paths/files, but allow user to create custom paths/filenames
rhel9cis_journal_upload_serverkeyfile: "/etc/ssl/private/journal-upload.pem"
rhel9cis_journal_servercertificatefile: "/etc/ssl/certs/journal-upload.pem"
rhel9cis_journal_trustedcertificatefile: "/etc/ssl/ca/trusted.pem"
# 4.2.2.1
# The variables below related to journald, please set these to your site specific values
# rhel9cis_journald_systemmaxuse is the max amount of disk space the logs will use
rhel9cis_journald_systemmaxuse: 10M
# rhel9cis_journald_systemkeepfree is the amount of disk space to keep free
rhel9cis_journald_systemkeepfree: 100G
rhel9cis_journald_runtimemaxuse: 10M
rhel9cis_journald_runtimekeepfree: 100G
# rhel9cis_journald_MaxFileSec is how long in time to keep log files. Values are Xm, Xh, Xday, Xweek, Xmonth, Xyear, for example 2week is two weeks
rhel9cis_journald_maxfilesec: 1month
#### 4.3
rhel9cis_logrotate: "daily"
## Section5 vars
# This will allow use of drop in files when CIS adopts them.
rhel9_cis_sshd_config_file: /etc/ssh/sshd_config
rhel9cis_sshd:
clientalivecountmax: 0
clientaliveinterval: 900
ciphers: "aes256-ctr,aes192-ctr,aes128-ctr"
macs: "hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com"
logingracetime: 60
# WARNING: make sure you understand the precedence when working with these values!!
# allowusers:
# allowgroups: systems dba
# denyusers:
# denygroups:
rhel9cis_pam_faillock:
attempts: 5
interval: 900
unlock_time: 900
fail_for_root: no
remember: 5
pwhash: sha512
# 5.2.5 SSH LogLevel setting. Options are INFO or VERBOSE
rhel9cis_ssh_loglevel: INFO
@ -513,9 +578,9 @@ rhel9cis_ssh_maxsessions: 4
rhel9cis_inactivelock:
lock_days: 30
rhel9cis_use_authconfig: false
# 5.3.1/5.3.2 Custom authselect profile settings. Settings in place now will fail, they are place holders from the control example
# Due to the way many multiple options and ways to configure this control needs to be enabled and settings adjusted to minimise risk
rhel9cis_use_authconfig: false
rhel9cis_authselect:
custom_profile_name: custom-profile
default_file_to_copy: "sssd --symlink-meta"
@ -531,22 +596,37 @@ rhel9cis_pass:
max_days: 365
min_days: 7
warn_age: 7
# Syslog system - either rsyslog or syslog-ng
rhel9cis_syslog: rsyslog
rhel9cis_rsyslog_ansiblemanaged: true
rhel9cis_vartmp:
source: /tmp
fstype: none
opts: "defaults,nodev,nosuid,noexec,bind"
enabled: no
# 5.5.1
## PAM
rhel9cis_pam_password:
minlen: "14"
minclass: "4"
minlen: 14
minclass: 4
# Starting GID for interactive users
rhel9cis_int_gid: 1000
rhel9cis_pam_faillock:
unlock_time: 900
deny: 5
remember: 5
# UID settings for interactive users
# These are discovered via logins.def if set true
discover_int_uid: false
min_int_uid: 1000
max_int_uid: 65533
# 5.3.3 var log location variable
rhel9cis_sudolog_location: "/var/log/sudo.log"
#### 5.3.6
rhel9cis_sudo_timestamp_timeout: 15
### 5.4.2 authselect and faillock
## This option is used at your own risk it will enable faillock for users
## Only to be used on a new clean system if not using authselect
## THIS CAN BREAK ACCESS EVEN FOR ROOT - UNDERSTAND RISKS ##
rhel9cis_add_faillock_without_authselect: false
# This needs to be set to ACCEPT
rhel9cis_5_4_2_risks: NEVER
# RHEL-09-5.4.5
# Session timeout setting file (TMOUT setting can be set in multiple files)
@ -557,11 +637,8 @@ rhel9cis_shell_session_timeout:
# RHEL-09-5.4.1.5 Allow ansible to expire password for account with a last changed date in the future. False will just display users in violation, true will expire those users passwords
rhel9cis_futurepwchgdate_autofix: true
# 5.7
# rhel9cis_sugroup: sugroup # change accordingly wheel is default
# wheel users list
rhel9cis_sugroup_users: "root"
# 5.3.7
rhel9cis_sugroup: nosugroup
## Section6 vars
@ -571,20 +648,28 @@ rhel9cis_rpm_audit_file: /var/tmp/rpm_file_check
# RHEL-09_6.1.10 Allow ansible to adjust world-writable files. False will just display world-writable files, True will remove world-writable
rhel9cis_no_world_write_adjust: true
rhel9cis_passwd_label: "{{ (this_item | default(item)).id }}: {{ (this_item | default(item)).dir }}"
# 6.2.9
rhel9cis_dotperm_ansiblemanaged: true
# 6.2.16
## Dont follow symlinks for changes to user home directory thanks to @dulin-gnet and comminty for rhel8-cis reedbacj
rhel_09_6_2_16_home_follow_symlinks: false
#### Goss Configuration Settings ####
# Set correct env for the run_audit.sh script from https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git"
audit_run_script_environment:
AUDIT_BIN: "{{ audit_bin }}"
AUDIT_FILE: 'goss.yml'
AUDIT_CONTENT_LOCATION: "{{ audit_out_dir }}"
### Goss binary settings ###
goss_version:
release: v0.3.16
checksum: 'sha256:827e354b48f93bce933f5efcd1f00dc82569c42a179cf2d384b040d8a80bfbfb'
release: v0.3.21
checksum: 'sha256:9a9200779603acf0353d2c0e85ae46e083596c10838eaf4ee050c924678e4fe3'
audit_bin_path: /usr/local/bin/
audit_bin: "{{ audit_bin_path }}goss"
audit_format: json
# if get_goss_file == download change accordingly
goss_url: "https://github.com/aelsabbahy/goss/releases/download/{{ goss_version.release }}/goss-linux-amd64"
goss_url: "https://github.com/goss-org/goss/releases/download/{{ goss_version.release }}/goss-linux-amd64"
## if get_goss_file - copy the following needs to be updated for your environment
## it is expected that it will be copied from somewhere accessible to the control node
@ -595,7 +680,7 @@ copy_goss_from_path: /some/accessible/path
## managed by the control audit_content
# git
audit_file_git: "https://github.com/ansible-lockdown/{{ benchmark }}-Audit.git"
audit_git_version: main
audit_git_version: "benchmark_{{ benchmark_version }}"
# copy:
audit_local_copy: "some path to copy from"
@ -603,15 +688,12 @@ audit_local_copy: "some path to copy from"
# get_url:
audit_files_url: "some url maybe s3?"
# Where the goss audit configuration will be stored
audit_files: "/var/tmp/{{ benchmark }}-Audit/"
## Goss configuration information
# Where the goss configs and outputs are stored
audit_out_dir: '/var/tmp'
audit_out_dir: '/opt'
audit_conf_dir: "{{ audit_out_dir }}/{{ benchmark }}-Audit/"
pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_pre_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}_post_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
pre_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}-{{ benchmark }}_pre_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
post_audit_outfile: "{{ audit_out_dir }}/{{ ansible_hostname }}-{{ benchmark }}_post_scan_{{ ansible_date_time.epoch }}.{{ audit_format }}"
## The following should not need changing
goss_file: "{{ audit_conf_dir }}goss.yml"

View file

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

View file

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

View file

@ -1,134 +1,105 @@
---
# handlers file for RHEL9-CIS
- name: sysctl flush ipv4 route table
become: yes
sysctl:
- name: Reload sysctl
ansible.builtin.shell: sysctl --system
when:
- sysctl_updated.changed
- name: Sysctl flush ipv4 route table
ansible.posix.sysctl:
name: net.ipv4.route.flush
value: '1'
sysctl_set: yes
ignore_errors: yes
when: ansible_virtualization_type != "docker"
tags:
- skip_ansible_lint
sysctl_set: true
ignore_errors: true # noqa ignore-errors
when:
- rhel9cis_flush_ipv4_route
- not system_is_container
- name: sysctl flush ipv6 route table
become: yes
sysctl:
- name: Sysctl flush ipv6 route table
ansible.posix.sysctl:
name: net.ipv6.route.flush
value: '1'
sysctl_set: yes
when: ansible_virtualization_type != "docker"
sysctl_set: true
when:
- rhel9cis_flush_ipv6_route
- not system_is_container
- name: update sysctl
template:
src: etc/99-sysctl.conf.j2
dest: /etc/sysctl.d/99-sysctl.conf
owner: root
group: root
mode: 0600
notify: reload sysctl
when: ansible_virtualization_type != "docker"
- name: reload sysctl
sysctl:
name: net.ipv4.route.flush
value: '1'
state: present
reload: yes
ignoreerrors: yes
when: ansible_virtualization_type != "docker"
- name: systemd restart tmp.mount
become: yes
systemd:
- name: Systemd restart tmp.mount
ansible.builtin.systemd:
name: tmp.mount
daemon_reload: yes
enabled: yes
masked: no
daemon_reload: true
enabled: true
masked: false
state: reloaded
- name: systemd restart var-tmp.mount
become: yes
systemd:
name: var-tmp.mount
daemon_reload: yes
enabled: yes
masked: no
state: reloaded
- name: Remount tmp
ansible.posix.mount:
path: /tmp
state: remounted
- name: remount tmp
command: mount -o remount /tmp
args:
warn: false
- name: restart firewalld
become: yes
service:
- name: Restart firewalld
ansible.builtin.systemd:
name: firewalld
state: restarted
- name: restart xinetd
become: yes
service:
name: xinetd
state: restarted
- name: restart sshd
become: yes
service:
- name: Restart sshd
ansible.builtin.systemd:
name: sshd
state: restarted
- name: restart postfix
become: yes
service:
- name: Restart postfix
ansible.builtin.systemd:
name: postfix
state: restarted
- name: reload dconf
become: yes
command: dconf update
- name: Reload dconf
ansible.builtin.shell: dconf update
- name: update auditd
template:
src: audit/99_auditd.rules.j2
dest: /etc/audit/rules.d/99_auditd.rules
owner: root
group: root
mode: 0600
notify: restart auditd
- name: restart auditd
command: /sbin/service auditd restart
changed_when: no
check_mode: no
failed_when: no
args:
warn: no
when:
- not rhel9cis_skip_for_travis
- name: Grub2cfg
ansible.builtin.shell: "grub2-mkconfig -o /boot/grub2/grub.cfg"
ignore_errors: true # noqa ignore-errors
tags:
- skip_ansible_lint
- name: grub2cfg
command: "grub2-mkconfig -o {{ grub_cfg.stat.lnk_source }}"
ignore_errors: True
tags:
- skip_ansible_lint
- name: restart rsyslog
become: yes
service:
- name: Restart rsyslog
ansible.builtin.systemd:
name: rsyslog
state: restarted
- name: restart syslog-ng
become: yes
service:
name: syslog-ng
- name: Restart journald
ansible.builtin.systemd:
name: systemd-journald
state: restarted
- name: systemd_daemon_reload
systemd:
daemon-reload: yes
- name: Restart systemd_journal_upload
ansible.builtin.systemd:
name: systemd-journal-upload
state: restarted
- name: Systemd daemon reload
ansible.builtin.systemd:
daemon-reload: true
## Auditd tasks note order for handlers to run
- name: Auditd immutable check
ansible.builtin.shell: grep -c "^-e 2" /etc/audit/rules.d/99_auditd.rules
changed_when: false
register: auditd_immutable_check
- name: Audit immutable fact
ansible.builtin.debug:
msg: "Reboot required for auditd to apply new rules as immutable set"
notify: Change_requires_reboot
when:
- auditd_immutable_check.stdout == '1'
- name: Restart auditd
ansible.builtin.shell: service auditd restart
tags:
- skip_ansible_lint
- name: Change_requires_reboot
ansible.builtin.set_fact:
change_requires_reboot: true

View file

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

View file

@ -1,18 +1,32 @@
---
galaxy_info:
author: "Sam Doran, Josh Springer, Daniel Shepherd, Bas Meijeri, James Cassell, Mike Renfro, DFed, George Nalen, Mark Bolwell"
description: "Apply the RHEL 8 CIS"
description: "Apply the RHEL 9 CIS"
company: "MindPoint Group"
license: MIT
role_name: rhel9_cis
min_ansible_version: 2.9.0
namespace: mindpointgroup
min_ansible_version: 2.10.0
platforms:
- name: EL
versions:
- 9
- "9"
galaxy_tags:
- system
- security
- cis
- stig
- hardening
- benchmark
- compliance
- redhat
- complianceascode
- disa
- rhel9
- cis
- rocky
- alma
collections:
- community.general
- community.crypto
- ansible.posix
dependencies: []

View file

@ -0,0 +1,27 @@
---
# This is a playbook to test the tasks.
- name: Converge
hosts: all
gather_facts: true
vars:
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
ansible_user: root
system_is_container: true
rhel9cis_selinux_disable: true
rhel9cis_rule_5_3_4: false
rhel9cis_rule_1_1_10: false
rhel9cis_firewall: "none"
rhel9cis_rule_4_1_1_1: false
rhel9cis_rule_4_1_1_2: false
rhel9cis_rule_4_1_1_3: false
rhel9cis_rule_4_1_1_4: false
rhel9cis_rule_4_2_1_2: false
rhel9cis_rule_4_2_1_4: false
rhel9cis_rule_5_1_1: false
pre_tasks:
tasks:
- name: "Include tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"

View file

@ -0,0 +1,34 @@
---
# Molecule configuration
# https://molecule.readthedocs.io/en/latest/
driver:
name: docker
platforms:
- name: ubi9
image: registry.access.redhat.com/ubi9/ubi-init
pre_build_image: true
volumes:
- /sys/fs/cgroup:/sys/fs/cgroup:ro
privileged: true
command: "/usr/sbin/init"
capabilities:
- SYS_ADMIN
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
callbacks_enabled: profile_tasks, timer
lint: |
set -e
yamllint .
ansible-lint
flake8
verifier:
name: ansible

View file

@ -0,0 +1,13 @@
---
- name: Verify
hosts: all
gather_facts: false
vars:
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
tasks:
- name: "Include verify tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"
tasks_from: verify

View file

@ -0,0 +1,18 @@
---
# This is a playbook to test the tasks.
- name: Converge
hosts: all
become: true
gather_facts: true
vars:
ansible_user: "{{ lookup('env', 'USER') }}"
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
rhel9cis_rule_5_3_4: false
pre_tasks:
tasks:
- name: "Include tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"

View file

@ -0,0 +1,30 @@
---
# Molecule configuration
# https://molecule.readthedocs.io/en/latest/
driver:
name: delegated
options:
managed: false
ansible_connection_options:
ansible_connection: local
platforms:
- name: localhost
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
stdout_callback: yaml
callbacks_enabled: profile_tasks, timer
lint: |
set -e
yamllint .
ansible-lint
flake8
verifier:
name: ansible

View file

@ -0,0 +1,14 @@
---
- name: Verify
hosts: all
gather_facts: false
become: true
vars:
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
tasks:
- name: "Include verify tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"
tasks_from: verify

27
molecule/wsl/converge.yml Normal file
View file

@ -0,0 +1,27 @@
---
# This is a playbook to test the tasks.
- name: Converge
hosts: all
become: true
gather_facts: true
vars:
ansible_user: "{{ lookup('env', 'USER') }}"
system_is_container: true
rhel8cis_selinux_disable: true
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
rhel8cis_rule_5_3_4: false
rhel8cis_rule_1_1_10: false
rhel8cis_rsyslog_ansiblemanaged: false
rhel8cis_rule_3_4_1_3: false
rhel8cis_rule_3_4_1_4: false
rhel8cis_rule_4_2_1_2: false
rhel8cis_rule_4_2_1_4: false
rhel8cis_rule_5_1_1: false
pre_tasks:
tasks:
- name: "Include tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"

29
molecule/wsl/molecule.yml Normal file
View file

@ -0,0 +1,29 @@
---
# Molecule configuration
# https://molecule.readthedocs.io/en/latest/
driver:
name: delegated
options:
managed: false
ansible_connection_options:
ansible_connection: local
platforms:
- name: localhost
provisioner:
name: ansible
config_options:
defaults:
interpreter_python: auto_silent
callbacks_enabled: profile_tasks, timer
lint: |
set -e
yamllint .
ansible-lint
flake8
verifier:
name: ansible

13
molecule/wsl/verify.yml Normal file
View file

@ -0,0 +1,13 @@
---
- name: Verify
hosts: all
gather_facts: false
vars:
role_name: "{{ lookup('env', 'MOLECULE_PROJECT_DIRECTORY') | basename }}"
tasks:
- name: "Include verify tasks"
ansible.builtin.include_role:
name: "{{ role_name }}"
tasks_from: verify

5
requirements.txt Normal file
View file

@ -0,0 +1,5 @@
passlib
lxml
xmltodict
jmespath
yamllint

View file

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

View file

@ -1,7 +1,7 @@
---
- name: Download audit binary
get_url:
ansible.builtin.get_url:
url: "{{ goss_url }}"
dest: "{{ audit_bin }}"
owner: root
@ -11,8 +11,8 @@
when:
- get_goss_file == 'download'
- name: copy audit binary
copy:
- name: Copy audit binary
ansible.builtin.copy:
src:
dest: "{{ audit_bin }}"
mode: 0555
@ -20,3 +20,11 @@
group: root
when:
- get_goss_file == 'copy'
- name: Install git if not present
ansible.builtin.package:
name: git
state: present
register: git_installed
when:
- '"git" not in ansible_facts.packages'

View file

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

46
tasks/auditd.yml Normal file
View file

@ -0,0 +1,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
- 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
notify:
- 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: warning_facts.yml
vars:
warn_control_id: 'Auditd template updated, see diff output for details'
when:
- rhel9cis_auditd_template_updated.changed
- rhel9cis_auditd_file.stat.exists
- 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
- 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

View file

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

View file

@ -1,111 +1,190 @@
---
# tasks file for RHEL9-CIS
- name: Check OS version and family
fail:
msg: "This role can only be run against RHEL 8. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported."
ansible.builtin.assert:
that: (ansible_distribution != 'CentOS' and ansible_os_family == 'RedHat' or ansible_os_family == "Rocky") and ansible_distribution_major_version is version_compare('9', '==')
fail_msg: "This role can only be run against Supported OSs. {{ ansible_distribution }} {{ ansible_distribution_major_version }} is not supported."
success_msg: "This role is running against a supported OS {{ ansible_distribution }} {{ ansible_distribution_major_version }}"
when:
- ansible_os_family == 'RedHat'
- ansible_distribution_major_version is version_compare('9', '!=')
- os_check
- not system_is_ec2
tags:
- always
- always
- name: Check ansible version
fail:
msg: You must use ansible 2.9 or greater
when: not ansible_version.full is version_compare('2.9', '>=')
ansible.builtin.assert:
that: ansible_version.full is version_compare(min_ansible_version, '>=')
fail_msg: "You must use Ansible {{ min_ansible_version }} or greater"
success_msg: "This role is running a supported version of ansible {{ ansible_version.full }} >= {{ min_ansible_version }}"
tags:
- always
- always
- name: "Check password set for {{ ansible_user }}"
block:
- name: Capture current password state of "{{ ansible_user }}"
ansible.builtin.shell: "grep {{ ansible_user }} /etc/shadow | awk -F: '{print $2}'"
changed_when: false
failed_when: false
check_mode: false
register: ansible_user_password_set
- name: "Assert that password set for {{ ansible_user }} and account not locked"
ansible.builtin.assert:
that: ansible_user_password_set.stdout | length != 0 and ansible_user_password_set.stdout != "!!"
fail_msg: "You have {{ sudo_password_rule }} enabled but the user = {{ ansible_user }} has no password set - It can break access"
success_msg: "You a password set for the {{ ansible_user }}"
vars:
sudo_password_rule: rhel9cis_rule_5_3_4
when:
- rhel9cis_rule_5_3_4
- not system_is_ec2
tags:
- user_passwd
- name: "Ensure root password is set"
block:
- name: "Ensure root password is set"
ansible.builtin.shell: passwd -S root | grep "Password set, SHA512 crypt"
changed_when: false
register: root_passwd_set
- name: "Ensure root password is set"
ansible.builtin.assert:
that: root_passwd_set.rc == 0
fail_msg: "You have rule 5.6.6 enabled this requires that you have a root password set"
success_msg: "You have a root password set"
when:
- rhel9cis_rule_5_6_6
tags:
- level1-server
- level1-workstation
- patch
- accounts
- root
- rule_5.6.6
- name: Setup rules if container
block:
- name: Discover and set container variable if required
ansible.builtin.set_fact:
system_is_container: true
- name: Load variable for container
ansible.builtin.include_vars:
file: "{{ container_vars_file }}"
- name: Output if discovered is a container
ansible.builtin.debug:
msg: system has been discovered as a container
when:
- system_is_container
when:
- ansible_connection == 'docker' or
ansible_virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]
tags:
- container_discovery
- always
- name: Check crypto-policy input
assert:
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
assert:
that: rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword'
msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set"
ansible.builtin.assert:
that: rhel9cis_bootloader_password_hash.find('grub.pbkdf2.sha512') != -1 and rhel9cis_bootloader_password_hash != 'grub.pbkdf2.sha512.changethispassword'
msg: "This role will not be able to run single user password commands as rhel9cis_bootloader_password_hash variable has not been set correctly"
when:
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_5_2
- name: "check sugroup exists if used"
block:
- name: "Check su group exists if defined"
shell: grep -w "{{ rhel9cis_sugroup }}" /etc/group
register: sugroup_exists
changed_when: false
failed_when: sugroup_exists.rc >= 2
tags:
- skip_ansible_lint
- name: Check sugroup if defined exists before continuing
assert:
that: sugroup_exists.rc == 0
msg: "The variable rhel9cis_sugroup is defined but does not exist please rectify"
when:
- rhel9cis_sugroup is defined
- rhel9cis_rule_5_7
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
tags:
- rule_5.7
- include: prelim.yml
become: yes
tags:
- prelim_tasks
- always
- import_tasks: pre_remediation_audit.yml
when:
- run_audit
- always
- name: Gather the package facts
package_facts:
ansible.builtin.package_facts:
manager: auto
tags:
- always
- always
- include: parse_etc_password.yml
become: yes
when: rhel9cis_section6
- name: Include OS specific variables
ansible.builtin.include_vars: "{{ ansible_distribution }}.yml"
tags:
- always
- include: section_1/main.yml
become: yes
- name: Include preliminary steps
ansible.builtin.import_tasks: prelim.yml
tags:
- prelim_tasks
- always
- name: run pre_remediation audit
ansible.builtin.include_tasks: pre_remediation_audit.yml
when:
- run_audit
- name: run Section 1 tasks
ansible.builtin.import_tasks: section_1/main.yml
when: rhel9cis_section1
tags:
- rhel9cis_section1
- rhel9cis_section1
- include: section_2/main.yml
become: yes
- name: run Section 2 tasks
ansible.builtin.import_tasks: section_2/main.yml
when: rhel9cis_section2
- include: section_3/main.yml
become: yes
when: rhel9cis_section3
- include: section_4/main.yml
become: yes
when: rhel9cis_section4
- include: section_5/main.yml
become: yes
when: rhel9cis_section5
- include: section_6/main.yml
become: yes
when: rhel9cis_section6
- include: post.yml
become: yes
tags:
- post_tasks
- always
- rhel9cis_section2
- import_tasks: post_remediation_audit.yml
- name: run Section 3 tasks
ansible.builtin.import_tasks: section_3/main.yml
when: rhel9cis_section3
tags:
- rhel9cis_section3
- name: run Section 4 tasks
ansible.builtin.import_tasks: section_4/main.yml
when: rhel9cis_section4
tags:
- rhel9cis_section4
- name: run Section 5 tasks
ansible.builtin.import_tasks: section_5/main.yml
when: rhel9cis_section5
tags:
- rhel9cis_section5
- name: run Section 6 tasks
ansible.builtin.import_tasks: section_6/main.yml
when: rhel9cis_section6
tags:
- rhel9cis_section6
- name: run auditd logic
ansible.builtin.import_tasks: auditd.yml
when: update_audit_template
tags:
- always
- name: run post remediation tasks
ansible.builtin.import_tasks: post.yml
tags:
- post_tasks
- always
- name: run post_remediation audit
ansible.builtin.import_tasks: post_remediation_audit.yml
when:
- run_audit
- run_audit
- name: Show Audit Summary
debug:
ansible.builtin.debug:
msg: "{{ audit_results.split('\n') }}"
when:
- run_audit
when: run_audit
- name: If Warnings found Output count and control IDs affected
ansible.builtin.debug:
msg: "You have {{ warn_count }} Warning(s) that require investigating that are related to the following benchmark ID(s) {{ warn_control_list }}"
when: warn_count != 0
tags:
- always

View file

@ -3,15 +3,15 @@
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd"
block:
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Parse /etc/passwd"
command: cat /etc/passwd
changed_when: no
check_mode: no
ansible.builtin.shell: cat /etc/passwd
changed_when: false
check_mode: false
register: rhel9cis_passwd_file_audit
- name: "PRELIM | 5.5.2 | 6.2.7 | 6.2.8 | 6.2.20 | Split passwd entries"
set_fact:
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 }}"
with_items: "{{ rhel9cis_passwd_file_audit.stdout_lines }}"
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>[^:]*)

View file

@ -1,56 +1,66 @@
---
# Post tasks
- name: Perform DNF package cleanup
dnf:
autoremove: yes
changed_when: no
- name: trigger update sysctl
command: /bin/true
changed_when: false
check_mode: false
notify: update sysctl
when:
- rhel9cis_rule_1_6_1 or
rhel9cis_rule_1_6_2 or
rhel9cis_rule_3_1_2 or
rhel9cis_rule_3_1_2 or
rhel9cis_rule_3_2_1 or
rhel9cis_rule_3_2_2 or
rhel9cis_rule_3_2_3 or
rhel9cis_rule_3_2_4 or
rhel9cis_rule_3_2_5 or
rhel9cis_rule_3_2_6 or
rhel9cis_rule_3_2_7 or
rhel9cis_rule_3_2_8 or
rhel9cis_rule_3_2_9
- name: POST | Gather the package facts after remediation
ansible.builtin.package_facts:
manager: auto
tags:
- sysctl
- always
- name: trigger update auditd
command: /bin/true
notify: update auditd
changed_when: false
check_mode: false
- name: POST | Update sysctl
ansible.builtin.template:
src: "etc/sysctl.d/{{ item }}.j2"
dest: "/etc/sysctl.d/{{ item }}"
owner: root
group: root
mode: 0600
register: sysctl_updated
notify: Reload sysctl
loop:
- 60-kernel_sysctl.conf
- 60-disable_ipv6.conf
- 60-netipv4_sysctl.conf
- 60-netipv6_sysctl.conf
when:
- rhel9cis_rule_4_1_3 or
rhel9cis_rule_4_1_4 or
rhel9cis_rule_4_1_5 or
rhel9cis_rule_4_1_6 or
rhel9cis_rule_4_1_7 or
rhel9cis_rule_4_1_8 or
rhel9cis_rule_4_1_9 or
rhel9cis_rule_4_1_10 or
rhel9cis_rule_4_1_11 or
rhel9cis_rule_4_1_12
- rhel9cis_sysctl_update
- not system_is_container
- "'procps-ng' in ansible_facts.packages"
- name: Flush handlers
ansible.builtin.meta: flush_handlers
- name: POST | reboot system if changes require it and not skipped
block:
- name: POST | Reboot system if changes require it and not skipped
ansible.builtin.reboot:
when:
- change_requires_reboot
- not skip_reboot
- name: POST | Warning a reboot required but skip option set
ansible.builtin.debug:
msg: "Warning!! changes have been made that require a reboot to be implemented but skip reboot was set - Can affect compliance check results"
changed_when: true
when:
- change_requires_reboot
- skip_reboot
- name: "POST | Warning a reboot required but skip option set | warning count"
ansible.builtin.import_tasks: warning_facts.yml
when:
- change_requires_reboot
- skip_reboot
vars:
warn_control_id: Reboot_required
tags:
- auditd
- name: flush handlers
meta: flush_handlers
- name: Reboot host
reboot:
when:
- not rhel9cis_skip_reboot
- grub
- level1-server
- level1-workstation
- level2-server
- level2-workstation
- rhel9cis_section1
- rhel9cis_section2
- rhel9cis_section3
- rhel9cis_section4
- rhel9cis_section5
- rhel9cis_section6

View file

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

View file

@ -1,44 +1,32 @@
---
- name: Pre Audit | Setup the audit
include_tasks: LE_audit_setup.yml
ansible.builtin.include_tasks: LE_audit_setup.yml
when:
- setup_audit
tags:
- setup_audit
- name: "Pre Audit | Ensure {{ audit_conf_dir }} exists"
file:
ansible.builtin.file:
path: "{{ audit_conf_dir }}"
state: directory
mode: '0755'
- name: Pre Audit | If using git for content set up
block:
- name: Pre Audit | Install git (rh8 python3)
package:
name: git
state: present
when: ansible_distribution_major_version == 8
- name: Pre Audit | Install git (rh7 python2)
package:
name: git
state: present
vars:
ansible_python_interpreter: "{{ python2_bin }}"
when: ansible_distribution_major_version == 7
- name: Pre Audit | retrieve audit content files from git
git:
repo: "{{ audit_file_git }}"
dest: "{{ audit_conf_dir }}"
version: "{{ audit_git_version }}"
- name: Pre Audit | retrieve audit content files from git
ansible.builtin.git:
repo: "{{ audit_file_git }}"
dest: "{{ audit_conf_dir }}"
version: "{{ audit_git_version }}"
when:
- audit_content == 'git'
- name: Pre Audit | confirm audit branch vs benchmark version
ansible.builtin.debug:
msg: "Audit will run the branch {{ audit_git_version }} for this Benchmark {{ benchmark_version }}"
- name: Pre Audit | copy to audit content files to server
copy:
ansible.builtin.copy:
src: "{{ audit_local_copy }}"
dest: "{{ audit_conf_dir }}"
mode: 0644
@ -46,36 +34,38 @@
- audit_content == 'copy'
- name: Pre Audit | get audit content from url
get_url:
ansible.builtin.get_url:
url: "{{ audit_files_url }}"
dest: "{{ audit_conf_dir }}"
owner: root
group: root
mode: 0755
when:
- audit_content == 'get_url'
- name: Pre Audit | Check Goss is available
block:
- name: Pre Audit | Check for goss file
stat:
ansible.builtin.stat:
path: "{{ audit_bin }}"
register: goss_available
- name: Pre Audit | If audit ensure goss is available
assert:
msg: "Audit has been selected: unable to find goss binary at {{ audit_bin }}"
when:
- not goss_available.stat.exists
- name: Pre Audit | Alert if goss not available
ansible.builtin.assert:
that: goss_available.stat.exists
fail_msg: "Audit binary file {{ audit_bin }} does not exist"
when:
- run_audit
- name: "Pre Audit | Check whether machine is UEFI-based"
stat:
ansible.builtin.stat:
path: /sys/firmware/efi
register: rhel9_efi_boot
tags:
- goss_template
- name: Pre Audit | Copy ansible default vars values to test audit
template:
ansible.builtin.template:
src: ansible_vars_goss.yml.j2
dest: "{{ audit_vars_path }}"
mode: 0600
@ -85,20 +75,21 @@
- goss_template
- name: "Pre Audit | Run pre_remediation {{ benchmark }} audit"
shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}"
vars:
warn: false
ansible.builtin.shell: "{{ audit_conf_dir }}/run_audit.sh -v {{ audit_vars_path }} -o {{ pre_audit_outfile }} -g {{ group_names }}"
environment: "{{ audit_run_script_environment | default({}) }}"
changed_when: audit_run_pre_remediation.rc == 0
register: audit_run_pre_remediation
- name: Pre Audit | Capture audit data if json format
block:
- name: "Pre Audit | capture data {{ pre_audit_outfile }}"
command: "cat {{ pre_audit_outfile }}"
ansible.builtin.shell: "cat {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
- name: Pre Audit | Capture pre-audit result
set_fact:
pre_audit_summary: "{{ pre_audit.stdout | from_json |json_query(summary) }}"
ansible.builtin.set_fact:
pre_audit_summary: "{{ pre_audit.stdout | from_json | json_query(summary) }}"
vars:
summary: 'summary."summary-line"'
when:
@ -107,12 +98,12 @@
- name: Pre Audit | Capture audit data if documentation format
block:
- name: "Pre Audit | capture data {{ pre_audit_outfile }}"
command: "tail -2 {{ pre_audit_outfile }}"
ansible.builtin.shell: "tail -2 {{ pre_audit_outfile }}"
register: pre_audit
changed_when: false
- name: Pre Audit | Capture pre-audit result
set_fact:
ansible.builtin.set_fact:
pre_audit_summary: "{{ pre_audit.stdout_lines }}"
when:
- audit_format == "documentation"

View file

@ -1,119 +1,263 @@
---
# Preliminary tasks that should always be run
# List users in order to look files inside each home directory
- name: "PRELIM | List users accounts"
command: "awk -F: '{print $1}' /etc/passwd"
args:
warn: no
changed_when: no
check_mode: no
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 | capture /etc/password variables"
ansible.builtin.include_tasks: parse_etc_password.yml
tags:
- rule_5.5.2
- rule_5.6.2
- rule_6.2.9
- rule_6.2.10
- rule_6.2.11
- rhel9cis_section5
- rhel9cis_section6
- level1-server
- name: "PRELIM | Interactive User accounts"
ansible.builtin.shell: 'cat /etc/passwd | grep -Ev "nologin|/sbin" | cut -d: -f6'
changed_when: false
register: interactive_users_home
tags:
- always
- name: "PRELIM | Gather accounts with empty password fields"
shell: "cat /etc/shadow | awk -F: '($2 == \"\" ) {j++;print $1; } END {exit j}'"
args:
warn: no
changed_when: no
check_mode: no
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 | Gather UID 0 accounts other than root"
shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'"
args:
warn: no
changed_when: no
check_mode: no
register: uid_zero_accounts_except_root
ansible.builtin.shell: "cat /etc/passwd | awk -F: '($3 == 0 && $1 != \"root\") {i++;print $1 } END {exit i}'"
changed_when: false
check_mode: false
register: rhel9cis_uid_zero_accounts_except_root
tags:
- rule_6.2.9
- level1-server
- level1-workstation
- users
- name: "PRELIM | Gather system-wide crypto-policy"
shell: update-crypto-policies --show
args:
warn: no
changed_when: no
check_mode: no
register: system_wide_crypto_policy
- name: "PRELIM | Setup crypto-policy"
block:
- name: "PRELIM | Install crypto-policies"
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: system_wide_crypto_policy
when:
- rhel9cis_rule_1_10
tags:
- level1-server
- level1-workstation
- rule_1.10
- crypto
- name: "PRELIM | if systemd coredump"
stat:
ansible.builtin.stat:
path: /etc/systemd/coredump.conf
register: systemd_coredump
when:
- rhel9cis_rule_1_6_1
- 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"
set_fact:
ansible.builtin.set_fact:
mount_names: "{{ ansible_mounts | map(attribute='mount') | list }}"
- name: "PRELIM | Section 4.1 | Configure System Accounting (auditd)"
package:
name: audit
state: present
when: rhel9cis_level_2
- name: "PRELIM | 4.1.12 | Ensure successful file system mounts are collected"
shell: for i in $(df | grep '^/dev' | awk '{ print $NF }'); do find $i -xdev -type f -perm -4000 -o -type f -perm -2000 2>/dev/null; done
changed_when: false
failed_when: false
check_mode: no
register: priv_procs
tags:
- always
- level1-server
- level1-workstation
- name: "PRELIM | Section 5.1 | Configure cron"
package:
name: cronie
state: present
- name: "PRELIM | Install authconfig"
package:
name: authconfig
- name: "PRELIM | Ensure python3-libselinux is installed"
ansible.builtin.package:
name: python3-libselinux
state: present
when:
- rhel9cis_use_authconfig
- rhel9cis_rule_5_3_1 or
rhel9cis_rule_5_3_2 or
rhel9cis_rule_5_3_3
- '"python3-libselinux" not in ansible_facts.packages'
- name: "PRELIM | Set facts based on boot type"
block:
- name: "PRELIM | Check whether machine is UEFI-based"
stat:
ansible.builtin.stat:
path: /sys/firmware/efi
register: rhel_09_efi_boot
- name: "PRELIM | AUDIT | set legacy boot and grub path | Bios"
set_fact:
- 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"
set_fact:
ansible.builtin.set_fact:
grub2_path: /etc/grub2-efi.cfg
when: rhel_09_efi_boot.stat.exists
# - name: debug legacy boot var
# debug:
# msg: |
# legacy_boot={{ rhel9cis_legacy_boot }}
# grub2_path={{ grub2_path }}
- name: "PRELIM | AUDIT | Ensure permissions on bootloader config are configured | Get grub config file stats"
stat:
path: "{{ grub2_path }}"
changed_when: false
register: grub_cfg
# - name: debug grub stat
# debug:
# var: grub_cfg.stat
- name: "PRELIM | Check for rhnsd service"
shell: "systemctl show rhnsd | grep LoadState | cut -d = -f 2"
changed_when: false
check_mode: false
register: rhnsd_service_status
- name: "PRELIM | Update to latest gpg keys"
ansible.builtin.package:
name: "{{ gpg_key_package }}"
state: latest
when:
- rhel9cis_rule_1_2_2
- rhel9cis_rule_1_2_4
- ansible_distribution != 'RedHat'
- ansible_distribution != 'OracleLinux'
- 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:
- skip_ansible_lint
- 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"
ansible.builtin.file:
path: "{{ rhel9_cis_sshd_config_file }}"
owner: root
group: root
mode: 0600
state: touch
when:
- rhel9_cis_sshd_config_file != '/etc/ssh/sshd_config'
- "'openssh-server' in ansible_facts.packages"
tags:
- ssh
- level1_server
- level1_workstation
- name: "PRELIM | Install authconfig"
ansible.builtin.package:
name: authconfig
state: present
become: true
when:
- rhel9cis_use_authconfig
- rhel9cis_rule_5_3_1 or
rhel9cis_rule_5_3_2 or
rhel9cis_rule_5_3_3 or
'"authconfig" not in ansible_facts.packages or
"auditd-lib" not in ansible_facts.packages'
tags:
- level1-server
- level1-workstation
- rule_5.3.1 or
rule_5.3.2 or
rule_5.3.3
- authconfig
- auditd
- name: "PRELIM | 5.3.4 | Find all sudoers files."
ansible.builtin.shell: "find /etc/sudoers /etc/sudoers.d/ -type f ! -name '*~' ! -name '*.*'"
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_sudoers_files
when:
- rhel9cis_rule_5_3_4 or
rhel9cis_rule_5_3_5
tags:
- rule_5.3.4
- rule_5.3.5
- name: "PRELIM | Discover Interactive UID MIN and MIN from logins.def"
block:
- name: "PRELIM | Capture UID_MIN information from logins.def"
ansible.builtin.shell: grep -w "^UID_MIN" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: uid_min_id
- name: "PRELIM | Capture UID_MAX information from logins.def"
ansible.builtin.shell: grep -w "^UID_MAX" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: uid_max_id
- name: "PRELIM | Capture GID_MIN information from logins.def"
ansible.builtin.shell: grep -w "^GID_MIN" /etc/login.defs | awk '{print $NF}'
changed_when: false
register: gid_min_id
- name: "PRELIM | 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
tags:
- always

View file

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

View file

@ -0,0 +1,81 @@
---
- 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: 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.builtin.mount:
name: /tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_2_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_2_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_2_4 %}nosuid{% endif %}
notify: Remount tmp
loop: "{{ ansible_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

@ -0,0 +1,49 @@
---
- 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: warning_facts.yml
vars:
warn_control_id: '1.1.3.1'
required_mount: '/var'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_3_1
tags:
- level2-server
- level2-workstation
- patch
- mounts
- rule_1.1.3.1
# skips if mount is absent
- name: |
"1.1.3.2 | PATCH | Ensure nodev option set on /var partition"
"1.1.3.3 | PATCH | Ensure nosuid option set on /var partition"
ansible.builtin.mount:
name: /var
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_3_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_3_3 %}nosuid,{% endif %}
loop: "{{ ansible_mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var"
- rhel9cis_rule_1_1_3_2 or
rhel9cis_rule_1_1_3_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- skip_ansible_lint
- rule_1.1.3.2
- rule_1.1.3.3

View file

@ -0,0 +1,53 @@
---
# 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: warning_facts.yml
vars:
warn_control_id: '1.1.4.1'
required_mount: '/var/tmp'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_4_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.4.1
# skips if mount is absent
- name: |
"1.1.4.2 | PATCH | Ensure noexec option set on /var/tmp partition"
"1.1.4.3 | PATCH | Ensure nosuid option set on /var/tmp partition"
"1.1.4.4 | PATCH | Ensure nodev option set on /var/tmp partition"
ansible.builtin.mount:
name: /var/tmp
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_4_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_4_3 %}nosuid,{% endif %}{% if rhel9cis_rule_1_1_4_4 %}nodev{% endif %}
loop: "{{ ansible_mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/tmp"
- rhel9cis_rule_1_1_4_2 or
rhel9cis_rule_1_1_4_3 or
rhel9cis_rule_1_1_4_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- skip_ansible_lint
- rule_1.1.4.2
- rule_1.1.4.3
- rule_1.1.4.4

View file

@ -0,0 +1,53 @@
---
- 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: warning_facts.yml
vars:
warn_control_id: '1.1.5.1'
required_mount: '/var/log'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_5_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.5.1
- skip_ansible_lint
- name: |
"1.1.5.2 | PATCH | Ensure nodev option set on /var/log partition"
"1.1.5.3 | PATCH | Ensure noexec option set on /var/log partition"
"1.1.5.4 | PATCH | Ensure nosuid option set on /var/log partition"
ansible.builtin.mount:
name: /var/log
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_5_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_5_3 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_5_4 %}nosuid{% endif %}
loop: "{{ ansible_mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/log"
- rhel9cis_rule_1_1_5_2 or
rhel9cis_rule_1_1_5_3 or
rhel9cis_rule_1_1_5_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- skip_ansible_lint
- rule_1.1.5.2
- rule_1.1.5.3
- rule_1.1.5.4

View file

@ -0,0 +1,52 @@
---
- 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: warning_facts.yml
vars:
warn_control_id: '1.1.6.1'
required_mount: '/var/log/audit'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_6_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.6.1
- name: |
"1.1.6.2 | PATCH | Ensure noexec option set on /var/log/audit partition"
"1.1.6.3 | PATCH | Ensure nodev option set on /var/log/audit partition"
"1.1.6.4 | PATCH | Ensure nosuid option set on /var/log/audit partition"
ansible.builtin.mount:
name: /var/log/audit
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_6_2 %}noexec,{% endif %}{% if rhel9cis_rule_1_1_6_3 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_6_4 %}nosuid{% endif %}
loop: "{{ ansible_mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/var/log/audit"
- rhel9cis_rule_1_1_6_2 or
rhel9cis_rule_1_1_6_3 or
rhel9cis_rule_1_1_6_4
tags:
- level1-server
- level1-workstation
- patch
- mounts
- skip_ansible_lint
- rule_1.1.6.2
- rule_1.1.6.3
- rule_1.1.6.4

View file

@ -0,0 +1,52 @@
---
- 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: warning_facts.yml
vars:
warn_control_id: '1.1.7.1'
required_mount: '/home'
when:
- required_mount not in mount_names
- rhel9cis_rule_1_1_7_1
tags:
- level2-server
- level2-workstation
- audit
- mounts
- rule_1.1.7.1
- skip_ansible_lint
- name: |
"1.1.7.2 | PATCH | Ensure nodev option set on /home partition
1.1.7.3 | PATCH | Ensure nosuid option set on /home partition"
ansible.builtin.mount:
name: /home
src: "{{ item.device }}"
fstype: "{{ item.fstype }}"
state: present
opts: defaults,{% if rhel9cis_rule_1_1_7_2 %}nodev,{% endif %}{% if rhel9cis_rule_1_1_7_3 %}nosuid,{% endif %}
loop: "{{ ansible_mounts }}"
loop_control:
label: "{{ item.device }}"
notify: Change_requires_reboot
when:
- item.mount == "/home"
- rhel9cis_rule_1_1_7_1
- rhel9cis_rule_1_1_7_2 or
rhel9cis_rule_1_1_7_3
tags:
- level1-server
- level1-workstation
- patch
- mounts
- rule_1.1.7.2
- rule_1.1.7.3
- rule_1.1.7.4
- skip_ansible_lint

View file

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

View file

@ -1,9 +1,10 @@
---
- name: "1.10 | L1 | PATCH | Ensure system-wide crypto policy is not legacy"
shell: |
- name: "1.10 | PATCH | Ensure system-wide crypto policy is not legacy"
ansible.builtin.shell: |
update-crypto-policies --set "{{ rhel9cis_crypto_policy }}"
update-crypto-policies
notify: Change_requires_reboot
when:
- rhel9cis_rule_1_10
- system_wide_crypto_policy['stdout'] == 'LEGACY'

View file

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

View file

@ -1,100 +1,121 @@
---
- name: "1.2.1 | L1 | PATCH | Ensure Red Hat Subscription Manager connection is configured"
redhat_subscription:
state: present
username: "{{ rhel9cis_rh_sub_user }}"
password: "{{ rhel9cis_rh_sub_password }}"
auto_attach: true
no_log: true
- 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 keys installed that are not expected
when:
- os_installed_pub_keys.rc == 1 or
os_gpg_key_check.rc == 1
when:
- ansible_distribution == "RedHat"
- rhel9cis_rhnsd_required
- rhel9cis_rule_1_2_1
- ansible_distribution == "RedHat" or
ansible_distribution == "Rocky" or
ansible_distribution == "AlmaLinux"
tags:
- level1-server
- level1-workstation
- notscored
- manual
- patch
- rule_1.2.1
- skip_ansible_lint # Added as no_log still errors on ansuible-lint
- name: "1.2.2 | L1 | PATCH | Disable the rhnsd Daemon"
service:
name: rhnsd
state: stopped
enabled: no
masked: true
- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated"
block:
- name: "1.2.2 | AUDIT | Ensure gpgcheck is globally activated | Find repos"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: yum_repos
- name: "1.2.2 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos"
ansible.builtin.replace:
name: "{{ item.path }}"
regexp: "^gpgcheck=0"
replace: "gpgcheck=1"
loop: "{{ yum_repos.files }}"
loop_control:
label: "{{ item.path }}"
when:
- ansible_distribution == "RedHat"
- rhnsd_service_status.stdout == "loaded" and not rhel9cis_rhnsd_required
- rhel9cis_rule_1_2_2
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.2
- name: "1.2.3 | L1 | AUDIT | Ensure GPG keys are configured"
command: gpg --quiet --with-fingerprint /etc/pki/rpm-gpg/RPM-GPG-KEY-{{ ansible_distribution|lower }}-release
when:
- rhel9cis_rule_1_2_3
- ansible_distribution == "RedHat"
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.3
- name: "1.2.4 | L1 | PATCH | Ensure gpgcheck is globally activated"
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured"
block:
- name: "1.2.4 | L1 | AUDIT | Ensure gpgcheck is globally activated | Find repos"
find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: yum_repos
changed_when: false
- name: "1.2.4 | L1 | PATCH | Ensure gpgcheck is globally activated | Update yum.repos"
replace:
name: "{{ item.path }}"
regexp: "^gpgcheck=0"
replace: "gpgcheck=1"
with_items:
- "{{ yum_repos.files }}"
when:
- rhel9cis_rule_1_2_4
tags:
- level1-server
- level1-workstation
- scored
- patch
- rule_1.2.4
- name: "1.2.5 | L1 | Ensure package manager repositories are configured"
block:
- name: "1.2.5 | L1 | AUDIT | Ensure package manager repositories are configured | Get repo list"
command: dnf repolist
- 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: no
args:
warn: false
check_mode: false
- name: "1.2.5 | L1 | AUDIT | Ensure package manager repositories are configured | Display repo list"
debug:
- name: "1.2.3 | AUDIT | Ensure package manager repositories are configured | Display repo list"
ansible.builtin.debug:
msg:
- "Alert! Below are the configured repos. Please review and make sure all align with site policy"
- "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: warning_facts.yml
vars:
warn_control_id: '1.2.3'
when:
- rhel9cis_rule_1_2_5
- rhel9cis_rule_1_2_3
tags:
- level1-server
- level1-workstation
- notscored
- patch
- rule_1.2.5
- manual
- audit
- rule_1.2.3
- skip_ansible_lint
- name: "1.2.4 | AUDIT | Ensure repo_gpgcheck is globally activated"
block:
- name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | dnf.conf"
ansible.builtin.lineinfile:
path: /etc/dnf/dnf.conf
regexp: '^repo_gpgcheck'
line: repo_gpgcheck=1
- name: "1.2.4 | AUDIT| Ensure repo_gpgcheck is globally activated | get repo files"
ansible.builtin.find:
paths: /etc/yum.repos.d
patterns: "*.repo"
register: repo_files
- name: "1.2.4 | PATCH | Ensure repo_gpgcheck is globally activated | amend repo files"
ansible.builtin.replace:
path: "{{ item.path }}"
regexp: '^repo_gpgcheck( |)=( |)0'
replace: repo_gpgcheck=1
loop: "{{ repo_files.files }}"
loop_control:
label: "{{ item.path }}"
when:
- rhel9cis_rule_1_2_4
- not rhel9cis_rhel_default_repo or ansible_distribution != 'RedHat'
- ansible_distribution != 'OracleLinux'
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_1.2.4

View file

@ -1,44 +1,78 @@
---
- name: "1.3.1 | L1 | PATCH | Ensure sudo is installed"
package:
name: sudo
state: present
- 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
changed_when: false
failed_when: false
async: 45
poll: 0
args:
creates: /var/lib/aide/aide.db.new.gz
when: not ansible_check_mode
- name: "1.3.1 | PATCH | Ensure AIDE is installed | 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
- scored
- sudo
- aide
- patch
- rule_1.3.1
- name: "1.3.2 | L1 | PATCH | Ensure sudo commands use pty"
lineinfile:
dest: /etc/sudoers
line: "Defaults use_pty"
state: present
- 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
- scored
- aide
- file_integrity
- patch
- rule_1.3.2
- name: "1.3.3 | L1 | PATCH | Ensure sudo log file exists"
lineinfile:
dest: /etc/sudoers
regexp: '^Defaults logfile='
line: 'Defaults logfile="{{ rhel9cis_varlog_location }}"'
state: present
- name: "1.3.3 | Ensure cryptographic mechanisms are used to protect the integrity of audit tools"
ansible.builtin.blockinfile:
path: /etc/aide.conf
marker: "# {mark} Audit tools - CIS benchmark - Ansible-lockdown"
block: |
/sbin/auditctl p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/auditd p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/augenrules p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/aureport p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/ausearch p+i+n+u+g+s+b+acl+xattrs+sha512
/sbin/autrace p+i+n+u+g+s+b+acl+xattrs+sha512
validate: aide -D --config %s
when:
- rhel9cis_rule_1_3_3
- rhel9cis_rule_1_3_2
- not system_is_ec2
tags:
- level1-server
- level1-workstation
- scored
- aide
- file_integrity
- patch
- rule_1.3.3

View file

@ -1,50 +1,44 @@
---
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed"
block:
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed | Install AIDE"
package:
name: aide
state: present
- name: "1.4.1 | L1 | PATCH | Ensure AIDE is installed | Configure AIDE"
command: /usr/sbin/aide --init -B 'database_out=file:/var/lib/aide/aide.db.gz'
changed_when: false
failed_when: false
async: 45
poll: 0
args:
creates: /var/lib/aide/aide.db.gz
when: not ansible_check_mode
- 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_config_aide
- rhel9cis_set_boot_pass
- rhel9cis_rule_1_4_1
tags:
- level1-server
- level1-workstation
- scored
- aide
- grub
- patch
- rule_1.4.1
- name: "1.4.2 | L1 | PATCH | Ensure filesystem integrity is regularly checked"
cron:
name: Run AIDE integrity check
cron_file: "{{ rhel9cis_aide_cron['cron_file'] }}"
user: "{{ rhel9cis_aide_cron['cron_user'] }}"
minute: "{{ rhel9cis_aide_cron['aide_minute'] | default('0') }}"
hour: "{{ rhel9cis_aide_cron['aide_hour'] | default('5') }}"
day: "{{ rhel9cis_aide_cron['aide_day'] | default('*') }}"
month: "{{ rhel9cis_aide_cron['aide_month'] | default('*') }}"
weekday: "{{ rhel9cis_aide_cron['aide_weekday'] | default('*') }}"
job: "{{ rhel9cis_aide_cron['aide_job'] }}"
- 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
tags:
- level1-server
- level1-workstation
- scored
- aide
- file_integrity
- grub
- patch
- rule_1.4.2

View file

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

View file

@ -0,0 +1,132 @@
---
- 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:
- not rhel9cis_selinux_disable
- 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:
- not rhel9cis_selinux_disable
- 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:
- not rhel9cis_selinux_disable
- 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: 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

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

View file

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

View file

@ -1,96 +1,93 @@
---
- name: "1.8.1.1 | L1 | PATCH | Ensure message of the day is configured properly"
template:
- 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_8_1_1
- rhel9cis_rule_1_7_1
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.8.1.1
- rule_1.7.1
- name: "1.8.1.2 | L1 | PATCH | Ensure local login warning banner is configured properly"
template:
- 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_8_1_2
- rhel9cis_rule_1_7_2
tags:
- level1-server
- level1-workstation
- patch
- rule_1.8.1.2
- rule_1.7.2
- name: "1.8.1.3 | L1 | PATCH | Ensure remote login warning banner is configured properly"
template:
- 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_8_1_3
- rhel9cis_rule_1_7_3
tags:
- level1-server
- level1-workstation
- banner
- patch
- rule_1.8.1.3
- rule_1.7.3
- name: "1.8.1.4 | L1 | PATCH | Ensure permissions on /etc/motd are configured"
file:
dest: /etc/motd
state: file
- 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_8_1_4
- rhel9cis_rule_1_7_4
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.4
- rule_1.7.4
- name: "1.8.1.5 | L1 | PATCH | Ensure permissions on /etc/issue are configured"
file:
dest: /etc/issue
state: file
- 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_8_1_5
- rhel9cis_rule_1_7_5
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.5
- rule_1.7.5
- name: "1.8.1.6 | L1 | PATCH | Ensure permissions on /etc/issue.net are configured"
file:
dest: /etc/issue.net
state: file
- 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_8_1_6
- rhel9cis_rule_1_7_6
tags:
- level1-server
- level1-workstation
- perms
- patch
- rule_1.8.1.6
- rule_1.7.6

View file

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

View file

@ -0,0 +1,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
tags:
- level2-server
- patch
- gui
- gdm
- rule_1.8.1
- 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
tags:
- level1-server
- level1-workstation
- patch
- gui
- gdm
- rule_1.8.2
- name: "1.8.3 | PATCH | Ensure GDM disable-user-list option is enabled"
ansible.builtin.lineinfile:
path: "{{ item.file }}"
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
create: true
owner: root
group: root
mode: 0644
notify: Reload dconf
loop:
- { file: '/etc/dconf/profile/gdm', regexp: 'user-db', line: 'user-db:user' }
- { file: '/etc/dconf/profile/gdm', regexp: 'system-db', line: 'system-db:gdm' }
- { file: '/etc/dconf/profile/gdm', regexp: 'file-db', line: 'file-db:/usr/share/gdm/greeter-dconf-defaults'}
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: '\[org\/gnome\/login-screen\]', line: '[org/gnome/login-screen]' }
- { file: '/etc/dconf/db/gdm.d/00-login-screen', regexp: 'disable-user-list=', line: 'disable-user-list=true' }
when:
- rhel9cis_rule_1_8_3
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.3
- 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
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.4
- name: "1.8.5 PATCH | Ensure GDM screen locks cannot be overridden"
block:
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock directory"
ansible.builtin.file:
path: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks"
owner: root
group: root
mode: 0755
state: directory
- name: "1.8.5 | PATCH | Ensure GDM screen locks cannot be overridden | Make lock file"
ansible.builtin.template:
src: etc/dconf/db/00-screensaver_lock.j2
dest: "/etc/dconf/db/{{ rhel9cis_dconf_db_name }}.d/locks/00-screensaver"
owner: root
group: root
mode: 0644
notify: Reload dconf
when:
- rhel9cis_rule_1_8_5
- rhel9cis_gui
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.5
- 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
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.6
- 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
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.7
- 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
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.8
- 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
tags:
- level1-server
- level2-workstation
- patch
- gui
- rule_1.8.9
- 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
tags:
- level1-server
- level1-workstation
- patch
- gui
- rule_1.8.4

View file

@ -1,9 +1,10 @@
---
- name: "1.9 | L1 | PATCH | Ensure updates, patches, and additional security software are installed"
package:
- 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
- not system_is_ec2

View file

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

View file

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

View file

@ -0,0 +1,40 @@
---
- name: "2.1.1 | PATCH | Ensure time synchronization is in use"
ansible.builtin.package:
name: chrony
state: present
when:
- rhel9cis_rule_2_1_1
- not system_is_container
tags:
- level1-server
- level1-workstation
- patch
- rule_2.1.1
- name: "2.1.2 | PATCH | Ensure chrony is configured"
block:
- name: "2.1.2 | PATCH | Ensure chrony is configured | Set configuration"
ansible.builtin.template:
src: etc/chrony.conf.j2
dest: /etc/chrony.conf
owner: root
group: root
mode: 0644
- 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
tags:
- level1-server
- level1-workstation
- patch
- rule_2.1.2

View file

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

View file

@ -1,288 +1,349 @@
---
- name: "2.2.2 | L1 | PATCH | Ensure X Window System is not installed"
block:
- name: "2.2.2 | L1 | AUDIT | Ensure X Window System is not installed | capture xorg-x11 packages"
shell: rpm -qa | grep xorg-x11
args:
warn: no
failed_when: xorg_x11_installed.rc >=2
check_mode: no
changed_when: false
register: xorg_x11_installed
- name: "2.2.2 | L1 | PATCH | Ensure X Window System is not installed | remove packages if found"
shell: "dnf remove {{ item }}"
args:
warn: no
with_items:
- xorg_x11_installed.stdout_lines
when: xorg_x11_installed.stdout | length > 0
- name: "2.2.1 | PATCH | Ensure xorg-x11-server-common is not installed"
ansible.builtin.package:
name: xorg-x11-server-common
state: absent
when:
- not rhel9cis_xwindows_required
- rhel9cis_rule_2_2_2
- rhel9cis_rule_2_2_1
- "'xorg-x11-server-common' in ansible_facts.packages"
- not rhel9cis_gui
tags:
- level1-server
- scored
- xwindows
- patch
- x11
- rule_2.2.1
- name: "2.2.2 | PATCH | Ensure Avahi Server is not installed"
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: "2.2.3 | L1 | PATCH | Ensure rsync service is not enabled "
service:
name: rsyncd
state: stopped
enabled: no
- name: "2.2.3 | PATCH | Ensure CUPS is not installed"
ansible.builtin.package:
name: cups
state: absent
when:
- not rhel9cis_rsyncd_server
- "'rsyncd' in ansible_facts.packages"
- not rhel9cis_cups_server
- "'cups' in ansible_facts.packages"
- rhel9cis_rule_2_2_3
tags:
- level1-server
- level1-workstation
- patch
- cups
- rule_2.2.3
- name: "2.2.4 | L1 | PATCH | Ensure Avahi Server is not enabled"
service:
name: avahi-daemon
state: stopped
enabled: no
- name: "2.2.4 | PATCH | Ensure DHCP Server is not installed"
ansible.builtin.package:
name: dhcp-server
state: absent
when:
- not rhel9cis_avahi_server
- "'avahi' in ansible_facts.packages"
- not rhel9cis_dhcp_server
- "'dhcp-server' in ansible_facts.packages"
- rhel9cis_rule_2_2_4
tags:
- level1-server
- level1-workstation
- scored
- avahi
- services
- patch
- dhcp
- rule_2.2.4
- name: "2.2.5 | L1 | PATCH | Ensure SNMP Server is not enabled"
service:
name: snmpd
state: stopped
enabled: no
- name: "2.2.5 | PATCH | Ensure DNS Server is not installed"
ansible.builtin.package:
name: bind
state: absent
when:
- not rhel9cis_snmp_server
- "'net-snmp' in ansible_facts.packages"
- 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 | L1 | PATCH | Ensure HTTP Proxy Server is not enabled"
service:
name: squid
state: stopped
enabled: no
- name: "2.2.6 | PATCH | Ensure VSFTP Server is not installed"
ansible.builtin.package:
name: vsftpd
state: absent
when:
- not rhel9cis_squid_server
- "'squid' in ansible_facts.packages"
- 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 | L1 | PATCH | Ensure Samba is not enabled"
service:
name: smb
state: stopped
enabled: no
- name: "2.2.7 | PACH | Ensure TFTP Server is not installed"
ansible.builtin.package:
name: tftp-server
state: absent
when:
- not rhel9cis_smb_server
- "'samba' in ansible_facts.packages"
- 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 | L1 | PATCH | Ensure IMAP and POP3 server is not enabled"
service:
name: dovecot
state: stopped
enabled: no
- 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:
- not rhel9cis_dovecot_server
- "'dovecot' in ansible_facts.packages"
- rhel9cis_rule_2_2_8
tags:
- level1-server
- level1-workstation
- patch
- httpd
- nginx
- webserver
- rule_2.2.8
- name: "2.2.9 | L1 | PATCH | Ensure HTTP server is not enabled"
service:
name: httpd
state: stopped
enabled: no
- 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:
- not rhel9cis_httpd_server
- "'httpd' in ansible_facts.packages"
- rhel9cis_rule_2_2_9
tags:
- level1-server
- level1-workstation
- patch
- dovecot
- imap
- pop3
- rule_2.2.9
- name: "2.2.10 | L1 | PATCH | Ensure FTP Server is not enabled"
service:
name: vsftpd
state: stopped
enabled: no
- name: "2.2.10 | PATCH | Ensure Samba is not enabled"
ansible.builtin.package:
name: samba
state: absent
when:
- not rhel9cis_vsftpd_server
- "'vsftpd' in ansible_facts.packages"
- 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 | L1 | PATCH | Ensure DNS Server is not enabled"
service:
name: named
state: stopped
enabled: no
- name: "2.2.11 | PATCH | Ensure HTTP Proxy Server is not installed"
ansible.builtin.package:
name: squid
state: absent
when:
- not rhel9cis_named_server
- "'bind' in ansible_facts.packages"
- 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 | L1 | PATCH | Ensure NFS is not enabled"
service:
name: nfs-server
state: stopped
enabled: no
- name: "2.2.12 | PATCH | Ensure net-snmp is not installed"
ansible.builtin.package:
name: net-snmp
state: absent
when:
- not rhel9cis_nfs_rpc_server
- "'nfs-utils' in ansible_facts.packages"
- not rhel9cis_snmp_server
- "'net-snmp' in ansible_facts.packages"
- rhel9cis_rule_2_2_12
tags:
- level1-server
- level1-workstation
- scored
- nfs
- services
- patch
- snmp
- rule_2.2.12
- name: "2.2.13 | L1 | PATCH | Ensure RPC is not enabled"
service:
name: rpcbind
state: stopped
enabled: no
- name: "2.2.13 | PATCH | Ensure telnet-server is not installed"
ansible.builtin.package:
name: telnet-server
state: absent
when:
- not rhel9cis_nfs_rpc_server
- "'rpcbind' in ansible_facts.packages"
- not rhel9cis_telnet_server
- "'telnet-server' in ansible_facts.packages"
- rhel9cis_rule_2_2_13
tags:
- level1-server
- level1-workstation
- scored
- rpc
- services
- patch
- rule_2.2.7
- telnet
- rule_2.2.13
- name: "2.2.14 | L1 | PATCH | Ensure LDAP server is not enabled"
service:
name: slapd
state: stopped
enabled: no
- name: "2.2.14 | PATCH | Ensure dnsmasq is not installed"
ansible.builtin.package:
name: dnsmasq
state: absent
notify: Restart postfix
when:
- not rhel9cis_ldap_server
- "'openldap-servers' in ansible_facts.packages"
- not rhel9cis_is_mail_server
- "'dnsmasq' in ansible_facts.packages"
- rhel9cis_rule_2_2_14
tags:
- level1-server
- level1-workstation
- scored
- ldap
- services
- patch
- rule_2.2.6
- dnsmasq
- rule_2.2.14
- name: "2.2.15 | L1 | PATCH | Ensure DHCP Server is not enabled"
service:
name: dhcpd
state: stopped
enabled: no
- 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_dhcp_server
- "'dhcp' in ansible_facts.packages"
- not rhel9cis_is_mail_server
- "'postfix' in ansible_facts.packages"
- rhel9cis_rule_2_2_15
tags:
- level1-server
- level1-workstation
- scored
- dhcp
- services
- patch
- postfix
- rule_2.2.15
- name: "2.2.16 | L1 | PATCH | Ensure CUPS is not enabled"
service:
name: cups
state: stopped
enabled: no
# 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:
- not rhel9cis_use_nfs_server
- rhel9cis_use_nfs_service
when:
- not rhel9cis_cups_server
- "'cups' in ansible_facts.packages"
- "'nfs-utils' in ansible_facts.packages"
- rhel9cis_rule_2_2_16
tags:
- level1-server
- level2-workstation
- scored
- cups
- services
- level1-workstation
- patch
- nfs
- services
- rule_2.2.16
- name: "2.2.17 | L1 | PATCH | Ensure NIS Server is not enabled"
service:
name: ypserv
state: stopped
enabled: no
# 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:
- not rhel9cis_nis_server
- "'ypserv' in ansible_facts.packages"
- "'rpcbind' in ansible_facts.packages"
- rhel9cis_rule_2_2_17
tags:
- level1-server
- level1-workstation
- patch
- rpc
- rule_2.2.17
- name: "2.2.18 | L1 | PATCH | Ensure mail transfer agent is configured for local-only mode"
lineinfile:
dest: /etc/postfix/main.cf
regexp: "^(#)?inet_interfaces"
line: "inet_interfaces = loopback-only"
notify: restart postfix
# 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:
- not rhel9cis_is_mail_server
- "'postfix' in ansible_facts.packages"
- "'rsync' in ansible_facts.packages"
- rhel9cis_rule_2_2_18
tags:
- level1-server
- level1-workstation
- patch
- rule_2.2.1
- rsync
- rule_2.2.18

View file

@ -1,43 +1,61 @@
---
- name: "2.3.1 | L1 | PATCH | Ensure NIS Client is not installed"
package:
name: ypbind
state: absent
when:
- not rhel9cis_ypbind_required
- "'ypbind' in ansible_facts.packages"
- rhel9cis_rule_2_3_1
tags:
- level1-server
- level1-workstation
- patch
- rule_2.3.1
- name: "2.3.2 | L1 | PATCH | Ensure telnet client is not installed"
package:
- name: "2.3.1 | PATCH | Ensure telnet client is not installed"
ansible.builtin.package:
name: telnet
state: absent
when:
- not rhel9cis_telnet_required
- "'telnet' in ansible_facts.packages"
- rhel9cis_rule_2_3_2
- rhel9cis_rule_2_3_1
tags:
- level1-server
- level1-workstation
- patch
- rule_2.3.2
- telnet
- rule_2.3.1
- name: "2.3.3 | L1 | PATCH | Ensure LDAP client is not installed"
package:
- name: "2.3.2 | PATCH | Ensure LDAP client is not installed"
ansible.builtin.package:
name: openldap-clients
state: absent
when:
- not rhel9cis_openldap_clients_required
- "'openldap-clients' in ansible_facts.packages"
- rhel9cis_rule_2_3_2
tags:
- level1-server
- level1-workstation
- patch
- ldap
- rule_2.3.2
- name: "2.3.3 | PATCH | Ensure TFTP client is not installed"
ansible.builtin.package:
name: tftp
state: absent
when:
- not rhel9cis_tftp_client
- "'tftp' in ansible_facts.packages"
- rhel9cis_rule_2_3_3
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_tftp_client
- "'ftp' in ansible_facts.packages"
- rhel9cis_rule_2_3_4
tags:
- level1-server
- level1-workstation
- patch
- ftp
- rule_2.3.4

View file

@ -0,0 +1,39 @@
---
- 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=sockets
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: 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,13 +1,13 @@
---
- name: "SECTION | 2.1 | xinetd"
include: cis_2.1.1.yml
- name: "SECTION | 2.2.1 | Time Synchronization"
include: cis_2.2.1.x.yml
- name: "SECTION | 2.1 | Time Synchronization"
ansible.builtin.import_tasks: cis_2.1.x.yml
- name: "SECTION | 2.2 | Special Purpose Services"
include: cis_2.2.x.yml
ansible.builtin.import_tasks: cis_2.2.x.yml
- name: "SECTION | 2.3 | Service Clients"
include: cis_2.3.x.yml
ansible.builtin.import_tasks: cis_2.3.x.yml
- name: "SECTION | 2.4 | Nonessential services removed"
ansible.builtin.import_tasks: cis_2.4.yml

View file

@ -1,43 +1,83 @@
---
- name: "3.1.1 | L1 | PATCH | Ensure IP forwarding is disabled"
# 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 | L1 | PATCH | Ensure IP forwarding is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- name: "3.1.1 | PATCH | Ensure IPv6 status is identified | refresh"
ansible.builtin.set_fact:
rhel9cis_sysctl_update: true
rhel9cis_flush_ipv6_route: true
- name: "3.1.1 | L1 | PATCH | Ensure IP forwarding is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- sysctl flush ipv6 route table
- update sysctl
when: rhel9cis_ipv6_required
- 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_is_router
- not rhel9cis_ipv6_required
- rhel9cis_rule_3_1_1
tags:
- level1-server
- level1-workstation
- sysctl
- manual
- patch
- ipv6
- networking
- rule_3.1.1
- name: "3.1.2 | L1 | PATCH | Ensure packet redirect sending is disabled"
debug:
msg: "Control being set via Handler 'update sysctl' which writes to /etc/sysctl.d/99-sysctl.conf"
notify:
- update sysctl
- sysctl flush ipv4 route table
- 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"
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
when:
- not rhel9cis_is_router
- rhel9cis_rule_3_1_2
tags:
- level1-server
- level1-workstation
- sysctl
- patch
- wireless
- rule_3.1.2
- name: "3.1.3 | PATCH | Ensure TIPC is disabled"
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.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
tags:
- level2-server
- level2-workstation
- patch
- tipc
- rule_3.1.3

View file

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

View file

@ -1,61 +1,194 @@
---
- name: "3.3.1 | L2 | PATCH | Ensure DCCP is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install dccp(\\s|$)"
line: "install dccp /bin/true"
create: yes
mode: 0600
- 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
when:
- rhel9cis_rule_3_3_1
tags:
- level2-server
- level2-workstation
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.1
- name: "3.3.2 | L2 | PATCH | Ensure SCTP is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install sctp(\\s|$)"
line: "install sctp /bin/true"
create: yes
mode: 0600
- name: "3.3.2 | PATCH | Ensure ICMP redirects are not accepted"
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.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.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:
- level2-server
- level2-workstation
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.2
- name: "3.3.3 | L2 | PATCH | Ensure RDS is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install rds(\\s|$)"
line: "install rds /bin/true"
create: yes
mode: 0600
- 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:
- level2-server
- level2-workstation
- level1-server
- level1-workstation
- sysctl
- patch
- rule_3.3.3
- name: "3.3.4 | L2 | PATCH | Ensure TIPC is disabled"
lineinfile:
dest: /etc/modprobe.d/CIS.conf
regexp: "^(#)?install tipc(\\s|$)"
line: "install tipc /bin/true"
create: yes
mode: 0600
- 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:
- level2-server
- level2-workstation
- 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
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"
when:
- rhel9cis_ipv6_required
- rhel9cis_rule_3_3_9
tags:
- level2-server
- level2-workstation
- sysctl
- patch
- rule_3.3.9

View file

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

View file

@ -0,0 +1,59 @@
---
- 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,10 +1,16 @@
---
- name: "3.4.2.1 | L1 | PATCH | Ensure firewalld service is enabled and running"
service:
name: firewalld
state: started
enabled: yes
- 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
@ -12,40 +18,155 @@
- level1-server
- level1-workstation
- patch
- rule_3_4_2_1
- firewalld
- rule_3.4.2.1
- name: "3.4.2.2 | L1 | PATCH | Ensure iptables is not enabled with firewalld"
systemd:
name: iptables
enabled: false
masked: true
ignore_errors: true
- 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: 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 == "firewalld"
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_2
tags:
- skip_ansible_lint
- level1-server
- level1-workstation
- patch
- rule_3_4_2_2
- nftables
- rule_3.4.2.2
- name: "3.4.2.3 | L1 | PATCH | Ensure nftables is not enabled with firewalld"
systemd:
name: nftables
enabled: false
masked: true
- 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 == "firewalld"
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- rule_3_4_2_3
- nftables
- rule_3.4.2.3
- name: "3.4.2.4 | L1 | PATCH | Ensure default zone is set"
command: firewall-cmd --set-default-zone="{{ rhel9cis_default_zone }}"
- 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
@ -53,50 +174,126 @@
- level1-server
- level1-workstation
- patch
- nftables
- rule_3.4.2.4
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone"
- name: "3.4.2.5 | AUDIT | Ensure firewalld drops unnecessary services and ports"
block:
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and polocies"
shell: "nmcli -t connection show | awk -F: '{ if($4){print $4} }' | while read INT; do firewall-cmd --get-active-zones | grep -B1 $INT; done"
- 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: no
register: rhel9cis_3_4_2_5_interfacepolicy
check_mode: false
register: rhel9cis_3_4_2_5_servicesport
- name: "3.4.2.5 | L1 | AUDIT | Ensure network interfaces are assigned to appropriate zone | Get list of interfaces and polocies | Show the interface to policy"
debug:
- 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 policies tied to the interfaces, please correct as needed"
- "{{ rhel9cis_3_4_2_5_interfacepolicy.stdout_lines }}"
- "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_firewall == "firewalld"
- rhel9cis_rule_3_4_2_5
tags:
- level1-server
- level1-workstation
- manual
- audit
- rule_3.4.2.5
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports"
- name: "3.4.2.6 | PATCH | Ensure nftables established connections are configured"
block:
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Get list of services and ports"
shell: "firewall-cmd --get-active-zones | awk '!/:/ {print $1}' | while read ZN; do firewall-cmd --list-all --zone=$ZN; done"
- name: "3.4.2.6 | AUDIT | EEnsure 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
check_mode: no
register: rhel9cis_3_4_2_6_servicesport
register: rhel9cis_3_4_2_6_inconnectionrule
- name: "3.4.2.6 | L1 | AUDIT | Ensure firewalld drops unnecessary services and ports | Show services and ports"
debug:
msg:
- "The items below are the services and ports that are accepted, please correct as needed"
- "{{ rhel9cis_3_4_2_6_servicesport.stdout_lines }}"
- 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 == "firewalld"
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_2_6
tags:
- level1-server
- level1-workstation
- audit
- 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,264 +0,0 @@
---
- name: "3.4.3.1 | L1 | PATCH | Ensure iptables are flushed with nftables"
command: ip6tables -F
when:
- rhel9cis_rule_3_4_3_1
- rhel9cis_firewall != "iptables"
- rhel9cis_ipv6_required
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.1
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists"
block:
- name: "3.4.3.2 | L1 | AUDIT | Ensure a table exists | Check for tables"
command: nft list tables
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_2_nft_tables
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists | Show existing tables"
debug:
msg:
- "Below are the current nft tables, please review"
- "{{ rhel9cis_3_4_3_2_nft_tables.stdout_lines }}"
when: rhel9cis_3_4_3_2_nft_tables.stdout | length > 0
- name: "3.4.3.2 | L1 | AUDIT | Ensure an nftables table exists | Alert on no tables"
debug:
msg:
- "Warning! You currently have no nft tables, please review your setup"
- 'Use the command "nft create table inet <table name>" to create a new table'
when:
- rhel9cis_3_4_3_2_nft_tables.stdout | length == 0
- not rhel9cis_nft_tables_autonewtable
- name: "3.4.3.2 | L1 | PATCH | Ensure a table exists | Create table if needed"
command: nft create table inet "{{ rhel9cis_nft_tables_tablename }}"
failed_when: no
when: rhel9cis_nft_tables_autonewtable
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_2
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.2
- name: "3.4.3.3 | L1 | PATCH | Ensure nftables base chains exist"
block:
- name: "3.4.3.3 | L1 | Ensure nftables base chains exist | Get current chains for INPUT"
shell: nft list ruleset | grep 'hook input'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_input_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Get current chains for FORWARD"
shell: nft list ruleset | grep 'hook forward'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_forward_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Get current chains for OUTPUT"
shell: nft list ruleset | grep 'hook output'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_3_output_chains
- name: "3.4.3.3 | L1 | AUDIT | Ensure nftables base chains exist | Display chains for review"
debug:
msg:
- "Below are the current INPUT chains"
- "{{ rhel9cis_3_4_3_3_input_chains.stdout_lines }}"
- "Below are the current FORWARD chains"
- "{{ rhel9cis_3_4_3_3_forward_chains.stdout_lines }}"
- "Below are teh current OUTPUT chains"
- "{{ rhel9cis_3_4_3_3_output_chains.stdout_lines }}"
when: not rhel9cis_nft_tables_autochaincreate
- name: "3.4.3.3 | L1 | PATCH | Ensure nftables base chains exist | Create chains if needed"
shell: "{{ item }}"
args:
warn: no
failed_when: no
with_items:
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" input { type filter hook input priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { type filter hook forward priority 0 \; }
- nft create chain inet "{{ rhel9cis_nft_tables_tablename }}" output { type filter hook output priority 0 \; }
when: rhel9cis_nft_tables_autochaincreate
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_3
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.3
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured"
block:
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather iif lo accept existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'iif "lo" accept'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_iiflo
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip saddr existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_ipsaddr
- name: "3.4.3.4 | L1 | AUDIT | Ensure nftables loopback traffic is configured | Gather ip6 saddr existence"
shell: nft list ruleset | awk '/hook input/,/}/' | grep 'ip6 saddr'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_4_ip6saddr
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set iif lo accept rule"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input iif lo accept
when: '"iif \"lo\" accept" not in rhel9cis_3_4_3_4_iiflo.stdout'
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set ip sddr rule"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip saddr 127.0.0.0/8 counter drop
when: '"ip saddr 127.0.0.0/8 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_3_4_ipsaddr.stdout'
- name: "3.4.3.4 | L1 | PATCH | Ensure nftables loopback traffic is configured | Set ip6 saddr rule"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip6 saddr ::1 counter drop
when: '"ip6 saddr ::1 counter packets 0 bytes 0 drop" not in rhel9cis_3_4_3_4_ip6saddr.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_4
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.4
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured"
block:
- name: "3.4.3.5 | L1 | AUDIT | Ensure nftables outbound and established connections are configured | Gather incoming connection rules"
shell: nft list ruleset | awk '/hook input/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_5_inconnectionrule
- name: "3.4.3.5 | L1 | AUDIT | Ensure nftables outbound and established connections are configured | Gather outbound connection rules"
shell: nft list ruleset | awk '/hook output/,/}/' | grep -E 'ip protocol (tcp|udp|icmp) ct state'
changed_when: false
failed_when: false
register: rhel9cis_3_4_3_5_outconnectionrule
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input tcp established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol tcp ct state established accept
when: '"ip protocol tcp ct state established accept" not in rhel9cis_3_4_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input udp established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol udp ct state established accept
when: '"ip protocol udp ct state established accept" not in rhel9cis_3_4_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add input icmp established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input ip protocol icmp ct state established accept
when: '"ip protocol icmp ct state established accept" not in rhel9cis_3_4_3_5_inconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output tcp new, related, established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol tcp ct state new,related,established accept
when: '"ip protocol tcp ct state established,related,new accept" not in rhel9cis_3_4_3_5_outconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output udp new, related, established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol udp ct state new,related,established accept
when: '"ip protocol udp ct state established,related,new accept" not in rhel9cis_3_4_3_5_outconnectionrule.stdout'
- name: "3.4.3.5 | L1 | PATCH | Ensure nftables outbound and established connections are configured | Add output icmp new, related, established accept policy"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" output ip protocol icmp ct state new,related,established accept
when: '"ip protocol icmp ct state established,related,new accept" not in rhel9cis_3_4_3_5_outconnectionrule.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_5
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.5
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy"
block:
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook input deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook input'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_inputpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook forward deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook forward'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_forwardpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for hook output deny policy"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'hook output'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_outputpolicy
- name: "3.4.3.6 | L1 | AUDIT | Ensure nftables default deny firewall policy | Check for SSH allow"
shell: nft list table inet "{{ rhel9cis_nft_tables_tablename }}" | grep 'ssh'
failed_when: false
changed_when: false
register: rhel9cis_3_4_3_6_sshallowcheck
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Enable SSH traffic"
command: nft add rule inet "{{ rhel9cis_nft_tables_tablename }}" input tcp dport ssh accept
when: '"tcp dport ssh accept" not in rhel9cis_3_4_3_6_sshallowcheck.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Set hook input deny policy"
command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" input { policy drop \; }
when: '"type filter hook input priority 0; policy drop;" not in rhel9cis_3_4_3_6_inputpolicy.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Create hook forward deny policy"
command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" forward { policy drop \; }
when: '"type filter hook forward priority 0; policy drop;" not in rhel9cis_3_4_3_6_forwardpolicy.stdout'
- name: "3.4.3.6 | L1 | PATCH | Ensure nftables default deny firewall policy | Create hook output deny policy"
command: nft chain inet "{{ rhel9cis_nft_tables_tablename }}" output { policy drop \; }
when: '"type filter hook output priority 0; policy drop;" not in rhel9cis_3_4_3_6_outputpolicy.stdout'
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_6
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.6
- name: "3.4.3.7 | L1 | PATCH | Ensure nftables service is enabled | Check if nftables is enabled"
service:
name: nftables
enabled: yes
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_7
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.7
- name: "3.4.3.8 | L1 | PATCH | Ensure nftables rules are permanent"
lineinfile:
path: /etc/sysconfig/nftables.conf
state: present
insertafter: EOF
line: include "/etc/nftables/inet-{{ rhel9cis_nft_tables_tablename }}"
when:
- rhel9cis_firewall == "nftables"
- rhel9cis_rule_3_4_3_8
tags:
- level1-server
- level1-workstation
- patch
- rule_3.4.3.8

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -1,15 +1,15 @@
---
- name: "4.1.1.1 | L2 | PATCH | Ensure auditd is installed"
- name: "4.1.1.1 | PATCH | Ensure auditd is installed"
block:
- name: "4.1.1.1 | L2 | PATCH | Ensure auditd is installed | Install auditd packages"
package:
- 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 | L2 | PATCH | Ensure auditd is installed | Install auditd-lib packages"
package:
- 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'
@ -19,85 +19,87 @@
- level2-server
- level2-workstation
- patch
- auditd
- rule_4.1.1.1
- name: "4.1.1.2 | L2 | PATCH | Ensure auditd service is enabled"
service:
name: auditd
state: started
enabled: yes
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled"
block:
- name: "4.1.1.2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX"
ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
changed_when: false
failed_when: false
check_mode: false
register: rhel9cis_4_1_1_2_grub_cmdline_linux
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting"
ansible.builtin.replace:
path: /etc/default/grub
regexp: 'audit=.'
replace: 'audit=1'
notify: Grub2cfg
when: "'audit=' in rhel9cis_4_1_1_2_grub_cmdline_linux.stdout"
- name: "4.1.1.2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing"
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_2_grub_cmdline_linux.stdout }} audit=1"'
notify: Grub2cfg
when: "'audit=' not in rhel9cis_4_1_1_2_grub_cmdline_linux.stdout"
when:
- not rhel9cis_skip_for_travis
- rhel9cis_rule_4_1_1_2
- ansible_connection != 'docker'
tags:
- level2-server
- level2-workstation
- auditd
- patch
- auditd
- grub
- rule_4.1.1.2
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled"
- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient"
block:
- name: "4.1.1.3 | L2 | AUDIT | Ensure auditing for processes that start prior to auditd is enabled | Get GRUB_CMDLINE_LINUX"
shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
- name: "4.1.1.3 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX"
ansible.builtin.shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
changed_when: false
failed_when: false
check_mode: no
check_mode: false
register: rhel9cis_4_1_1_3_grub_cmdline_linux
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Replace existing setting"
replace:
dest: /etc/default/grub
regexp: 'audit=.'
replace: 'audit=1'
notify: grub2cfg
when: "'audit=' in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting"
ansible.builtin.replace:
path: /etc/default/grub
regexp: 'audit_backlog_limit=\d+'
replace: 'audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}'
notify: Grub2cfg
when: "'audit_backlog_limit=' in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
- name: "4.1.1.3 | L2 | PATCH | Ensure auditing for processes that start prior to auditd is enabled | Add audit setting if missing"
lineinfile:
- name: "4.1.1.3 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing"
ansible.builtin.lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_3_grub_cmdline_linux.stdout }} audit=1"'
notify: grub2cfg
when: "'audit=' not in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
line: '{{ rhel9cis_4_1_1_3_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"'
notify: Grub2cfg
when: "'audit_backlog_limit=' not in rhel9cis_4_1_1_3_grub_cmdline_linux.stdout"
when:
- rhel9cis_rule_4_1_1_3
tags:
- level2-server
- level2-workstation
- auditd
- patch
- auditd
- grub
- rule_4.1.1.3
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient"
block:
- name: "4.1.1.4 | L2 | AUDIT | Ensure audit_backlog_limit is sufficient | Get GRUB_CMDLINE_LINUX"
shell: grep 'GRUB_CMDLINE_LINUX=' /etc/default/grub | sed 's/.$//'
changed_when: false
failed_when: false
check_mode: no
register: rhel9cis_4_1_1_4_grub_cmdline_linux
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient | Replace existing setting"
replace:
dest: /etc/default/grub
regexp: 'audit_backlog_limit=\d+'
replace: 'audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}'
notify: grub2cfg
when: "'audit_backlog_limit=' in rhel9cis_4_1_1_4_grub_cmdline_linux.stdout"
- name: "4.1.1.4 | L2 | PATCH | Ensure audit_backlog_limit is sufficient | Add audit_backlog_limit setting if missing"
lineinfile:
path: /etc/default/grub
regexp: '^GRUB_CMDLINE_LINUX='
line: '{{ rhel9cis_4_1_1_4_grub_cmdline_linux.stdout }} audit_backlog_limit={{ rhel9cis_audit_back_log_limit }}"'
notify: grub2cfg
when: "'audit_backlog_limit=' not in rhel9cis_4_1_1_4_grub_cmdline_linux.stdout"
- 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,45 +1,42 @@
---
- name: "4.1.2.1 | L2 | PATCH | Ensure audit log storage size is configured"
lineinfile:
dest: /etc/audit/auditd.conf
- 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_max_log_file_size }}"
state: present
notify: restart auditd
notify: Restart auditd
when:
- rhel9cis_rule_4_1_2_1
tags:
- level2-server
- level2-workstation
- auditd
- patch
- auditd
- rule_4.1.2.1
- name: "4.1.2.2 | L2 | PATCH | Ensure audit logs are not automatically deleted"
lineinfile:
dest: /etc/audit/auditd.conf
- 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'] }}"
state: present
notify: restart auditd
notify: Restart auditd
when:
- rhel9cis_rule_4_1_2_2
tags:
- level2-server
- level2-workstation
- auditd
- patch
- auditd
- rule_4.1.2.2
- name: "4.1.2.3 | L2 | PATCH | Ensure system is disabled when audit logs are full"
lineinfile:
dest: /etc/audit/auditd.conf
- 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 }}"
state: present
notify: restart auditd
with_items:
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 }}' }
@ -48,6 +45,21 @@
tags:
- level2-server
- level2-workstation
- auditd
- 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
tags:
- level2-server
- level2-workstation
- patch
- auditd

View file

@ -0,0 +1,292 @@
---
# 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 -4000 -o -type f -perm -2000 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.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

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

View file

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

View file

@ -1,7 +1,7 @@
---
- name: "4.2.1.1 | L1 | PATCH | Ensure rsyslog installed"
package:
- name: "4.2.1.1 | PATCH | Ensure rsyslog installed"
ansible.builtin.package:
name: rsyslog
state: present
when:
@ -11,12 +11,13 @@
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.1
- name: "4.2.1.2 | L1 | PATCH | Ensure rsyslog Service is enabled"
service:
- name: "4.2.1.2 | PATCH | Ensure rsyslog Service is enabled"
ansible.builtin.systemd:
name: rsyslog
enabled: yes
enabled: true
when:
- rhel9cis_rule_4_2_1_2
tags:
@ -26,92 +27,27 @@
- rsyslog
- rule_4.2.1.2
- name: "4.2.1.3 | L1 | PATCH | Ensure rsyslog default file permissions configured"
lineinfile:
dest: /etc/rsyslog.conf
regexp: '^\$FileCreateMode'
line: '$FileCreateMode 0640'
notify: restart rsyslog
- 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
- rhel9cis_syslog == "rsyslog"
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.3
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured"
block:
- name: "4.2.1.4 | L1 | AUDIT | Ensure logging is configured | rsyslog current config message out"
command: cat /etc/rsyslog.conf
become: yes
changed_when: false
failed_when: no
check_mode: no
register: rhel_09_4_2_1_4_audit
- name: "4.2.1.4 | L1 | AUDIT | Ensure logging is configured | rsyslog current config message out"
debug:
msg:
- "These are the current logging configurations for rsyslog, please review:"
- "{{ rhel_09_4_2_1_4_audit.stdout_lines }}"
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | mail.* log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MAIL LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# mail logging additions to meet CIS standards
mail.* -/var/log/mail
mail.info -/var/log/mail.info
mail.warning -/var/log/mail.warning
mail.err /var/log/mail.err
insertafter: '# Log all the mail messages in one place.'
notify: restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | news.crit log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} NEWS LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# news logging additions to meet CIS standards
news.crit -/var/log/news/news.crit
news.notice -/var/log/news/news.crit
insertafter: '# Save news errors of level crit and higher in a special file.'
notify: restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | Misc. log setting"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MISC. LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# misc. logging additions to meet CIS standards
*.=warning;*.=err -/var/log/warn
*.crit /var/log/warn
*.*;mail.none;news.none /var/log/messages
insertafter: '#### RULES ####'
notify: restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.4 | L1 | PATCH | Ensure logging is configured | Local log settings"
blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} LOCAL LOG SETTINGS (ANSIBLE MANAGED)"
block: |
# local log settings
local0,local1.* -/var/log/localmessages
local2,local3.* -/var/log/localmessages
local4,local5.* -/var/log/localmessages
local6,local7.* -/var/log/localmessages
*.emrg :omusrmsg:*
insertafter: '#### RULES ####'
notify: restart rsyslog
- 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:
@ -121,57 +57,160 @@
- rsyslog
- rule_4.2.1.4
- name: "4.2.1.5 | L1 | PATCH | Ensure rsyslog is configured to send logs to a remote log host"
blockinfile:
- 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
changed_when: false
failed_when: false
check_mode: false
register: rhel_09_4_2_1_5_audit
- name: "4.2.1.5 | AUDIT | Ensure logging is configured | rsyslog current config message out"
ansible.builtin.debug:
msg:
- "These are the current logging configurations for rsyslog, please review:"
- "{{ rhel_09_4_2_1_5_audit.stdout_lines }}"
- name: "4.2.1.5 | PATCH | Ensure logging is configured | mail.* log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
marker: "# {mark} MAIL LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# mail logging additions to meet CIS standards
mail.* -/var/log/mail
mail.info -/var/log/mail.info
mail.warning -/var/log/mail.warning
mail.err /var/log/mail.err
insertafter: '# Log all the mail messages in one place.'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | news.crit log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} NEWS LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# news logging additions to meet CIS standards
news.crit -/var/log/news/news.crit
news.notice -/var/log/news/news.crit
insertafter: '# Save news errors of level crit and higher in a special file.'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Misc. log setting"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "# {mark} MISC. LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# misc. logging additions to meet CIS standards
*.=warning;*.=err -/var/log/warn
*.crit /var/log/warn
*.*;mail.none;news.none /var/log/messages
insertafter: '#### RULES ####'
notify: Restart rsyslog
when: rhel9cis_rsyslog_ansiblemanaged
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Local log settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} LOCAL LOG SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# local log settings to meet CIS standards
local0,local1.* -/var/log/localmessages
local2,local3.* -/var/log/localmessages
local4,local5.* -/var/log/localmessages
local6,local7.* -/var/log/localmessages
*.emrg :omusrmsg:*
insertafter: '#### RULES ####'
notify: Restart rsyslog
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Auth Settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} Auth SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# Private settings to meet CIS standards
auth,authpriv.* /var/log/secure
insertafter: '#### RULES ####'
notify: Restart rsyslog
- name: "4.2.1.5 | PATCH | Ensure logging is configured | Cron Settings"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
marker: "#{mark} Cron SETTINGS - CIS benchmark - Ansible-lockdown"
block: |
# Cron settings to meet CIS standards
cron.* /var/log/cron
insertafter: '#### RULES ####'
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_5
tags:
- level1-server
- level1-workstation
- patch
- rsyslog
- rule_4.2.1.5
- name: "4.2.1.6 | PATCH | Ensure rsyslog is configured to send logs to a remote log host"
ansible.builtin.blockinfile:
path: /etc/rsyslog.conf
state: present
block: |
# remote host is: name/ip:port, e.g. 192.168.0.1:514, port optional
*.* @@{{ rhel9cis_remote_log_server }}
# 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
notify: Restart rsyslog
when:
- rhel9cis_rule_4_2_1_5
- rhel9cis_remote_log_server is defined
- rhel9cis_rule_4_2_1_6
- rhel9cis_remote_log_server
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.5
- rsyslog
- rule_4.2.1.6
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts."
- name: "4.2.1.7 | PATCH | Ensure rsyslog is not configured to recieve logs from a remote client"
block:
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts. | When not log host"
replace:
- 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 }})'
regexp: '{{ item }}'
replace: '#\1'
notify: restart rsyslog
with_items:
notify: Restart rsyslog
loop:
- '^(\$ModLoad imtcp)'
- '^(\$InputTCPServerRun)'
- '^(module\(load="imtcp"\))'
- '^(input\(type="imtcp")'
when: not rhel9cis_system_is_log_server
- name: "4.2.1.6 | L1 | PATCH | Ensure remote rsyslog messages are only accepted on designated log hosts. | When log host"
replace:
- 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
with_items:
notify: Restart rsyslog
loop:
- 'ModLoad imtcp'
- 'InputTCPServerRun'
when: rhel9cis_system_is_log_server
when:
- rhel9cis_rule_4_2_1_6
- rhel9cis_rule_4_2_1_7
tags:
- level1-server
- level1-workstation
- patch
- rule_4.2.1.6
- rsyslog
- rule_4.2.1.7

View file

@ -1,43 +1,199 @@
---
- name: "4.2.2.1 | L1 | PATCH | Ensure journald is configured to send logs to rsyslog"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#ForwardToSyslog=|^ForwardToSyslog="
line: ForwardToSyslog=yes
- 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
- 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
- rule_4.2.2.1
- journald
- rule_4.2.2.1.4
- name: "4.2.2.2 | L1 | PATCH | Ensure journald is configured to compress large log files"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#Compress=|^Compress="
line: Compress=yes
state: present
- 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: 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
- patch
- audit
- journald
- rule_4.2.2.2
- name: "4.2.2.3 | L1 | PATCH | Ensure journald is configured to write logfiles to persistent disk"
lineinfile:
dest: /etc/systemd/journald.conf
regexp: "^#Storage=|^Storage="
line: Storage=persistent
state: present
- 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,13 +1,30 @@
---
- name: "4.2.3 | L1 | PATCH | Ensure permissions on all logfiles are configured"
command: find /var/log -type f -exec chmod g-wx,o-rwx "{}" +
changed_when: false
failed_when: false
- 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
register: logfiles
- name: "4.2.3 | PATCH | Ensure permissions on all logfiles are configured | change permissions"
ansible.builtin.file:
path: "{{ item.path }}"
mode: 0640
loop: "{{ logfiles.files }}"
loop_control:
label: "{{ item.path }}"
when:
- item.path != "/var/log/btmp"
- item.path != "/var/log/utmp"
- item.path != "/var/log/wtmp"
when:
- rhel9cis_rule_4_2_3
tags:
- level1-server
- level1-workstation
- patch
- logfiles
- rule_4.2.3

View file

@ -1,24 +1,55 @@
---
- name: "4.3 | L1 | PATCH | Ensure logrotate is configured"
- name: "4.3 | PATCH | Ensure logrotate is configured"
block:
- name: "4.3 | L1 | AUDIT | Ensure logrotate is configured | Get logrotate settings"
find:
paths: /etc/logrotate.d/
register: log_rotates
- name: "4.3 | PATCH | Ensure logrotate is configured | installed"
ansible.builtin.package:
name: rsyslog-logrotate
state: present
- name: "4.3 | L1 | PATCH | Ensure logrotate is configured"
replace:
path: "{{ item.path }}"
- 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 }}"
with_items:
- "{{ log_rotates.files }}"
- { path: "/etc/logrotate.conf" }
- 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: 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,23 +1,29 @@
---
- name: "SECTION | 4.1| Configure System Accounting (auditd)"
include: cis_4.1.1.x.yml
- name: "SECTION | 4.1 | Configure System Accounting (auditd)"
ansible.builtin.import_tasks: cis_4.1.1.x.yml
when:
- not system_is_container
- name: "SECTION | 4.1.2.x| Configure Data Retention"
include: cis_4.1.2.x.yml
- name: "SECTION | 4.1.2 | Configure Data Retention"
ansible.builtin.import_tasks: cis_4.1.2.x.yml
- name: "SECTION | 4.1.x| Auditd rules"
include: cis_4.1.x.yml
- name: "SECTION | 4.1.3 | Configure Auditd rules"
ansible.builtin.import_tasks: cis_4.1.3.x.yml
- name: "SECTION | 4.2.x| Configure Logging"
include: cis_4.2.1.x.yml
- name: "SECTION | 4.1.4 | Configure Audit files"
ansible.builtin.import_tasks: cis_4.1.4.x.yml
- name: "SECTION | 4.2 | Configure Logging"
ansible.builtin.import_tasks: cis_4.2.1.x.yml
when: rhel9cis_syslog == 'rsyslog'
- name: "SECTION | 4.2.2.x| Configure journald"
include: cis_4.2.2.x.yml
- name: "SECTION | 4.2.2 | Configure journald"
ansible.builtin.import_tasks: cis_4.2.2.x.yml
when: rhel9cis_syslog == 'journald'
- name: "SECTION | 4.2.3 | Configure logile perms"
include: cis_4.2.3.yml
ansible.builtin.import_tasks: cis_4.2.3.yml
- name: "SECTION | 4.3 | Configure logrotate"
include: cis_4.3.yml
ansible.builtin.import_tasks: cis_4.3.yml

View file

@ -1,20 +1,21 @@
---
- name: "5.1.1 | L1 | PATCH | Ensure cron daemon is enabled"
service:
- name: "5.1.1 | PATCH | Ensure cron daemon is enabled"
ansible.builtin.service:
name: crond
enabled: yes
enabled: true
when:
- rhel9cis_rule_5_1_1
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.1
- name: "5.1.2 | L1 | PATCH | Ensure permissions on /etc/crontab are configured"
file:
dest: /etc/crontab
- name: "5.1.2 | PATCH | Ensure permissions on /etc/crontab are configured"
ansible.builtin.file:
path: /etc/crontab
owner: root
group: root
mode: 0600
@ -24,11 +25,12 @@
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.2
- name: "5.1.3 | L1 | PATCH | Ensure permissions on /etc/cron.hourly are configured"
file:
dest: /etc/cron.hourly
- 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
@ -39,11 +41,12 @@
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.3
- name: "5.1.4 | L1 | PATCH | Ensure permissions on /etc/cron.daily are configured"
file:
dest: /etc/cron.daily
- 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
@ -54,11 +57,12 @@
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.4
- name: "5.1.5 | L1 | PATCH | Ensure permissions on /etc/cron.weekly are configured"
file:
dest: /etc/cron.weekly
- 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
@ -71,9 +75,9 @@
- patch
- rule_5.1.5
- name: "5.1.6 | L1 | PATCH | Ensure permissions on /etc/cron.monthly are configured"
file:
dest: /etc/cron.monthly
- 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
@ -86,9 +90,9 @@
- patch
- rule_5.1.6
- name: "5.1.7 | L1 | PATCH | Ensure permissions on /etc/cron.d are configured"
file:
dest: /etc/cron.d
- 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
@ -99,42 +103,25 @@
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.7
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users"
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users"
block:
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Remove at.deny"
file:
dest: /etc/at.deny
- name: "5.1.8 | PATCH | Ensure cron is restricted to authorized users | Remove cron.deny"
ansible.builtin.file:
path: /etc/cron.deny
state: absent
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Check if at.allow exists"
stat:
path: "/etc/at.allow"
register: p
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Ensure at.allow is restricted to authorized users"
file:
dest: /etc/at.allow
state: '{{ "file" if p.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Remove cron.deny"
file:
dest: /etc/cron.deny
state: absent
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Check if cron.allow exists"
stat:
- 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: p
register: rhel9cis_5_1_8_cron_allow_state
- name: "5.1.8 | L1 | PATCH | Ensure at/cron is restricted to authorized users | Ensure cron.allow is restricted to authorized users"
file:
dest: /etc/cron.allow
state: '{{ "file" if p.stat.exists else "touch" }}'
- 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
@ -144,4 +131,33 @@
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.8
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users"
block:
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Remove at.deny"
ansible.builtin.file:
path: /etc/at.deny
state: absent
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Check if at.allow exists"
ansible.builtin.stat:
path: "/etc/at.allow"
register: rhel9cis_5_1_9_at_allow_state
- name: "5.1.9 | PATCH | Ensure at is restricted to authorized users | Ensure at.allow is restricted to authorized users"
ansible.builtin.file:
path: /etc/at.allow
state: '{{ "file" if rhel9cis_5_1_9_at_allow_state.stat.exists else "touch" }}'
owner: root
group: root
mode: 0600
when:
- rhel9cis_rule_5_1_9
tags:
- level1-server
- level1-workstation
- patch
- cron
- rule_5.1.9

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