ComplianceAsCode / content

Security automation content in SCAP, Bash, Ansible, and other formats

Home Page:https://complianceascode.readthedocs.io/en/latest/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

mount_option_boot_nosuid fails to remediate with Ansible

vojtapolasek opened this issue · comments

Description of problem:

Remdiation of the rule mount_option_boot_nosuid does not happen because it gets skipped due to conditionals. But the scan after the remediation marks this rule as failing. That suggests that the remediation should happen.

Here is the relevant output from the Ansible playbook. This happens on RHEL 9.4 when anssi_bp28_high profile is selected:

TASK [Add nosuid Option to /boot: Check information associated to mountpoint] ***
ok: [localhost] => {"changed": false, "cmd": ["findmnt", "--fstab", "/boot"], "delta": "0:00:00.003191", "end": "2024-05-01 16:16:36.176566", "failed_when_result": false, "msg": "", "rc": 0, "start": "2024-05-01 16:16:36.173375", "stderr": "", "stderr_lines": [], "stdout": "TARGET SOURCE                                    FSTYPE OPTIONS\n/boot  UUID=14449e35-73b5-4911-b886-8f4e20a75b29 xfs    defaults,noexec", "stdout_lines": ["TARGET SOURCE                                    FSTYPE OPTIONS", "/boot  UUID=14449e35-73b5-4911-b886-8f4e20a75b29 xfs    defaults,noexec"]}

TASK [Add nosuid Option to /boot: Create mount_info dictionary variable] *******
ok: [localhost] => (item=['target', '/boot']) => {"ansible_facts": {"mount_info": {"fstype": "xfs", "options": "defaults,noexec", "source": "UUID=14449e35-73b5-4911-b886-8f4e20a75b29", "target": "/boot"}}, "ansible_loop_var": "item", "changed": false, "item": ["target", "/boot"]}
ok: [localhost] => (item=['source', 'UUID=14449e35-73b5-4911-b886-8f4e20a75b29']) => {"ansible_facts": {"mount_info": {"fstype": "xfs", "options": "defaults,noexec", "source": "UUID=14449e35-73b5-4911-b886-8f4e20a75b29", "target": "/boot"}}, "ansible_loop_var": "item", "changed": false, "item": ["source", "UUID=14449e35-73b5-4911-b886-8f4e20a75b29"]}
ok: [localhost] => (item=['fstype', 'xfs']) => {"ansible_facts": {"mount_info": {"fstype": "xfs", "options": "defaults,noexec", "source": "UUID=14449e35-73b5-4911-b886-8f4e20a75b29", "target": "/boot"}}, "ansible_loop_var": "item", "changed": false, "item": ["fstype", "xfs"]}
ok: [localhost] => (item=['options', 'defaults,noexec']) => {"ansible_facts": {"mount_info": {"fstype": "xfs", "options": "defaults,noexec", "source": "UUID=14449e35-73b5-4911-b886-8f4e20a75b29", "target": "/boot"}}, "ansible_loop_var": "item", "changed": false, "item": ["options", "defaults,noexec"]}

TASK [Add nosuid Option to /boot: If /boot not mounted, craft mount_info manually] ***
skipping: [localhost] => (item=['target', '/boot'])  => {"ansible_loop_var": "item", "changed": false, "item": ["target", "/boot"], "skip_reason": "Conditional result was False"}
skipping: [localhost] => (item=['source', ''])  => {"ansible_loop_var": "item", "changed": false, "item": ["source", ""], "skip_reason": "Conditional result was False"}
skipping: [localhost] => (item=['fstype', ''])  => {"ansible_loop_var": "item", "changed": false, "item": ["fstype", ""], "skip_reason": "Conditional result was False"}
skipping: [localhost] => (item=['options', 'defaults'])  => {"ansible_loop_var": "item", "changed": false, "item": ["options", "defaults"], "skip_reason": "Conditional result was False"}
skipping: [localhost] => {"changed": false, "msg": "All items skipped"}

TASK [Add nosuid Option to /boot: Make sure nosuid option is part of the to /boot options] ***
ok: [localhost] => (Redacted by Contest)

TASK [Add nosuid Option to /boot: Ensure /boot is mounted with nosuid option] ***
changed: [localhost] => {"backup_file": "", "boot": "yes", "changed": true, "dump": "0", "fstab": "/etc/fstab", "fstype": "xfs", "name": "/boot", "opts": "defaults,noexec,nosuid", "passno": "0", "src": "UUID=14449e35-73b5-4911-b886-8f4e20a75b29"}

SCAP Security Guide Version:

Stabilization-v0.1.73, commit 0b096bc

Operating System Version:

RHEL 8 and 9

Steps to Reproduce:

1.remediate anssi_bp28_high or stig through Ansible playbook
2.perform oscap scan of the same profile

Actual Results:

rule mount_option_boot_nosuid remediation is skipped but in the end the rule is reported as failed

Expected Results:

The remediation is performed correctly and the final scan shows rule as passing.

Additional Information/Debugging Steps:

Note that for ANSSI High profile, the similar thing happens for the rule mount_option_boot_noexec.

From the Ansible output above we can see that only one task of the tasks was skipped and that was the one where the mount_info Ansible fact is created manually if it doesn't exist. But as we can see from the task right above the skipped task the mount_info fact exists in this case, and we can see that the task that actually contains the mount module invocation which is the last task in the output has been executed and ended in the changed state. So I think the remediation actually isn't skipped and even could be performed correctly.

We need to investigate if there is any interference of other tasks with this rules's tasks or anything happening between the time of remediation and a new scan.

I thinkt that the Ansible Tasks for the rule mount_option_boot_nosuid are in conflict with Ansible Task remediating rule mount_option_nodev_nonroot_local_partitions which is executed after them.

I have done an experiment in which I have removed mount_option_nodev_nonroot_local_partitions from the anssi controls file and rebuild content and executed the given contest test in a lab environment using this command:

tmt -c distro=rhel-9 run -vvva -e CONTEST_CONTENT=/root/content plans -n /plans/default provision -h connect -k ~/.ssh/id_rsa -u root -g $HOSTNAME  discover -h fmf -t /hardening/host-os/ansible/anssi_bp28_high report

In this experiment the rule mount_option_boot_nosuid is passing in the final scan.

Could it be that the Ansible Task for mount_option_nodev_nonroot_local_partitions reinserts the originally gathered ansible_facts but the reality changed meanwhile so it reinserts the original options?

Look to the beaker output in the original run:


TASK [Ensure non-root local partitions are mounted with nodev option] **********
skipping: [localhost] => (item={'mount': '/', 'device': '/dev/mapper/rhel_scap--t9-root', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'size_total': 37558423552, 'size_available': 34363658240, 'block_size': 4096, 'block_total': 9169537, 'block_available': 8389565, 'block_used': 779972, 'inode_total': 18348032, 'inode_available': 18298009, 'inode_used': 50023, 'uuid': 'e293e634-45dd-4d94-b7b4-39592fdcf8d0'})  => {"ansible_loop_var": "item", "changed": false, "false_condition": "item.mount is match('/\\w')", "item": {"block_available": 8389565, "block_size": 4096, "block_total": 9169537, "block_used": 779972, "device": "/dev/mapper/rhel_scap--t9-root", "fstype": "xfs", "inode_available": 18298009, "inode_total": 18348032, "inode_used": 50023, "mount": "/", "options": "rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota", "size_available": 34363658240, "size_total": 37558423552, "uuid": "e293e634-45dd-4d94-b7b4-39592fdcf8d0"}, "skip_reason": "Conditional result was False"}
changed: [localhost] => (item={'mount': '/boot', 'device': '/dev/vda1', 'fstype': 'xfs', 'options': 'rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota', 'size_total': 1063256064, 'size_available': 824438784, 'block_size': 4096, 'block_total': 259584, 'block_available': 201279, 'block_used': 58305, 'inode_total': 524288, 'inode_available': 523978, 'inode_used': 310, 'uuid': '6ff757af-96dd-4022-aa8a-a5c79ca8dad0'}) => {"ansible_loop_var": "item", "backup_file": "", "boot": "yes", "changed": true, "dump": "0", "fstab": "/etc/fstab", "fstype": "xfs", "item": {"block_available": 201279, "block_size": 4096, "block_total": 259584, "block_used": 58305, "device": "/dev/vda1", "fstype": "xfs", "inode_available": 523978, "inode_total": 524288, "inode_used": 310, "mount": "/boot", "options": "rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota", "size_available": 824438784, "size_total": 1063256064, "uuid": "6ff757af-96dd-4022-aa8a-a5c79ca8dad0"}, "name": "/boot", "opts": "rw,seclabel,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota,nodev", "passno": "0", "src": "/dev/vda1"}

In the latest runs, this still seems to be an issue.

There is a similar issue with image builder on this rule as well.

Is there a possibility they are related?

I can confirm the issue with the rule appears now in Imagebuilder tests during daily productization.

I created a different issue to track the problem with Imagebuilder. This issue was originally about Ansible remediation of the rule, Imagebuilder uses Bash remediation.
The new issue is https://github.com/ComplianceAsCode/content/issues/11996I can confirm the issue with the rule appears now in Imagebuilder tests during daily productization.