Bug 1741455

Summary: Ansible playbooks for OSPP and PCI-DSS profiles exit after failure is encountered
Product: Red Hat Enterprise Linux 8 Reporter: Matus Marhefka <mmarhefk>
Component: scap-security-guideAssignee: Watson Yuuma Sato <wsato>
Status: CLOSED ERRATA QA Contact: Matus Marhefka <mmarhefk>
Severity: high Docs Contact: Jan Fiala <jafiala>
Priority: high    
Version: 8.1CC: ggasparb, jcerny, matyc, mhaicman, mjahoda, mlysonek, vpolasek
Target Milestone: rc   
Target Release: 8.1   
Hardware: Unspecified   
OS: Unspecified   
Whiteboard:
Fixed In Version: scap-security-guide-0.1.46-1.el8 Doc Type: Bug Fix
Doc Text:
.Ansible playbooks for OSPP and PCI-DSS profiles no longer exit after encountering a failure Previously, Ansible remediations for the Security Content Automation Protocol (OSPP) and the Payment Card Industry Data Security Standard (PCI-DSS) profiles failed due to incorrect ordering and other errors in the remediations. This update fixes the ordering and errors in generated Ansible remediation playbooks, and Ansible remediations now work correctly.
Story Points: ---
Clone Of: Environment:
Last Closed: 2019-11-05 21:17:09 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Matus Marhefka 2019-08-15 08:09:58 UTC
Description of problem:
Ansible playbooks for OSPP and PCI-DSS profiles shipped in the SSG package exit after failure is encountered.

Failure for the OSPP playbook run:
==========
...
TASK [Enable service fapolicyd] ************************************************
fatal: [192.168.122.24]: FAILED! => {"changed": false, "msg": "Could not find the requested service fapolicyd: host"}

PLAY RECAP *********************************************************************
192.168.122.24             : ok=25   changed=13   unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
==========


Failure for the PCI-DSS playbook run:
==========
...
TASK [enable syslog plugin] ****************************************************
fatal: [192.168.122.24]: FAILED! => {"changed": false, "msg": "Destination /etc/audit/plugins.d/syslog.conf does not exist !", "rc": 257}

PLAY RECAP *********************************************************************
192.168.122.24             : ok=8    changed=4    unreachable=0    failed=1    skipped=0    rescued=0    ignored=1  
==========


Version-Release number of selected component (if applicable):
scap-security-guide-0.1.45-2.el8.noarch


How reproducible:
always


Steps to Reproduce:
Run playbook using ansible-playbook.


Actual results:
Playbooks for both shipped profiles (OSPP and PCI-DSS) exit when a failure is encountered.


Expected results:
Playbooks for both shipped profiles (OSPP and PCI-DSS) finish without any errors and put system into the compliant state according to the remediations.

Comment 2 Jan Černý 2019-08-22 12:50:49 UTC
The problem with task "Enable service fapolicyd" is caused by the fact that the playbook is generated from a SCAP datastream. In the datastream, the rule service_fapolicyd_installed is before rule package_fapolicyd_installed. That means the task that enables the service is inserted into the playbook before the task that would install the RPM package which provides the service. Ansible tasks are executed always from the top to the bottom as they are defined in the playbook. That means at the moment the playbook tries to enable the service the service file is not found. The Ansible service module considers enabling a non-existing service a fatal error, so the attempt to enable the service leads to terminating the whole playbook run.

Ideally we should make sure that the task which enables the service is inserted to the playbook always before the task that installs the RPM  package which provides the service. Since our playbooks aren't written manually but generated from a SCAP datastream it essentially means that we should ensure the same order in SCAP datastream. However, the SCAP Security Guide build system doesn't support any rule ordering or rule dependencies at the moment. Every rule is considered a stand-alone unit. It seems that this approach isn't able to handle the common use-cases like enabling services from packages which are not installed by default.

As a mitigation of this problem, I have amended the template from which the Ansible tasks for enabling system services are generated. The task will check if the package which provides the service is present and the service will be enabled only if the service is present.
This fix has been submited to upstream in https://github.com/ComplianceAsCode/content/pull/4749
The same problem can affect also rules that enable systemd timers, so this PR amends both templates for services and templates for timers.
The patch should prevent the failures due to non-existent services. However, as a result, the users will have to run playbook at least 2 times to achieve a compliant state of the system.

The second problem reported by the reporter is caused by the fact that the given configuration file doesn't exist at the moment when the Ansible task is executed. I have created a patch in upstream in https://github.com/ComplianceAsCode/content/pull/4756 that proposes to create the file if it doesn't exist by using "create: yes" keyword from Ansible lineinfile module. The patch adds this keyword also to other Ansible tasks in the upstream repository that are missing it.





I have discovered another problem that is related to Ansible task which enables fapolicyd service. If fapolicyd package is already present before the ansible-playbook command is invoked, the service gets successfully enabled. But, that is the last task in playbook that is successful, and the next task always fails and terminates with the following error:

----8<----8<----8<----8<----8<----8<----
fatal: [localhost]: FAILED! => {"msg": "failed to transfer file to /root/.ansible/tmp/ansible-tmp-1566475092.171077-17672708694646/AnsiballZ_setup.py: [Errno 1] Operation not permitted: b'/root/.ansible/tmp/ansible-local-5312ufqw4bxf/tmpu7qy5tlt'"}
----8<----8<----8<----8<----8<----8<----

Enabling fapolicyd service disables any execution of any further ansible task or playbook.
I think that is because the default fapolicyd policy  denies Ansible access.
The offending fapolicyd rule seems to be `deny_audit  all ftype=text/x-python` on line 38 in /etc/fapolicyd/fapolicyd.rules. This rule denies all processes access to mime type text/python files. Commenting out this rule and restarting the fapolicyd service enables Ansible playbooks again.

We can do one of the following:
- Submit a bug against the default fapolicyd policy so that they allow executing Ansible playbooks.
- Remove the task that enables fapolicyd from our Playbooks
- Add a rule that modifies the fapolicyd policy to the Playbooks (but as I mentioned before currently we can't guarantee that this will get executed before the task that enables the fapolicyd service is executed)

Comment 3 Watson Yuuma Sato 2019-08-22 13:09:55 UTC
Thank you for the investigation and report, Jan.

Do I assume correctly that when remediating with Bash, or with --remediate, fapolicyd doesn't block the bash script nor oscap?

Comment 6 Jan Černý 2019-08-28 14:12:49 UTC
The problem with default fapolicyd policy has been reported to them in https://bugzilla.redhat.com/show_bug.cgi?id=1746464

Comment 7 Jan Černý 2019-08-28 14:15:36 UTC
Fapolicyd doesn't seem to affect oscap scan results for the OSPP profile, I have tried to run scan of OSPP using datastream built from current upstream master on 2 RHEL 8.1 VMs - one with fapolicyd running and second with fapolicyd disabled - and the results are identical (obviously except rule service_fapolicyd_enabled).

Comment 8 Jan Černý 2019-08-29 08:38:34 UTC
There is another fix needed, because after applying PRs mentioned in comment 2 (https://github.com/ComplianceAsCode/content/pull/4749 and https://github.com/ComplianceAsCode/content/pull/4756) a new issue is uncoevered:

TASK [Read files with incorrect hash] ******************************************
fatal: [192.168.122.248]: FAILED! => {"changed": false, "cmd": "set -o pipefail\nrpm -Va | grep -E '^..5.* /(bin|sbin|lib|lib64|usr)/' | awk '{print $NF}'\n", "delta": "0:00:09.943420", "end": "2019-08-26 09:44:51.612218", "msg": "non-zero return code", "rc": 1, "start": "2019-08-26 09:44:41.668798", "stderr": "", "stderr_lines": [], "stdout": "", "stdout_lines": []}


This issue has been fixed in upstream in:
https://github.com/ComplianceAsCode/content/pull/4766

Comment 9 Jan Černý 2019-08-29 08:39:17 UTC
Ansible remediation for rule service_fapolicyd_enabled is removed in https://github.com/ComplianceAsCode/content/pull/4774

Comment 10 Watson Yuuma Sato 2019-09-02 20:10:15 UTC
Fix for rpm_verify_hashes done in https://github.com/ComplianceAsCode/content/pull/4766 is incorrect.
PR https://github.com/ComplianceAsCode/content/pull/4785 is the appropriate fix.

Comment 20 errata-xmlrpc 2019-11-05 21:17:09 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory, and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2019:3453