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 4a5adc9..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,17 +24,6 @@ # A workflow run is made up of one or more jobs # that can run sequentially or in parallel jobs: - # This will create messages for first time contributers and direct them to the Discord server - welcome: - runs-on: self-hosted - - steps: - - uses: actions/first-interaction@main - with: - repo-token: ${{ secrets.GITHUB_TOKEN }} - pr-message: |- - Congrats on opening your first pull request and thank you for taking the time to help improve Ansible-Lockdown! - Please join in the conversation happening on the [Discord Server](https://www.lockdownenterprise.com/discord) as well. # This workflow contains a single job that tests the playbook playbook-test: diff --git a/.gitignore b/.gitignore index 609a095..6d9e260 100644 --- a/.gitignore +++ b/.gitignore @@ -44,5 +44,5 @@ benchparse/ # GitHub Action/Workflow files .github/ -# Precommit +# ansible-lint cache .ansible/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d7c341f..ebc85d7 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -41,12 +41,12 @@ repos: - id: detect-secrets - repo: https://github.com/gitleaks/gitleaks - rev: v8.24.0 + rev: v8.26.0 hooks: - id: gitleaks - repo: https://github.com/ansible-community/ansible-lint - rev: v25.1.3 + rev: v25.4.0 hooks: - id: ansible-lint name: Ansible-lint @@ -65,7 +65,7 @@ repos: # - ansible-core>=2.10.1 - repo: https://github.com/adrienverge/yamllint.git - rev: v1.36.2 # or higher tag + rev: v1.37.1 # or higher tag hooks: - id: yamllint name: Check YAML Lint diff --git a/README.md b/README.md index d78b0c5..ac56944 100644 --- a/README.md +++ b/README.md @@ -24,6 +24,7 @@ ![Issues Open](https://img.shields.io/github/issues-raw/ansible-lockdown/UBUNTU24-CIS?label=Open%20Issues) ![Issues Closed](https://img.shields.io/github/issues-closed-raw/ansible-lockdown/UBUNTU24-CIS?label=Closed%20Issues&&color=success) ![Pull Requests](https://img.shields.io/github/issues-pr/ansible-lockdown/UBUNTU24-CIS?label=Pull%20Requests) +[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit)](https://github.com/pre-commit/pre-commit) ![License](https://img.shields.io/github/license/ansible-lockdown/UBUNTU24-CIS?label=License) diff --git a/defaults/main.yml b/defaults/main.yml index 79c677c..e1888b0 100644 --- a/defaults/main.yml +++ b/defaults/main.yml @@ -21,6 +21,10 @@ skip_reboot: true benchmark: UBUNTU24-CIS benchmark_version: v1.0.0 +# Create managed not custom local_facts files +create_benchmark_facts: true +ansible_facts_path: /etc/ansible/facts.d + # Used for audit ubtu24cis_level_1: true ubtu24cis_level_2: true @@ -102,6 +106,18 @@ audit_conf_dest: "/opt" # Where the audit logs are stored audit_log_dir: '/opt' +# Method of getting,uploading the summary files +## Enable the collection of audit files +fetch_audit_output: false +## Ensure access and permissions are available 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 ######## @@ -628,7 +644,7 @@ ubtu24cis_purge_apt: false ## Ignore change_when for apt update task # Modifies behavior of 'changed_when' for 'apt update' task in prelim that always changes -ignore_apt_update_changed_when: false +ubtu24cis_ignore_apt_update_changed_when: false ## ## Section 1 Control Variables diff --git a/handlers/main.yml b/handlers/main.yml index 15636b6..494b802 100644 --- a/handlers/main.yml +++ b/handlers/main.yml @@ -21,6 +21,7 @@ listen: "Remount /tmp" - name: "Remounting /tmp systemd" + when: ubtu24cis_tmp_svc vars: mount_point: '/tmp' ansible.builtin.systemd: @@ -257,7 +258,7 @@ listen: Restart auditd - name: Start auditd process - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: auditd state: started listen: Restart auditd diff --git a/tasks/audit_only.yml b/tasks/audit_only.yml index 008d358..845d9d9 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 - when: fetch_audit_files - ansible.builtin.fetch: - dest: "{{ audit_capture_files_dir }}/{{ inventory_hostname }}/" - flat: true - mode: 'go-wx' - src: "{{ pre_audit_outfile }}" - - name: Audit_only | Show Audit Summary when: audit_only ansible.builtin.debug: diff --git a/tasks/fetch_audit_output.yml b/tasks/fetch_audit_output.yml new file mode 100644 index 0000000..563b699 --- /dev/null +++ b/tasks/fetch_audit_output.yml @@ -0,0 +1,46 @@ +--- + +# Stage to copy audit output to a centralised location + +- name: "POST | FETCH | 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: "POST | FETCH | 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: "POST | FETCH | 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: "POST | FETCH | 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" + + - name: "POST | FETCH | Fetch files and copy to controller | Warning if issues with fetch_audit_files" + vars: + warn_control_id: "FETCH_AUDIT_FILES" + ansible.builtin.import_tasks: + file: warning_facts.yml diff --git a/tasks/main.yml b/tasks/main.yml index cfdb641..e2f1742 100644 --- a/tasks/main.yml +++ b/tasks/main.yml @@ -38,7 +38,9 @@ sudo_password_rule: ubtu24cis_rule_5_2_4 # pragma: allowlist secret - name: Ensure root password is set - when: ubtu24cis_rule_5_4_2_4 + when: + - ubtu24cis_section5 + - ubtu24cis_rule_5_4_2_4 tags: always block: - name: Ensure root password is set @@ -65,7 +67,8 @@ - name: Setup rules if container when: - ansible_connection == 'docker' or - ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"] + (ansible_facts.virtualization_type is defined and + ansible_facts.virtualization_type in ["docker", "lxc", "openvz", "podman", "container"]) tags: always block: - name: Discover and set container variable if required @@ -169,6 +172,39 @@ ansible.builtin.import_tasks: file: post_remediation_audit.yml +- name: Add ansible file showing Benchmark and levels applied if audit details not present + when: + - create_benchmark_facts + - (post_audit_summary is defined) or + (ansible_local['compliance_facts']['lockdown_audit_details']['audit_summary'] is undefined and post_audit_summary is undefined) + tags: + - always + - benchmark + block: + - name: Create ansible facts directory if audit facts not present + ansible.builtin.file: + path: "{{ ansible_facts_path }}" + state: directory + owner: root + group: root + mode: 'u=rwx,go=rx' + + - name: Create ansible facts file and levels applied if audit facts not present + ansible.builtin.template: + src: etc/ansible/compliance_facts.j2 + dest: "{{ ansible_facts_path }}/compliance_facts.fact" + owner: root + group: root + mode: 'u-x,go=r' + +- name: Fetch audit files + when: + - fetch_audit_output + - run_audit + tags: always + ansible.builtin.import_tasks: + file: fetch_audit_output.yml + - name: Show Audit Summary when: run_audit tags: run_audit diff --git a/tasks/prelim.yml b/tasks/prelim.yml index 9930ab5..813e966 100644 --- a/tasks/prelim.yml +++ b/tasks/prelim.yml @@ -55,7 +55,7 @@ tags: always ansible.builtin.package: update_cache: true - changed_when: not ignore_apt_update_changed_when + changed_when: not ubtu24cis_ignore_apt_update_changed_when - name: Include audit specific variables when: @@ -150,6 +150,41 @@ max_int_uid: "{{ prelim_uid_max_id.stdout }}" min_int_gid: "{{ prelim_gid_min_id.stdout }}" +- name: "PRELIM | AUDIT | Capture pam configs related files" + tags: always + ansible.builtin.find: + paths: + - '/usr/share/pam-configs/' + - '/etc/pam.d/' + register: prelim_pam_conf_files + +- name: PRELIM | PATCH | Ensure conf.d directory exists required for 5.3.3.2.x + when: + - ubtu24cis_rule_5_3_3_2_1 or + ubtu24cis_rule_5_3_3_2_6 + tags: always + ansible.builtin.file: + path: "{{ item.path }}" + state: "{{ item.state }}" + owner: root + group: root + mode: 'g-w,o-rwx' + modification_time: preserve + access_time: preserve + register: prelim_pwquality_dummy + changed_when: prelim_pwquality_dummy.diff == "absent" + loop: + - { path: '/etc/security/pwquality.conf.d', state: 'directory' } + - { path: '/etc/security/pwquality.conf.d/cis_dummy.conf', state: 'touch' } + +- name: "PRELIM | AUDIT | Capture pam security related files" + tags: always + ansible.builtin.find: + paths: + - /etc/security/pwquality.conf.d/ + patterns: '*.conf' + register: prelim_pam_pwquality_confs + - name: "PRELIM | AUDIT | Interactive Users" tags: always ansible.builtin.shell: > @@ -243,6 +278,22 @@ name: acl state: present +- name: "PRELIM | PATCH | Install cron" + when: ubtu24cis_rule_2_4_1_1 + tags: always + ansible.builtin.package: + name: cron + state: present + +- name: "PRELIM | PATCH | Install UFW" + when: + - ubtu24cis_rule_2_4_1_1 + - ubtu24cis_firewall_package == "ufw" + tags: always + ansible.builtin.package: + name: ufw + state: present + ## Optional - name: "Optional | PATCH | UFW firewall force to use /etc/sysctl.conf settings" diff --git a/tasks/section_1/cis_1.1.2.4.x.yml b/tasks/section_1/cis_1.1.2.4.x.yml index eb6e907..0739370 100644 --- a/tasks/section_1/cis_1.1.2.4.x.yml +++ b/tasks/section_1/cis_1.1.2.4.x.yml @@ -22,12 +22,12 @@ register: discovered_var_mount - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Absent" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.debug: msg: "Warning!! {{ required_mount }} is not mounted on a separate partition" - name: "1.1.2.4.1 | AUDIT | Ensure /var is a separate partition | Present" - when: discovered_dev_shm_mount is undefined + when: discovered_var_mount is undefined ansible.builtin.import_tasks: file: warning_facts.yml diff --git a/tasks/section_1/cis_1.2.2.x.yml b/tasks/section_1/cis_1.2.2.x.yml index 92eb1c7..22664b5 100644 --- a/tasks/section_1/cis_1.2.2.x.yml +++ b/tasks/section_1/cis_1.2.2.x.yml @@ -10,7 +10,7 @@ - NIST800-53R5_SI-2 - patch block: - - name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installedi | Update" + - name: "1.2.2.1 | PATCH | Ensure updates, patches, and additional security software are installed | Update" ansible.builtin.package: name: "*" state: latest diff --git a/tasks/section_2/cis_2.1.x.yml b/tasks/section_2/cis_2.1.x.yml index 166cd5d..411eccf 100644 --- a/tasks/section_2/cis_2.1.x.yml +++ b/tasks/section_2/cis_2.1.x.yml @@ -46,7 +46,7 @@ when: - not ubtu24cis_avahi_server - not ubtu24cis_avahi_mask - - "'avahi' in ansible_facts.packages or 'avahi-autopd' in ansible_facts.packages" + - "'avahi' in ansible_facts.packages or 'avahi-autoipd' in ansible_facts.packages" ansible.builtin.package: name: - avahi-autoipd @@ -672,7 +672,7 @@ - rule_2.1.21 - NIST800-53R5_CM-7 vars: - warn_control_id: '2.2.21' + warn_control_id: '2.1.21' block: - name: "2.1.21 | PATCH | Ensure mail transfer agents are configured for local-only mode | Make changes if exim4 installed" when: "'exim4' in ansible_facts.packages" diff --git a/tasks/section_2/cis_2.3.3.x.yml b/tasks/section_2/cis_2.3.3.x.yml index 19177b9..4f4f516 100644 --- a/tasks/section_2/cis_2.3.3.x.yml +++ b/tasks/section_2/cis_2.3.3.x.yml @@ -15,9 +15,9 @@ ansible.builtin.template: src: "{{ item }}.j2" dest: "/{{ item }}" - mode: 'go-r' + mode: 'g=r,o-rwx' owner: root - group: root + group: "{% if ubtu24cis_rule_2_3_3_2 %}_chrony{% else %}root{% endif %}" loop: - etc/chrony/sources.d/pool.sources - etc/chrony/sources.d/server.sources diff --git a/tasks/section_2/cis_2.4.1.x.yml b/tasks/section_2/cis_2.4.1.x.yml index a81990b..d32bf66 100644 --- a/tasks/section_2/cis_2.4.1.x.yml +++ b/tasks/section_2/cis_2.4.1.x.yml @@ -154,5 +154,5 @@ ansible.builtin.file: path: /etc/cron.allow owner: root - group: root + group: '{{ (discovered_cron_allow_status.stat.gr_name == "crontab") | ternary(omit,"root") }}' mode: 'u-x,g-wx,o-rwx' diff --git a/tasks/section_5/cis_5.3.3.1.x.yml b/tasks/section_5/cis_5.3.3.1.x.yml index 1b05935..727a154 100644 --- a/tasks/section_5/cis_5.3.3.1.x.yml +++ b/tasks/section_5/cis_5.3.3.1.x.yml @@ -28,12 +28,10 @@ - name: "5.3.3.1.1 | PATCH | Ensure password failed attempts lockout is configured | if exists remove deny from faillock line in pam-auth conf files" when: discovered_faillock_deny_files.stdout | length > 0 ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: '(*.pam_faillock.so\s*)deny\s*=\s*\d+\b(.*)' replace: \1\2 - with_fileglob: - - '/usr/share/pam-configs/*' - - '/etc/pam.d/*' + loop: "{{ prelim_pam_conf_files.files }}" - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured" when: ubtu24cis_rule_5_3_3_1_2 @@ -63,12 +61,10 @@ - name: "5.3.3.1.2 | PATCH | Ensure password unlock time is configured | if exists remove unlock_time from faillock line in pam-auth conf files" when: discovered_faillock_unlock_files.stdout | length > 0 ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: '(*.pam_faillock.so\s*)unlock_time\s*=\s*\b(.*)' replace: \1\2 - with_fileglob: - - '/usr/share/pam-configs/*' - - '/etc/pam.d/*' + loop: "{{ prelim_pam_conf_files.files }}" - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account" when: ubtu24cis_rule_5_3_3_1_3 @@ -98,9 +94,7 @@ - name: "5.3.3.1.3 | PATCH | Ensure password failed attempts lockout includes root account | if exists remove unlock_time from faillock line in pam-auth conf files" when: discovered_faillock_rootlock_files.stdout | length > 0 ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: '(*.pam_faillock.so\s*)(even_deny_root\b|root_unlock_time\s*=\s*\d+\b)(.*)' replace: \1\3 - with_fileglob: - - '/usr/share/pam-configs/*' - - '/etc/pam.d/*' + loop: "{{ prelim_pam_conf_files.files }}" diff --git a/tasks/section_5/cis_5.3.3.2.x.yml b/tasks/section_5/cis_5.3.3.2.x.yml index 33268a1..4846b41 100644 --- a/tasks/section_5/cis_5.3.3.2.x.yml +++ b/tasks/section_5/cis_5.3.3.2.x.yml @@ -11,15 +11,15 @@ - pam block: - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Remove difok from conf files except expected file" - when: item != ubtu24cis_passwd_difok_file + when: "ubtu24cis_passwd_difok_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'difok\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.1 | PATCH | Ensure password number of changed characters is configured | Ensure difok file exists" ansible.builtin.template: @@ -40,15 +40,15 @@ - pam block: - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Remove minlen from conf files except expected file" - when: item != ubtu24cis_passwd_minlen_file + when: "ubtu24cis_passwd_minlen_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'minlen\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.2 | PATCH | Ensure minimum password length is configured | Ensure minlen file exists" ansible.builtin.template: @@ -69,15 +69,15 @@ - pam block: - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Remove pwd complex settings from conf files except expected file" - when: item != ubtu24cis_passwd_complex_file + when: "ubtu24cis_passwd_complex_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: '(minclass|[dulo]credit)\s*=\s*(-\d|\d+)\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.3 | PATCH | Ensure password complexity is configured | Ensure complexity file exists" ansible.builtin.template: @@ -98,15 +98,15 @@ - pam block: - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Remove maxrepeat settings from conf files except expected file" - when: item != ubtu24cis_passwd_maxrepeat_file + when: "ubtu24cis_passwd_maxrepeat_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'maxrepeat\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.4 | PATCH | Ensure password same consecutive characters is configured | Ensure maxrepeat file exists" ansible.builtin.template: @@ -127,15 +127,15 @@ - pam block: - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Remove maxsequence settings from conf files except expected file" - when: item != ubtu24cis_passwd_maxsequence_file + when: "ubtu24cis_passwd_maxsequence_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'maxsequence\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.5 | PATCH | Ensure password maximum sequential characters is configured | Ensure maxsequence file exists" ansible.builtin.template: @@ -156,15 +156,15 @@ - pam block: - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Remove dictcheck settings from conf files except expected file" - when: item != ubtu24cis_passwd_dictcheck_file + when: "ubtu24cis_passwd_dictcheck_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'dictcheck\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.6 | PATCH | Ensure password dictionary check is enabled | Ensure dictcheck file exists" ansible.builtin.template: @@ -185,15 +185,15 @@ - pam block: - name: "5.3.3.2.7 | PATCH | Ensure password quality checking is enforced | Remove quality enforcement settings from conf files except expected file" - when: item != ubtu24cis_passwd_quality_enforce_file + when: "ubtu24cis_passwd_quality_enforce_file not in item.path" ansible.builtin.replace: - path: "{{ item }}" + path: "{{ item.path }}" regexp: 'enforcing\s*=\s*\d+\b' replace: '' - with_fileglob: - - '/etc/security/pwquality.conf' - - '/etc/security/pwquality.conf.d/*.conf' - - '/etc/pam.d/common-password' + with_items: + - "{{ prelim_pam_pwquality_confs.files }}" + - { path: '/etc/security/pwquality.conf'} + - { path: '/etc/pam.d/common-password' } - name: "5.3.3.2.7 | PATCH | Ensure password quality checking is enforced | Ensure quality enforcement file exists" ansible.builtin.template: diff --git a/tasks/section_6/cis_6.1.4.1.yml b/tasks/section_6/cis_6.1.4.1.yml index 5d3d70c..2b4a629 100644 --- a/tasks/section_6/cis_6.1.4.1.yml +++ b/tasks/section_6/cis_6.1.4.1.yml @@ -30,11 +30,14 @@ loop: "{{ discovered_logfiles.stdout_lines }}" - name: "6.1.4.1 | PATCH | Ensure access to all logfiles has been configured | change permissions" + when: + - discovered_system_logfiles.stdout_lines is defined + - item == "/var/log/btmp" + - item == "/var/log/utmp" + - item == "/var/log/wtmp" + - item == "/var/log/lastlog" + - "'sssd' in item or 'SSSD' in item" ansible.builtin.file: path: "{{ item }}" mode: 'ug-x,o-wx' - with_fileglob: - - "/var/log/*tmp" - - "/var/log/lastlog*" - - "/var/log/sssd*" - - "/var/log/SSSD*" + loop: "{{ discovered_system_logfiles.stdout_lines }}" diff --git a/tasks/section_6/cis_6.2.1.x.yml b/tasks/section_6/cis_6.2.1.x.yml index 2580628..093e558 100644 --- a/tasks/section_6/cis_6.2.1.x.yml +++ b/tasks/section_6/cis_6.2.1.x.yml @@ -4,7 +4,7 @@ when: - ubtu24cis_rule_6_2_1_1 - "'auditd' not in ansible_facts.packages or - 'audisd-plugins' not in ansible_facts.packages" + 'audispd-plugins' not in ansible_facts.packages" tags: - level2-server - level2-workstation @@ -30,7 +30,7 @@ - NIST800-53R5_AU-3 - NIST800-53R5_AU-12 - auditd - ansible.builtin.systemd_service: + ansible.builtin.systemd: name: auditd state: started enabled: true diff --git a/templates/audit/99_auditd.rules.j2 b/templates/audit/99_auditd.rules.j2 index 4c888da..0f7af4b 100644 --- a/templates/audit/99_auditd.rules.j2 +++ b/templates/audit/99_auditd.rules.j2 @@ -43,8 +43,8 @@ {{ arch_syscalls.append( syscall) }} {% endif %} {% endfor %} --a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale --a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k system-locale +-a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -k system-locale +-a always,exit -F arch=b32 -S {{ arch_syscalls|join(',') }} -k system-locale -w /etc/issue -p wa -k system-locale -w /etc/issue.net -p wa -k system-locale -w /etc/hosts -p wa -k system-locale @@ -99,7 +99,7 @@ {% endif %} {% endfor %} -a always,exit -F arch=b64 -S {{ arch_syscalls|join(',') }} -F auid>=1000 -F auid!=unset -k perm_mod -{% set syscalls = ["etxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} +{% set syscalls = ["setxattr","lsetxattr","fsetxattr","removexattr","lremovexattr","fremovexattr"] %} {% set arch_syscalls = [] %} {% for syscall in syscalls %} {% if syscall in supported_syscalls %} diff --git a/templates/etc/ansible/compliance_facts.j2 b/templates/etc/ansible/compliance_facts.j2 new file mode 100644 index 0000000..43b4628 --- /dev/null +++ b/templates/etc/ansible/compliance_facts.j2 @@ -0,0 +1,40 @@ +# CIS Hardening Carried out +# Added as part of ansible-lockdown CIS baseline +# provided by Mindpoint Group - A Tyto Athene Company + +[lockdown_details] +# Benchmark release +Benchmark_release = CIS-{{ benchmark_version }} +Benchmark_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} +# If options set (doesn't mean it ran all controls) +level_1_hardening_enabled = {{ ubtu24cis_level_1 }} +level_2_hardening_enabled = {{ ubtu24cis_level_2 }} + +{% if ansible_run_tags | length > 0 %} +# If tags used to stipulate run level +{% if 'level1-server' in ansible_run_tags %} +Level_1_Server_tag_run = true +{% endif %} +{% if 'level2-server' in ansible_run_tags %} +Level_2_Server_tag_run = true +{% endif %} +{% if 'level1-workstation' in ansible_run_tags %} +Level_1_workstation_tag_run = true +{% endif %} +{% if 'level2-workstation' in ansible_run_tags %} +Level_2_workstation_tag_run = true +{% endif %} +{% endif %} + +[lockdown_audit_details] +{% if run_audit %} +# Audit run +audit_run_date = {{ '%Y-%m-%d - %H:%M:%S' | ansible.builtin.strftime }} +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 %}