Red Hat® Ansible® Automation is a powerful tool for automating the configuration of systems. By running a predefined file called an Ansible Playbook, you can quickly configure the system according to your needs.
Ansible Automation can easily be used for security compliance automation, because it allows you to keep your system hardened, and it can operate on a large scale. Using Ansible Automation, you can set everything you need, including minimal password lengths, firewall rules, package installation, or the disabling of services.
ComplianceAsCode works great with Ansible Automation.
ComplianceAsCode connects a human-readable security policy with Ansible tasks that implement the settings required by the security policy.
The rules in ComplianceAsCode profiles contain Ansible tasks that configure the system to conform to the rule.
From these Ansible tasks and rule metadata, ComplianceAsCode generates an Ansible Playbook that you can use to harden your system.
After running the playbook, your system meets the requirements of the security policy.
ComplianceAsCode generates a playbook for each profile that conforms to the profile definition.
Moreover, it generates separate playbooks for every rule.
-
Learn how to add an Ansible task for a rule
-
Learn how to leverage
ComplianceAsCodestructure when creating Ansible content -
Learn how to generate Ansible Playbooks from a
ComplianceAsCoderepository -
Learn how to use the Ansible Playbooks generated by
ComplianceAsCode
|
Important
|
Content used in this lab has been altered to increase its educative potential, and is therefore different from the content in ComplianceAsCode upstream repository or the content in the scap-security-guide package shipped in Red Hat® products. |
-
The
ComplianceAsCoderepository was already cloned. -
Ansible Automation was installed.
-
The following dependencies required for the
ComplianceAsCodecontent build were installed usingyum install:-
Generic build utilities:
cmakeandmake, -
Utilities for generating SCAP content:
openscap-scanner -
Python dependencies for putting content together:
python3-pyyamlandpython3-jinja2
-
The ComplianceAsCode project consists of human-readable files that are compiled into standard-compliant files that are difficult to read and edit directly.
For your convenience, the environment is already set up, so the content is built and ready to be used. No worries, though—you get to rebuild it later in the exercise.
To start the hands-on section, take the following steps:
-
Go to: Lab 4 Environment
-
Wait until all the steps being executed in the terminal are complete.
Ansible tasks can be attached to every rule in a ComplianceAsCode project.
A lot of rules already contain Ansible tasks.
As an example, you add a new Ansible task for the accounts_tmout rule.
You have already encountered this rule in Lab Exercise 1.
This rule is about the interactive session timeout for inactive users.
Terminating an idle session within a short time period reduces the risk of unauthorized operations.
The Ansible task that you add configures the session timeout in the respective configuration file.
You work in the context of Red Hat® Enterprise Linux® 8 (RHEL 8) product and the OSPP profile for Red Hat® Enterprise Linux® 8,
but the structure is the same for all rules in ComplianceAsCode.
As you already know from Lab Exercise 1, source code for the accounts_tmout rule is located in the linux_os/guide/system/accounts/accounts-session/accounts_tmout directory.
-
Switch to the rule directory and examine its content.
[... ]$ cd linux_os/guide/system/accounts/accounts-session/accounts_tmout [... accounts_tmout]$ ls bash oval rule.yml tests
As you learned in previous lab exercises, the
rule.ymlfile contains the rule description, rationale, and metadata.NoteApart from
rule.yml, there are also three subdirectories in theaccounts_tmoutdirectory:-
bashcontains source code for a Bash script that can fix the timeout settings, also called "Bash remediation." -
ovalcontains source code for an OVAL check that checks if the timeout is set. -
testscontains test scenarios which are used to test checks and remediations of a rule.
-
-
To add Ansible tasks in this rule, you first create a new directory called
ansiblein the rule directory, at the same level as thebashandovaldirectories. Create a newansibledirectory and change into it:[... accounts_tmout]$ mkdir ansible [... ansible]$ cd ansible
-
Next, you create a new file in this directory that contains your Ansible task.
NoteIn
ComplianceAsCode, the file needs to have a specific name. You have two options:-
shared.ymlis an universal name, the "shared" in this context means that the task can be applied to any product—that is, any Linux distribution. -
product_id.yml, (for example,fedora.yml), can be used if the task is specific to a single Linux distribution and cannot be extended to other Linux distributions.
-
-
Because the interactive session timeout is not a specific feature of RHEL 8, but is handled the same way in most Linux distributions, you can name the file
shared.yml. Create a newshared.ymlfile in theansibledirectory and open it in the text editor.[... ansible]$ open shared.yml
-
Next, you start to write the Ansible content in this file. It is not in the format of an Ansible Playbook—instead, it uses a special format. It is a simple YAML file.
The first part of this file must be a header that helps the build system integrate the Ansible tasks with the SCAP content and also with the rule metadata.
Add the following content to the top of the
shared.ymlfile, including the#characters. If you want to copy and paste the text, you have to useCtrl+Vto paste it:# platform = multi_platform_all # reboot = false # strategy = restrict # complexity = low # disruption = low
Do not close the file yet.
NoteThe header contains optional metadata. The
platformandrebootfields have well-defined meanings:-
platformis a comma-separated list of products that the Ansible tasks are applicable to. It can be an operating system name such asRed Hat Enterprise Linux 8, or a wildcard string that matches multiple products—for example,multi_platform_rhel. Here we use the wildcard string,multi_platform_all, that matches all of the possible platforms. -
rebootspecifies if a reboot is needed to activate the settings. This can be eithertrueorfalse. Here, we signal that a reboot is not needed. This value is purely informational and setting it totruedoes not cause Ansible Automation to reboot the system.
The other fields are optional, and their meanings are fuzzier:
-
strategyis the method or approach for making the described fix. It is typically one of the following:configure,disable,enable,patch,restrict, orunknown. -
complexityis the estimated complexity or difficulty of applying the fix to the target. It can beunknown,low,medium, orhigh. -
disruptionis an estimate of the potential for disruption or operational degradation that the application of this fix imposes on the target. It can beunknown,low,medium, orhigh.
-
-
Now, you add an Ansible task or tasks for this rule below the header in
shared.yml. Add the following content at the end of theshared.ymlfile. Again, do not close the file just yet.- name: configure timeout lineinfile: create: yes dest: /etc/profile regexp: "^#?TMOUT" line: "TMOUT=600"At this point, expect the entire file to look like this:
# platform = multi_platform_all # reboot = false # strategy = restrict # complexity = low # disruption = low - name: configure timeout lineinfile: create: yes dest: /etc/profile regexp: "^#?TMOUT" line: "TMOUT=600"NoteIf you are familiar with Ansible Automation, you probably know that you just wrote an Ansible task. Normally, Ansible tasks are low-level components of Ansible Playbooks. The
ComplianceAsCodeproject allows content contributors to focus on tasks, and the playbook that aggregates them is generated by the project. When writing tasks, you can use the standard Ansible syntax and write the Ansible tasks the exact same way as you write in Ansible Playbooks. You can use any Ansible module.Using Ansible language, you have defined a new Ansible task with the name "configure timeout". It uses the lineinfile Ansible module, which can add, modify, and remove lines in configuration files. Using the
lineinfilemodule, you insert the lineTMOUT=600to/etc/profile.Note that the
regexpline defines a regular expression that determines what Ansible Automation is going to do. If the regular expression matches a line, it is substituted withline, so the linesTMOUT=1800and#TMOUT=600are replaced byTMOUT=600. If no line matches the regular expression, contents oflineare simply appended todest, which in this case is/etc/profile.In this rule, you add only a single Ansible task. If your goals need to be achieved by multiple Ansible tasks, they all go into the same file.
In
ComplianceAsCode, the general rule is that the Ansible tasks must conform to the rule description inrule.ymlfor the given rule. Tasks must not do anything different than what therule.ymldescription requires. Think of the rule description as a natural language specification of what needs to be implemented in Ansible Automation.
At this point, your task does not fully conform to the rule description in rule.yml.
The difference is that rule.yml does not define a specific value for the timeout.
-
Check that
rule.ymldoes not specify whether the timeout should be 600 seconds or a different amount of time. In fact, the rule is parameterized by a variable,var_accounts_tmout. The specific value for a timeout variable is set by settingvar_accounts_tmoutin the profile definition. This way, every profile can define a different timeout but still reuse the same source code.You need to fix the Ansible task to use the
var_accounts_tmoutvariable instead of explicitly setting 600 seconds in the task. The general format for binding a variable fromComplianceAsCodeprofiles is{{{ ansible_instantiate_variables("var_accounts_tmout") }}}. -
Add the following line right after the
# disruption = lowline in theshared.ymlfile:{{{ ansible_instantiate_variables("var_accounts_tmout") }}}Now, you can use the bound variable in the
configure timeoutAnsible task as an Ansible variable using the standard Ansible syntax. When theshared.ymlfile is processed by theComplianceAsCodebuild system, this variable binding is resolved automatically and a new Ansible variable is created in thevarslist in the generated playbook. -
Replace
line: "TMOUT=600"withline: "TMOUT={{ var_accounts_tmout }}"to use the variable in the task.At this point you have completed adding Ansible tasks for the
accounts_tmoutrule. Expect the contents of theshared.ymlfile to look like this:# platform = multi_platform_all # reboot = false # strategy = restrict # complexity = low # disruption = low {{{ ansible_instantiate_variables("var_accounts_tmout") }}} - name: configure timeout lineinfile: create: yes dest: /etc/profile regexp: ^#?TMOUT line: "TMOUT={{ var_accounts_tmout }}" -
You can now save the file by pressing
Ctrl+Sto save the file.
You now generate a playbook for the accounts_tmout rule you modified.
You do this in the context of the Red Hat® Enterprise Linux® 8 product and the OSPP profile for Red Hat® Enterprise Linux® 8.
To generate Ansible Playbooks, a complete build of the content for the product needs to be performed. That means that all of the other playbooks for all of the other rules are generated as well. Moreover, the SCAP content is also generated.
-
Go back to the project root directory and run the following command to build the RHEL 8 product:
[... ansible]$ cd /workspace/content [... ]$ ADDITIONAL_CMAKE_OPTIONS="-DSSG_ANSIBLE_PLAYBOOKS_PER_RULE_ENABLED=ON" ./build_product rhel8
-
The Playbooks are generated in the
build/rhel8/playbooksdirectory. Check the contents of this directory:[... ]$ ls build/rhel8/playbooks all anssi_bp28_high anssi_bp28_minimal cis_server_l1 cis_workstation_l2 cui hipaa ospp rht-ccp stig anssi_bp28_enhanced anssi_bp28_intermediary cis cis_workstation_l1 cjis e8 ism_o pci-dss standard stig_gui
Note that there is a directory for each profile in the RHEL8 product. That is because each profile consists of a different set of rules and the rules are parameterized by variables which can have different values in each profile.
-
The
accounts_tmoutrule is, for example, a part of the OSPP profile, so take a peek into theosppdirectory:[... ]$ ls build/rhel8/playbooks/ospp
There are many playbook files in the
osppdirectory. One of them is theaccounts_tmout.ymlfile, which is the Ansible Playbook that contains the Ansible tasks you added in theaccounts_tmoutrule. -
Open it in the text editor:
[... ]$ open build/rhel8/playbooks/ospp/accounts_tmout.yml
The contents of the
build/rhel8/playbooks/ospp/accounts_tmout.ymlfile look like this:# platform = multi_platform_all # reboot = false # strategy = restrict # complexity = low # disruption = low - name: Set Interactive Session Timeout hosts: '@@HOSTS@@' become: true vars: var_accounts_tmout: '600' tags: - CCE-80673-7 - NIST-800-171-3.1.11 - NIST-800-53-AC-12 - NIST-800-53-AC-2(5) - NIST-800-53-CM-6(a) - NIST-800-53-SC-10 - accounts_tmout - low_complexity - low_disruption - medium_severity - no_reboot_needed - restrict_strategy tasks: - name: configure timeout lineinfile: create: true dest: /etc/profile regexp: ^#?TMOUT line: TMOUT={{ var_accounts_tmout }}TipIf you see a typo in the YAML file, edit the source again and rebuild.
This is a normal Ansible Playbook that Ansible users are familiar with. The name of the playbook is the same as the title of the rule, which is defined in
rule.yml. -
The
hostssection contains only a placeholder string,'@@HOSTS@@', which needs to be replaced by a list of IP addresses or hosts that the playbook applies to. You have to edit this in order to check the playbook. To use your playbook on your environment (on a local host), replace'@@HOSTS@@'with'localhost'and pressCtrl+Sto save the file.[... ]$ open build/rhel8/playbooks/ospp/accounts_tmout.yml ... - name: Set Interactive Session Timeout hosts: 'localhost' become: true ...
Note that the timeout value supplied by the
var_accounts_tmoutvariable was set to a specific value (600 seconds) during the build process, and the variable was added to thevarssection of the playbook.Note also that the playbook has tags in the
tagssection that were added based on metadata inrule.yml. At the beginning, it contains the CCE (Common Configuration Enumeration) identifier. Finally, thetasks:section contains the Ansible task that you created. -
Run the playbook:
[... ]$ ansible-playbook build/rhel8/playbooks/ospp/accounts_tmout.yml
-
Check if it has any effect:
[... ]$ cat /etc/profile
Note that
TMOUT=600is at the end of the file!The biggest advantage of using Ansible tasks in
ComplianceAsCodeis that it gets integrated with the SCAP content, the HTML report, and the HTML guide as well. -
Navigate to the
build/guidesfolder.: -
Right click the
ssg-rhel8-guide-ospp.htmlfile and selectOpen with Live Serverto preview the file. Note: Your browser may block the pop-up. You must allow it when asked. -
A new tab opens and you can see your
OSPPprofile, which contains two rules. -
Check the "Set Interactive Session Timeout" rule. Click the blue
(show)link to the right of the green "Remediation Ansible snippet" label and you see your recently added Ansible content.
In the previous section, you learned about using a playbook for the accounts_tmout rule.
However, security policies are usually complex, which in turn means that profiles consist of many rules.
It is not convenient to have a separate Ansible Playbook for each rule, because that means you need to apply many Ansible Playbooks to the system.
Fortunately, ComplianceAsCode also generates Ansible Playbooks that contain all of the tasks for a given profile in a single playbook.
The playbooks are located in the build/ansible directory.
This directory contains Ansible Playbooks for each profile.
The Playbooks files have .yml extension.
[... ]$ ls build/ansible all-profile-playbooks-rhel8 rhel8-playbook-anssi_bp28_minimal.yml rhel8-playbook-cis.yml rhel8-playbook-hipaa.yml rhel8-playbook-rht-ccp.yml rhel8-playbook-anssi_bp28_enhanced.yml rhel8-playbook-cis_server_l1.yml rhel8-playbook-cjis.yml rhel8-playbook-ism_o.yml rhel8-playbook-standard.yml rhel8-playbook-anssi_bp28_high.yml rhel8-playbook-cis_workstation_l1.yml rhel8-playbook-cui.yml rhel8-playbook-ospp.yml rhel8-playbook-stig_gui.yml rhel8-playbook-anssi_bp28_intermediary.yml rhel8-playbook-cis_workstation_l2.yml rhel8-playbook-e8.yml rhel8-playbook-pci-dss.yml rhel8-playbook-stig.yml
-
Check the contents of the OSPP profile playbook in your editor and verify that a task for the
accounts_tmoutrule is there among all the other tasks.[... ]$ open build/ansible/rhel8-playbook-ospp.yml
At this point, you have per-rule Ansible Playbooks available, as well as per-profile ones. You can integrate these into your CI/CD pipelines and infrastructure management as needed.
