OpenScap
https://www.open-scap.org/tools/scap-workbench/
https://github.com/OpenSCAP/scap-workbench
# Install
[root@rhel9 scap-workbench-1.2.1]# subscription-manager repos \
--enable=codeready-builder-for-rhel-9-x86_64-rpms \
&& dnf install scap-security-guide openscap-scanner -y
[root@rhel9 scap-workbench-1.2.1]# oscap --help
# Initial scan without fixing
sudo oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis \
--results scan-xccdf-results.xml \
--report scan-xccdf-results.html \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Initial scan with fixing the failed items
sudo oscap xccdf eval \
--remediate \ # Be careful with this
--profile xccdf_org.ssgproject.content_profile_cis \
--results scan-xccdf-results.xml \
--report scan-xccdf-results.html \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml # based on system(pkg scap-security-guide provide)
# Initial scan with fixing and skip some items
sudo oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis \
--results scan-xccdf-results.xml \
--report scan-xccdf-results.html \
--remediate \
--skip-rule xccdf_org.ssgproject.content_rule_partition_for_var_log \
--skip-rule xccdf_org.ssgproject.content_rule_accounts_umask_etc_bashrc \
--skip-rule xccdf_org.ssgproject.content_rule_accounts_umask_etc_login_defs \
--skip-rule xccdf_org.ssgproject.content_rule_accounts_umask_etc_profile \
--skip-rule xccdf_org.ssgproject.content_rule_service_firewalld_enabled \
--skip-rule xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_restricted \
--skip-rule xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_trusted \
--skip-rule xccdf_org.ssgproject.content_rule_sysctl_net_ipv4_ip_forward \
--skip-rule xccdf_org.ssgproject.content_rule_selinux_not_disabled \
--skip-rule xccdf_org.ssgproject.content_rule_selinux_state \
--skip-rule xccdf_org.ssgproject.content_rule_sshd_set_keepalive \
--skip-rule xccdf_org.ssgproject.content_rule_sshd_limit_user_access \
--skip-rule xccdf_org.ssgproject.content_rule_sshd_set_max_sessions \
--skip-rule xccdf_org.ssgproject.content_rule_audit_rules_privileged_commands \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_disk_full_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action \
--skip-rule xccdf_org.ssgproject.content_rule_sudo_require_authentication \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Initial scan with fixing and skip some items
sudo oscap xccdf eval \
--profile xccdf_org.ssgproject.content_profile_cis \
--results scan-xccdf-results.xml \
--report scan-xccdf-results.html \
--remediate \
--skip-rule xccdf_org.ssgproject.content_rule_sudo_require_authentication \
--skip-rule xccdf_org.ssgproject.content_rule_service_firewalld_enabled \
--skip-rule xccdf_org.ssgproject.content_rule_selinux_not_disabled \
--skip-rule xccdf_org.ssgproject.content_rule_selinux_state \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_disk_full_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action \
--skip-rule xccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action \
--skip-rule xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_restricted \
--skip-rule xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_trusted \
/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml
# Scan multiple servers with ansible
[work@az-dxb-nl-rh-uat-jump01 ~]$ vim openscan.yml
[work@az-dxb-nl-rh-uat-jump01 ~]$ cat openscan.yml
---
- name: Run OpenSCAP scan on all servers and save reports on control node
hosts: all
become: true
become_user: root
remote_user: work
vars:
report_dir: /tmp
local_report_dir: "/home/work/openscap_reports"
scap_datastream: "/usr/share/xml/scap/ssg/content/ssg-rhel9-ds.xml"
scap_profile: "xccdf_org.ssgproject.content_profile_cis"
skip_rules:
- xccdf_org.ssgproject.content_rule_partition_for_var_log
- xccdf_org.ssgproject.content_rule_accounts_umask_etc_bashrc
- xccdf_org.ssgproject.content_rule_accounts_umask_etc_login_defs
- xccdf_org.ssgproject.content_rule_accounts_umask_etc_profile
- xccdf_org.ssgproject.content_rule_service_firewalld_enabled
- xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_restricted
- xccdf_org.ssgproject.content_rule_firewalld_loopback_traffic_trusted
- xccdf_org.ssgproject.content_rule_sysctl_net_ipv4_ip_forward
- xccdf_org.ssgproject.content_rule_selinux_not_disabled
- xccdf_org.ssgproject.content_rule_selinux_state
- xccdf_org.ssgproject.content_rule_sshd_set_keepalive
- xccdf_org.ssgproject.content_rule_sshd_limit_user_access
- xccdf_org.ssgproject.content_rule_sshd_set_max_sessions
- xccdf_org.ssgproject.content_rule_audit_rules_privileged_commands
- xccdf_org.ssgproject.content_rule_auditd_data_disk_full_action
- xccdf_org.ssgproject.content_rule_auditd_data_retention_admin_space_left_action
- xccdf_org.ssgproject.content_rule_auditd_data_retention_max_log_file_action
- xccdf_org.ssgproject.content_rule_sudo_require_authentication
- xccdf_org.ssgproject.content_rule_auditd_data_retention_space_left_action
tasks:
- name: Gather installed package facts
ansible.builtin.package_facts:
manager: auto
- name: Ensure openscap-scanner is installed
ansible.builtin.package:
name: openscap-scanner
state: present
when: "'openscap-scanner' not in ansible_facts.packages"
- name: Ensure scap-security-guide is installed
ansible.builtin.package:
name: scap-security-guide
state: present
when: "'scap-security-guide' not in ansible_facts.packages"
- name: Clean previous OpenSCAP reports from remote /tmp
ansible.builtin.file:
path: "{{ item }}"
state: absent
loop:
- "{{ report_dir }}/scan-xccdf-results.html"
- "{{ report_dir }}/scan-xccdf-results.xml"
- name: Build OpenSCAP command dynamically
ansible.builtin.set_fact:
openscap_command: >-
oscap xccdf eval
--remediate
--profile {{ scap_profile }}
{% for rule in skip_rules %}
--skip-rule {{ rule }}
{% endfor %}
--report {{ report_dir }}/scan-xccdf-results.html
--results {{ report_dir }}/scan-xccdf-results.xml
{{ scap_datastream }}
- name: Run OpenSCAP scan with skip rules
ansible.builtin.command: "{{ openscap_command }}"
args:
creates: "{{ report_dir }}/scan-xccdf-results.html"
register: scan_output
failed_when: scan_output.rc not in [0, 2]
- name: Ensure local report directory exists on control node
delegate_to: localhost
become: false
ansible.builtin.file:
path: "{{ local_report_dir }}"
state: directory
mode: '0755'
- name: Fetch HTML report to control node
become: false
ansible.builtin.fetch:
src: "{{ report_dir }}/scan-xccdf-results.html"
dest: "{{ local_report_dir }}/{{ inventory_hostname }}-report.html"
flat: yes
- name: Print OpenSCAP scan summary
debug:
var: scan_output.stdout_lines
[work@az-dxb-nl-rh-uat-jump01 ~]$ ansible-playbook openscan.yml
[work@az-dxb-nl-rh-uat-jump01 ~]$ ll ./openscap_reports
