Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor Ansible remediations that search local file systems #10912

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,66 +4,13 @@
# complexity = low
# disruption = low

- name: "{{{ rule_title }}} - Define Excluded (Non-Local) File Systems and Paths"
{{{ ansible_create_list_of_local_paths(list_name="search_paths") }}}

- name: "{{{ rule_title }}} - Define Rule Specific Facts"
ansible.builtin.set_fact:
excluded_fstypes:
- afs
- ceph
- cifs
- smb3
- smbfs
- sshfs
- ncpfs
- ncp
- nfs
- nfs4
- gfs
- gfs2
- glusterfs
- gpfs
- pvfs2
- ocfs2
- lustre
- davfs
- fuse.sshfs
excluded_paths:
- dev
- proc
- run
- sys
search_paths: []
shosts_equiv_files:
- /shosts.equiv

- name: "{{{ rule_title }}} - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths"
ansible.builtin.find:
paths: /
file_type: directory
excludes: "{{ excluded_paths }}"
hidden: true
recurse: false
register: result_relevant_root_dirs

- name: "{{{ rule_title }}} - Include Relevant Root Directories in a List of Paths to be Searched"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.path]) }}"
loop: "{{ result_relevant_root_dirs.files }}"

- name: "{{{ rule_title }}} - Increment Search Paths List with Local Partitions Mount Points"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.mount]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.fstype not in excluded_fstypes
- item.mount != '/'

- name: "{{{ rule_title }}} - Increment Search Paths List with Local NFS File System Targets"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.device.split(':')[1]]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.device is search("localhost:")

- name: "{{{ rule_title }}} - Find All shosts.equiv Files in Local File Systems"
ansible.builtin.command:
cmd: find {{ item }} -xdev -type f -name "shosts.equiv"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@
# strategy = restrict
# complexity = low
# disruption = low
- name: "Find local mount points"
shell: |
set -o pipefail
df --local | awk '{print $6}' | grep -v Mounted | grep -v '^/dev' || true
register: local_mount_points

- name: "Detect the .shosts files on the system"
find:
paths: "{{ item }}"
recurse: yes
patterns: [".shosts"]
hidden: yes
file_type: "file"
check_mode: no
with_items: "{{ local_mount_points.stdout_lines }}"
register: shosts_locations
{{{ ansible_create_list_of_local_paths(list_name="search_paths") }}}

- name: "Remove .shosts Files"
file:
path: "{{ item.path }}"
state: absent
with_items: "{{ shosts_locations.results | map(attribute='files') | list }}"
when: shosts_locations is success
- name: "{{{ rule_title }}} - Define Rule Specific Facts"
ansible.builtin.set_fact:
user_shosts_files:
- /.shosts

- name: "{{{ rule_title }}} - Find All .shosts Files in Local File Systems"
ansible.builtin.command:
cmd: find {{ item }} -xdev -type f -name ".shosts"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will this be reported as not permitted shell command?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It is using the cmd module and the test only cares about shell module, so it won't be reported as an issue.

loop: "{{ search_paths }}"
changed_when: false
register: result_found_shosts_files

- name: "{{{ rule_title }}} - Create List of .shosts Files Present in Local File Systems"
ansible.builtin.set_fact:
user_shosts_files: '{{ user_shosts_files | union(item.stdout_lines) | list }}'
loop: "{{ result_found_shosts_files.results }}"

- name: "{{{ rule_title }}} - Ensure No .shosts Files Are Present in the System"
ansible.builtin.file:
path: '{{ item }}'
state: absent
loop: '{{ user_shosts_files }}'
Original file line number Diff line number Diff line change
Expand Up @@ -4,28 +4,16 @@
# complexity = low
# disruption = low

- name: Ensure SHA_CRYPT_MIN_ROUNDS has minimum value of 5000
replace:
- name: "{{{ rule_title }}} - Ensure SHA_CRYPT_MIN_ROUNDS has Minimum Value of 5000"
ansible.builtin.replace:
path: /etc/login.defs
regexp: '(^\s*SHA_CRYPT_MIN_ROUNDS\s+)(?!(?:[5-9]\d{3,}|\d{5,}))\S*(\s*$)'
replace: '\g<1>5000\g<2>'
backup: no

- name: Check to see if SHA_CRYPT_MIN_ROUNDS is explicitly configured
shell: |
set -o pipefail
grep -e '^\s*SHA_CRYPT_MIN_ROUNDS\s\+' /etc/login.defs || true
register: check_sha_crypt_min_rounds_result

# NOTE(gyee): there's a possibility that the value of SHA_CRYPT_MIN_ROUNDS is
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was the comment useful?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SHA_CRYPT_MIN_ROUNDS is specific for SHA-512-based passwords so it is not supported in all cases. In most of the cases (and distros) it is not expected to be set. I think the comments were unnecessary and also the case is now represented in test scenarios. IMO the comment won't be missed.

# greater than the value of SHA_CRYPT_MAX_ROUNDS. But as far as we're,
# concerned, this is not a problem as per login.defs,
# if SHA_CRYPT_MIN_ROUNDS > SHA_CRYPT_MAX_ROUNDS, the highest value will be
# used. In that case, we don't need to touch SHA_CRYPT_MAX_ROUNDS.
- name: Ensure SHA_CRYPT_MAX_ROUNDS has minimum value of 5000
replace:
- name: "{{{ rule_title }}} - Ensure SHA_CRYPT_MAX_ROUNDS has Minimum Value of 5000"
ansible.builtin.replace:
path: /etc/login.defs
regexp: '(^\s*SHA_CRYPT_MAX_ROUNDS\s+)(?!(?:[5-9]\d{3,}|\d{5,}))\S*(\s*$)'
replace: '\g<1>5000\g<2>'
backup: no
when: '"SHA_CRYPT_MIN_ROUNDS" not in check_sha_crypt_min_rounds_result.stdout'

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/bash

source common.sh

echo "SHA_CRYPT_MIN_ROUNDS 5000" > "/etc/login.defs"
echo "SHA_CRYPT_MAX_ROUNDS 5000" >> "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Default values are 5000 if the parameters are not defined.
echo "SHA_CRYPT_MIN_ROUNDS 5000" > "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Default values are 5000 if the parameters are not defined.
echo "SHA_CRYPT_MAX_ROUNDS 5000" > "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

# Default values are 5000 if the parameters are not defined.
truncate -s 0 "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

echo "SHA_CRYPT_MIN_ROUNDS 5000" > "/etc/login.defs"
echo "SHA_CRYPT_MAX_ROUNDS 4999" >> "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#!/bin/bash

source common.sh

echo "SHA_CRYPT_MIN_ROUNDS 4999" > "/etc/login.defs"
echo "SHA_CRYPT_MAX_ROUNDS 5000" >> "/etc/login.defs"
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/bash

echo "SHA_CRYPT_MIN_ROUNDS 4999" > "/etc/login.defs"
echo "SHA_CRYPT_MAX_ROUNDS 4999" >> "/etc/login.defs"
Original file line number Diff line number Diff line change
Expand Up @@ -4,64 +4,11 @@
# complexity = low
# disruption = medium

- name: "{{{ rule_title }}} - Define Excluded (Non-Local) File Systems and Paths"
ansible.builtin.set_fact:
excluded_fstypes:
- afs
- ceph
- cifs
- smb3
- smbfs
- sshfs
- ncpfs
- ncp
- nfs
- nfs4
- gfs
- gfs2
- glusterfs
- gpfs
- pvfs2
- ocfs2
- lustre
- davfs
- fuse.sshfs
excluded_paths:
- dev
- proc
- run
- sys
search_paths: []
world_writable_dirs: []

- name: "{{{ rule_title }}} - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths"
ansible.builtin.find:
paths: /
file_type: directory
excludes: "{{ excluded_paths }}"
hidden: true
recurse: false
register: result_relevant_root_dirs

- name: "{{{ rule_title }}} - Include Relevant Root Directories in a List of Paths to be Searched"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.path]) }}"
loop: "{{ result_relevant_root_dirs.files }}"

- name: "{{{ rule_title }}} - Increment Search Paths List with Local Partitions Mount Points"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.mount]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.fstype not in excluded_fstypes
- item.mount != '/'
{{{ ansible_create_list_of_local_paths(list_name="search_paths") }}}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that the fail of the test scenario world_writable_dir_on_nonlocal_fs.fail.sh on the CI is caused by the invocation of systemctl command in this scenario, which hits the problem that there is no Dbus in the container back end environment that we use in CI.

+ systemctl restart nfs-server
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

When executed local with a virtual machine back end the test is passing.

[jcerny@fedora scap-security-guide{pr/10912}]$ python3 tests/automatus.py rule --remediate-using ansible --libvirt qemu:///system ssgts_rhel9 dir_perms_world_writable_root_owned
Setting console output to log level INFO
INFO - The base image option has not been specified, choosing libvirt-based test environment.
INFO - Logging into /home/jcerny/work/git/scap-security-guide/logs/rule-custom-2023-07-27-1438/test_suite.log
INFO - xccdf_org.ssgproject.content_rule_dir_perms_world_writable_root_owned
INFO - Script world_writable_dir_on_nonlocal_fs.fail.sh using profile (all) OK
INFO - Script world_writable_dir_owned_by_uid_2.fail.sh using profile (all) OK
INFO - Script all_dirs_ok.pass.sh using profile (all) OK

I think the problem isn't related to the contents of this PR.


- name: "{{{ rule_title }}} - Increment Search Paths List with Local NFS File System Targets"
- name: "{{{ rule_title }}} - Define Rule Specific Facts"
ansible.builtin.set_fact:
search_paths: "{{ search_paths | union([item.device.split(':')[1]]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.device is search("localhost:")
world_writable_dirs: []

- name: "{{{ rule_title }}} - Find All Uncompliant Directories in Local File Systems"
ansible.builtin.command:
Expand Down
70 changes: 70 additions & 0 deletions shared/macros/10-ansible.jinja
Original file line number Diff line number Diff line change
Expand Up @@ -1670,3 +1670,73 @@ Part of the grub2_bootloader_argument_absent template.
{{%- macro ansible_mount_conditional(path) -%}}
'"{{{ path }}}" in ansible_mounts | map(attribute="mount") | list'
{{%- endmacro -%}}

{{#
Create a list of paths composed by root directories and mount points representing local file systems.
This list excludes all local directories and mount points using known remote file systems.
It also excludes local directories and mount points with pseudo file systems. The list of paths
created by this macro can be used to efficiently locate local files or directories in a system.

:param list_name: Prefered list name to be used in subsequent tasks.
:type pam_file: str

#}}
{{%- macro ansible_create_list_of_local_paths(list_name="search_paths") -%}}
- name: "{{{ rule_title }}} - Define Excluded (Non-Local) File Systems and Paths"
ansible.builtin.set_fact:
excluded_fstypes:
- afs
- ceph
- cifs
- smb3
- smbfs
- sshfs
- ncpfs
- ncp
- nfs
- nfs4
- gfs
- gfs2
- glusterfs
- gpfs
- pvfs2
- ocfs2
- lustre
- davfs
- fuse.sshfs
excluded_paths:
- dev
- proc
- run
- sys
{{{ list_name }}}: []

- name: "{{{ rule_title }}} - Find Relevant Root Directories Ignoring Pre-Defined Excluded Paths"
ansible.builtin.find:
paths: /
file_type: directory
excludes: "{{ excluded_paths }}"
hidden: true
recurse: false
register: result_relevant_root_dirs

- name: "{{{ rule_title }}} - Include Relevant Root Directories in a List of Paths to be Searched"
ansible.builtin.set_fact:
{{{ list_name }}}: "{{ {{{ list_name }}} | union([item.path]) }}"
loop: "{{ result_relevant_root_dirs.files }}"

- name: "{{{ rule_title }}} - Increment Search Paths List with Local Partitions Mount Points"
ansible.builtin.set_fact:
{{{ list_name }}}: "{{ {{{ list_name }}} | union([item.mount]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.fstype not in excluded_fstypes
- item.mount != '/'

- name: "{{{ rule_title }}} - Increment Search Paths List with Local NFS File System Targets"
ansible.builtin.set_fact:
{{{ list_name }}}: "{{ {{{ list_name }}} | union([item.device.split(':')[1]]) }}"
loop: '{{ ansible_mounts }}'
when:
- item.device is search("localhost:")
{{%- endmacro -%}}