A role to implement Center for Internet Security (CIS) controls for RHEL (7-9) and RHEL clones (Oracle, CentOS), recent Fedora (31-32), SLES 15, and Ubuntu [18-22].04 LTS and certain Windows servers.
The Center for Internet Security provides a set of security benchmarks for operating systems designed to decrease the vulnerability vectors of a system.
These benchmarks are published in PDFs for non-commercial use. This role is an implementation of those controls for various Operating Systems per the list below. The controls themselves are not published here and you should visit CIS for a copy of the PDF. These automations are provided as a resposne and a tool to help systems administrators secure machines based off those recommendations. This collection is not endorsed by the Center for Internet Security in any way.
This collection contains a role that is designed to layer under other Ansible roles that install software packages, users, etc. It should be idempotent and can be run at any time. As usual with Ansible, make sure that later playbooks don't modify files that are modified in this role.
Benchmark Versions:
Operating System | OS Benchmark version |
---|---|
RHEL 7 | v2.2.0 |
RHEL 8 | v2.0.1 |
RHEL 9 | V1.0.0 |
CentOS 7 | v2.2.0 |
CentOS 8 | v1.0.0 |
Fedora 31 | (Fedora 28) v1.1.0 |
Fedora 32 | (Fedora 28) v1.1.0 |
Oracle Linux 7 | v2.2.0 |
Oracle Linux 8 | v1.0.0 |
SUSE Linux Enterprise 15 SP1 | (SUSE Linux Enterprise 12) v2.1.0 |
Ubuntu 18.04 LTS | v2.0.1 |
Ubuntu 20.04 LTS | (Ubuntu 18.04 LTS) v2.0.1 |
Ubuntu 22.04 LTS | v1.0.0 |
Windows Server 2019 | v1.8.1 |
Windows 10 | (Windows Server 2019) v1.8.1 |
- Some distributions use older CIS benchmarks that were the most recent at the time of creation. Efforts have been made to update the controls to work with the newer operating systems. Older versions of the benchmarks are listed in parenthesis.
- SUSE Linux Enterprise 15 SP1 uses the RHEL 7 task file since their controls are so similar. If you want to exclude a SUSE tag, make sure you use the associated RHEL 7 tag number if they are different. Tags can be found in the appropriate controls_list file found in the docs directory.
To implement the collection correctly, you will require the following
Control machine:
- Ansible 2.11+
- Machine connected to a package repository source (Satellite or yum repo)
Target machine:
- SSH connection with prviiledge escalation on Linux machines.
- Python interpreter
- WinRM connection with user with admin priviledge for Windows. Alternatively you can use an SSH connection.
- PowerShell v3 or higher
Some of the Ansible modules that are used require Ansible 2.7 and newer.
For most of the collection to work, you will need to have a package repo where you can install packages for the target machine. Registering with Satellite, a package repository, SCM, or a local package collection is recommended before using this, unless you exclude any tags that install packages.
The collection is designed to run on the machines in the chart above. It may run on other Red Hat and Ubuntu deriviatives, but it has not been tested on them. Upon initiation, the collection will automatically detect the OS and run the appropriate task list.
As the role runs, you will see an output listing the control number and a brief description of the task being performed (or skipped):
TASK [security-rollup : 1.7.1.3 - Set SELinux policy to targeted] ******************************
ok: [192.168.122.252]
The controls are implemented as Ansible tags. By default all tags are run on a given system. To disable a tag from running, run the playbook with the tag excluded (--skip-tags "x.y.z"):
ansible-playbook -i <inventory> <playbook.yml> --skip-tags "x.y.z"
Multiple tags can be listed, separated by commas:
ansible-playbook -i <inventory> <playbook.yml> --skip-tags "x.y.z,a.b.c"
Note: Some automation tasks handle multiple controls. In the role you may see something like this:
- name: 6.1.[2,4] - Ensure permissions on /etc/passwd /etc/group
file:
path: /etc/{{item}}
owner: root
group: root
mode: 0644
loop:
- passwd
- group
tags:
- 6.1.2
- 6.1.4
- In this control, two tags are being processed, '6.1.2' and '6.1.4' if you want this control to not run, you must exclude both tags:
ansible-playbook -i <inventory> <playbook.yml> --skip-tags "6.1.2,6.1.4"
Some controls are surrouned by Ansible blocks that themselves have tags. Excluding the tag that applies to the block will exclude all of the tasks inside of the block. If the block's tag is not excluded, then individual tasks inside of the block can be excluded by excluding their tags.
The list of tags and their associated crontol descriptions are listed in the controls_list file for Linux and [control_list_win](./docs/controls_list_win.md_ file for Windows) in the docs directory.
In addition to tags, there are a number of variables that can be set which will enable or disable tasks, or set values. These are explained and given default values in the roles/cis-security/defaults/main.yml file. Do not set these values in that file, but create and include your own variable file to override the defaults or set them as host variables.
Every effort has been made to make the controls idempotent, however some Ansible modules do not have the ability to measure every need as currently written and shell or command has been utilized to implement controls. This has the effect of bringing down the quality score on Ansible Galaxy, but the roles can be run multiple times without fear of breaking.
A secondary purpose of this collection is to show numerous ways that Ansible can be used to manage systems with various modules. The first time a module is used it is commented on many times to explain what the module is doing. Other times you may see something like the following:
- name: 5.4.4 - Ensure umask is set
replace:
path: "{{ item }}"
replace: " umask {{ default_umask }}"
regexp: '^\s*umask\s*022'
loop:
- /etc/bashrc
- /etc/profile
when: ansible_distribution != "SLES"
tags:
- 5.4.4
- name: 5.4.5 - Ensure shell timeout is {{ shell_timeout }} seconds or less
blockinfile:
path: "{{ item }}"
block: "TMOUT={{ shell_timeout }}"
marker: "# {mark} Ansible Managed CIS Timeout"
loop:
- /etc/bashrc
- /etc/profile
when: ansible_distribution != "SLES"
tags:
- 5.4.5
Both of these tasks manipulate the same file in the same way. They could have been written with the same module, even in the same task with a loop, but here it illustrates different ways files can be manipuldated with modules.
- 1/20/2020 - [email protected] - Initial creation
- 1/22/2020 - [email protected] - Added enhanced selinux controls
- 2/18/2020 - [email protected] - Added support for Ubuntu 18.04 LTS, added RHEL clone links
- 2/20/2020 - [email protected] - Fixed numerous tests and rearranged network controls
- 2/25/2020 - [email protected] - Added SLES 15 SP 1 support
- 3/17/2020 - [email protected] - Added Windows 2019 support
- 7/28/2022 - [email protected] - Adapted as a collection. Support for Ubuntu 20.04 and Windows 10
- 7/28/2022 - [email protected] - Fixed formatting