diff --git a/.ansible-lint b/.ansible-lint index 44e6589..f197168 100644 --- a/.ansible-lint +++ b/.ansible-lint @@ -18,6 +18,7 @@ skip_list: - '306' - '602' - '208' + - 'tag[no-duplicate]' use_default_rules: true rulesdir: - ./rules/ diff --git a/.github/workflows/devel_pipeline_validation.yml b/.github/workflows/devel_pipeline_validation.yml index afe85e0..10750a2 100644 --- a/.github/workflows/devel_pipeline_validation.yml +++ b/.github/workflows/devel_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - devel + - benchmark* paths: - '**.yml' - '**.sh' @@ -70,7 +71,6 @@ echo IAC_BRANCH=main >> $GITHUB_ENV fi - # Pull in terraform code for linux servers - name: Clone GitHub IaC plan uses: actions/checkout@v4 diff --git a/.github/workflows/main_pipeline_validation.yml b/.github/workflows/main_pipeline_validation.yml index ab11c37..6792a00 100644 --- a/.github/workflows/main_pipeline_validation.yml +++ b/.github/workflows/main_pipeline_validation.yml @@ -7,6 +7,7 @@ types: [opened, reopened, synchronize] branches: - main + - latest paths: - '**.yml' - '**.sh' @@ -23,6 +24,7 @@ # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: + # This workflow contains a single job that tests the playbook playbook-test: # The type of runner that the job will run on diff --git a/Changelog.md b/Changelog.md index 8679f41..fc462b5 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,6 @@ # Changes to RHEL8STIG -## 3.4 STIG v2r1 +## 4.0.0 STIG v2r1 RuleIDs updated for all controls Nist Control ID associations added @@ -16,7 +16,9 @@ Nist Control ID associations added - RHEL-08-040370 - RHEL-08-010001 - removed as not a NIST value -Min OS version updated to 8.10 +Min OS version updated to 2.10 + +workflow updates ## 3.3 STIG V1R14 diff --git a/defaults/main.yml b/defaults/main.yml index 4e56319..fcb463f 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -55,6 +55,10 @@ rhel8stig_skip_reboot: true # Defined will change if control requires change_requires_reboot: false +# Create managed not custom local_facts files +create_benchmark_facts: true +ansible_facts_path: /etc/ansible/facts.d + ########################################### ### Goss is required on the remote host ### ### vars/auditd.yml for other settings ### @@ -69,11 +73,7 @@ audit_run_heavy_tests: true ## Only run Audit do not remediate audit_only: false -### As part of audit_only ### -# This will enable files to be copied back to control node in audit_only mode -fetch_audit_files: false -# Path to copy the files to will create dir structure in audit_only mode -audit_capture_files_dir: /some/location to copy to on control node + ############################# # How to retrieve audit binary @@ -103,6 +103,20 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' +## Ability to collect and take audit files moving to a centralised location +# This enables the collection of the files from the host +fetch_audit_output: false + +# Method of getting,uploading the summary files +## Ensure access and permissions are avaiable for these to occur. +## options are +# fetch - fetches from server and moves to location on the ansible controller (could be a mount point available to controller) +# copy - copies file to a location available to the managed node +audit_output_collection_method: fetch + +# Location to put the audit files +audit_output_destination: /opt/audit_summaries/ + ### Goss Settings ## ####### END ######## diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index ab5a573..b3a8081 100644 --- a/tasks/audit_only.yml +++ b/tasks/audit_only.yml @@ -10,14 +10,6 @@ delegate_to: localhost become: false -- name: Audit_only | Get audits from systems and put in group dir - ansible.builtin.fetch: - dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" - flat: true - mode: '0644' - src: "{{ pre_audit_outfile }}" - when: fetch_audit_files - - name: Audit_only | Show Audit Summary when: - audit_only diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml new file mode 100644 index 0000000..3c510df --- /dev/null +++ b/tasks/fetch_audit_output.yml @@ -0,0 +1,40 @@ +--- + +# Stage to copy audit output to a centralised location + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller" + when: audit_output_collection_method == "fetch" + ansible.builtin.fetch: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + flat: true + failed_when: false + register: discovered_audit_fetch_state + loop: + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + become: false + +# Added this option for continuity but could be changed by adjusting the variable audit_conf_dest +# Allowing backup to one location +- name: "FETCH_AUDIT_FILES | Copy files to location available to managed node" + when: audit_output_collection_method == "copy" + ansible.builtin.copy: + src: "{{ item }}" + dest: "{{ audit_output_destination }}" + mode: 'u-x,go-wx' + flat: true + failed_when: false + register: discovered_audit_copy_state + loop: + - "{{ pre_audit_outfile }}" + - "{{ post_audit_outfile }}" + +- name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + when: + - (audit_output_collection_method == "fetch" and not discovered_audit_fetch_state.changed) or + (audit_output_collection_method == "copy" and not discovered_audit_copy_state.changed) + block: + - name: "FETCH_AUDIT_FILES | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + ansible.builtin.debug: + msg: "Warning!! Unable to write to localhost {{ audit_output_destination }} for audit file copy" diff --git a/tasks/fix-cat1.yml b/tasks/fix-cat1.yml index 73bac96..1adf8cf 100644 --- a/tasks/fix-cat1.yml +++ b/tasks/fix-cat1.yml @@ -108,7 +108,7 @@ replace: "{{ rhel8stig_replace_quoted_params }}" vars: query: "{{ prelim_rhel8stig_boot_part.stdout }}" - key: GRUB_CMDLINE_LINUX # noqa var-naming[no-reserved] + key: GRUB_CMDLINE_LINUX # noqa: var-naming[no-reserved] param: boot value: UUID={{ prelim_rhel8stig_boot_uuid.stdout }} insert: true diff --git a/tasks/main.yml b/tasks/main.yml index a0444be..c40f34c 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -141,7 +141,7 @@ file: fix-cat1.yml when: rhel8stig_cat1_patch tags: - - CAT1 + - rhel8stig_cat1 - high - name: Include CAT II patches @@ -149,7 +149,7 @@ file: fix-cat2.yml when: rhel8stig_cat2_patch tags: - - CAT2 + - rhel8stig_cat2 - medium - name: Include CAT III patches @@ -157,7 +157,7 @@ file: fix-cat3.yml when: rhel8stig_cat3_patch tags: - - CAT3 + - rhel8stig_cat3 - low - name: Flush handlers @@ -187,6 +187,36 @@ tags: - run_audit +- name: Add ansible file showing Benchmark and levels applied + block: + - name: Create ansible facts directory + ansible.builtin.file: + path: "{{ ansible_facts_path }}" + state: directory + owner: root + group: root + mode: 'u=rwx,go=rx' + + - name: Create ansible facts file + ansible.builtin.template: + src: etc/ansible/compliance_facts.j2 + dest: "{{ ansible_facts_path }}/compliance_facts.fact" + owner: root + group: root + mode: "u-x,go-wx" + when: create_benchmark_facts + tags: + - always + - benchmark + +- name: Fetch audit files + ansible.builtin.import_tasks: + file: fetch_audit_output.yml + when: + - fetch_audit_output + - run_audit + tags: always + - name: Show Audit Summary ansible.builtin.debug: msg: "{{ audit_results.split('\n') }}" diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 new file mode 100644 index 0000000..ce87b67 --- /dev/null +++ b/templates/etc/ansible/compliance_facts.j2 @@ -0,0 +1,37 @@ +# STIG Hardening Carried out +# Added as part of ansible-lockdown STIG baseline +# provided by Mindpoint Group - A Tyto Athene Company + +[lockdown_details] +# Benchmark release +Benchmark_release = STIG-{{ benchmark_version }} +Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} +# If options set (doesn't mean it ran all controls) +cat_1_hardening_enabled = {{ rhel8stig_cat1_patch }} +cat_2_hardening_enabled = {{ rhel8stig_cat2_patch }} +cat_3_hardening_enabled = {{ rhel8stig_cat3_patch }} + +{% if ansible_run_tags | length > 0 %} +# If tags used to stipulate run level +{% if 'rhel8stig_cat1' in ansible_run_tags %} +Cat_1_Server_tag_run = true +{% endif %} +{% if 'rhel8stig_cat2' in ansible_run_tags %} +Cat_2_Server_tag_run = true +{% endif %} +{% if 'rhel8stig_cat3' in ansible_run_tags %} +Cat_3_Server_tag_run = true +{% endif %} +{% endif %} + +[lockdown_audit_details] +{% if run_audit %} +# Audit run +audit_file_local_location = {{ audit_log_dir }} +{% if not audit_only %} +audit_summary = {{ post_audit_results }} +{% endif %} +{% if fetch_audit_output %} +audit_files_centralized_location = {{ audit_output_destination }} +{% endif %} +{% endif %}