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

feat: several role improvements #8

Merged
merged 2 commits into from
Dec 6, 2023
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
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ ansible-galaxy collection install -vv -r meta/collection-requirements.yml

### fapolicyd_setup_enable_service

Default `false` - if set to `true` the variable makes the service started
and enabled fapolicyd service after successful deployment.
Default `true` - if set to `false` the variable makes the service stopped
and disabled.

### fapolicyd_setup_trust

Expand Down
17 changes: 8 additions & 9 deletions defaults/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,24 @@
# Enable or disable service after configuration
# to allow testing and verification before use.
# NB. See ima_evm_setup if planning to use IMA.
fapolicyd_setup_enable_service: false
fapolicyd_setup_enable_service: true

# trust list for fapolicyd configuration file
# default "rpmdb,file"
fapolicyd_setup_trust: "{{ '' if ansible_facts.distribution_version is
version('8.2', '<=') else 'rpmdb,file' }}"
fapolicyd_setup_trust: "{{ '' if __fapolicyd_trust_supported
else 'rpmdb,file' }}"

# set integrity
# default "none"
# can be "none", "size", "sha256", "ima"
# in case of ima, kernel's IMA has to be setup correctly
fapolicyd_setup_integrity: "{{ '' if ansible_facts.distribution_version is
version('8.3', '<=') else 'none' }}"
fapolicyd_setup_integrity: "{{ '' if __fapolicyd_integrity_supported
else 'none' }}"

# set permissive mode
fapolicyd_setup_permissive: false

# fapolicyd trust file managament
# fapolicyd trust file management
# list of trusted files

fapolicyd_add_trusted_file: "{{ '' if ansible_facts.distribution_version is
version('8.2', '<=') else [] }}"
fapolicyd_add_trusted_file: "{{ '' if __fapolicyd_trustfiles_supported
else [] }}"
1 change: 0 additions & 1 deletion examples/simple.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
- name: Example fapolicyd role invocation
hosts: all
vars:
fapolicyd_setup_enable_service: true
fapolicyd_setup_integrity: sha256
fapolicyd_setup_trust: rpmdb,file
fapolicyd_add_trusted_file:
Expand Down
114 changes: 81 additions & 33 deletions tasks/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
- Only Enterprise Linux >= 8.1 and Fedora are supported
- System - {{ ansible_facts.os_family }}
- Version - {{ ansible_facts.distribution_version }}
when: (ansible_facts.os_family != "RedHat") or
(ansible_facts.distribution_version is version("8.1", "<"))
when: not __fapolicyd_supported

- name: Check trust compatibility
fail:
Expand All @@ -19,7 +18,7 @@
ignore_errors: true
when:
- fapolicyd_setup_trust | length > 0
- ansible_facts.distribution_version is version("8.2", "<=")
- not __fapolicyd_trust_supported
register: __failed_check_trust

- name: Check integrity compatibility
Expand All @@ -30,7 +29,7 @@
ignore_errors: true
when:
- fapolicyd_setup_integrity | length > 0
- ansible_facts.distribution_version is version("8.3", "<=")
- not __fapolicyd_integrity_supported
register: __failed_check_integrity

- name: Check trust files compatibility
Expand All @@ -41,7 +40,7 @@
ignore_errors: true
when:
- fapolicyd_add_trusted_file | length > 0
- ansible_facts.distribution_version is version("8.3", "<=")
- not __fapolicyd_trustfiles_supported
register: __failed_check_trusted_file

- name: Check failed conditions
Expand All @@ -52,18 +51,13 @@

- name: Install fapolicyd packages
package:
name: "{{ __fapolicyd_packages }}"
name: "{{ __pkgs }}"
state: present
use: "{{ (__fapolicyd_is_ostree | d(false)) |
ternary('ansible.posix.rhel_rpm_ostree', omit) }}"

- name: Install fapolicyd-selinux packages
package:
name: "{{ __fapolicyd_selinux_packages }}"
state: present
use: "{{ (__fapolicyd_is_ostree | d(false)) |
ternary('ansible.posix.rhel_rpm_ostree', omit) }}"
when: ansible_facts.distribution_version is version("8.3", ">=")
vars:
__pkgs: "{{ __fapolicyd_packages + (__fapolicyd_selinux_packages
if __fapolicyd_selinux_supported else []) }}"

- name: Copy fapolicyd configuration file
template:
Expand All @@ -79,39 +73,93 @@
check_mode: false
changed_when: false
when:
- ansible_facts.distribution_version is version("8.6", ">=")
- __fapolicyd_configcheck_supported | bool
- __fapolicy_conf is changed

- name: Trustdb cleanup
command: fapolicyd-cli --file delete /
when: ansible_facts.distribution_version is version("8.3", ">=")
changed_when: true
failed_when: false

- name: Add file to trustdb
command: fapolicyd-cli --file add {{ item | quote }}
loop: "{{ (fapolicyd_add_trusted_file is string) |
ternary([fapolicyd_add_trusted_file], fapolicyd_add_trusted_file) }}"
when:
- fapolicyd_add_trusted_file | length > 0
- ansible_facts.distribution_version is version("8.3", ">=")
changed_when: true

- name: Start fapolicyd service
service:
name: "{{ __fapolicyd_services }}"
state: restarted
state: started
enabled: true
when: fapolicyd_setup_enable_service | bool
ignore_errors: true
register: __fapolicyd_start

- name: Restart fapolicyd service
service:
name: "{{ __fapolicyd_services }}"
state: restarted
enabled: true
when:
- fapolicyd_setup_enable_service | bool
- __fapolicy_conf is changed
ignore_errors: true
register: __fapolicyd_restart

- name: Check fapolicyd logs
command: journalctl -n5 -u {{ __fapolicyd_services | quote }}
register: __fapolicyd_results
changed_when: false
when: __fapolicyd_restart is failed
failed_when: __fapolicyd_restart is failed
when: __fapolicyd_start is failed or __fapolicyd_restart is failed
failed_when: __fapolicyd_start is failed or __fapolicyd_restart is failed

- name: Trustdb cleanup
command: fapolicyd-cli --file delete /
changed_when: true
failed_when: false

- name: Add file to trustdb
command: fapolicyd-cli --file add {{ item | quote }}
loop: "{{ (fapolicyd_add_trusted_file is string) |
ternary([fapolicyd_add_trusted_file], fapolicyd_add_trusted_file) }}"
when: item | length > 0
changed_when: true

# The problem is that there is a race condition between calling `systemctl
# restart fapolicyd`` and when fapolicyd will actually enforce the policy - so
# we have to look for the right string in the fapolicyd logs. Also - I don't
# think we can move this into a script, because that script might be excluded by
# policy!
# NOTE: I tried using `fapolicyd-cli --update` as recommended by the
# documentation but it does not seem to work in all cases e.g. on RHEL 8.8 if
# you are deleting entries but not adding entries, it seems to do nothing - the
# only reliable way to update the trustdb is to restart the daemon and check for
# "fapolicyd[...]: Starting to listen for events" in the journald output
- name: Update fapolicyd db
when: fapolicyd_setup_enable_service | bool
shell:
cmd: |
set -euo pipefail
# get current journal cursor
cursor=""
while [ -z "$cursor" ]; do
sleep 1
cursor="$(journalctl -u fapolicyd -n 0 --show-cursor |
awk '/^-- cursor:/ {print $3}')" || :
done
systemctl restart fapolicyd
search_str='fapolicyd[^:\ ]*:\ Starting to listen for events$'
# wait until we see the search_str - wait up to 30 seconds
waittime=30 # seconds
endtime="$(expr "$(date +%s)" + "$waittime")"
set +o pipefail # the read will always return a failure code at EOF
journalctl -u fapolicyd --no-tail -f --after-cursor "$cursor" | \
while read -r line; do
if [[ "$line" =~ $search_str ]]; then
echo INFO: trustdb is updated
exit 0
fi
done & pid=$!
while ps -p "$pid"; do
if [ "$(date +%s)" -gt "$endtime" ]; then
echo ERROR: failed to update the trustdb
exit 1
fi
sleep 1
done
echo INFO: trustdb is updated
exit 0 # success
changed_when: true

- name: Making sure fapolicyd does not run if it was set so
service:
Expand Down
32 changes: 32 additions & 0 deletions tasks/set_vars.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,35 @@
vars:
__vars_file: "{{ role_path }}/vars/{{ item }}"
when: __vars_file is file

# fapolicyd only supported on EL
# NOTE - some RedHat os_family like CentOS stream and Fedora
# only have major version - in that case, assume the version is
# compatible with the highest released minor version of the
# major version e.g. CentOS stream 8 is the same as EL 8.9
# or higher
- name: Set fapolicyd feature facts for OS versions
vars:
# use temp vars for readability
__major_ver: "{{ ansible_facts['distribution_major_version'] }}"
__ver: "{{ ansible_facts['distribution_version'] }}"
__distro_ver: "{{ (__major_ver == __ver) |
ternary(__major_ver ~ '.9999', __ver) }}"
__is_redhat: "{{ ansible_facts['os_family'] == 'RedHat' }}"
set_fact:
__fapolicyd_supported: "{{ __is_redhat and
__distro_ver is version('8.1', '>=') }}"
__fapolicyd_trust_supported: "{{ __is_redhat and
__distro_ver is version('8.3', '>=') }}"
__fapolicyd_integrity_supported: "{{ __is_redhat and
__distro_ver is version('8.4', '>=') }}"
__fapolicyd_trustfiles_supported: "{{ __is_redhat and
__distro_ver is version('8.4', '>=') }}"
__fapolicyd_selinux_supported: "{{ __is_redhat and
__distro_ver is version('8.3', '>=') }}"
__fapolicyd_configcheck_supported: "{{ __is_redhat and
__distro_ver is version('8.6', '>=') }}"
__fapolicyd_watch_fs_supported: "{{ __is_redhat and
__distro_ver is version('8.2', '>=') }}"
__fapolicyd_syslog_format_supported: "{{ __is_redhat and
__distro_ver is version('8.3', '>=') }}"
4 changes: 2 additions & 2 deletions templates/fapolicyd.conf.j2
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ detailed_report = 1
db_max_size = 50
subj_cache_size = 1549
obj_cache_size = 8191
{% if ansible_facts.distribution_version is version("8.2", ">=") %}
{% if __fapolicyd_watch_fs_supported %}
watch_fs = ext2,ext3,ext4,tmpfs,xfs,vfat,iso9660,btrfs
{% endif %}

{% if fapolicyd_setup_trust | length > 0 %}
trust = {{ fapolicyd_setup_trust }}
{% endif %}

{% if ansible_facts.distribution_version is version("8.3", ">=") %}
{% if __fapolicyd_syslog_format_supported %}
syslog_format = rule,dec,perm,auid,pid,exe,:,path,ftype,trust
{% endif %}

Expand Down
Loading