feat(dlp-phase2): add endpoint signal collector for clipboard usb print and policy wiring
This commit is contained in:
@@ -14,7 +14,7 @@
|
|||||||
- `aw-server/` — установочные скрипты, env-шаблон, systemd unit и RU patch для Web UI.
|
- `aw-server/` — установочные скрипты, env-шаблон, systemd unit и RU patch для Web UI.
|
||||||
- `ansible/` — Ansible-ensemble для автоматизированного сервера (Debian/CT).
|
- `ansible/` — Ansible-ensemble для автоматизированного сервера (Debian/CT).
|
||||||
- `windows/` — PowerShell toolkit: single-user, domain-users, ensemble orchestration, hardening/recovery, validation.
|
- `windows/` — PowerShell toolkit: single-user, domain-users, ensemble orchestration, hardening/recovery, validation.
|
||||||
- `windows/` — PowerShell toolkit + phase-1 DLP policy/incident pipeline (`aw-dlp-incidents_*`).
|
- `windows/` — PowerShell toolkit + phase-2 DLP telemetry (`aw-dlp-incidents_*`, `aw-dlp-endpoint-signals_*`).
|
||||||
- `scripts/quality-gate.sh` — локальный preflight-пайплайн проверок.
|
- `scripts/quality-gate.sh` — локальный preflight-пайплайн проверок.
|
||||||
|
|
||||||
## Базовый сценарий
|
## Базовый сценарий
|
||||||
|
|||||||
@@ -25,11 +25,12 @@
|
|||||||
- Incident generation в отдельный AW bucket.
|
- Incident generation в отдельный AW bucket.
|
||||||
- Incident cooldown/dedup.
|
- Incident cooldown/dedup.
|
||||||
|
|
||||||
### Phase 2 (следующий шаг)
|
### Phase 2 (внедрено частично)
|
||||||
|
|
||||||
- USB/print/clipboard collectors.
|
- USB/print/clipboard collectors (endpoint signals) — внедрено.
|
||||||
- File-operation telemetry (create/copy/archive/upload hints).
|
- Incident pipeline расширен на endpoint события — внедрено.
|
||||||
- Central incident aggregation/export.
|
- File-operation telemetry (create/copy/archive/upload hints) — в backlog.
|
||||||
|
- Central incident aggregation/export — в backlog.
|
||||||
|
|
||||||
### Phase 3
|
### Phase 3
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
- `windows/hardening-recovery.ps1` — повторная регистрация задач, ACL и recovery-loop.
|
- `windows/hardening-recovery.ps1` — повторная регистрация задач, ACL и recovery-loop.
|
||||||
- `windows/validate-deployment.ps1` — машинная проверка состояния и JSON-отчёт.
|
- `windows/validate-deployment.ps1` — машинная проверка состояния и JSON-отчёт.
|
||||||
- `windows/browser-domains-native-collector.ps1` — native collector доменов браузера с категоризацией.
|
- `windows/browser-domains-native-collector.ps1` — native collector доменов браузера с категоризацией.
|
||||||
|
- `windows/dlp-endpoint-signals-collector.ps1` — phase-2 collector (clipboard/USB/print signals).
|
||||||
- `windows/web-category-rules.example.json` — пример кастомных правил категоризации.
|
- `windows/web-category-rules.example.json` — пример кастомных правил категоризации.
|
||||||
- `windows/dlp-policy.example.json` — пример DLP-политики (phase-1: alerting incidents).
|
- `windows/dlp-policy.example.json` — пример DLP-политики (phase-1: alerting incidents).
|
||||||
|
|
||||||
@@ -124,6 +125,7 @@ CSV-формат: колонка `User`, `Username`, `SamAccountName` или `Lo
|
|||||||
- `C:\ProgramData\ActivityWatch\launch-watchers.ps1` — per-user launcher.
|
- `C:\ProgramData\ActivityWatch\launch-watchers.ps1` — per-user launcher.
|
||||||
- `C:\ProgramData\ActivityWatch\recovery-loop.ps1` — system recovery loop.
|
- `C:\ProgramData\ActivityWatch\recovery-loop.ps1` — system recovery loop.
|
||||||
- `C:\ProgramData\ActivityWatch\browser-domains-native-collector.ps1` — runtime collector.
|
- `C:\ProgramData\ActivityWatch\browser-domains-native-collector.ps1` — runtime collector.
|
||||||
|
- `C:\ProgramData\ActivityWatch\dlp-endpoint-signals-collector.ps1` — runtime endpoint collector.
|
||||||
- `C:\ProgramData\ActivityWatch\dlp-policy.json` — активная DLP-политика.
|
- `C:\ProgramData\ActivityWatch\dlp-policy.json` — активная DLP-политика.
|
||||||
- `C:\ProgramData\ActivityWatch\logs\` — логи collector'а.
|
- `C:\ProgramData\ActivityWatch\logs\` — логи collector'а.
|
||||||
|
|
||||||
|
|||||||
@@ -73,6 +73,7 @@ Invoke-WebRequest https://aw.example.local/api/0/info
|
|||||||
- `aw-watcher-window_<hostname>`
|
- `aw-watcher-window_<hostname>`
|
||||||
- `aw-watcher-web-edge_<hostname>` или другой browser bucket
|
- `aw-watcher-web-edge_<hostname>` или другой browser bucket
|
||||||
- `aw-detmir-web-category_<hostname>`
|
- `aw-detmir-web-category_<hostname>`
|
||||||
|
- `aw-dlp-endpoint-signals_<hostname>`
|
||||||
- `aw-dlp-incidents_<hostname>` (при срабатывании policy rule с `action=alert|block|quarantine`)
|
- `aw-dlp-incidents_<hostname>` (при срабатывании policy rule с `action=alert|block|quarantine`)
|
||||||
|
|
||||||
Проверка через API:
|
Проверка через API:
|
||||||
|
|||||||
@@ -241,6 +241,8 @@ function Copy-ActivityWatchCollectorAssets {
|
|||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$CollectorScriptSource,
|
[string]$CollectorScriptSource,
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$EndpointCollectorScriptSource,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ExampleRulesSource,
|
[string]$ExampleRulesSource,
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$ExamplePolicySource,
|
[string]$ExamplePolicySource,
|
||||||
@@ -253,12 +255,14 @@ function Copy-ActivityWatchCollectorAssets {
|
|||||||
New-ActivityWatchDirectory -Path $StateRoot
|
New-ActivityWatchDirectory -Path $StateRoot
|
||||||
|
|
||||||
$collectorTarget = Join-Path $StateRoot 'browser-domains-native-collector.ps1'
|
$collectorTarget = Join-Path $StateRoot 'browser-domains-native-collector.ps1'
|
||||||
|
$endpointCollectorTarget = Join-Path $StateRoot 'dlp-endpoint-signals-collector.ps1'
|
||||||
$exampleRulesTarget = Join-Path $StateRoot 'web-category-rules.example.json'
|
$exampleRulesTarget = Join-Path $StateRoot 'web-category-rules.example.json'
|
||||||
$rulesTarget = Join-Path $StateRoot 'web-category-rules.json'
|
$rulesTarget = Join-Path $StateRoot 'web-category-rules.json'
|
||||||
$examplePolicyTarget = Join-Path $StateRoot 'dlp-policy.example.json'
|
$examplePolicyTarget = Join-Path $StateRoot 'dlp-policy.example.json'
|
||||||
$policyTarget = Join-Path $StateRoot 'dlp-policy.json'
|
$policyTarget = Join-Path $StateRoot 'dlp-policy.json'
|
||||||
|
|
||||||
Copy-Item -LiteralPath $CollectorScriptSource -Destination $collectorTarget -Force
|
Copy-Item -LiteralPath $CollectorScriptSource -Destination $collectorTarget -Force
|
||||||
|
Copy-Item -LiteralPath $EndpointCollectorScriptSource -Destination $endpointCollectorTarget -Force
|
||||||
Copy-Item -LiteralPath $ExampleRulesSource -Destination $exampleRulesTarget -Force
|
Copy-Item -LiteralPath $ExampleRulesSource -Destination $exampleRulesTarget -Force
|
||||||
Copy-Item -LiteralPath $ExamplePolicySource -Destination $examplePolicyTarget -Force
|
Copy-Item -LiteralPath $ExamplePolicySource -Destination $examplePolicyTarget -Force
|
||||||
|
|
||||||
@@ -276,11 +280,12 @@ function Copy-ActivityWatchCollectorAssets {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return [pscustomobject]@{
|
return [pscustomobject]@{
|
||||||
CollectorScript = $collectorTarget
|
CollectorScript = $collectorTarget
|
||||||
ExampleRules = $exampleRulesTarget
|
EndpointCollectorScript = $endpointCollectorTarget
|
||||||
ActiveRules = $rulesTarget
|
ExampleRules = $exampleRulesTarget
|
||||||
ExamplePolicy = $examplePolicyTarget
|
ActiveRules = $rulesTarget
|
||||||
ActivePolicy = $policyTarget
|
ExamplePolicy = $examplePolicyTarget
|
||||||
|
ActivePolicy = $policyTarget
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -301,6 +306,8 @@ function New-ActivityWatchDeploymentConfig {
|
|||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$CollectorScript,
|
[string]$CollectorScript,
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
|
[string]$EndpointCollectorScript,
|
||||||
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$RulesPath,
|
[string]$RulesPath,
|
||||||
[Parameter(Mandatory = $true)]
|
[Parameter(Mandatory = $true)]
|
||||||
[string]$PolicyPath,
|
[string]$PolicyPath,
|
||||||
@@ -332,6 +339,7 @@ function New-ActivityWatchDeploymentConfig {
|
|||||||
stateRoot = $StateRoot
|
stateRoot = $StateRoot
|
||||||
logsRoot = $LogsRoot
|
logsRoot = $LogsRoot
|
||||||
collectorScript = $CollectorScript
|
collectorScript = $CollectorScript
|
||||||
|
endpointCollectorScript = $EndpointCollectorScript
|
||||||
rulesPath = $RulesPath
|
rulesPath = $RulesPath
|
||||||
policyPath = $PolicyPath
|
policyPath = $PolicyPath
|
||||||
launchScript = $LaunchScriptPath
|
launchScript = $LaunchScriptPath
|
||||||
@@ -418,11 +426,11 @@ function Test-ProcessInSession {
|
|||||||
|
|
||||||
function Test-CollectorRunning {
|
function Test-CollectorRunning {
|
||||||
param(
|
param(
|
||||||
[string]`$CollectorScript,
|
[string]`$ScriptPath,
|
||||||
[int]`$SessionId
|
[int]`$SessionId
|
||||||
)
|
)
|
||||||
|
|
||||||
`$escapedCollector = [Regex]::Escape(`$CollectorScript)
|
`$escapedCollector = [Regex]::Escape(`$ScriptPath)
|
||||||
`$processes = Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
`$processes = Get-CimInstance Win32_Process -ErrorAction SilentlyContinue |
|
||||||
Where-Object {
|
Where-Object {
|
||||||
(`$_.Name -ieq 'powershell.exe' -or `$_.Name -ieq 'pwsh.exe') -and
|
(`$_.Name -ieq 'powershell.exe' -or `$_.Name -ieq 'pwsh.exe') -and
|
||||||
@@ -433,10 +441,36 @@ function Test-CollectorRunning {
|
|||||||
return [bool](`$processes | Select-Object -First 1)
|
return [bool](`$processes | Select-Object -First 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Start-CollectorScriptIfNeeded {
|
||||||
|
param(
|
||||||
|
[string]`$ScriptPath,
|
||||||
|
[string]`$ConfigPath,
|
||||||
|
[string]`$PowerShellExe,
|
||||||
|
[int]`$SessionId
|
||||||
|
)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath `$ScriptPath)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Test-CollectorRunning -ScriptPath `$ScriptPath -SessionId `$SessionId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Process -FilePath `$PowerShellExe -ArgumentList @(
|
||||||
|
'-NoProfile',
|
||||||
|
'-WindowStyle', 'Hidden',
|
||||||
|
'-ExecutionPolicy', 'Bypass',
|
||||||
|
'-File', `$ScriptPath,
|
||||||
|
'-ConfigPath', `$ConfigPath
|
||||||
|
) -WindowStyle Hidden
|
||||||
|
}
|
||||||
|
|
||||||
`$config = Get-DeploymentConfig -Path `$ConfigPath
|
`$config = Get-DeploymentConfig -Path `$ConfigPath
|
||||||
`$sessionId = (Get-Process -Id `$PID).SessionId
|
`$sessionId = (Get-Process -Id `$PID).SessionId
|
||||||
`$installRoot = [string]`$config.paths.installRoot
|
`$installRoot = [string]`$config.paths.installRoot
|
||||||
`$collectorScript = [string]`$config.paths.collectorScript
|
`$collectorScript = [string]`$config.paths.collectorScript
|
||||||
|
`$endpointCollectorScript = if (`$config.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]`$config.paths.endpointCollectorScript } else { '' }
|
||||||
`$afkExe = Join-Path `$installRoot 'aw-watcher-afk\aw-watcher-afk.exe'
|
`$afkExe = Join-Path `$installRoot 'aw-watcher-afk\aw-watcher-afk.exe'
|
||||||
`$windowExe = Join-Path `$installRoot 'aw-watcher-window\aw-watcher-window.exe'
|
`$windowExe = Join-Path `$installRoot 'aw-watcher-window\aw-watcher-window.exe'
|
||||||
`$serverArgs = @('--host', [string]`$config.server.host, '--port', [string]`$config.server.port)
|
`$serverArgs = @('--host', [string]`$config.server.host, '--port', [string]`$config.server.port)
|
||||||
@@ -458,15 +492,8 @@ if (-not (Test-ProcessInSession -Name 'aw-watcher-window' -SessionId `$sessionId
|
|||||||
Start-Process -FilePath `$windowExe -ArgumentList `$serverArgs -WindowStyle Hidden
|
Start-Process -FilePath `$windowExe -ArgumentList `$serverArgs -WindowStyle Hidden
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((Test-Path -LiteralPath `$collectorScript) -and -not (Test-CollectorRunning -CollectorScript `$collectorScript -SessionId `$sessionId)) {
|
Start-CollectorScriptIfNeeded -ScriptPath `$collectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
|
||||||
Start-Process -FilePath `$powershellExe -ArgumentList @(
|
Start-CollectorScriptIfNeeded -ScriptPath `$endpointCollectorScript -ConfigPath `$ConfigPath -PowerShellExe `$powershellExe -SessionId `$sessionId
|
||||||
'-NoProfile',
|
|
||||||
'-WindowStyle', 'Hidden',
|
|
||||||
'-ExecutionPolicy', 'Bypass',
|
|
||||||
'-File', `$collectorScript,
|
|
||||||
'-ConfigPath', `$ConfigPath
|
|
||||||
) -WindowStyle Hidden
|
|
||||||
}
|
|
||||||
"@
|
"@
|
||||||
|
|
||||||
Set-Content -LiteralPath $Path -Value $content -Encoding UTF8
|
Set-Content -LiteralPath $Path -Value $content -Encoding UTF8
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ $configPath = Join-Path $StateRoot 'deployment-config.json'
|
|||||||
$launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
|
$launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
|
||||||
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
|
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
|
||||||
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
|
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
|
||||||
|
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
|
||||||
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
|
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
|
||||||
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
|
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
|
||||||
|
|
||||||
@@ -48,6 +49,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
|
|||||||
|
|
||||||
$assetResult = Copy-ActivityWatchCollectorAssets `
|
$assetResult = Copy-ActivityWatchCollectorAssets `
|
||||||
-CollectorScriptSource $collectorSource `
|
-CollectorScriptSource $collectorSource `
|
||||||
|
-EndpointCollectorScriptSource $endpointCollectorSource `
|
||||||
-ExampleRulesSource $exampleRulesSource `
|
-ExampleRulesSource $exampleRulesSource `
|
||||||
-ExamplePolicySource $examplePolicySource `
|
-ExamplePolicySource $examplePolicySource `
|
||||||
-StateRoot $StateRoot `
|
-StateRoot $StateRoot `
|
||||||
@@ -66,6 +68,7 @@ $config = New-ActivityWatchDeploymentConfig `
|
|||||||
-StateRoot $StateRoot `
|
-StateRoot $StateRoot `
|
||||||
-LogsRoot $logsRoot `
|
-LogsRoot $logsRoot `
|
||||||
-CollectorScript $assetResult.CollectorScript `
|
-CollectorScript $assetResult.CollectorScript `
|
||||||
|
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
|
||||||
-RulesPath $assetResult.ActiveRules `
|
-RulesPath $assetResult.ActiveRules `
|
||||||
-PolicyPath $assetResult.ActivePolicy `
|
-PolicyPath $assetResult.ActivePolicy `
|
||||||
-PollSeconds $PollSeconds `
|
-PollSeconds $PollSeconds `
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ $configPath = Join-Path $StateRoot 'deployment-config.json'
|
|||||||
$launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
|
$launchScriptPath = Join-Path $StateRoot 'launch-watchers.ps1'
|
||||||
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
|
$recoveryScriptPath = Join-Path $StateRoot 'recovery-loop.ps1'
|
||||||
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
|
$collectorSource = Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1'
|
||||||
|
$endpointCollectorSource = Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1'
|
||||||
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
|
$exampleRulesSource = Join-Path $PSScriptRoot 'web-category-rules.example.json'
|
||||||
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
|
$examplePolicySource = Join-Path $PSScriptRoot 'dlp-policy.example.json'
|
||||||
|
|
||||||
@@ -46,6 +47,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $InstallRoot | Out-Null
|
|||||||
|
|
||||||
$assetResult = Copy-ActivityWatchCollectorAssets `
|
$assetResult = Copy-ActivityWatchCollectorAssets `
|
||||||
-CollectorScriptSource $collectorSource `
|
-CollectorScriptSource $collectorSource `
|
||||||
|
-EndpointCollectorScriptSource $endpointCollectorSource `
|
||||||
-ExampleRulesSource $exampleRulesSource `
|
-ExampleRulesSource $exampleRulesSource `
|
||||||
-ExamplePolicySource $examplePolicySource `
|
-ExamplePolicySource $examplePolicySource `
|
||||||
-StateRoot $StateRoot `
|
-StateRoot $StateRoot `
|
||||||
@@ -64,6 +66,7 @@ $config = New-ActivityWatchDeploymentConfig `
|
|||||||
-StateRoot $StateRoot `
|
-StateRoot $StateRoot `
|
||||||
-LogsRoot $logsRoot `
|
-LogsRoot $logsRoot `
|
||||||
-CollectorScript $assetResult.CollectorScript `
|
-CollectorScript $assetResult.CollectorScript `
|
||||||
|
-EndpointCollectorScript $assetResult.EndpointCollectorScript `
|
||||||
-RulesPath $assetResult.ActiveRules `
|
-RulesPath $assetResult.ActiveRules `
|
||||||
-PolicyPath $assetResult.ActivePolicy `
|
-PolicyPath $assetResult.ActivePolicy `
|
||||||
-PollSeconds $PollSeconds `
|
-PollSeconds $PollSeconds `
|
||||||
|
|||||||
@@ -0,0 +1,405 @@
|
|||||||
|
[CmdletBinding()]
|
||||||
|
param(
|
||||||
|
[string]$ConfigPath = 'C:\ProgramData\ActivityWatch\deployment-config.json',
|
||||||
|
[string]$ServerHost,
|
||||||
|
[int]$ServerPort,
|
||||||
|
[ValidateSet('http', 'https')]
|
||||||
|
[string]$ServerScheme,
|
||||||
|
[string]$PolicyPath,
|
||||||
|
[string]$LogPath,
|
||||||
|
[int]$PollSeconds
|
||||||
|
)
|
||||||
|
|
||||||
|
Set-StrictMode -Version Latest
|
||||||
|
$ErrorActionPreference = 'Stop'
|
||||||
|
|
||||||
|
function Get-DeploymentConfig {
|
||||||
|
param([string]$Path)
|
||||||
|
if ($Path -and (Test-Path -LiteralPath $Path)) {
|
||||||
|
return Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||||
|
}
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Write-EndpointLog {
|
||||||
|
param([string]$Message)
|
||||||
|
try {
|
||||||
|
Add-Content -LiteralPath $script:LogPath -Value ('{0} {1}' -f (Get-Date -Format s), $Message)
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Ensure-Bucket {
|
||||||
|
param(
|
||||||
|
[string]$BucketId,
|
||||||
|
[string]$ClientName,
|
||||||
|
[string]$BucketType
|
||||||
|
)
|
||||||
|
|
||||||
|
if ($script:KnownBuckets.ContainsKey($BucketId)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
$body = @{
|
||||||
|
client = $ClientName
|
||||||
|
type = $BucketType
|
||||||
|
hostname = $script:Hostname
|
||||||
|
} | ConvertTo-Json -Compress
|
||||||
|
|
||||||
|
Invoke-RestMethod -Method Post -Uri "$($script:ApiBase)/buckets/$BucketId" -ContentType 'application/json' -Body $body | Out-Null
|
||||||
|
$script:KnownBuckets[$BucketId] = $true
|
||||||
|
}
|
||||||
|
|
||||||
|
function Send-EndpointSignalHeartbeat {
|
||||||
|
param(
|
||||||
|
[string]$SignalType,
|
||||||
|
[hashtable]$Data
|
||||||
|
)
|
||||||
|
|
||||||
|
$bucketId = 'aw-dlp-endpoint-signals_' + $script:Hostname
|
||||||
|
Ensure-Bucket -BucketId $bucketId -ClientName 'aw-dlp-endpoint-signals' -BucketType 'aw.dlp.endpoint.signal'
|
||||||
|
|
||||||
|
$payload = @{
|
||||||
|
timestamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
|
||||||
|
duration = 0
|
||||||
|
data = @{
|
||||||
|
signalType = $SignalType
|
||||||
|
username = $env:USERNAME
|
||||||
|
sessionId = $script:SessionId
|
||||||
|
hostname = $script:Hostname
|
||||||
|
source = 'endpoint-signals-phase2'
|
||||||
|
} + $Data
|
||||||
|
} | ConvertTo-Json -Depth 6 -Compress
|
||||||
|
|
||||||
|
Invoke-RestMethod -Method Post -Uri "$($script:ApiBase)/buckets/$bucketId/heartbeat?pulsetime=$script:PulseSeconds" -ContentType 'application/json' -Body $payload | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Send-DlpIncidentHeartbeat {
|
||||||
|
param(
|
||||||
|
[string]$RuleId,
|
||||||
|
[string]$Action,
|
||||||
|
[string]$Severity,
|
||||||
|
[string]$Message,
|
||||||
|
[string]$SignalType,
|
||||||
|
[hashtable]$Data
|
||||||
|
)
|
||||||
|
|
||||||
|
$bucketId = 'aw-dlp-incidents_' + $script:Hostname
|
||||||
|
Ensure-Bucket -BucketId $bucketId -ClientName 'aw-dlp-incidents' -BucketType 'aw.dlp.incident'
|
||||||
|
|
||||||
|
$payload = @{
|
||||||
|
timestamp = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ss.fffZ')
|
||||||
|
duration = 0
|
||||||
|
data = @{
|
||||||
|
ruleId = $RuleId
|
||||||
|
action = $Action
|
||||||
|
severity = $Severity
|
||||||
|
message = $Message
|
||||||
|
signalType = $SignalType
|
||||||
|
username = $env:USERNAME
|
||||||
|
sessionId = $script:SessionId
|
||||||
|
hostname = $script:Hostname
|
||||||
|
source = 'endpoint-signals-phase2'
|
||||||
|
} + $Data
|
||||||
|
} | ConvertTo-Json -Depth 7 -Compress
|
||||||
|
|
||||||
|
Invoke-RestMethod -Method Post -Uri "$($script:ApiBase)/buckets/$bucketId/heartbeat?pulsetime=$script:PulseSeconds" -ContentType 'application/json' -Body $payload | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
function Get-StringHash {
|
||||||
|
param([AllowNull()][string]$Value)
|
||||||
|
if ($null -eq $Value) { return $null }
|
||||||
|
$bytes = [Text.Encoding]::UTF8.GetBytes($Value)
|
||||||
|
$sha = [Security.Cryptography.SHA256]::Create()
|
||||||
|
try {
|
||||||
|
($sha.ComputeHash($bytes) | ForEach-Object { $_.ToString('x2') }) -join ''
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
$sha.Dispose()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Load-DlpPolicy {
|
||||||
|
param([string]$Path)
|
||||||
|
|
||||||
|
$script:Policy = [ordered]@{
|
||||||
|
defaults = [ordered]@{
|
||||||
|
enabled = $true
|
||||||
|
cooldownSeconds = 300
|
||||||
|
action = 'alert'
|
||||||
|
severity = 'medium'
|
||||||
|
}
|
||||||
|
endpoint = [ordered]@{
|
||||||
|
clipboard = @()
|
||||||
|
usb = @()
|
||||||
|
print = @()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $Path -or -not (Test-Path -LiteralPath $Path)) {
|
||||||
|
Write-EndpointLog ("policy not found, using defaults: {0}" -f $Path)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$raw = Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||||
|
if ($raw.defaults) {
|
||||||
|
if ($raw.defaults.PSObject.Properties.Name -contains 'enabled') { $script:Policy.defaults.enabled = [bool]$raw.defaults.enabled }
|
||||||
|
if ($raw.defaults.cooldownSeconds) { $script:Policy.defaults.cooldownSeconds = [int]$raw.defaults.cooldownSeconds }
|
||||||
|
if ($raw.defaults.action) { $script:Policy.defaults.action = [string]$raw.defaults.action }
|
||||||
|
if ($raw.defaults.severity) { $script:Policy.defaults.severity = [string]$raw.defaults.severity }
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($raw.endpoint) {
|
||||||
|
if ($raw.endpoint.clipboard) { $script:Policy.endpoint.clipboard = @($raw.endpoint.clipboard) }
|
||||||
|
if ($raw.endpoint.usb) { $script:Policy.endpoint.usb = @($raw.endpoint.usb) }
|
||||||
|
if ($raw.endpoint.print) { $script:Policy.endpoint.print = @($raw.endpoint.print) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-EndpointLog ("policy parse failed: {0}" -f $_.Exception.Message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Should-EmitByCooldown {
|
||||||
|
param(
|
||||||
|
[string]$Fingerprint,
|
||||||
|
[int]$CooldownSeconds
|
||||||
|
)
|
||||||
|
|
||||||
|
$now = (Get-Date).ToUniversalTime()
|
||||||
|
if ($script:Cooldown.ContainsKey($Fingerprint)) {
|
||||||
|
$last = [datetime]$script:Cooldown[$Fingerprint]
|
||||||
|
if ((New-TimeSpan -Start $last -End $now).TotalSeconds -lt $CooldownSeconds) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:Cooldown[$Fingerprint] = $now
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
|
function Evaluate-ClipboardRules {
|
||||||
|
param(
|
||||||
|
[string]$ClipboardText,
|
||||||
|
[string]$ClipboardHash
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($rule in @($script:Policy.endpoint.clipboard)) {
|
||||||
|
if (-not $rule) { continue }
|
||||||
|
if ($rule.PSObject.Properties.Name -contains 'enabled' -and -not [bool]$rule.enabled) { continue }
|
||||||
|
$ruleId = [string]$rule.id
|
||||||
|
if (-not $ruleId) { continue }
|
||||||
|
$minLength = if ($rule.minLength) { [int]$rule.minLength } else { 0 }
|
||||||
|
$regexPatterns = if ($rule.regexPatterns) { @($rule.regexPatterns) } else { @() }
|
||||||
|
if ($ClipboardText.Length -lt $minLength) { continue }
|
||||||
|
|
||||||
|
$matched = $false
|
||||||
|
foreach ($pattern in $regexPatterns) {
|
||||||
|
if ($ClipboardText -match [string]$pattern) {
|
||||||
|
$matched = $true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (-not $matched) { continue }
|
||||||
|
|
||||||
|
$cooldown = if ($rule.cooldownSeconds) { [int]$rule.cooldownSeconds } else { [int]$script:Policy.defaults.cooldownSeconds }
|
||||||
|
$fingerprint = "clipboard|$ruleId|$ClipboardHash|$env:USERNAME"
|
||||||
|
if (-not (Should-EmitByCooldown -Fingerprint $fingerprint -CooldownSeconds ([Math]::Max($cooldown, 30)))) { continue }
|
||||||
|
|
||||||
|
$action = if ($rule.action) { [string]$rule.action } else { [string]$script:Policy.defaults.action }
|
||||||
|
$severity = if ($rule.severity) { [string]$rule.severity } else { [string]$script:Policy.defaults.severity }
|
||||||
|
$message = if ($rule.message) { [string]$rule.message } else { "Clipboard rule matched: $ruleId" }
|
||||||
|
|
||||||
|
Send-DlpIncidentHeartbeat -RuleId $ruleId -Action $action -Severity $severity -Message $message -SignalType 'clipboard' -Data @{
|
||||||
|
clipboardHash = $ClipboardHash
|
||||||
|
clipboardLength = $ClipboardText.Length
|
||||||
|
}
|
||||||
|
Write-EndpointLog ("incident clipboard rule={0} action={1} severity={2}" -f $ruleId, $action, $severity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Evaluate-UsbRules {
|
||||||
|
param(
|
||||||
|
[string]$DriveLetter,
|
||||||
|
[string]$VolumeName
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($rule in @($script:Policy.endpoint.usb)) {
|
||||||
|
if (-not $rule) { continue }
|
||||||
|
if ($rule.PSObject.Properties.Name -contains 'enabled' -and -not [bool]$rule.enabled) { continue }
|
||||||
|
$ruleId = [string]$rule.id
|
||||||
|
if (-not $ruleId) { continue }
|
||||||
|
|
||||||
|
$cooldown = if ($rule.cooldownSeconds) { [int]$rule.cooldownSeconds } else { [int]$script:Policy.defaults.cooldownSeconds }
|
||||||
|
$fingerprint = "usb|$ruleId|$DriveLetter|$env:USERNAME"
|
||||||
|
if (-not (Should-EmitByCooldown -Fingerprint $fingerprint -CooldownSeconds ([Math]::Max($cooldown, 30)))) { continue }
|
||||||
|
|
||||||
|
$action = if ($rule.action) { [string]$rule.action } else { [string]$script:Policy.defaults.action }
|
||||||
|
$severity = if ($rule.severity) { [string]$rule.severity } else { [string]$script:Policy.defaults.severity }
|
||||||
|
$message = if ($rule.message) { [string]$rule.message } else { "USB rule matched: $ruleId" }
|
||||||
|
|
||||||
|
Send-DlpIncidentHeartbeat -RuleId $ruleId -Action $action -Severity $severity -Message $message -SignalType 'usb_insert' -Data @{
|
||||||
|
driveLetter = $DriveLetter
|
||||||
|
volumeName = $VolumeName
|
||||||
|
}
|
||||||
|
Write-EndpointLog ("incident usb rule={0} action={1} severity={2} drive={3}" -f $ruleId, $action, $severity, $DriveLetter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Evaluate-PrintRules {
|
||||||
|
param(
|
||||||
|
[string]$PrinterName,
|
||||||
|
[string]$DocumentName,
|
||||||
|
[string]$Owner
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach ($rule in @($script:Policy.endpoint.print)) {
|
||||||
|
if (-not $rule) { continue }
|
||||||
|
if ($rule.PSObject.Properties.Name -contains 'enabled' -and -not [bool]$rule.enabled) { continue }
|
||||||
|
$ruleId = [string]$rule.id
|
||||||
|
if (-not $ruleId) { continue }
|
||||||
|
|
||||||
|
$match = $true
|
||||||
|
if ($rule.printerRegex) {
|
||||||
|
$match = $match -and ($PrinterName -match [string]$rule.printerRegex)
|
||||||
|
}
|
||||||
|
if ($rule.documentRegex) {
|
||||||
|
$match = $match -and ($DocumentName -match [string]$rule.documentRegex)
|
||||||
|
}
|
||||||
|
if (-not $match) { continue }
|
||||||
|
|
||||||
|
$cooldown = if ($rule.cooldownSeconds) { [int]$rule.cooldownSeconds } else { [int]$script:Policy.defaults.cooldownSeconds }
|
||||||
|
$fingerprint = "print|$ruleId|$PrinterName|$Owner|$env:USERNAME"
|
||||||
|
if (-not (Should-EmitByCooldown -Fingerprint $fingerprint -CooldownSeconds ([Math]::Max($cooldown, 30)))) { continue }
|
||||||
|
|
||||||
|
$action = if ($rule.action) { [string]$rule.action } else { [string]$script:Policy.defaults.action }
|
||||||
|
$severity = if ($rule.severity) { [string]$rule.severity } else { [string]$script:Policy.defaults.severity }
|
||||||
|
$message = if ($rule.message) { [string]$rule.message } else { "Print rule matched: $ruleId" }
|
||||||
|
|
||||||
|
Send-DlpIncidentHeartbeat -RuleId $ruleId -Action $action -Severity $severity -Message $message -SignalType 'print_job' -Data @{
|
||||||
|
printerName = $PrinterName
|
||||||
|
documentName = $DocumentName
|
||||||
|
owner = $Owner
|
||||||
|
}
|
||||||
|
Write-EndpointLog ("incident print rule={0} action={1} severity={2} printer={3}" -f $ruleId, $action, $severity, $PrinterName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$deploymentConfig = Get-DeploymentConfig -Path $ConfigPath
|
||||||
|
$resolvedServerHost = if ($ServerHost) { $ServerHost } elseif ($deploymentConfig) { [string]$deploymentConfig.server.host } else { throw 'ServerHost is required.' }
|
||||||
|
$resolvedServerPort = if ($PSBoundParameters.ContainsKey('ServerPort')) { $ServerPort } elseif ($deploymentConfig) { [int]$deploymentConfig.server.port } else { 5600 }
|
||||||
|
$resolvedServerScheme = if ($ServerScheme) { $ServerScheme } elseif ($deploymentConfig) { [string]$deploymentConfig.server.scheme } else { 'http' }
|
||||||
|
$resolvedPolicyPath = if ($PolicyPath) { $PolicyPath } elseif ($deploymentConfig -and $deploymentConfig.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$deploymentConfig.paths.policyPath } else { 'C:\ProgramData\ActivityWatch\dlp-policy.json' }
|
||||||
|
$resolvedPollSeconds = if ($PSBoundParameters.ContainsKey('PollSeconds')) { $PollSeconds } elseif ($deploymentConfig) { [int]$deploymentConfig.collector.pollSeconds } else { 5 }
|
||||||
|
$resolvedLogsRoot = if ($deploymentConfig) { [string]$deploymentConfig.paths.logsRoot } else { 'C:\ProgramData\ActivityWatch\logs' }
|
||||||
|
$resolvedLogPath = if ($LogPath) { $LogPath } else { Join-Path $resolvedLogsRoot ("endpoint-signals-{0}.log" -f $env:USERNAME) }
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $resolvedLogsRoot)) {
|
||||||
|
New-Item -Path $resolvedLogsRoot -ItemType Directory -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
$script:ApiBase = '{0}://{1}:{2}/api/0' -f $resolvedServerScheme, $resolvedServerHost, $resolvedServerPort
|
||||||
|
$script:Hostname = $env:COMPUTERNAME
|
||||||
|
$script:SessionId = (Get-Process -Id $PID).SessionId
|
||||||
|
$script:KnownBuckets = @{}
|
||||||
|
$script:Cooldown = @{}
|
||||||
|
$script:SeenUsb = @{}
|
||||||
|
$script:SeenPrintJob = @{}
|
||||||
|
$script:LastClipboardHash = $null
|
||||||
|
$script:PulseSeconds = [Math]::Max($resolvedPollSeconds * 3, 30)
|
||||||
|
$script:LogPath = $resolvedLogPath
|
||||||
|
|
||||||
|
Load-DlpPolicy -Path $resolvedPolicyPath
|
||||||
|
Write-EndpointLog ("endpoint collector started against {0}" -f $script:ApiBase)
|
||||||
|
|
||||||
|
while ($true) {
|
||||||
|
try {
|
||||||
|
if (-not $script:Policy.defaults.enabled) {
|
||||||
|
Start-Sleep -Seconds $resolvedPollSeconds
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$clipboardText = Get-Clipboard -Raw -ErrorAction SilentlyContinue
|
||||||
|
if ($clipboardText) {
|
||||||
|
$clipboardHash = Get-StringHash -Value $clipboardText
|
||||||
|
if ($clipboardHash -and $clipboardHash -ne $script:LastClipboardHash) {
|
||||||
|
$script:LastClipboardHash = $clipboardHash
|
||||||
|
Send-EndpointSignalHeartbeat -SignalType 'clipboard_change' -Data @{
|
||||||
|
clipboardHash = $clipboardHash
|
||||||
|
clipboardLength = $clipboardText.Length
|
||||||
|
}
|
||||||
|
Evaluate-ClipboardRules -ClipboardText $clipboardText -ClipboardHash $clipboardHash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$usbDrives = Get-CimInstance Win32_LogicalDisk -Filter "DriveType=2" -ErrorAction SilentlyContinue
|
||||||
|
$currentUsb = @{}
|
||||||
|
foreach ($drive in @($usbDrives)) {
|
||||||
|
$deviceId = [string]$drive.DeviceID
|
||||||
|
if (-not $deviceId) { continue }
|
||||||
|
$currentUsb[$deviceId] = $true
|
||||||
|
if (-not $script:SeenUsb.ContainsKey($deviceId)) {
|
||||||
|
$script:SeenUsb[$deviceId] = (Get-Date).ToUniversalTime()
|
||||||
|
$volumeName = [string]$drive.VolumeName
|
||||||
|
Send-EndpointSignalHeartbeat -SignalType 'usb_insert' -Data @{
|
||||||
|
driveLetter = $deviceId
|
||||||
|
volumeName = $volumeName
|
||||||
|
}
|
||||||
|
Evaluate-UsbRules -DriveLetter $deviceId -VolumeName $volumeName
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach ($known in @($script:SeenUsb.Keys)) {
|
||||||
|
if (-not $currentUsb.ContainsKey($known)) {
|
||||||
|
$script:SeenUsb.Remove($known)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$printJobs = Get-CimInstance Win32_PrintJob -ErrorAction SilentlyContinue
|
||||||
|
foreach ($job in @($printJobs)) {
|
||||||
|
$jobId = [string]$job.JobId
|
||||||
|
if (-not $jobId) { continue }
|
||||||
|
if ($script:SeenPrintJob.ContainsKey($jobId)) { continue }
|
||||||
|
$script:SeenPrintJob[$jobId] = (Get-Date).ToUniversalTime()
|
||||||
|
|
||||||
|
$printerName = [string]$job.Name
|
||||||
|
$documentName = [string]$job.Document
|
||||||
|
$owner = [string]$job.Owner
|
||||||
|
|
||||||
|
Send-EndpointSignalHeartbeat -SignalType 'print_job' -Data @{
|
||||||
|
printerName = $printerName
|
||||||
|
documentName = $documentName
|
||||||
|
owner = $owner
|
||||||
|
}
|
||||||
|
Evaluate-PrintRules -PrinterName $printerName -DocumentName $documentName -Owner $owner
|
||||||
|
}
|
||||||
|
|
||||||
|
$cleanupBefore = (Get-Date).ToUniversalTime().AddHours(-8)
|
||||||
|
foreach ($k in @($script:SeenPrintJob.Keys)) {
|
||||||
|
$ts = [datetime]$script:SeenPrintJob[$k]
|
||||||
|
if ($ts -lt $cleanupBefore) {
|
||||||
|
$script:SeenPrintJob.Remove($k)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch {
|
||||||
|
Write-EndpointLog ("collector error: {0}" -f $_.Exception.Message)
|
||||||
|
}
|
||||||
|
|
||||||
|
Start-Sleep -Seconds $resolvedPollSeconds
|
||||||
|
}
|
||||||
@@ -54,5 +54,46 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"endpoint": {
|
||||||
|
"clipboard": [
|
||||||
|
{
|
||||||
|
"id": "clipboard-sensitive-keywords",
|
||||||
|
"enabled": true,
|
||||||
|
"cooldownSeconds": 300,
|
||||||
|
"action": "alert",
|
||||||
|
"severity": "high",
|
||||||
|
"message": "В буфере обнаружены чувствительные ключевые слова",
|
||||||
|
"minLength": 20,
|
||||||
|
"regexPatterns": [
|
||||||
|
"(?i)парол(ь|и)",
|
||||||
|
"(?i)password",
|
||||||
|
"(?i)secret",
|
||||||
|
"(?i)cvv",
|
||||||
|
"(?i)паспорт"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"usb": [
|
||||||
|
{
|
||||||
|
"id": "usb-media-connected",
|
||||||
|
"enabled": true,
|
||||||
|
"cooldownSeconds": 300,
|
||||||
|
"action": "alert",
|
||||||
|
"severity": "medium",
|
||||||
|
"message": "Подключен съемный носитель"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"print": [
|
||||||
|
{
|
||||||
|
"id": "print-sensitive-docs",
|
||||||
|
"enabled": true,
|
||||||
|
"cooldownSeconds": 300,
|
||||||
|
"action": "alert",
|
||||||
|
"severity": "high",
|
||||||
|
"message": "Печать документа с признаками чувствительных данных",
|
||||||
|
"documentRegex": "(?i)(salary|зарплат|passport|паспорт|договор|contract)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ $effectiveConfigPath = if ($ConfigPath) { $ConfigPath } else { Join-Path $effect
|
|||||||
$effectiveLaunchScript = Join-Path $effectiveStateRoot 'launch-watchers.ps1'
|
$effectiveLaunchScript = Join-Path $effectiveStateRoot 'launch-watchers.ps1'
|
||||||
$effectiveRecoveryScript = Join-Path $effectiveStateRoot 'recovery-loop.ps1'
|
$effectiveRecoveryScript = Join-Path $effectiveStateRoot 'recovery-loop.ps1'
|
||||||
$effectiveCollector = Join-Path $effectiveStateRoot 'browser-domains-native-collector.ps1'
|
$effectiveCollector = Join-Path $effectiveStateRoot 'browser-domains-native-collector.ps1'
|
||||||
|
$effectiveEndpointCollector = Join-Path $effectiveStateRoot 'dlp-endpoint-signals-collector.ps1'
|
||||||
$effectiveRules = Join-Path $effectiveStateRoot 'web-category-rules.json'
|
$effectiveRules = Join-Path $effectiveStateRoot 'web-category-rules.json'
|
||||||
$effectivePolicy = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$existingConfig.paths.policyPath } else { Join-Path $effectiveStateRoot 'dlp-policy.json' }
|
$effectivePolicy = if ($existingConfig -and $existingConfig.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$existingConfig.paths.policyPath } else { Join-Path $effectiveStateRoot 'dlp-policy.json' }
|
||||||
|
|
||||||
@@ -80,6 +81,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $effectiveInstallRoot | Out-Null
|
|||||||
|
|
||||||
$assetResult = Copy-ActivityWatchCollectorAssets `
|
$assetResult = Copy-ActivityWatchCollectorAssets `
|
||||||
-CollectorScriptSource (Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1') `
|
-CollectorScriptSource (Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1') `
|
||||||
|
-EndpointCollectorScriptSource (Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1') `
|
||||||
-ExampleRulesSource (Join-Path $PSScriptRoot 'web-category-rules.example.json') `
|
-ExampleRulesSource (Join-Path $PSScriptRoot 'web-category-rules.example.json') `
|
||||||
-ExamplePolicySource (Join-Path $PSScriptRoot 'dlp-policy.example.json') `
|
-ExamplePolicySource (Join-Path $PSScriptRoot 'dlp-policy.example.json') `
|
||||||
-StateRoot $effectiveStateRoot `
|
-StateRoot $effectiveStateRoot `
|
||||||
@@ -87,6 +89,7 @@ $assetResult = Copy-ActivityWatchCollectorAssets `
|
|||||||
-CustomPolicySource $CustomPolicyPath
|
-CustomPolicySource $CustomPolicyPath
|
||||||
|
|
||||||
$effectivePolicy = [string]$assetResult.ActivePolicy
|
$effectivePolicy = [string]$assetResult.ActivePolicy
|
||||||
|
$effectiveEndpointCollector = [string]$assetResult.EndpointCollectorScript
|
||||||
|
|
||||||
$taskDefinitions = New-ActivityWatchUserTaskDefinitions -Users $effectiveUsers
|
$taskDefinitions = New-ActivityWatchUserTaskDefinitions -Users $effectiveUsers
|
||||||
Write-ActivityWatchLaunchScript -Path $effectiveLaunchScript -ConfigPath $effectiveConfigPath
|
Write-ActivityWatchLaunchScript -Path $effectiveLaunchScript -ConfigPath $effectiveConfigPath
|
||||||
@@ -100,6 +103,7 @@ $config = New-ActivityWatchDeploymentConfig `
|
|||||||
-StateRoot $effectiveStateRoot `
|
-StateRoot $effectiveStateRoot `
|
||||||
-LogsRoot $effectiveLogsRoot `
|
-LogsRoot $effectiveLogsRoot `
|
||||||
-CollectorScript $effectiveCollector `
|
-CollectorScript $effectiveCollector `
|
||||||
|
-EndpointCollectorScript $effectiveEndpointCollector `
|
||||||
-RulesPath $effectiveRules `
|
-RulesPath $effectiveRules `
|
||||||
-PolicyPath $effectivePolicy `
|
-PolicyPath $effectivePolicy `
|
||||||
-PollSeconds $effectivePollSeconds `
|
-PollSeconds $effectivePollSeconds `
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ $config = Read-ActivityWatchDeploymentConfig -Path $ConfigPath
|
|||||||
$installRoot = [string]$config.paths.installRoot
|
$installRoot = [string]$config.paths.installRoot
|
||||||
$stateRoot = [string]$config.paths.stateRoot
|
$stateRoot = [string]$config.paths.stateRoot
|
||||||
$collectorScript = [string]$config.paths.collectorScript
|
$collectorScript = [string]$config.paths.collectorScript
|
||||||
|
$endpointCollectorScript = if ($config.paths.PSObject.Properties.Name -contains 'endpointCollectorScript') { [string]$config.paths.endpointCollectorScript } else { Join-Path $stateRoot 'dlp-endpoint-signals-collector.ps1' }
|
||||||
$rulesPath = [string]$config.paths.rulesPath
|
$rulesPath = [string]$config.paths.rulesPath
|
||||||
$policyPath = if ($config.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$config.paths.policyPath } else { Join-Path $stateRoot 'dlp-policy.json' }
|
$policyPath = if ($config.paths.PSObject.Properties.Name -contains 'policyPath') { [string]$config.paths.policyPath } else { Join-Path $stateRoot 'dlp-policy.json' }
|
||||||
$launchScript = [string]$config.paths.launchScript
|
$launchScript = [string]$config.paths.launchScript
|
||||||
@@ -22,6 +23,7 @@ $requiredFiles = @(
|
|||||||
(Join-Path $installRoot 'aw-watcher-afk\aw-watcher-afk.exe'),
|
(Join-Path $installRoot 'aw-watcher-afk\aw-watcher-afk.exe'),
|
||||||
(Join-Path $installRoot 'aw-watcher-window\aw-watcher-window.exe'),
|
(Join-Path $installRoot 'aw-watcher-window\aw-watcher-window.exe'),
|
||||||
$collectorScript,
|
$collectorScript,
|
||||||
|
$endpointCollectorScript,
|
||||||
$rulesPath,
|
$rulesPath,
|
||||||
$policyPath,
|
$policyPath,
|
||||||
$launchScript,
|
$launchScript,
|
||||||
|
|||||||
Reference in New Issue
Block a user