diff --git a/ansible/deploy_aw_windows.yml b/ansible/deploy_aw_windows.yml index 288802b..2b129ae 100644 --- a/ansible/deploy_aw_windows.yml +++ b/ansible/deploy_aw_windows.yml @@ -100,6 +100,7 @@ - email-outbound-collector.ps1 - file-operations-collector.ps1 - worktime-session-collector.ps1 + - export-evtx-for-hayabusa.ps1 - migrate-awatch-rus-paths.ps1 - deploy-domain-users.ps1 - deploy-ensemble.ps1 diff --git a/ansible/group_vars/aw_windows.yml b/ansible/group_vars/aw_windows.yml index 284497c..85a03a1 100644 --- a/ansible/group_vars/aw_windows.yml +++ b/ansible/group_vars/aw_windows.yml @@ -32,8 +32,8 @@ aw_windows_policy_engine_host: "{{ aw_windows_server_host }}" aw_windows_policy_engine_port: 5601 aw_windows_policy_engine_scheme: "http" -aw_windows_afk_enabled: false -aw_windows_window_enabled: false +aw_windows_afk_enabled: true +aw_windows_window_enabled: true aw_windows_file_ops_enabled: true aw_windows_email_collector_enabled: true aw_windows_email_collector_mode: "both" diff --git a/aw-server/aw-ru-patch.js b/aw-server/aw-ru-patch.js index be2b911..40cc189 100755 --- a/aw-server/aw-ru-patch.js +++ b/aw-server/aw-ru-patch.js @@ -1581,6 +1581,9 @@ let applyPatchScheduled = false; let networkPatchesInstalled = false; let dlpOverlayFailureCount = 0; + let applyPatchInFlight = false; + let observerAttached = false; + let staticPatchRouteKey = ""; function getTrendsHostFromSettings(settings) { if (!settings || typeof settings !== "object") return ""; @@ -1818,38 +1821,63 @@ }); } + function detachObserver() { + if (!observerAttached) return; + observer.disconnect(); + observerAttached = false; + } + + function attachObserver() { + if (observerAttached || !document.body) return; + observer.observe(document.body, { childList: true, subtree: true }); + observerAttached = true; + } + function applyPatch() { - enforceSafeActivityViewForPveHost(); - ensureSettingsHost(); - ensureHostGroupsData().catch(function () {}); - normalizeCategoryBuilderUnknownHostRefs(); - installCategoryBuilderNetworkPatch(); - injectStyles(); - walk(document.body); - translateAttributes(document.body); - hideNoiseNavigation(document.body); - patchActivityHeading(document.body); - patchCategoryBuilderHostLabel(document.body); - injectPveAuditCenter(document.body); - injectDlpNavigation(document.body); - if (isDlpSignalBucketRoute() && dlpOverlayFailureCount === 0) { - try { - injectDlpReviewCenter(document.body); - } catch (error) { - dlpOverlayFailureCount += 1; - const existing = document.body.querySelector("[data-aw-ru-dlp-center='1']"); - if (existing && existing.parentElement) existing.parentElement.removeChild(existing); + if (applyPatchInFlight || !document.body) return; + applyPatchInFlight = true; + detachObserver(); + try { + const routeKey = window.location.hash || "#"; + const routeChanged = routeKey !== staticPatchRouteKey; + enforceSafeActivityViewForPveHost(); + ensureSettingsHost(); + ensureHostGroupsData().catch(function () {}); + normalizeCategoryBuilderUnknownHostRefs(); + installCategoryBuilderNetworkPatch(); + injectStyles(); + if (routeChanged) { + walk(document.body); + translateAttributes(document.body); + hideNoiseNavigation(document.body); + patchActivityHeading(document.body); + patchCategoryBuilderHostLabel(document.body); + staticPatchRouteKey = routeKey; } - } else if (!isDlpSignalBucketRoute()) { - injectDlpReviewCenter(document.body); + injectPveAuditCenter(document.body); + injectDlpNavigation(document.body); + if (isDlpSignalBucketRoute() && dlpOverlayFailureCount === 0) { + try { + injectDlpReviewCenter(document.body); + } catch (error) { + dlpOverlayFailureCount += 1; + const existing = document.body.querySelector("[data-aw-ru-dlp-center='1']"); + if (existing && existing.parentElement) existing.parentElement.removeChild(existing); + } + } else if (!isDlpSignalBucketRoute()) { + injectDlpReviewCenter(document.body); + } + injectDlpAlertsCenter(document.body); + injectHostGroupsCenter(document.body).catch(function () {}); + redirectBareTrendsRoute(); + } finally { + applyPatchInFlight = false; + attachObserver(); } - injectDlpAlertsCenter(document.body); - injectHostGroupsCenter(document.body).catch(function () {}); - redirectBareTrendsRoute(); } function scheduleApplyPatch() { - if (applyPatchScheduled) return; + if (applyPatchScheduled || applyPatchInFlight) return; applyPatchScheduled = true; window.setTimeout(function () { applyPatchScheduled = false; @@ -1858,15 +1886,17 @@ } const observer = new MutationObserver(function () { + if (applyPatchInFlight) return; scheduleApplyPatch(); }); window.addEventListener("load", function () { applyPatch(); - observer.observe(document.body, { childList: true, subtree: true }); + attachObserver(); }); window.addEventListener("hashchange", function () { redirectBareTrendsRoute(); + staticPatchRouteKey = ""; scheduleApplyPatch(); }); })(); diff --git a/aw-server/aw-worktime-autoheal.sh b/aw-server/aw-worktime-autoheal.sh index c464186..9189a3c 100644 --- a/aw-server/aw-worktime-autoheal.sh +++ b/aw-server/aw-worktime-autoheal.sh @@ -27,7 +27,7 @@ need_heal="$("$PYTHON_BIN" - <<'PY' import json, urllib.request, datetime, os, sys AW=os.environ.get("AW_URL","http://127.0.0.1:5600") host=os.environ.get("HOST","SHARKON2025") -bucket=f"aw-watcher-window_{host}" +bucket=f"aw-rdp-window_{host}" msk=datetime.timezone(datetime.timedelta(hours=3)) start=datetime.datetime.now(msk).replace(hour=0,minute=0,second=0,microsecond=0).astimezone(datetime.timezone.utc) @@ -75,8 +75,8 @@ import json, urllib.request, datetime, os AW=os.environ.get("AW_URL","http://127.0.0.1:5600") host=os.environ.get("HOST","SHARKON2025") sb=f"aw-worktime-sessions_{host}" -afk=f"aw-watcher-afk_{host}" -win=f"aw-watcher-window_{host}" +afk=f"aw-rdp-afk_{host}" +win=f"aw-rdp-window_{host}" msk=datetime.timezone(datetime.timedelta(hours=3)) start=datetime.datetime.now(msk).replace(hour=0,minute=0,second=0,microsecond=0).astimezone(datetime.timezone.utc) diff --git a/aw-server/aw-worktime-ui-bridge.py b/aw-server/aw-worktime-ui-bridge.py index ae8edc5..91ec1b3 100644 --- a/aw-server/aw-worktime-ui-bridge.py +++ b/aw-server/aw-worktime-ui-bridge.py @@ -16,8 +16,8 @@ TIMEOUT = float(os.environ.get("AW_WORKTIME_UI_BRIDGE_TIMEOUT", "20")) SESSIONS_BUCKET = f"aw-worktime-sessions_{HOST}" -AFK_BUCKET = f"aw-watcher-afk_{HOST}" -WINDOW_BUCKET = f"aw-watcher-window_{HOST}" +AFK_BUCKET = f"aw-rdp-afk_{HOST}" +WINDOW_BUCKET = f"aw-rdp-window_{HOST}" def _req(method: str, path: str, payload=None): diff --git a/windows/hardening-recovery.ps1 b/windows/hardening-recovery.ps1 index 46fbfc6..dd9852e 100755 --- a/windows/hardening-recovery.ps1 +++ b/windows/hardening-recovery.ps1 @@ -21,6 +21,8 @@ param( [bool]$IncidentScreenshotEnabled, [string]$IncidentArtifactsRoot, [string]$EvtxExportRoot, + [int]$EvtxRetentionDays, + [string[]]$EvtxChannels, [bool]$LogonMarkerEnabled, [string]$AwHostname, [string]$CustomRulesPath, @@ -86,8 +88,8 @@ $effectiveIncidentCaptureEnabled = if ($PSBoundParameters.ContainsKey('IncidentC $effectiveIncidentScreenshotEnabled = if ($PSBoundParameters.ContainsKey('IncidentScreenshotEnabled')) { [bool]$IncidentScreenshotEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'incidentCapture' -and $existingConfig.incidentCapture.PSObject.Properties.Name -contains 'screenshotEnabled') { [bool]$existingConfig.incidentCapture.screenshotEnabled } else { $true } $effectiveIncidentArtifactsRoot = if ($PSBoundParameters.ContainsKey('IncidentArtifactsRoot') -and $IncidentArtifactsRoot) { $IncidentArtifactsRoot } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'incidentCapture' -and $existingConfig.incidentCapture.PSObject.Properties.Name -contains 'artifactsRoot') { [string]$existingConfig.incidentCapture.artifactsRoot } else { Join-Path $effectiveStateRoot 'incident-artifacts' } $effectiveEvtxExportRoot = if ($PSBoundParameters.ContainsKey('EvtxExportRoot') -and $EvtxExportRoot) { $EvtxExportRoot } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'evtxExportRoot') { [string]$existingConfig.forensics.evtxExportRoot } else { Join-Path $effectiveStateRoot 'forensics\evtx-exports' } -$effectiveEvtxRetentionDays = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'retentionDays') { [int]$existingConfig.forensics.retentionDays } else { 14 } -$effectiveEvtxChannels = if ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'evtxChannels') { @($existingConfig.forensics.evtxChannels) } else { @() } +$effectiveEvtxRetentionDays = if ($PSBoundParameters.ContainsKey('EvtxRetentionDays')) { [int]$EvtxRetentionDays } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'retentionDays') { [int]$existingConfig.forensics.retentionDays } else { 14 } +$effectiveEvtxChannels = if ($PSBoundParameters.ContainsKey('EvtxChannels')) { @($EvtxChannels) } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'forensics' -and $existingConfig.forensics.PSObject.Properties.Name -contains 'evtxChannels') { @($existingConfig.forensics.evtxChannels) } else { @() } $effectiveLogonMarkerEnabled = if ($PSBoundParameters.ContainsKey('LogonMarkerEnabled')) { [bool]$LogonMarkerEnabled } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'sessionEvents' -and $existingConfig.sessionEvents.PSObject.Properties.Name -contains 'logonEnabled') { [bool]$existingConfig.sessionEvents.logonEnabled } else { $true } $effectiveAwHostname = if ($PSBoundParameters.ContainsKey('AwHostname') -and -not [string]::IsNullOrWhiteSpace($AwHostname)) { [string]$AwHostname } elseif ($existingConfig -and $existingConfig.PSObject.Properties.Name -contains 'awHostname' -and -not [string]::IsNullOrWhiteSpace([string]$existingConfig.awHostname)) { [string]$existingConfig.awHostname } else { [string]$env:COMPUTERNAME } $effectiveVersion = if ($Version) { $Version } elseif ($existingConfig) { [string]$existingConfig.package.version } else { 'v0.13.2' }