fix(windows): finish rust collector cleanup

This commit is contained in:
igor04091968
2026-06-11 06:28:35 +03:00
parent 1c710dfe94
commit 2ccf33e1f5
11 changed files with 73 additions and 33 deletions
+2 -6
View File
@@ -18,7 +18,7 @@
aw_windows_package_version: "v0.13.2"
aw_windows_package_url: "https://github.com/ActivityWatch/activitywatch/releases/download/v0.13.2/activitywatch-v0.13.2-windows-x86_64.zip"
aw_windows_package_zip_path: ""
aw_windows_domain: "HOST-EXAMPLE"
aw_windows_domain: "SHARKON2025"
aw_windows_builtin_administrator_name: "Администратор"
aw_windows_users:
- Администратор
@@ -171,18 +171,15 @@
- "{{ aw_windows_deploy_root }}"
- "{{ aw_windows_deploy_root }}\\windows"
- name: Загрузить Windows toolkit развёртывания
- name: Загрузить Windows toolkit развёртывания (без PS-дубликатов — заменены Rust)
ansible.windows.win_copy:
src: "{{ aw_windows_repo_root }}/windows/{{ item }}"
dest: "{{ aw_windows_deploy_root }}\\windows\\{{ item }}"
loop:
- ActivityWatch.Windows.Common.psd1
- ActivityWatch.Windows.Common.psm1
- browser-domains-native-collector.ps1
- dlp-endpoint-signals-collector.ps1
- dlp-policy-client.ps1
- email-outbound-collector.ps1
- file-operations-collector.ps1
- worktime-session-collector.ps1
- export-evtx-for-hayabusa.ps1
- export-upload-hayabusa-to-aw-server.ps1
@@ -193,7 +190,6 @@
- deploy-ensemble.ps1
- hardening-recovery.ps1
- AWatchRusCollectorGuardService.cs
- aw-collector-guard.ps1
- install-collector-guard-service.ps1
- rebuild-worktime-tasks.ps1
- audit-cryptopro.ps1
+4 -4
View File
@@ -42,13 +42,13 @@ aw_windows_builtin_administrator_name: "Администратор"
Назначение: явно фиксировать локализованное имя встроенной учетной записи Administrator с SID `*-500`.
Для текущего Windows host `HOST-EXAMPLE` task name должен строиться как:
Для текущего Windows host `SHARKON2025` task name должен строиться как:
```text
ActivityWatch Launch [HOST-EXAMPLE_Администратор]
ActivityWatch Launch [SHARKON2025_Администратор]
```
Если task по `HOST-EXAMPLE_Administrator` не найден, recovery/deploy path обязан пробовать кириллическое имя `Администратор`. Это зафиксировано через:
Если task по `SHARKON2025_Administrator` не найден, recovery/deploy path обязан пробовать кириллическое имя `Администратор`. Это зафиксировано через:
- default vars в `ansible/deploy_aw_windows.yml`;
- `ansible/group_vars/aw_windows.yml`;
@@ -60,7 +60,7 @@ ActivityWatch Launch [HOST-EXAMPLE_Администратор]
`ActivityWatch.Windows.Common.psm1` усилил recovery path:
- `Get-ActivityWatchBuiltInAdministratorName` сначала смотрит env override, затем SID-500 lookup, затем host-specific fallback `HOST-EXAMPLE -> Администратор`;
- `Get-ActivityWatchBuiltInAdministratorName` сначала смотрит env override, затем SID-500 lookup, затем host-specific fallback `SHARKON2025 -> Администратор`;
- `Normalize-ActivityWatchUsers` стабилизирован для pipeline/list cases;
- удаление scheduled tasks стало устойчивее к частично удаленным task definitions;
- recovery task может ориентироваться на live interactive session и запускаться в interactive logon context, когда это безопаснее для watcher'ов.
+2 -2
View File
@@ -191,7 +191,7 @@ Ansible playbook `ansible/deploy_aw_windows.yml` выполняет этот mig
.\windows\deploy-domain-users.ps1 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-Domain HOST-EXAMPLE `
-Domain SHARKON2025 `
-Users user2,user3,user4,user5 `
-InstallRoot 'C:\Program Files\AWatch-rus\bin' `
-StateRoot 'C:\ProgramData\AWatch-rus' `
@@ -205,7 +205,7 @@ Single-user pilot в таком же стиле:
.\windows\deploy-single-user.ps1 `
-ServerHost <AW_SERVER_HOST> `
-ServerPort 5600 `
-TargetUser 'HOST-EXAMPLE\user1' `
-TargetUser 'SHARKON2025\user1' `
-InstallRoot 'C:\Program Files\AWatch-rus\bin' `
-StateRoot 'C:\ProgramData\AWatch-rus' `
-CustomRulesPath C:\Program Files\AWatch-rus\windows\web-category-rules.example.json `
+1 -1
View File
@@ -43,7 +43,7 @@ Get-ScheduledTask -TaskName 'ActivityWatch*' |
Точечная проверка:
```powershell
Get-ScheduledTask | Where-Object TaskName -eq 'ActivityWatch Launch [HOST-EXAMPLE_user1]'
Get-ScheduledTask | Where-Object TaskName -eq 'ActivityWatch Launch [SHARKON2025_user1]'
Get-ScheduledTask | Where-Object TaskName -eq 'ActivityWatch Recovery'
```
@@ -883,11 +883,14 @@ function New-ActivityWatchDeploymentConfig {
[Parameter(Mandatory = $true)]
[string]$LogsRoot,
[Parameter(Mandatory = $true)]
[AllowEmptyString()]
[string]$CollectorScript,
[Parameter(Mandatory = $true)]
[AllowEmptyString()]
[string]$EndpointCollectorScript,
[string]$PolicyClientScript,
[Parameter(Mandatory = $true)]
[AllowEmptyString()]
[string]$FileCollectorScript,
[Parameter(Mandatory = $true)]
[string]$SessionCollectorScript,
+4 -4
View File
@@ -322,18 +322,18 @@ function Invoke-GuardSelfTest {
$oldComputerName = $env:COMPUTERNAME
try {
$env:COMPUTERNAME = 'HOST-EXAMPLE'
$env:COMPUTERNAME = 'SHARKON2025'
$sessionRecords = @(
[pscustomobject]@{ SessionName = 'USER5'; UserName = 'USER5'; SessionId = 2; State = 'Disc'; IsLive = $false },
[pscustomobject]@{ SessionName = 'console'; UserName = ''; SessionId = 1; State = 'Conn'; IsLive = $true }
)
$taskDefs = @(
[pscustomobject]@{ taskName = 'ActivityWatch Launch [HOST-EXAMPLE_user5]'; userId = 'HOST-EXAMPLE\user5' }
[pscustomobject]@{ taskName = 'ActivityWatch Launch [SHARKON2025_user5]'; userId = 'SHARKON2025\user5' }
)
if (-not (Test-ActivityWatchUserHasManagedSession -UserId 'HOST-EXAMPLE\user5' -SessionRecords $sessionRecords -IncludeDisconnected)) {
if (-not (Test-ActivityWatchUserHasManagedSession -UserId 'SHARKON2025\user5' -SessionRecords $sessionRecords -IncludeDisconnected)) {
throw 'expected disconnected managed session to match task user'
}
if (Test-ActivityWatchUserHasManagedSession -UserId 'HOST-EXAMPLE\user5' -SessionRecords $sessionRecords -IncludeLive) {
if (Test-ActivityWatchUserHasManagedSession -UserId 'SHARKON2025\user5' -SessionRecords $sessionRecords -IncludeLive) {
throw 'disconnected managed session should not match live-only filter'
}
$managed = @(Get-ActivityWatchManagedInteractiveSessions -TaskDefinitions $taskDefs -SessionRecords $sessionRecords -IncludeDisconnected)
+16 -3
View File
@@ -66,9 +66,6 @@ $effectiveLogsRoot = if ($existingConfig) { [string]$existingConfig.paths.logsRo
$effectiveConfigPath = if ($ConfigPath) { $ConfigPath } else { Join-Path $effectiveStateRoot 'deployment-config.json' }
$effectiveLaunchScript = Join-Path $effectiveStateRoot 'launch-watchers.ps1'
$effectiveRecoveryScript = Join-Path $effectiveStateRoot 'recovery-loop.ps1'
$effectiveCollector = Join-Path $effectiveStateRoot 'browser-domains-native-collector.ps1'
$effectiveEndpointCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]$existingConfig.paths.endpointCollectorScript } else { Join-Path $effectiveStateRoot 'dlp-endpoint-signals-collector.ps1' }
$effectiveFileCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'fileCollectorScript') { [string]$existingConfig.paths.fileCollectorScript } else { Join-Path $effectiveStateRoot 'file-operations-collector.ps1' }
$effectiveSessionCollector = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'sessionCollectorScript') { [string]$existingConfig.paths.sessionCollectorScript } else { Join-Path $effectiveStateRoot 'worktime-session-collector.ps1' }
$effectiveEvtxExportScript = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'evtxExportScript') { [string]$existingConfig.paths.evtxExportScript } else { Join-Path $effectiveStateRoot 'export-evtx-for-hayabusa.ps1' }
$effectiveHayabusaUploadScript = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'hayabusaUploadScript') { [string]$existingConfig.paths.hayabusaUploadScript } else { Join-Path $effectiveStateRoot 'export-upload-hayabusa-to-aw-server.ps1' }
@@ -78,6 +75,18 @@ $effectivePolicy = if ($existingConfig -and $existingConfig.paths.PSObject.Prope
$effectivePolicyClientScript = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'policyClientScript') { [string]$existingConfig.paths.policyClientScript } else { Join-Path $effectiveStateRoot 'dlp-policy-client.ps1' }
$effectiveTelemetryExecutable = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'file1cTelemetryExecutable' -and -not [string]::IsNullOrWhiteSpace([string]$existingConfig.paths.file1cTelemetryExecutable)) { [string]$existingConfig.paths.file1cTelemetryExecutable } else { Join-Path $PSScriptRoot 'aw-windows-telemetry.exe' }
function Resolve-OptionalExistingPath {
param([AllowEmptyString()][string]$Path)
if ([string]::IsNullOrWhiteSpace($Path)) {
return ''
}
if (Test-Path -LiteralPath $Path) {
return $Path
}
return ''
}
$effectiveServerHost = if ($ServerHost) { $ServerHost } elseif ($existingConfig) { [string]$existingConfig.server.host } else { $null }
$effectiveServerPort = if ($PSBoundParameters.ContainsKey('ServerPort')) { $ServerPort } elseif ($existingConfig) { [int]$existingConfig.server.port } else { 5600 }
$effectiveServerScheme = if ($ServerScheme) { $ServerScheme } elseif ($existingConfig) { [string]$existingConfig.server.scheme } else { 'http' }
@@ -174,6 +183,10 @@ $assetResult = Copy-ActivityWatchCollectorAssets `
-CustomRulesSource $CustomRulesPath `
-CustomPolicySource $CustomPolicyPath
$effectiveCollector = if (-not [string]::IsNullOrWhiteSpace([string]$assetResult.CollectorScript)) { [string]$assetResult.CollectorScript } elseif ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'collectorScript') { Resolve-OptionalExistingPath -Path ([string]$existingConfig.paths.collectorScript) } else { '' }
$effectiveEndpointCollector = if (-not [string]::IsNullOrWhiteSpace([string]$assetResult.EndpointCollectorScript)) { [string]$assetResult.EndpointCollectorScript } elseif ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { Resolve-OptionalExistingPath -Path ([string]$existingConfig.paths.endpointCollectorScript) } else { '' }
$effectiveFileCollector = if (-not [string]::IsNullOrWhiteSpace([string]$assetResult.FileCollectorScript)) { [string]$assetResult.FileCollectorScript } elseif ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'fileCollectorScript') { Resolve-OptionalExistingPath -Path ([string]$existingConfig.paths.fileCollectorScript) } else { '' }
$taskDefinitions = New-ActivityWatchUserTaskDefinitions -Users $effectiveUsers
Write-ActivityWatchLaunchScript -Path $effectiveLaunchScript -ConfigPath $effectiveConfigPath
Write-ActivityWatchRecoveryScript -Path $effectiveRecoveryScript -ConfigPath $effectiveConfigPath
@@ -5,7 +5,7 @@
#define AwDefaultServerHost "aw-server"
#define AwDefaultServerPort "5600"
#define AwDefaultWorktimeReportBase "http://aw-server:5610"
#define AwDefaultWorktimeHost "HOST-EXAMPLE"
#define AwDefaultWorktimeHost "SHARKON2025"
#define AwDefaultUsers "user1,user2,user3,user4,user5"
#define AwDefaultInstallRoot "C:\\Program Files\\AWatch-rus\\bin"
#define AwDefaultStateRoot "C:\\ProgramData\\AWatch-rus"
@@ -13,7 +13,7 @@
; This installer wraps the standalone-service path.
; It is suitable for standalone/headless deployment and must not be treated
; as the canonical multi-user RDP deployment path used on HOST-EXAMPLE.
; as the canonical multi-user RDP deployment path used on SHARKON2025.
[Setup]
AppId={{6D6A1F74-0F4F-4A57-B5E3-1C2C2F56C0E9}
@@ -45,16 +45,12 @@ Source: "..\..\deploy-single-user.ps1"; DestDir: "{app}\windows"; Flags: ignorev
Source: "..\..\deploy-domain-users.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\deploy-ensemble.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\AWatchRusCollectorGuardService.cs"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\aw-collector-guard.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\install-collector-guard-service.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\..\adk-rust\target\x86_64-pc-windows-gnu\release\aw-windows-telemetry.exe"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\hardening-recovery.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\validate-deployment.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\migrate-awatch-rus-paths.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\worktime-session-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\browser-domains-native-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\dlp-endpoint-signals-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\file-operations-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\email-outbound-collector.ps1"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\web-category-rules.example.json"; DestDir: "{app}\windows"; Flags: ignoreversion
Source: "..\..\dlp-policy.example.json"; DestDir: "{app}\windows"; Flags: ignoreversion
+32 -5
View File
@@ -91,15 +91,42 @@ function Update-AWatchConfigPaths {
[pscustomobject]$Config
)
function Resolve-OptionalCollectorRuntimePath {
param([Parameter(Mandatory = $true)][string]$FileName)
$stateCandidate = Join-Path $NewStateRoot $FileName
if (Test-Path -LiteralPath $stateCandidate) {
return $stateCandidate
}
if (Test-Path -LiteralPath (Join-Path $ToolkitRoot $FileName)) {
return $stateCandidate
}
return ''
}
function Set-ConfigPathValue {
param(
[Parameter(Mandatory = $true)][string]$Name,
[AllowEmptyString()][string]$Value
)
if ($Config.paths.PSObject.Properties.Name -contains $Name) {
$Config.paths.PSObject.Properties[$Name].Value = $Value
}
else {
$Config.paths | Add-Member -NotePropertyName $Name -NotePropertyValue $Value
}
}
$logsRoot = Join-Path $NewStateRoot 'logs'
$Config.paths.installRoot = $NewInstallRoot
$Config.paths.stateRoot = $NewStateRoot
$Config.paths.logsRoot = $logsRoot
$Config.paths.collectorScript = Join-Path $NewStateRoot 'browser-domains-native-collector.ps1'
$Config.paths.endpointCollectorScript = Join-Path $NewStateRoot 'dlp-endpoint-signals-collector.ps1'
if ($Config.paths.PSObject.Properties.Name -contains 'fileCollectorScript') {
$Config.paths.fileCollectorScript = Join-Path $NewStateRoot 'file-operations-collector.ps1'
}
Set-ConfigPathValue -Name 'collectorScript' -Value (Resolve-OptionalCollectorRuntimePath -FileName 'browser-domains-native-collector.ps1')
Set-ConfigPathValue -Name 'endpointCollectorScript' -Value (Resolve-OptionalCollectorRuntimePath -FileName 'dlp-endpoint-signals-collector.ps1')
Set-ConfigPathValue -Name 'fileCollectorScript' -Value (Resolve-OptionalCollectorRuntimePath -FileName 'file-operations-collector.ps1')
if ($Config.paths.PSObject.Properties.Name -contains 'file1cTelemetryExecutable') {
$Config.paths.file1cTelemetryExecutable = Join-Path $ToolkitRoot 'aw-windows-telemetry.exe'
}
+2 -2
View File
@@ -1,6 +1,6 @@
[CmdletBinding()]
param(
[string]$UserId = 'HOST-EXAMPLE\user1'
[string]$UserId = 'SHARKON2025\user1'
)
Set-StrictMode -Version Latest
@@ -13,7 +13,7 @@ Start-Sleep -Seconds 10
Get-Process notepad -ErrorAction SilentlyContinue | Stop-Process -Force -ErrorAction SilentlyContinue
'@ | Set-Content -LiteralPath $probeScriptPath -Encoding UTF8
schtasks /Run /TN 'ActivityWatch Launch [HOST-EXAMPLE_user1]' | Out-Null
schtasks /Run /TN 'ActivityWatch Launch [SHARKON2025_user1]' | Out-Null
Start-Sleep -Seconds 3
$taskName = 'AW User1 Notepad Probe'
+5
View File
@@ -123,9 +123,14 @@ function Test-UserHasSession {
function Get-CollectorProcesses {
param(
[Parameter(Mandatory = $true)]
[AllowEmptyString()]
[string]$ScriptPath
)
if ([string]::IsNullOrWhiteSpace($ScriptPath)) {
return @()
}
return @(
Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
Where-Object {