feat: deploy UseSAC fallback by default and prevent duplicate daily reports
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+33
-5
@@ -644,12 +644,35 @@ function Get-RdpMonitorSacBlockFromExample {
|
|||||||
}
|
}
|
||||||
return @(
|
return @(
|
||||||
'# --- Security Alert Center (SAC) ---'
|
'# --- Security Alert Center (SAC) ---'
|
||||||
'$UseSAC = ''dual'''
|
'$UseSAC = ''fallback'''
|
||||||
'$SacUrl = ''https://sac.kalinamall.ru'''
|
'$SacUrl = ''https://sac.kalinamall.ru'''
|
||||||
'$SacApiKey = ''sac_CHANGE_ME'''
|
'$SacApiKey = ''sac_CHANGE_ME'''
|
||||||
) -join "`r`n"
|
) -join "`r`n"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Sync-RdpMonitorUseSacFallbackMode {
|
||||||
|
param([string]$LocalSettings)
|
||||||
|
|
||||||
|
if (-not (Test-Path -LiteralPath $LocalSettings)) { return $false }
|
||||||
|
$c = Get-RdpMonitorSettingsRaw -Path $LocalSettings
|
||||||
|
if ([string]::IsNullOrWhiteSpace($c)) { return $false }
|
||||||
|
if ($c -match '(?m)^\s*\$UseSAC\s*=\s*[''"]fallback[''"]') { return $false }
|
||||||
|
if ($c -notmatch '(?m)^\s*\$UseSAC\s*=') { return $false }
|
||||||
|
|
||||||
|
$newContent = [regex]::Replace(
|
||||||
|
$c,
|
||||||
|
'(?m)^(\s*\$UseSAC\s*=\s*)[''"][^''"]+[''"]',
|
||||||
|
'$1''fallback'''
|
||||||
|
)
|
||||||
|
if ($newContent -eq $c) { return $false }
|
||||||
|
|
||||||
|
$bak = "$LocalSettings.bak.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||||
|
Copy-Item -LiteralPath $LocalSettings -Destination $bak -Force
|
||||||
|
[System.IO.File]::WriteAllText($LocalSettings, $newContent.TrimEnd() + "`r`n", $Utf8Bom)
|
||||||
|
Write-DeployLog "login_monitor.settings.ps1: UseSAC переключён на fallback (резервная копия: $bak)."
|
||||||
|
return $true
|
||||||
|
}
|
||||||
|
|
||||||
function Update-RdpMonitorSettingsSacBlockIfMissing {
|
function Update-RdpMonitorSettingsSacBlockIfMissing {
|
||||||
param(
|
param(
|
||||||
[string]$LocalSettings,
|
[string]$LocalSettings,
|
||||||
@@ -675,7 +698,7 @@ function Update-RdpMonitorSettingsSacBlockIfMissing {
|
|||||||
|
|
||||||
$bak = "$LocalSettings.bak.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
$bak = "$LocalSettings.bak.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
|
||||||
Copy-Item -LiteralPath $LocalSettings -Destination $bak -Force
|
Copy-Item -LiteralPath $LocalSettings -Destination $bak -Force
|
||||||
Write-DeployLog "Добавление блока SAC (UseSAC=dual) в login_monitor.settings.ps1; резервная копия: $bak"
|
Write-DeployLog "Добавление блока SAC (UseSAC=fallback) в login_monitor.settings.ps1; резервная копия: $bak"
|
||||||
|
|
||||||
if ($c -match '(?m)^\s*\$UseSAC\s*=') {
|
if ($c -match '(?m)^\s*\$UseSAC\s*=') {
|
||||||
$c = [regex]::Replace($c, '(?m)^\s*\$UseSAC\s*=.*$', '')
|
$c = [regex]::Replace($c, '(?m)^\s*\$UseSAC\s*=.*$', '')
|
||||||
@@ -689,7 +712,7 @@ function Update-RdpMonitorSettingsSacBlockIfMissing {
|
|||||||
|
|
||||||
$newContent = ($c.TrimEnd() + "`r`n`r`n" + $sacBlock + "`r`n").TrimEnd() + "`r`n"
|
$newContent = ($c.TrimEnd() + "`r`n`r`n" + $sacBlock + "`r`n").TrimEnd() + "`r`n"
|
||||||
[System.IO.File]::WriteAllText($LocalSettings, $newContent, $Utf8Bom)
|
[System.IO.File]::WriteAllText($LocalSettings, $newContent, $Utf8Bom)
|
||||||
Write-DeployLog "login_monitor.settings.ps1: добавлен блок SAC (UseSAC=dual из example на шаре)."
|
Write-DeployLog "login_monitor.settings.ps1: добавлен блок SAC (UseSAC=fallback из example на шаре)."
|
||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -717,7 +740,7 @@ function Sync-RdpMonitorSettingsFromShare {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($needsCreate) {
|
if ($needsCreate) {
|
||||||
Write-DeployLog "Создан login_monitor.settings.ps1 из example (Telegram + SAC dual)."
|
Write-DeployLog "Создан login_monitor.settings.ps1 из example (Telegram + SAC fallback)."
|
||||||
Copy-Item -LiteralPath $ExampleOnShare -Destination $LocalSettings -Force
|
Copy-Item -LiteralPath $ExampleOnShare -Destination $LocalSettings -Force
|
||||||
Invoke-RdpMonitorSettingsPostPatches -LocalSettings $LocalSettings | Out-Null
|
Invoke-RdpMonitorSettingsPostPatches -LocalSettings $LocalSettings | Out-Null
|
||||||
return
|
return
|
||||||
@@ -831,6 +854,7 @@ try {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$cmp = Compare-VersionStrings -Left $shareVerRaw -Right $localVerRaw
|
$cmp = Compare-VersionStrings -Left $shareVerRaw -Right $localVerRaw
|
||||||
|
$isScriptVersionUpgrade = ($null -ne $cmp -and $cmp -gt 0 -and -not [string]::IsNullOrWhiteSpace($localVerRaw))
|
||||||
if ($null -ne $cmp) {
|
if ($null -ne $cmp) {
|
||||||
if ($cmp -eq 0) {
|
if ($cmp -eq 0) {
|
||||||
if (-not $needsSacBootstrap) {
|
if (-not $needsSacBootstrap) {
|
||||||
@@ -869,7 +893,7 @@ try {
|
|||||||
|
|
||||||
if ($WhatIf) {
|
if ($WhatIf) {
|
||||||
if ($needsSettingsBootstrap) {
|
if ($needsSettingsBootstrap) {
|
||||||
Write-DeployLog "[WhatIf] Донастроить login_monitor.settings.ps1 (SAC dual из example)."
|
Write-DeployLog "[WhatIf] Донастроить login_monitor.settings.ps1 (SAC fallback из example)."
|
||||||
}
|
}
|
||||||
if ($needsBundleSync) {
|
if ($needsBundleSync) {
|
||||||
Write-DeployLog "[WhatIf] Синхронизировать пакет: $($DeployBundleFiles -join ', ')."
|
Write-DeployLog "[WhatIf] Синхронизировать пакет: $($DeployBundleFiles -join ', ')."
|
||||||
@@ -889,6 +913,10 @@ try {
|
|||||||
|
|
||||||
Sync-RdpMonitorSettingsFromShare -ExampleOnShare $settingsExampleShare -LocalSettings $settingsLocal
|
Sync-RdpMonitorSettingsFromShare -ExampleOnShare $settingsExampleShare -LocalSettings $settingsLocal
|
||||||
|
|
||||||
|
if ($isScriptVersionUpgrade) {
|
||||||
|
Sync-RdpMonitorUseSacFallbackMode -LocalSettings $settingsLocal | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
$installArgs = @(
|
$installArgs = @(
|
||||||
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $LocalScript, '-InstallTasks', '-SkipImmediateMainRun'
|
'-NoProfile', '-ExecutionPolicy', 'Bypass', '-File', $LocalScript, '-InstallTasks', '-SkipImmediateMainRun'
|
||||||
)
|
)
|
||||||
|
|||||||
+52
-10
@@ -3109,28 +3109,70 @@ function Test-DailyReportEnabledFlag {
|
|||||||
return $true
|
return $true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Read-LastDailyReportSentDate {
|
||||||
|
if (-not (Test-Path -LiteralPath $LastReportFile)) { return $null }
|
||||||
|
$txt = Get-Content -LiteralPath $LastReportFile -ErrorAction SilentlyContinue | Select-Object -First 1
|
||||||
|
if ([string]::IsNullOrWhiteSpace($txt)) { return $null }
|
||||||
|
$raw = $txt.Trim()
|
||||||
|
if ($raw -match '^(\d{4}-\d{2}-\d{2})') {
|
||||||
|
try { return [datetime]::ParseExact($matches[1], 'yyyy-MM-dd', $null).Date } catch { }
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return ([datetime]::ParseExact($raw, 'yyyy-MM-dd HH:mm:ss', $null)).Date
|
||||||
|
} catch {
|
||||||
|
return $null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Try-ClaimDailyReportSlotToday {
|
||||||
|
param([datetime]$Now)
|
||||||
|
|
||||||
|
$lockPath = Join-Path $script:InstallRoot 'Logs\.daily_report_claim.lock'
|
||||||
|
$lockStream = $null
|
||||||
|
try {
|
||||||
|
$lockStream = [System.IO.File]::Open(
|
||||||
|
$lockPath,
|
||||||
|
[System.IO.FileMode]::OpenOrCreate,
|
||||||
|
[System.IO.FileAccess]::ReadWrite,
|
||||||
|
[System.IO.FileShare]::None
|
||||||
|
)
|
||||||
|
} catch {
|
||||||
|
Write-Log 'Ежедневный отчёт: другой процесс уже отправляет (lock).'
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$lastDate = Read-LastDailyReportSentDate
|
||||||
|
if ($null -ne $lastDate -and $lastDate -ge $Now.Date) {
|
||||||
|
return $false
|
||||||
|
}
|
||||||
|
Write-TextFileUtf8Bom -Path $LastReportFile -Text ($Now.ToString('yyyy-MM-dd'))
|
||||||
|
return $true
|
||||||
|
} finally {
|
||||||
|
if ($null -ne $lockStream) {
|
||||||
|
$lockStream.Dispose()
|
||||||
|
}
|
||||||
|
Remove-Item -LiteralPath $lockPath -Force -ErrorAction SilentlyContinue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function Check-AndSendDailyReport {
|
function Check-AndSendDailyReport {
|
||||||
if (-not (Test-DailyReportEnabledFlag)) {
|
if (-not (Test-DailyReportEnabledFlag)) {
|
||||||
return (Get-NextLocalSlotBoundary -Hour $DailyReportHour -Minute $DailyReportMinute)
|
return (Get-NextLocalSlotBoundary -Hour $DailyReportHour -Minute $DailyReportMinute)
|
||||||
}
|
}
|
||||||
$lastReport = $null
|
|
||||||
if (Test-Path $LastReportFile) {
|
|
||||||
$txt = Get-Content $LastReportFile -ErrorAction SilentlyContinue
|
|
||||||
if ($txt) { $lastReport = [datetime]::ParseExact($txt, "yyyy-MM-dd HH:mm:ss", $null) }
|
|
||||||
}
|
|
||||||
|
|
||||||
$now = Get-Date
|
$now = Get-Date
|
||||||
$reportSlotToday = Get-Date -Year $now.Year -Month $now.Month -Day $now.Day -Hour $DailyReportHour -Minute $DailyReportMinute -Second 0
|
$reportSlotToday = Get-Date -Year $now.Year -Month $now.Month -Day $now.Day -Hour $DailyReportHour -Minute $DailyReportMinute -Second 0
|
||||||
$shouldSend = $false
|
$shouldSend = $false
|
||||||
if ($now -ge $reportSlotToday) {
|
if ($now -ge $reportSlotToday) {
|
||||||
if ($null -eq $lastReport) {
|
$lastDate = Read-LastDailyReportSentDate
|
||||||
|
if ($null -eq $lastDate -or $lastDate -lt $now.Date) {
|
||||||
$shouldSend = $true
|
$shouldSend = $true
|
||||||
} else {
|
|
||||||
$dLast = $lastReport.Date
|
|
||||||
if ($dLast -lt $now.Date) { $shouldSend = $true }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ($shouldSend) { Send-DailyReport | Out-Null }
|
if ($shouldSend -and (Try-ClaimDailyReportSlotToday -Now $now)) {
|
||||||
|
Send-DailyReport | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
return (Get-NextLocalSlotBoundary -Hour $DailyReportHour -Minute $DailyReportMinute)
|
return (Get-NextLocalSlotBoundary -Hour $DailyReportHour -Minute $DailyReportMinute)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ $NotifyOrder = 'tg'
|
|||||||
|
|
||||||
# --- Security Alert Center (SAC) ---
|
# --- Security Alert Center (SAC) ---
|
||||||
# off | exclusive | dual | fallback — см. security-alert-center/docs/agent-integration.md
|
# off | exclusive | dual | fallback — см. security-alert-center/docs/agent-integration.md
|
||||||
$UseSAC = 'dual'
|
$UseSAC = 'fallback'
|
||||||
$SacUrl = 'https://sac.kalinamall.ru'
|
$SacUrl = 'https://sac.kalinamall.ru'
|
||||||
$SacApiKey = 'sac_UkOsAT3UWiQS54KK5OJPBDCSucysQDrKFju28wmYiz8'
|
$SacApiKey = 'sac_UkOsAT3UWiQS54KK5OJPBDCSucysQDrKFju28wmYiz8'
|
||||||
# $SacSpoolDir = 'C:\ProgramData\RDP-login-monitor\sac-spool'
|
# $SacSpoolDir = 'C:\ProgramData\RDP-login-monitor\sac-spool'
|
||||||
|
|||||||
Reference in New Issue
Block a user