From 236286728357304fe8c75449f5df1ad7b23c9c5a Mon Sep 17 00:00:00 2001 From: thewismit Date: Mon, 16 Mar 2026 17:20:07 -0400 Subject: [PATCH 1/2] chore: add CODEOWNERS requiring owner review on all changes Co-Authored-By: Claude Opus 4.6 (1M context) --- .github/CODEOWNERS | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..42968ba --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,5 @@ +# All changes require owner review (public repo) +* @thewismit + +# CI/CD +/.github/workflows/ @thewismit From be89fcb7ee52337464df00ec9f3e143e648e7abb Mon Sep 17 00:00:00 2001 From: thewismit Date: Mon, 16 Mar 2026 18:26:33 -0400 Subject: [PATCH 2/2] fix: resolve 11 ansible-lint issues for clean CI - no-changed-when: added changed_when to snapshot/stop/rollback/start tasks - run-once[task]: added noqa for audit/smoke directory creation (delegate_to already used) - risky-shell-pipe: added set -o pipefail to disk usage check - yaml[line-length]: refactored smoke results content into task-level vars - name[template]: moved Jinja2 template to end of play name - fqcn[canonical]: use ansible.posix.authorized_key instead of ansible.builtin Co-Authored-By: Claude Opus 4.6 (1M context) --- playbooks/fleet-patch.yml | 22 ++++++++++++++++++---- remediation/host-recovery.yml | 2 +- roles/server_hardening/tasks/users.yml | 2 +- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/playbooks/fleet-patch.yml b/playbooks/fleet-patch.yml index 703a515..1e4ebb8 100644 --- a/playbooks/fleet-patch.yml +++ b/playbooks/fleet-patch.yml @@ -75,7 +75,7 @@ ansible.builtin.set_fact: audit_data: "{{ audit_script.stdout | from_json }}" - - name: Create audit output directory + - name: Create audit output directory # noqa: run-once[task] ansible.builtin.file: path: "{{ patch_audit_dir }}" state: directory @@ -131,6 +131,7 @@ - host_info | length > 0 - host_info.type == 'qm' register: qm_snap + changed_when: qm_snap.rc == 0 - name: Take LXC snapshot (pct) ansible.builtin.command: @@ -141,6 +142,7 @@ - host_info | length > 0 - host_info.type == 'pct' register: pct_snap + changed_when: pct_snap.rc == 0 - name: Verify snapshot exists ansible.builtin.command: @@ -240,7 +242,8 @@ tasks: - name: Check disk usage ansible.builtin.shell: - cmd: "df -h / | awk 'NR==2 {print $5}' | tr -d '%'" + cmd: "set -o pipefail; df -h / | awk 'NR==2 {print $5}' | tr -d '%'" + executable: /bin/bash register: disk_pct changed_when: false @@ -304,7 +307,7 @@ ansible.builtin.set_fact: smoke_all_passed: "{{ (svc_checks | rejectattr('passed') | list | length == 0) and (failed_units.stdout_lines | default([]) | length == 0) and (disk_pct.stdout | int <= 90) }}" - - name: Create smoke results directory + - name: Create smoke results directory # noqa: run-once[task] ansible.builtin.file: path: "{{ smoke_results_dir }}" state: directory @@ -314,8 +317,16 @@ run_once: true - name: Write smoke results + vars: + smoke_report: + host: "{{ inventory_hostname }}" + date: "{{ smoke_date }}" + disk_pct: "{{ disk_pct.stdout | int }}" + failed_units: "{{ failed_units.stdout_lines | default([]) }}" + service_checks: "{{ svc_checks }}" + all_passed: "{{ smoke_all_passed }}" ansible.builtin.copy: - content: "{{ {'host': inventory_hostname, 'date': smoke_date, 'disk_pct': disk_pct.stdout | int, 'failed_units': failed_units.stdout_lines | default([]), 'service_checks': svc_checks, 'all_passed': smoke_all_passed} | to_nice_json }}" + content: "{{ smoke_report | to_nice_json }}" dest: "{{ smoke_results_dir }}/{{ inventory_hostname }}-{{ smoke_date }}.json" mode: "0644" delegate_to: localhost @@ -373,6 +384,7 @@ cmd: "{{ host_info.type }} stop {{ host_info.vmid }}" delegate_to: "{{ host_info.pve_host }}" become: true + changed_when: true - name: Wait for guest to stop ansible.builtin.pause: @@ -383,12 +395,14 @@ cmd: "{{ host_info.type }} rollback {{ host_info.vmid }} {{ snapshot_name }}" delegate_to: "{{ host_info.pve_host }}" become: true + changed_when: true - name: Start guest ansible.builtin.command: cmd: "{{ host_info.type }} start {{ host_info.vmid }}" delegate_to: "{{ host_info.pve_host }}" become: true + changed_when: true - name: Wait for SSH to come back ansible.builtin.wait_for_connection: diff --git a/remediation/host-recovery.yml b/remediation/host-recovery.yml index bfb2aa9..170376d 100644 --- a/remediation/host-recovery.yml +++ b/remediation/host-recovery.yml @@ -2,7 +2,7 @@ # Remediation: attempt to recover an unresponsive VM/LXC via Proxmox # Called by remediation-bridge with -e "target_host=" -- name: REMEDIATION | Recover {{ target_host | default('undefined') }} via Proxmox +- name: "REMEDIATION | Recover via Proxmox — {{ target_host | default('undefined') }}" hosts: localhost connection: local gather_facts: false diff --git a/roles/server_hardening/tasks/users.yml b/roles/server_hardening/tasks/users.yml index b962c1b..3a000bc 100644 --- a/roles/server_hardening/tasks/users.yml +++ b/roles/server_hardening/tasks/users.yml @@ -17,7 +17,7 @@ mode: "0700" - name: USERS | Deploy SSH authorized keys - ansible.builtin.authorized_key: + ansible.posix.authorized_key: user: "{{ hardening_ops_user }}" key: "{{ item }}" state: present