From 5eb44ca0e65a2fc9bc3cf37505e4524afac9075e Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Thu, 16 Apr 2026 09:27:30 -0600 Subject: [PATCH 1/3] fix: add async options and correct secedit db path for audit and policy tasks **Changed:** - Added async and poll options to long-running SACL configuration tasks in security_audit_policy role to prevent timeouts and improve reliability - Updated secedit command in vulns_anonymous_enum role to use a temp database path, preventing potential conflicts with system database and aligning with best practices for policy application --- ansible/roles/security_audit_policy/tasks/main.yml | 6 ++++++ ansible/roles/vulns_anonymous_enum/tasks/main.yml | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/ansible/roles/security_audit_policy/tasks/main.yml b/ansible/roles/security_audit_policy/tasks/main.yml index 4c09a8b5..9af7e648 100644 --- a/ansible/roles/security_audit_policy/tasks/main.yml +++ b/ansible/roles/security_audit_policy/tasks/main.yml @@ -47,6 +47,8 @@ } else { Write-Output "SYSVOL not found - skipping (not a DC or not yet configured)" } + async: 1800 + poll: 30 register: sacl_sysvol changed_when: "'SACL configured' in sacl_sysvol.stdout" failed_when: false @@ -77,6 +79,8 @@ } else { Write-Output "NETLOGON not found at expected path - skipping" } + async: 1800 + poll: 30 register: sacl_netlogon changed_when: "'SACL configured' in sacl_netlogon.stdout" failed_when: false @@ -108,6 +112,8 @@ Write-Output "Path not found: {{ item.path }} - skipping" } loop: "{{ security_vars.audit_folders | default([]) }}" + async: 1800 + poll: 30 register: sacl_custom changed_when: "'SACL configured' in sacl_custom.stdout" failed_when: false diff --git a/ansible/roles/vulns_anonymous_enum/tasks/main.yml b/ansible/roles/vulns_anonymous_enum/tasks/main.yml index 618c33bc..4054f1ba 100644 --- a/ansible/roles/vulns_anonymous_enum/tasks/main.yml +++ b/ansible/roles/vulns_anonymous_enum/tasks/main.yml @@ -49,7 +49,8 @@ tags: lsa_policy - name: Apply LSAAnonymousNameLookup security policy - ansible.windows.win_shell: secedit /configure /db C:\Windows\Security\Database\secedit.sdb /cfg C:\temp-anon-policy.inf /overwrite /areas SECURITYPOLICY /log C:\Windows\Temp\secedit-anon.log /quiet + ansible.windows.win_shell: | + secedit /configure /db C:\Windows\Temp\secedit-anon.sdb /cfg C:\temp-anon-policy.inf /areas SECURITYPOLICY /log C:\Windows\Temp\secedit-anon.log /quiet register: secedit_result # Note: This will fail on Domain Controllers because LSAAnonymousNameLookup is controlled by Group Policy # The GPO update task below will handle the DC case From 1d5aca16ea24b9bbaefcb260ce8244d9cc2cfbcb Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Thu, 16 Apr 2026 15:37:30 -0600 Subject: [PATCH 2/3] ``` ci: support merge_group event in terratest workflow base ref selection **Added:** - Added handling for the `merge_group` event by setting `MERGE_GROUP_BASE_SHA` and updating base ref logic to use it when appropriate in the terratest workflow ``` --- .github/workflows/terratest.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/terratest.yaml b/.github/workflows/terratest.yaml index 2c6eeece..faa07867 100644 --- a/.github/workflows/terratest.yaml +++ b/.github/workflows/terratest.yaml @@ -54,6 +54,7 @@ jobs: env: EVENT_NAME: ${{ github.event_name }} BASE_BRANCH: ${{ github.base_ref }} + MERGE_GROUP_BASE_SHA: ${{ github.event.merge_group.base_sha }} run: | # Always run all tests for schedule and workflow_dispatch if [ "${EVENT_NAME}" = "schedule" ] || [ "${EVENT_NAME}" = "workflow_dispatch" ]; then @@ -65,6 +66,8 @@ jobs: if [ "${EVENT_NAME}" = "pull_request" ]; then BASE_REF="origin/${BASE_BRANCH}" + elif [ "${EVENT_NAME}" = "merge_group" ]; then + BASE_REF="${MERGE_GROUP_BASE_SHA}" else BASE_REF="HEAD^" fi From e6f5df0a996fb2cd4d5fa63e48b0207d6c532cb8 Mon Sep 17 00:00:00 2001 From: Jayson Grace Date: Thu, 16 Apr 2026 15:57:30 -0600 Subject: [PATCH 3/3] fix: prevent WUA 0x800703FA by setting DisableForceUnload registry key **Added:** - Set `DisableForceUnload` registry key to prevent forced user registry unload and fix Windows Update Agent error 0x800703FA in base playbooks and settings_updates role **Changed:** - Documented the new registry tweak in settings_updates/README.md under main.yml tasks - Updated playbook file reference in get-playbook-files.sh to use settings_updates/tasks/main.yml instead of default.yml **Removed:** - Removed settings_updates/tasks/default.yml and its tasks, consolidating update logic under main.yml --- ansible/playbooks/base/dc_base.yml | 7 +++++++ ansible/playbooks/base/member_base.yml | 7 +++++++ ansible/playbooks/base/mssql_base_sql.yml | 7 +++++++ ansible/roles/settings_updates/README.md | 6 +----- ansible/roles/settings_updates/tasks/default.yml | 11 ----------- ansible/roles/settings_updates/tasks/main.yml | 7 +++++++ scripts/get-playbook-files.sh | 2 +- 7 files changed, 30 insertions(+), 17 deletions(-) delete mode 100644 ansible/roles/settings_updates/tasks/default.yml diff --git a/ansible/playbooks/base/dc_base.yml b/ansible/playbooks/base/dc_base.yml index f06f0c33..296b5d96 100644 --- a/ansible/playbooks/base/dc_base.yml +++ b/ansible/playbooks/base/dc_base.yml @@ -154,6 +154,13 @@ } register: ssm_config + - name: Prevent forced user registry unload (fixes WUA 0x800703FA) + ansible.windows.win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\System + name: DisableForceUnload + data: 1 + type: dword + - name: Enable Windows Update service ansible.windows.win_service: name: wuauserv diff --git a/ansible/playbooks/base/member_base.yml b/ansible/playbooks/base/member_base.yml index 6b4cf400..356580ad 100644 --- a/ansible/playbooks/base/member_base.yml +++ b/ansible/playbooks/base/member_base.yml @@ -125,6 +125,13 @@ delay: 10 until: firewall_result is not failed + - name: Prevent forced user registry unload (fixes WUA 0x800703FA) + ansible.windows.win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\System + name: DisableForceUnload + data: 1 + type: dword + - name: Enable Windows Update service ansible.windows.win_service: name: wuauserv diff --git a/ansible/playbooks/base/mssql_base_sql.yml b/ansible/playbooks/base/mssql_base_sql.yml index 4b656aa1..84d20fda 100644 --- a/ansible/playbooks/base/mssql_base_sql.yml +++ b/ansible/playbooks/base/mssql_base_sql.yml @@ -157,6 +157,13 @@ Protocol: "UDP" Description: "Opens the discover port for MSSQL Browser" + - name: Prevent forced user registry unload (fixes WUA 0x800703FA) + ansible.windows.win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\System + name: DisableForceUnload + data: 1 + type: dword + - name: Enable Windows Update service ansible.windows.win_service: name: wuauserv diff --git a/ansible/roles/settings_updates/README.md b/ansible/roles/settings_updates/README.md index a33d4957..522d8af4 100644 --- a/ansible/roles/settings_updates/README.md +++ b/ansible/roles/settings_updates/README.md @@ -13,14 +13,10 @@ Install Windows updates on managed hosts ## Tasks -### default.yml - -- **Enable update service** (ansible.windows.win_service) -- **Install all updates and reboot as many times as needed** (ansible.windows.win_updates) - ### main.yml - **Run Windows Updates (skip on prebaked AMIs)** (block) - Conditional +- **Prevent forced user registry unload (fixes WUA 0x800703FA)** (ansible.windows.win_regedit) - **Reset Windows Update components** (ansible.windows.win_shell) - **Reboot to clear pending registry operations** (ansible.windows.win_reboot) - **Enable update service** (ansible.windows.win_service) diff --git a/ansible/roles/settings_updates/tasks/default.yml b/ansible/roles/settings_updates/tasks/default.yml deleted file mode 100644 index 56ec6d22..00000000 --- a/ansible/roles/settings_updates/tasks/default.yml +++ /dev/null @@ -1,11 +0,0 @@ ---- -- name: Enable update service - ansible.windows.win_service: - name: Windows Update - state: started - start_mode: auto - -- name: Install all updates and reboot as many times as needed - ansible.windows.win_updates: - category_names: '*' - reboot: true diff --git a/ansible/roles/settings_updates/tasks/main.yml b/ansible/roles/settings_updates/tasks/main.yml index 105abaef..c6a9b678 100644 --- a/ansible/roles/settings_updates/tasks/main.yml +++ b/ansible/roles/settings_updates/tasks/main.yml @@ -2,6 +2,13 @@ - name: Run Windows Updates (skip on prebaked AMIs) when: not ((goad_prebaked | default({})).windows_updated | default(false)) block: + - name: Prevent forced user registry unload (fixes WUA 0x800703FA) + ansible.windows.win_regedit: + path: HKLM:\SOFTWARE\Policies\Microsoft\Windows\System + name: DisableForceUnload + data: 1 + type: dword + - name: Reset Windows Update components ansible.windows.win_shell: | $ErrorActionPreference = 'SilentlyContinue' diff --git a/scripts/get-playbook-files.sh b/scripts/get-playbook-files.sh index 93ce17b2..1f27eb7e 100755 --- a/scripts/get-playbook-files.sh +++ b/scripts/get-playbook-files.sh @@ -24,7 +24,7 @@ case "${PLAYBOOK}" in "ansible/roles/common/tasks/main.yml" "ansible/roles/settings_keyboard/tasks/main.yml" "ansible/roles/settings_no_updates/tasks/main.yml" - "ansible/roles/settings_updates/tasks/default.yml" + "ansible/roles/settings_updates/tasks/main.yml" "ad/GOAD/data/${ENV}-config.json" "ansible/playbooks/data.yml" )