Русифицировать DLP PowerShell и исправить имя документа печати
This commit is contained in:
@@ -5,7 +5,7 @@ function Assert-Administrator {
|
||||
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
|
||||
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
|
||||
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
||||
throw 'Run this script from an elevated PowerShell session.'
|
||||
throw 'Запустите этот скрипт из PowerShell с правами администратора.'
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ function Get-ActivityWatchPackageRoot {
|
||||
Select-Object -First 1
|
||||
|
||||
if (-not $afkBinary) {
|
||||
throw "Cannot find aw-watcher-afk.exe under $ExpandedRoot."
|
||||
throw "Не удалось найти aw-watcher-afk.exe в $ExpandedRoot."
|
||||
}
|
||||
|
||||
return (Split-Path -Path (Split-Path -Path $afkBinary.FullName -Parent) -Parent)
|
||||
@@ -130,7 +130,7 @@ function Get-ActivityWatchExecutableMap {
|
||||
|
||||
foreach ($entry in $map.GetEnumerator()) {
|
||||
if (-not (Test-Path -LiteralPath $entry.Value)) {
|
||||
throw "Missing required ActivityWatch binary: $($entry.Value)"
|
||||
throw "Не найден обязательный исполняемый файл ActivityWatch: $($entry.Value)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,7 +194,7 @@ function Normalize-ActivityWatchUsers {
|
||||
Sort-Object -Unique
|
||||
|
||||
if (-not $normalized -or $normalized.Count -eq 0) {
|
||||
throw 'No target users resolved. Provide -Users or -UserListPath.'
|
||||
throw 'Не удалось определить целевых пользователей. Укажите -Users или -UserListPath.'
|
||||
}
|
||||
|
||||
return @($normalized)
|
||||
@@ -421,7 +421,7 @@ function Read-ActivityWatchDeploymentConfig {
|
||||
)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
throw "Deployment config not found: $Path"
|
||||
throw "Конфигурация развёртывания не найдена: $Path"
|
||||
}
|
||||
|
||||
return Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||
@@ -648,11 +648,11 @@ function Start-CollectorScriptIfNeeded {
|
||||
`$windowEnabled = if (`$config.PSObject.Properties.Name -contains 'collectors' -and `$config.collectors.PSObject.Properties.Name -contains 'windowEnabled') { [bool]`$config.collectors.windowEnabled } else { `$true }
|
||||
|
||||
if (`$afkEnabled -and -not (Test-Path -LiteralPath `$afkExe)) {
|
||||
throw "Missing aw-watcher-afk.exe: `$afkExe"
|
||||
throw "Не найден aw-watcher-afk.exe: `$afkExe"
|
||||
}
|
||||
|
||||
if (`$windowEnabled -and -not (Test-Path -LiteralPath `$windowExe)) {
|
||||
throw "Missing aw-watcher-window.exe: `$windowExe"
|
||||
throw "Не найден aw-watcher-window.exe: `$windowExe"
|
||||
}
|
||||
|
||||
if (`$afkEnabled -and -not (Test-ProcessInSession -Name 'aw-watcher-afk' -SessionId `$sessionId)) {
|
||||
@@ -860,7 +860,7 @@ function Set-ActivityWatchScheduledTaskAction {
|
||||
$taskCommand = ('"{0}" {1}' -f $Execute, $Arguments)
|
||||
& schtasks.exe /Change /TN $TaskName /TR $taskCommand | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "schtasks.exe /Change failed for $TaskName"
|
||||
throw "schtasks.exe /Change завершился с ошибкой для $TaskName"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -961,17 +961,17 @@ function Set-ActivityWatchAcl {
|
||||
|
||||
& icacls $InstallRoot /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)(F)' '*S-1-5-32-544:(OI)(CI)(F)' '*S-1-5-32-545:(OI)(CI)(RX)' | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "icacls failed for $InstallRoot"
|
||||
throw "icacls завершился с ошибкой для $InstallRoot"
|
||||
}
|
||||
|
||||
& icacls $StateRoot /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)(F)' '*S-1-5-32-544:(OI)(CI)(F)' '*S-1-5-32-545:(OI)(CI)(RX)' | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "icacls failed for $StateRoot"
|
||||
throw "icacls завершился с ошибкой для $StateRoot"
|
||||
}
|
||||
|
||||
& icacls $LogsRoot /inheritance:r /grant:r '*S-1-5-18:(OI)(CI)(F)' '*S-1-5-32-544:(OI)(CI)(F)' '*S-1-5-32-545:(OI)(CI)(M)' | Out-Null
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "icacls failed for $LogsRoot"
|
||||
throw "icacls завершился с ошибкой для $LogsRoot"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,7 @@ function Get-DeploymentConfig {
|
||||
}
|
||||
|
||||
$deploymentConfig = Get-DeploymentConfig -Path $ConfigPath
|
||||
$resolvedServerHost = if ($ServerHost) { $ServerHost } elseif ($deploymentConfig) { [string]$deploymentConfig.server.host } else { throw 'ServerHost is required.' }
|
||||
$resolvedServerHost = if ($ServerHost) { $ServerHost } elseif ($deploymentConfig) { [string]$deploymentConfig.server.host } else { throw 'Укажите ServerHost или подготовьте deployment-config.json.' }
|
||||
$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' }
|
||||
$resolvedRulesPath = if ($RulesPath) { $RulesPath } elseif ($deploymentConfig) { [string]$deploymentConfig.paths.rulesPath } else { 'C:\ProgramData\ActivityWatch\web-category-rules.json' }
|
||||
@@ -263,11 +263,11 @@ function Load-CustomCategoryRules {
|
||||
|
||||
if ($rules.Count -gt 0) {
|
||||
$script:CategoryRules = @($rules) + @($script:CategoryRules)
|
||||
Write-CollectorLog ("custom rules loaded: {0}" -f $rules.Count)
|
||||
Write-CollectorLog ("пользовательские правила загружены: {0}" -f $rules.Count)
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-CollectorLog ("custom rules load failed: {0}" -f $_.Exception.Message)
|
||||
Write-CollectorLog ("не удалось загрузить пользовательские правила: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,7 +338,7 @@ function Load-DlpPolicy {
|
||||
param([string]$Path)
|
||||
|
||||
if (-not $Path -or -not (Test-Path -LiteralPath $Path)) {
|
||||
Write-CollectorLog ("dlp policy not found, disabled: {0}" -f $Path)
|
||||
Write-CollectorLog ("DLP-политика не найдена, DLP отключен: {0}" -f $Path)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -372,7 +372,7 @@ function Load-DlpPolicy {
|
||||
enabled = if ($rule.PSObject.Properties.Name -contains 'enabled') { [bool]$rule.enabled } else { $true }
|
||||
action = if ($rule.action) { [string]$rule.action } else { [string]$script:DlpDefaults.action }
|
||||
severity = if ($rule.severity) { [string]$rule.severity } else { [string]$script:DlpDefaults.severity }
|
||||
message = if ($rule.message) { [string]$rule.message } else { "DLP rule matched: $($rule.id)" }
|
||||
message = if ($rule.message) { [string]$rule.message } else { "Сработало DLP-правило: $($rule.id)" }
|
||||
cooldownSeconds = if ($rule.cooldownSeconds) { [int]$rule.cooldownSeconds } else { [int]$script:DlpDefaults.cooldownSeconds }
|
||||
when = [pscustomobject]@{
|
||||
domains = if ($when.PSObject.Properties.Name -contains 'domains') { @($when.domains | ForEach-Object { ([string]$_).Trim().ToLowerInvariant() } | Where-Object { $_ }) } else { @() }
|
||||
@@ -388,10 +388,10 @@ function Load-DlpPolicy {
|
||||
}
|
||||
|
||||
$script:DlpRules = @($loaded)
|
||||
Write-CollectorLog ("dlp policy loaded: enabled={0}, rules={1}" -f $script:DlpDefaults.enabled, $script:DlpRules.Count)
|
||||
Write-CollectorLog ("DLP-политика загружена: включена={0}, правил={1}" -f $script:DlpDefaults.enabled, $script:DlpRules.Count)
|
||||
}
|
||||
catch {
|
||||
Write-CollectorLog ("dlp policy parse failed: {0}" -f $_.Exception.Message)
|
||||
Write-CollectorLog ("не удалось разобрать DLP-политику: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -625,7 +625,7 @@ function Capture-IncidentScreenshot {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-CollectorLog ("screenshot capture failed: {0}" -f $_.Exception.Message)
|
||||
Write-CollectorLog ("не удалось сделать снимок инцидента: {0}" -f $_.Exception.Message)
|
||||
return @{}
|
||||
}
|
||||
}
|
||||
@@ -775,7 +775,7 @@ function Send-CategoryHeartbeat {
|
||||
|
||||
Load-CustomCategoryRules -Path $resolvedRulesPath
|
||||
Load-DlpPolicy -Path $resolvedPolicyPath
|
||||
Write-CollectorLog ("collector started against {0}" -f $script:ApiBase)
|
||||
Write-CollectorLog ("коллектор запущен для {0}" -f $script:ApiBase)
|
||||
|
||||
while ($true) {
|
||||
try {
|
||||
@@ -815,7 +815,7 @@ while ($true) {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-CollectorLog ("collector error: {0}" -f $_.Exception.Message)
|
||||
Write-CollectorLog ("ошибка коллектора: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $resolvedPollSeconds
|
||||
|
||||
@@ -103,8 +103,8 @@ Register-ActivityWatchUserTasks -TaskDefinitions $taskDefinitions -LaunchScriptP
|
||||
Register-ActivityWatchRecoveryTask -TaskName $config.recovery.taskName -RecoveryScriptPath $recoveryScriptPath -ConfigPath $configPath
|
||||
Start-ActivityWatchTasks -TaskDefinitions $taskDefinitions -RecoveryTaskName $config.recovery.taskName
|
||||
|
||||
Write-Host 'ActivityWatch deployed for users:'
|
||||
Write-Host 'ActivityWatch развёрнут для пользователей:'
|
||||
$targetUsers | ForEach-Object { Write-Host " - $_" }
|
||||
Write-Host "Server: ${ServerScheme}://$ServerHost`:$ServerPort"
|
||||
Write-Host "State root: $StateRoot"
|
||||
Write-Host "Policy file: $($assetResult.ActivePolicy)"
|
||||
Write-Host "Сервер: ${ServerScheme}://$ServerHost`:$ServerPort"
|
||||
Write-Host "Каталог данных: $StateRoot"
|
||||
Write-Host "Файл DLP-политики: $($assetResult.ActivePolicy)"
|
||||
|
||||
@@ -46,7 +46,7 @@ $hardeningScript = Join-Path $PSScriptRoot 'hardening-recovery.ps1'
|
||||
$validationScript = Join-Path $PSScriptRoot 'validate-deployment.ps1'
|
||||
|
||||
if (-not (Test-Path -LiteralPath $deployScript)) {
|
||||
throw "Missing script: $deployScript"
|
||||
throw "Не найден скрипт: $deployScript"
|
||||
}
|
||||
|
||||
& $deployScript `
|
||||
@@ -118,7 +118,7 @@ $report = [ordered]@{
|
||||
|
||||
if ($ValidateAfterDeploy) {
|
||||
if (-not (Test-Path -LiteralPath $validationScript)) {
|
||||
throw "Missing script: $validationScript"
|
||||
throw "Не найден скрипт: $validationScript"
|
||||
}
|
||||
|
||||
$validation = & $validationScript -ConfigPath (Join-Path $StateRoot 'deployment-config.json')
|
||||
@@ -132,6 +132,6 @@ if ($reportDirectory) {
|
||||
|
||||
$report | ConvertTo-Json -Depth 12 | Set-Content -LiteralPath $effectiveReportPath -Encoding UTF8
|
||||
|
||||
Write-Host 'ActivityWatch ensemble deploy completed.'
|
||||
Write-Host "Users: $($resolvedUsers -join ', ')"
|
||||
Write-Host "Report: $effectiveReportPath"
|
||||
Write-Host 'Комплексное развёртывание ActivityWatch завершено.'
|
||||
Write-Host "Пользователи: $($resolvedUsers -join ', ')"
|
||||
Write-Host "Отчёт: $effectiveReportPath"
|
||||
|
||||
@@ -101,9 +101,9 @@ Register-ActivityWatchUserTasks -TaskDefinitions $taskDefinitions -LaunchScriptP
|
||||
Register-ActivityWatchRecoveryTask -TaskName $config.recovery.taskName -RecoveryScriptPath $recoveryScriptPath -ConfigPath $configPath
|
||||
Start-ActivityWatchTasks -TaskDefinitions $taskDefinitions -RecoveryTaskName $config.recovery.taskName
|
||||
|
||||
Write-Host "ActivityWatch deployed for $TargetUser"
|
||||
Write-Host "Server: ${ServerScheme}://$ServerHost`:$ServerPort"
|
||||
Write-Host "Install root: $InstallRoot"
|
||||
Write-Host "State root: $StateRoot"
|
||||
Write-Host "Rules file: $($assetResult.ActiveRules)"
|
||||
Write-Host "Policy file: $($assetResult.ActivePolicy)"
|
||||
Write-Host "ActivityWatch развёрнут для пользователя: $TargetUser"
|
||||
Write-Host "Сервер: ${ServerScheme}://$ServerHost`:$ServerPort"
|
||||
Write-Host "Каталог установки: $InstallRoot"
|
||||
Write-Host "Каталог данных: $StateRoot"
|
||||
Write-Host "Файл правил: $($assetResult.ActiveRules)"
|
||||
Write-Host "Файл DLP-политики: $($assetResult.ActivePolicy)"
|
||||
|
||||
@@ -210,7 +210,7 @@ function Capture-IncidentScreenshot {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-EndpointLog ("screenshot capture failed: {0}" -f $_.Exception.Message)
|
||||
Write-EndpointLog ("не удалось сделать снимок инцидента: {0}" -f $_.Exception.Message)
|
||||
return @{}
|
||||
}
|
||||
}
|
||||
@@ -246,7 +246,7 @@ function Load-DlpPolicy {
|
||||
}
|
||||
|
||||
if (-not $Path -or -not (Test-Path -LiteralPath $Path)) {
|
||||
Write-EndpointLog ("policy not found, using defaults: {0}" -f $Path)
|
||||
Write-EndpointLog ("DLP-политика не найдена, используются значения по умолчанию: {0}" -f $Path)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ function Load-DlpPolicy {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-EndpointLog ("policy parse failed: {0}" -f $_.Exception.Message)
|
||||
Write-EndpointLog ("не удалось разобрать DLP-политику: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,13 +319,13 @@ function Evaluate-ClipboardRules {
|
||||
|
||||
$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" }
|
||||
$message = if ($rule.message) { [string]$rule.message } else { "Сработало правило буфера обмена: $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)
|
||||
Write-EndpointLog ("инцидент буфера обмена правило={0} действие={1} важность={2}" -f $ruleId, $action, $severity)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -347,13 +347,13 @@ function Evaluate-UsbRules {
|
||||
|
||||
$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" }
|
||||
$message = if ($rule.message) { [string]$rule.message } else { "Сработало правило USB-носителя: $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)
|
||||
Write-EndpointLog ("инцидент USB правило={0} действие={1} важность={2} диск={3}" -f $ruleId, $action, $severity, $DriveLetter)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,14 +385,14 @@ function Evaluate-PrintRules {
|
||||
|
||||
$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" }
|
||||
$message = if ($rule.message) { [string]$rule.message } else { "Сработало правило печати: $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)
|
||||
Write-EndpointLog ("инцидент печати правило={0} действие={1} важность={2} принтер={3}" -f $ruleId, $action, $severity, $PrinterName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +402,52 @@ function Test-LooksLikeMojibakeQuestionMarks {
|
||||
return $Value -match '\?{2,}'
|
||||
}
|
||||
|
||||
function Test-DocumentNameNeedsFallback {
|
||||
param([AllowNull()][string]$Value)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($Value)) { return $true }
|
||||
$trimmed = $Value.Trim()
|
||||
if (Test-LooksLikeMojibakeQuestionMarks -Value $trimmed) { return $true }
|
||||
if ($trimmed -match '^[0-9]+$') { return $true }
|
||||
if ($trimmed -match '^(?i)(print document|document|local downlevel document)$') { return $true }
|
||||
return $false
|
||||
}
|
||||
|
||||
function Get-EventXmlValue {
|
||||
param(
|
||||
[Parameter(Mandatory = $true)][xml]$EventXml,
|
||||
[Parameter(Mandatory = $true)][string]$Name
|
||||
)
|
||||
|
||||
$node = $EventXml.Event.UserData.DocumentPrinted.$Name
|
||||
if ($null -ne $node) {
|
||||
return [string]$node
|
||||
}
|
||||
|
||||
return ''
|
||||
}
|
||||
|
||||
function Get-PrintJobPrinterName {
|
||||
param(
|
||||
[AllowNull()][string]$JobName,
|
||||
[AllowNull()][string]$FallbackPrinterName
|
||||
)
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($JobName)) {
|
||||
if (-not [string]::IsNullOrWhiteSpace($FallbackPrinterName)) {
|
||||
return $FallbackPrinterName.Trim()
|
||||
}
|
||||
return ''
|
||||
}
|
||||
|
||||
$parts = $JobName -split ',', 2
|
||||
if ($parts.Count -gt 0 -and -not [string]::IsNullOrWhiteSpace($parts[0])) {
|
||||
return $parts[0].Trim()
|
||||
}
|
||||
|
||||
return $JobName.Trim()
|
||||
}
|
||||
|
||||
function Normalize-OwnerForMatch {
|
||||
param([AllowNull()][string]$Value)
|
||||
if ([string]::IsNullOrWhiteSpace($Value)) { return '' }
|
||||
@@ -469,13 +515,50 @@ function Get-PrintServiceEventSummary {
|
||||
$propertyValues += [string]$prop.Value
|
||||
}
|
||||
|
||||
$xml = $null
|
||||
try {
|
||||
$xml = [xml]$Event.ToXml()
|
||||
}
|
||||
catch {
|
||||
}
|
||||
|
||||
$jobId = ''
|
||||
$documentName = ''
|
||||
$owner = ''
|
||||
$portName = ''
|
||||
$printerName = ''
|
||||
$sizeBytes = ''
|
||||
$pageCount = ''
|
||||
|
||||
if ($xml) {
|
||||
$jobId = Get-EventXmlValue -EventXml $xml -Name 'Param1'
|
||||
$documentName = Get-EventXmlValue -EventXml $xml -Name 'Param2'
|
||||
$owner = Get-EventXmlValue -EventXml $xml -Name 'Param3'
|
||||
$portName = Get-EventXmlValue -EventXml $xml -Name 'Param4'
|
||||
$printerName = Get-EventXmlValue -EventXml $xml -Name 'Param5'
|
||||
$sizeBytes = Get-EventXmlValue -EventXml $xml -Name 'Param7'
|
||||
$pageCount = Get-EventXmlValue -EventXml $xml -Name 'Param8'
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($jobId) -and $props.Count -ge 1) { $jobId = [string]$props[0].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($documentName) -and $props.Count -ge 2) { $documentName = [string]$props[1].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($owner) -and $props.Count -ge 3) { $owner = [string]$props[2].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($portName) -and $props.Count -ge 4) { $portName = [string]$props[3].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($printerName) -and $props.Count -ge 5) { $printerName = [string]$props[4].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($sizeBytes) -and $props.Count -ge 7) { $sizeBytes = [string]$props[6].Value }
|
||||
if ([string]::IsNullOrWhiteSpace($pageCount) -and $props.Count -ge 8) { $pageCount = [string]$props[7].Value }
|
||||
|
||||
[pscustomobject]@{
|
||||
RecordId = [string]$Event.RecordId
|
||||
TimeCreated = if ($Event.TimeCreated) { $Event.TimeCreated.ToString('o') } else { '' }
|
||||
PropertyCount = $props.Count
|
||||
DocumentName = if ($props.Count -ge 1) { [string]$props[0].Value } else { '' }
|
||||
Owner = if ($props.Count -ge 2) { [string]$props[1].Value } else { '' }
|
||||
PrinterName = if ($props.Count -ge 4) { [string]$props[3].Value } else { '' }
|
||||
JobId = $jobId
|
||||
DocumentName = $documentName
|
||||
Owner = $owner
|
||||
PortName = $portName
|
||||
PrinterName = $printerName
|
||||
SizeBytes = $sizeBytes
|
||||
PageCount = $pageCount
|
||||
PropertyValues = $propertyValues
|
||||
}
|
||||
}
|
||||
@@ -488,7 +571,7 @@ function Get-PrintServiceDocumentFallback {
|
||||
)
|
||||
|
||||
$preferred = [string]$EventSummary.DocumentName
|
||||
if (-not (Test-LooksLikeMojibakeQuestionMarks -Value $preferred) -and $preferred -notmatch '^[0-9]+$') {
|
||||
if (-not (Test-DocumentNameNeedsFallback -Value $preferred)) {
|
||||
return $preferred
|
||||
}
|
||||
|
||||
@@ -499,9 +582,10 @@ function Get-PrintServiceDocumentFallback {
|
||||
$candidate = [string]$value
|
||||
if ([string]::IsNullOrWhiteSpace($candidate)) { continue }
|
||||
if ($candidate -eq $preferred) { continue }
|
||||
if ($EventSummary.JobId -and $candidate -eq [string]$EventSummary.JobId) { continue }
|
||||
if ($Owner -and $candidate -like "*$Owner*") { continue }
|
||||
if ($PrinterName -and $candidate -like "*$PrinterName*") { continue }
|
||||
if (Test-LooksLikeMojibakeQuestionMarks -Value $candidate) { continue }
|
||||
if (Test-DocumentNameNeedsFallback -Value $candidate) { continue }
|
||||
|
||||
if ($candidate -match '[\\/:]' -and $candidate -match '\.[A-Za-z0-9]{1,8}$') {
|
||||
$pathCandidates.Add($candidate)
|
||||
@@ -546,7 +630,7 @@ function Write-PrintServiceEventTrace {
|
||||
}
|
||||
|
||||
Write-EndpointLog (
|
||||
'printservice-307 phase={0} recordId={1} time={2} owner={3} printer={4} document={5} resolved={6} properties=[{7}] reason={8}' -f
|
||||
'printservice-307 этап={0} recordId={1} время={2} владелец={3} принтер={4} документ={5} итоговыйДокумент={6} свойства=[{7}] причина={8}' -f
|
||||
$Phase,
|
||||
$EventSummary.RecordId,
|
||||
$EventSummary.TimeCreated,
|
||||
@@ -561,6 +645,7 @@ function Write-PrintServiceEventTrace {
|
||||
|
||||
function Get-BetterDocumentNameFromPrintServiceEvents {
|
||||
param(
|
||||
[string]$JobId,
|
||||
[string]$Owner,
|
||||
[string]$PrinterName
|
||||
)
|
||||
@@ -578,32 +663,41 @@ function Get-BetterDocumentNameFromPrintServiceEvents {
|
||||
$summary = Get-PrintServiceEventSummary -Event $event
|
||||
$resolvedDocument = Get-PrintServiceDocumentFallback -EventSummary $summary -Owner $Owner -PrinterName $PrinterName
|
||||
|
||||
$jobMatches = if ($JobId) { [string]$summary.JobId -eq [string]$JobId } else { $true }
|
||||
$ownerMatches = if ($Owner) { Test-OwnerLooseMatch -Expected $Owner -Actual $summary.Owner } else { $true }
|
||||
$printerMatches = if ($PrinterName) { Test-PrinterLooseMatch -Expected $PrinterName -Actual $summary.PrinterName } else { $true }
|
||||
|
||||
if ($pass -eq 'strict') {
|
||||
if ($JobId -and -not $jobMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'несовпадение-jobid-strict' -ResolvedDocument $resolvedDocument
|
||||
continue
|
||||
}
|
||||
if ($Owner -and -not $ownerMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'owner-mismatch-strict' -ResolvedDocument $resolvedDocument
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'несовпадение-владельца-strict' -ResolvedDocument $resolvedDocument
|
||||
continue
|
||||
}
|
||||
if ($PrinterName -and -not $printerMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'printer-mismatch-strict' -ResolvedDocument $resolvedDocument
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'несовпадение-принтера-strict' -ResolvedDocument $resolvedDocument
|
||||
continue
|
||||
}
|
||||
}
|
||||
else {
|
||||
if ($Owner -and $PrinterName -and -not $ownerMatches -and -not $printerMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'owner-and-printer-mismatch-relaxed' -ResolvedDocument $resolvedDocument
|
||||
if ($JobId -and (-not $jobMatches) -and $Owner -and $PrinterName -and -not $ownerMatches -and -not $printerMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'несовпадение-владельца-и-принтера-relaxed' -ResolvedDocument $resolvedDocument
|
||||
continue
|
||||
}
|
||||
if ((-not $JobId) -and $Owner -and $PrinterName -and -not $ownerMatches -and -not $printerMatches) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason 'несовпадение-владельца-и-принтера-relaxed' -ResolvedDocument $resolvedDocument
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if ([string]::IsNullOrWhiteSpace($resolvedDocument)) {
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason ('no-document-candidate-' + $pass) -ResolvedDocument ''
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'scan' -MatchReason ('нет-кандидата-документа-' + $pass) -ResolvedDocument ''
|
||||
continue
|
||||
}
|
||||
|
||||
$matchReasonBase = if (Test-LooksLikeMojibakeQuestionMarks -Value $summary.DocumentName) { 'fallback-used' } else { 'direct' }
|
||||
$matchReasonBase = if (Test-DocumentNameNeedsFallback -Value $summary.DocumentName) { 'использован-резервный-вариант' } else { 'напрямую' }
|
||||
Write-PrintServiceEventTrace -EventSummary $summary -Phase 'selected' -MatchReason ($matchReasonBase + '-' + $pass) -ResolvedDocument $resolvedDocument
|
||||
return $resolvedDocument
|
||||
}
|
||||
@@ -616,7 +710,7 @@ function Get-BetterDocumentNameFromPrintServiceEvents {
|
||||
}
|
||||
|
||||
$deploymentConfig = Get-DeploymentConfig -Path $ConfigPath
|
||||
$resolvedServerHost = if ($ServerHost) { $ServerHost } elseif ($deploymentConfig) { [string]$deploymentConfig.server.host } else { throw 'ServerHost is required.' }
|
||||
$resolvedServerHost = if ($ServerHost) { $ServerHost } elseif ($deploymentConfig) { [string]$deploymentConfig.server.host } else { throw 'Укажите ServerHost или подготовьте deployment-config.json.' }
|
||||
$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' }
|
||||
@@ -648,7 +742,7 @@ $script:IncidentScreenshotEnabled = $resolvedIncidentScreenshotEnabled
|
||||
$script:ScreenshotTypesLoaded = $false
|
||||
|
||||
Load-DlpPolicy -Path $resolvedPolicyPath
|
||||
Write-EndpointLog ("endpoint collector started against {0}" -f $script:ApiBase)
|
||||
Write-EndpointLog ("endpoint-коллектор запущен для {0}" -f $script:ApiBase)
|
||||
|
||||
while ($true) {
|
||||
try {
|
||||
@@ -709,13 +803,13 @@ while ($true) {
|
||||
if ($script:SeenPrintJob.ContainsKey($jobId)) { continue }
|
||||
$script:SeenPrintJob[$jobId] = (Get-Date).ToUniversalTime()
|
||||
|
||||
$printerName = [string]$job.Name
|
||||
$printerName = Get-PrintJobPrinterName -JobName ([string]$job.Name) -FallbackPrinterName ([string]$job.DriverName)
|
||||
$documentName = [string]$job.Document
|
||||
$owner = [string]$job.Owner
|
||||
$documentNameOriginal = $documentName
|
||||
|
||||
if (Test-LooksLikeMojibakeQuestionMarks -Value $documentName) {
|
||||
$eventDocumentName = Get-BetterDocumentNameFromPrintServiceEvents -Owner $owner -PrinterName $printerName
|
||||
if (Test-DocumentNameNeedsFallback -Value $documentName) {
|
||||
$eventDocumentName = Get-BetterDocumentNameFromPrintServiceEvents -JobId $jobId -Owner $owner -PrinterName $printerName
|
||||
if ($eventDocumentName) {
|
||||
$documentName = $eventDocumentName
|
||||
}
|
||||
@@ -726,6 +820,7 @@ while ($true) {
|
||||
documentName = $documentName
|
||||
documentNameOriginal = $documentNameOriginal
|
||||
owner = $owner
|
||||
printJobId = $jobId
|
||||
}
|
||||
Evaluate-PrintRules -PrinterName $printerName -DocumentName $documentName -Owner $owner
|
||||
}
|
||||
@@ -789,7 +884,7 @@ while ($true) {
|
||||
}
|
||||
}
|
||||
catch {
|
||||
Write-EndpointLog ("collector error: {0}" -f $_.Exception.Message)
|
||||
Write-EndpointLog ("ошибка коллектора: {0}" -f $_.Exception.Message)
|
||||
}
|
||||
|
||||
Start-Sleep -Seconds $resolvedPollSeconds
|
||||
|
||||
@@ -42,7 +42,7 @@ if (Test-Path -LiteralPath $ConfigPath) {
|
||||
}
|
||||
|
||||
if (-not $existingConfig -and (-not $ServerHost)) {
|
||||
throw 'deployment-config.json is missing. Provide -ServerHost and user parameters, or run a deploy script first.'
|
||||
throw 'deployment-config.json отсутствует. Укажите -ServerHost и параметры пользователей либо сначала выполните скрипт развёртывания.'
|
||||
}
|
||||
|
||||
$effectiveStateRoot = if ($StateRoot) { $StateRoot } elseif ($existingConfig) { [string]$existingConfig.paths.stateRoot } else { 'C:\ProgramData\ActivityWatch' }
|
||||
@@ -78,7 +78,7 @@ elseif ($existingConfig) {
|
||||
@($existingConfig.userTasks | ForEach-Object { [string]$_.userId })
|
||||
}
|
||||
else {
|
||||
throw 'Target users are missing.'
|
||||
throw 'Не указаны целевые пользователи.'
|
||||
}
|
||||
|
||||
New-ActivityWatchDirectory -Path $effectiveStateRoot
|
||||
@@ -96,6 +96,7 @@ Get-ActivityWatchExecutableMap -InstallRoot $effectiveInstallRoot | Out-Null
|
||||
$assetResult = Copy-ActivityWatchCollectorAssets `
|
||||
-CollectorScriptSource (Join-Path $PSScriptRoot 'browser-domains-native-collector.ps1') `
|
||||
-EndpointCollectorScriptSource (Join-Path $PSScriptRoot 'dlp-endpoint-signals-collector.ps1') `
|
||||
-SessionCollectorScriptSource (Join-Path $PSScriptRoot 'worktime-session-collector.ps1') `
|
||||
-ExampleRulesSource (Join-Path $PSScriptRoot 'web-category-rules.example.json') `
|
||||
-ExamplePolicySource (Join-Path $PSScriptRoot 'dlp-policy.example.json') `
|
||||
-StateRoot $effectiveStateRoot `
|
||||
@@ -139,6 +140,6 @@ Register-ActivityWatchUserTasks -TaskDefinitions $taskDefinitions -LaunchScriptP
|
||||
Register-ActivityWatchRecoveryTask -TaskName $config.recovery.taskName -RecoveryScriptPath $effectiveRecoveryScript -ConfigPath $effectiveConfigPath
|
||||
Start-ActivityWatchTasks -TaskDefinitions $taskDefinitions -RecoveryTaskName $config.recovery.taskName
|
||||
|
||||
Write-Host 'ActivityWatch hardening/recovery completed.'
|
||||
Write-Host "Config: $effectiveConfigPath"
|
||||
Write-Host "Users repaired: $($effectiveUsers -join ', ')"
|
||||
Write-Host 'Укрепление и восстановление ActivityWatch завершены.'
|
||||
Write-Host "Конфигурация: $effectiveConfigPath"
|
||||
Write-Host "Пользователи восстановлены: $($effectiveUsers -join ', ')"
|
||||
|
||||
@@ -65,7 +65,7 @@ $tasks = foreach ($taskName in $taskNames) {
|
||||
else {
|
||||
[pscustomobject]@{
|
||||
taskName = $taskName
|
||||
state = 'Missing'
|
||||
state = 'Отсутствует'
|
||||
present = $false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ function Get-Config {
|
||||
param([string]$Path)
|
||||
|
||||
if (-not (Test-Path -LiteralPath $Path)) {
|
||||
throw "Config not found: $Path"
|
||||
throw "Конфигурация не найдена: $Path"
|
||||
}
|
||||
|
||||
Get-Content -LiteralPath $Path -Raw | ConvertFrom-Json
|
||||
|
||||
Reference in New Issue
Block a user