Compare commits

..

7 Commits

Author SHA1 Message Date
PTah c12f169189 merge: sync remotes; keep deploy StartupRebootDetectMinutes bootstrap
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 11:04:04 +10:00
PTah 37fdeb44c5 feat: deploy bootstrap StartupRebootDetectMinutes in agent settings
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 11:02:50 +10:00
PTah 746f9e23b2 feat: detect OS reboot on startup via System log and LastBootUpTime
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 10:42:40 +10:00
PTah 35e25063e3 chore(github): generic NETLOGON paths, remove mirror scripts
Replace \\B26\\NETLOGON with \\dc.contoso.local\\NETLOGON.
Remove scripts/ mirror tools and tools/Push-KalinamallOnly.ps1.
Sanitize login_monitor.settings.example (placeholders, no secrets).
Simplify update-rdp-monitor.ps1 to use origin remote only.
Keep dev tooling under tools/ only.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 11:57:35 +10:00
PTah 8d17a0f560 chore(docs): GitHub default clone URL, remove .cursor from git
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 11:37:48 +10:00
PTah ae86cb3ea7 feat: persistent Security poll cursor with lookback replay (2.0.36-SAC)
Save last_security_poll.txt between runs and replay Security events up to SecurityEventsLookbackMinutes on startup so slow boot or late agent start does not miss RDP/WinRM-related logons.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 11:37:48 +10:00
PTah 1fcd5cb5cf feat: persistent Security poll cursor with lookback replay (2.0.36-SAC)
Save last_security_poll.txt between runs and replay Security events up to SecurityEventsLookbackMinutes on startup so slow boot or late agent start does not miss RDP/WinRM-related logons.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-16 09:40:15 +10:00
18 changed files with 256 additions and 110 deletions
+1
View File
@@ -1,2 +1,3 @@
.cursor/ .cursor/
tools/*.log
*.log *.log
+59 -3
View File
@@ -1,4 +1,4 @@
<# <#
.SYNOPSIS .SYNOPSIS
Доставка Login_Monitor.ps1 с файловой шары по версии (домен: ПК и серверы). Доставка Login_Monitor.ps1 с файловой шары по версии (домен: ПК и серверы).
.DESCRIPTION .DESCRIPTION
@@ -682,6 +682,49 @@ function Sync-RdpMonitorSettingsHeartbeatInterval {
return $true return $true
} }
function Test-RdpMonitorSettingsNeedsStartupRebootDetectMinutes {
param([string]$SettingsPath)
if (-not (Test-Path -LiteralPath $SettingsPath)) { return $true }
$c = Get-RdpMonitorSettingsRaw -Path $SettingsPath
if ([string]::IsNullOrWhiteSpace($c)) { return $true }
return ($c -notmatch '(?m)^\s*\$StartupRebootDetectMinutes\s*=\s*\d+')
}
function Sync-RdpMonitorSettingsStartupRebootDetectMinutesIfMissing {
param(
[string]$LocalSettings,
[int]$TargetMinutes = 5
)
if (-not (Test-RdpMonitorSettingsNeedsStartupRebootDetectMinutes -SettingsPath $LocalSettings)) {
return $false
}
if (-not (Test-Path -LiteralPath $LocalSettings)) { return $false }
$c = Get-RdpMonitorSettingsRaw -Path $LocalSettings
$block = @(
'# --- Окно (мин): LastBootUpTime + System 41/1074/6005/6008/6009 → os_reboot при старте ---'
"`$StartupRebootDetectMinutes = $TargetMinutes"
) -join "`r`n"
$bak = "$LocalSettings.bak.$(Get-Date -Format 'yyyyMMdd_HHmmss')"
Copy-Item -LiteralPath $LocalSettings -Destination $bak -Force
$insertAfterHeartbeat = '(?m)^(\s*\$HeartbeatInterval\s*=\s*\d+\s*)$'
if (-not [string]::IsNullOrWhiteSpace($c) -and $c -match $insertAfterHeartbeat) {
$newContent = [regex]::Replace($c, $insertAfterHeartbeat, ('$1' + "`r`n`r`n" + $block), 1)
} elseif (-not [string]::IsNullOrWhiteSpace($c)) {
$newContent = ($c.TrimEnd() + "`r`n`r`n" + $block + "`r`n")
} else {
$newContent = ($block + "`r`n")
}
[System.IO.File]::WriteAllText($LocalSettings, $newContent.TrimEnd() + "`r`n", $Utf8Bom)
Write-DeployLog "login_monitor.settings.ps1: добавлен `$StartupRebootDetectMinutes = $TargetMinutes (резервная копия: $bak)"
return $true
}
function Invoke-RdpMonitorSettingsPostPatches { function Invoke-RdpMonitorSettingsPostPatches {
param([string]$LocalSettings) param([string]$LocalSettings)
if (-not (Test-Path -LiteralPath $LocalSettings)) { return $false } if (-not (Test-Path -LiteralPath $LocalSettings)) { return $false }
@@ -693,6 +736,7 @@ function Invoke-RdpMonitorSettingsPostPatches {
if (Sync-RdpMonitorSettingsWinRmInboundBlock -LocalSettings $LocalSettings) { $changed = $true } if (Sync-RdpMonitorSettingsWinRmInboundBlock -LocalSettings $LocalSettings) { $changed = $true }
if (Sync-RdpMonitorSettingsMaxBackupDaysIfMissing -LocalSettings $LocalSettings) { $changed = $true } if (Sync-RdpMonitorSettingsMaxBackupDaysIfMissing -LocalSettings $LocalSettings) { $changed = $true }
if (Sync-RdpMonitorSettingsGetInventoryIfMissing -LocalSettings $LocalSettings) { $changed = $true } if (Sync-RdpMonitorSettingsGetInventoryIfMissing -LocalSettings $LocalSettings) { $changed = $true }
if (Sync-RdpMonitorSettingsStartupRebootDetectMinutesIfMissing -LocalSettings $LocalSettings) { $changed = $true }
return $changed return $changed
} }
@@ -828,7 +872,7 @@ function Get-RdpMonitorSacBlockFromExample {
return @( return @(
'# --- Security Alert Center (SAC) ---' '# --- Security Alert Center (SAC) ---'
'$UseSAC = ''fallback''' '$UseSAC = ''fallback'''
'$SacUrl = ''https://sac.kalinamall.ru''' '$SacUrl = ''https://sac.example.com'''
'$SacApiKey = ''sac_CHANGE_ME''' '$SacApiKey = ''sac_CHANGE_ME'''
) -join "`r`n" ) -join "`r`n"
} }
@@ -1346,9 +1390,10 @@ try {
$needsExchangeNoisePatch = Test-RdpMonitorSettingsNeedsExchangeNoisePatch -SettingsPath $settingsLocal $needsExchangeNoisePatch = Test-RdpMonitorSettingsNeedsExchangeNoisePatch -SettingsPath $settingsLocal
$needsWinRmInboundBlock = Test-RdpMonitorSettingsNeedsWinRmInboundBlock -SettingsPath $settingsLocal $needsWinRmInboundBlock = Test-RdpMonitorSettingsNeedsWinRmInboundBlock -SettingsPath $settingsLocal
$needsHeartbeatInterval = Test-RdpMonitorSettingsNeedsHeartbeatInterval -SettingsPath $settingsLocal $needsHeartbeatInterval = Test-RdpMonitorSettingsNeedsHeartbeatInterval -SettingsPath $settingsLocal
$needsStartupRebootDetectMinutes = Test-RdpMonitorSettingsNeedsStartupRebootDetectMinutes -SettingsPath $settingsLocal
$needsBundleSync = Test-RdpMonitorDeployBundleNeedsSync -ShareRoot $shareRoot $needsBundleSync = Test-RdpMonitorDeployBundleNeedsSync -ShareRoot $shareRoot
$needsTaskExecutionLimitFix = Test-RdpMonitorDeployMainTaskNeedsUnlimitedExecutionTime -ShareRoot $shareRoot $needsTaskExecutionLimitFix = Test-RdpMonitorDeployMainTaskNeedsUnlimitedExecutionTime -ShareRoot $shareRoot
$needsSacBootstrap = $needsSettingsBootstrap -or $needsBundleSync -or $needsDisplayNameHint -or $needsDailyReportHint -or $needsDailyReportRepair -or $needsExchangeNoisePatch -or $needsWinRmInboundBlock -or $needsHeartbeatInterval -or $needsTaskExecutionLimitFix $needsSacBootstrap = $needsSettingsBootstrap -or $needsBundleSync -or $needsDisplayNameHint -or $needsDailyReportHint -or $needsDailyReportRepair -or $needsExchangeNoisePatch -or $needsWinRmInboundBlock -or $needsHeartbeatInterval -or $needsStartupRebootDetectMinutes -or $needsTaskExecutionLimitFix
if (Test-RdpMonitorExchangeServerRole) { if (Test-RdpMonitorExchangeServerRole) {
Write-DeployLog "Обнаружена роль Exchange — при необходимости допишем WinRM/4624 noise settings в login_monitor.settings.ps1." Write-DeployLog "Обнаружена роль Exchange — при необходимости допишем WinRM/4624 noise settings в login_monitor.settings.ps1."
@@ -1390,6 +1435,8 @@ try {
Write-DeployLog "Версия совпадает ($shareVerRaw), но RDP-Login-Monitor имеет ExecutionTimeLimit=$limitLabel — перерегистрируем задачи (InstallTasks)." Write-DeployLog "Версия совпадает ($shareVerRaw), но RDP-Login-Monitor имеет ExecutionTimeLimit=$limitLabel — перерегистрируем задачи (InstallTasks)."
} elseif ($needsHeartbeatInterval) { } elseif ($needsHeartbeatInterval) {
Write-DeployLog "Версия совпадает ($shareVerRaw), но в settings нет `$HeartbeatInterval — допишем 14400 с (4 ч) и продолжим деплой." Write-DeployLog "Версия совпадает ($shareVerRaw), но в settings нет `$HeartbeatInterval — допишем 14400 с (4 ч) и продолжим деплой."
} elseif ($needsStartupRebootDetectMinutes) {
Write-DeployLog "Версия совпадает ($shareVerRaw), но в settings нет `$StartupRebootDetectMinutes — допишем 5 мин и продолжим деплой."
} }
} }
if ($cmp -lt 0 -and -not $AllowDowngrade) { if ($cmp -lt 0 -and -not $AllowDowngrade) {
@@ -1438,6 +1485,15 @@ try {
} }
} }
$startupRebootDetectChanged = Sync-RdpMonitorSettingsStartupRebootDetectMinutesIfMissing -LocalSettings $settingsLocal
if ($startupRebootDetectChanged) {
$canonicalSr = [System.IO.Path]::GetFullPath($LocalScript)
if (Test-RdpMonitorMainProcessRunning -CanonicalScript $canonicalSr) {
Set-RdpMonitorRestartRequestFromDeploy -Mode 'settings' -Reason 'startup_reboot_detect_deploy'
Write-DeployLog "StartupRebootDetectMinutes добавлен — запрошена перезагрузка settings у работающего монитора."
}
}
if ($isScriptVersionUpgrade) { if ($isScriptVersionUpgrade) {
Sync-RdpMonitorUseSacFallbackMode -LocalSettings $settingsLocal | Out-Null Sync-RdpMonitorUseSacFallbackMode -LocalSettings $settingsLocal | Out-Null
} }
+1 -1
View File
@@ -6,7 +6,7 @@
Security 4624/4625/4778/4634, симуляцию фильтров монитора, SAC spool, сессии RDP. Security 4624/4625/4778/4634, симуляцию фильтров монитора, SAC spool, сессии RDP.
Отчёт: C:\ProgramData\RDP-login-monitor\Logs\diagnose_YYYYMMDD_HHmmss.txt Отчёт: C:\ProgramData\RDP-login-monitor\Logs\diagnose_YYYYMMDD_HHmmss.txt
.EXAMPLE .EXAMPLE
powershell.exe -NoProfile -ExecutionPolicy Bypass -File Diagnose-RdpLoginMonitor.ps1 -MinutesBack 15 -ExpectedUser papatramp powershell.exe -NoProfile -ExecutionPolicy Bypass -File Diagnose-RdpLoginMonitor.ps1 -MinutesBack 15 -ExpectedUser jdoe
.NOTES .NOTES
Рекомендуется запуск от администратора. Без прав Security-журнал может быть неполным. Рекомендуется запуск от администратора. Без прав Security-журнал может быть неполным.
#> #>
+2 -2
View File
@@ -7,8 +7,8 @@
| Параметр | Значение | | Параметр | Значение |
|----------|----------| |----------|----------|
| `$RepoPath` | `C:\Soft\Git\RDP-login-monitor` | | `$RepoPath` | `C:\Soft\Git\RDP-login-monitor` |
| `$NetlogonDest` | `\\b26\NETLOGON\RDP-login-monitor` | | `$NetlogonDest` | `\\dc.contoso.local\NETLOGON\RDP-login-monitor` |
| `$GitUrl` | `https://git.kalinamall.ru/PapaTramp/RDP-login-monitor.git` | | `$GitUrl` | `https://github.com/PTah/RDP-login-monitor.git` |
| `$GitBranch` | `main` | | `$GitBranch` | `main` |
| `$LogFile` | `C:\soft\Logs\update-rdp-monitor.log` | | `$LogFile` | `C:\soft\Logs\update-rdp-monitor.log` |
+6 -6
View File
@@ -83,7 +83,7 @@ flowchart TD
**Мониторинг очередей транспорта и правил пересылки** — другой скрипт, **не** через GPO RDP-монитора: **Мониторинг очередей транспорта и правил пересылки** — другой скрипт, **не** через GPO RDP-монитора:
```powershell ```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange
``` ```
Подробно: [exchange-mail-security.md](exchange-mail-security.md). Подробно: [exchange-mail-security.md](exchange-mail-security.md).
@@ -105,7 +105,7 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-logi
```powershell ```powershell
$root = 'C:\ProgramData\RDP-login-monitor' $root = 'C:\ProgramData\RDP-login-monitor'
Copy-Item '\\B26\NETLOGON\RDP-login-monitor\login_monitor.settings.example.ps1' ` Copy-Item '\\dc.contoso.local\NETLOGON\RDP-login-monitor\login_monitor.settings.example.ps1' `
(Join-Path $root 'login_monitor.settings.ps1') (Join-Path $root 'login_monitor.settings.ps1')
notepad (Join-Path $root 'login_monitor.settings.ps1') notepad (Join-Path $root 'login_monitor.settings.ps1')
``` ```
@@ -116,7 +116,7 @@ DPAPI: **`Encrypt-DpapiForRdpMonitor.ps1`**.
```powershell ```powershell
$UseSAC = 'dual' # off | exclusive | dual | fallback $UseSAC = 'dual' # off | exclusive | dual | fallback
$SacUrl = 'https://sac.kalinamall.ru' $SacUrl = 'https://sac.example.com'
$SacApiKey = 'sac_...' $SacApiKey = 'sac_...'
``` ```
@@ -137,7 +137,7 @@ $SacApiKey = 'sac_...'
## GPO и периодический deploy ## GPO и периодический deploy
1. Файлы на `\\B26\NETLOGON\RDP-login-monitor\` (`update-rdp-monitor.ps1` на DC публикации). 1. Файлы на `\\dc.contoso.local\NETLOGON\RDP-login-monitor\` (`update-rdp-monitor.ps1` на DC публикации).
2. GPO на OU **компьютеров****Сценарии PowerShell** автозагрузки → `Deploy-LoginMonitor.ps1`. 2. GPO на OU **компьютеров****Сценарии PowerShell** автозагрузки → `Deploy-LoginMonitor.ps1`.
3. Security Filtering: группа компьютеров; на шару — Read для **SYSTEM** / Domain Computers. 3. Security Filtering: группа компьютеров; на шару — Read для **SYSTEM** / Domain Computers.
4. После смены membership — **перезагрузка** (не только `gpupdate`). 4. После смены membership — **перезагрузка** (не только `gpupdate`).
@@ -149,7 +149,7 @@ Deploy после `-InstallTasks` запускает монитор; задач
```powershell ```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\Install-DeployScheduledTask.ps1" ` powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\Install-DeployScheduledTask.ps1" `
-TaskName "RDP-Login-Monitor-Deploy" ` -TaskName "RDP-Login-Monitor-Deploy" `
-DeployScriptPath "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1" ` -DeployScriptPath "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1" `
-RepeatMinutes 60 ` -RepeatMinutes 60 `
-RunNow -RunNow
``` ```
@@ -157,7 +157,7 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\Install-DeploySchedul
**Ручной deploy** (от администратора): **Ручной deploy** (от администратора):
```powershell ```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1" powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1"
``` ```
Параметры: **`-WhatIf`**, **`-SkipStartMonitorAfterUpdate`**, **`-AllowDowngrade`**. Параметры: **`-WhatIf`**, **`-SkipStartMonitorAfterUpdate`**, **`-AllowDowngrade`**.
+5 -5
View File
@@ -106,7 +106,7 @@ $VipMailboxPatterns = @('*@domain.ru') # опционально
### 2. Деплой на Exchange (от администратора) ### 2. Деплой на Exchange (от администратора)
```powershell ```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange
``` ```
Скрипт копирует файлы в `C:\ProgramData\RDP-login-monitor\`, вызывает **`Install-DomainMonitors.ps1 -Target Exchange`**, который регистрирует задачи планировщика. Скрипт копирует файлы в `C:\ProgramData\RDP-login-monitor\`, вызывает **`Install-DomainMonitors.ps1 -Target Exchange`**, который регистрирует задачи планировщика.
@@ -120,7 +120,7 @@ powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-logi
$ex = 'C:\ProgramData\RDP-login-monitor' $ex = 'C:\ProgramData\RDP-login-monitor'
$src = Join-Path $ex 'exchange_monitor.settings.example.ps1' $src = Join-Path $ex 'exchange_monitor.settings.example.ps1'
if (-not (Test-Path -LiteralPath $src)) { if (-not (Test-Path -LiteralPath $src)) {
$src = '\\B26\NETLOGON\RDP-login-monitor\exchange_monitor.settings.example.ps1' $src = '\\dc.contoso.local\NETLOGON\RDP-login-monitor\exchange_monitor.settings.example.ps1'
} }
Copy-Item -LiteralPath $src -Destination (Join-Path $ex 'exchange_monitor.settings.ps1') Copy-Item -LiteralPath $src -Destination (Join-Path $ex 'exchange_monitor.settings.ps1')
notepad (Join-Path $ex 'exchange_monitor.settings.ps1') notepad (Join-Path $ex 'exchange_monitor.settings.ps1')
@@ -212,7 +212,7 @@ schtasks /Query /TN "RDP-Exchange-MailSecurity-Watchdog" /V /FO LIST
| `$InboxScanBatchSize` | 50 | Пауза каждые N ящиков | | `$InboxScanBatchSize` | 50 | Пауза каждые N ящиков |
| `$InboxScanBatchDelaySeconds` | 3 | Задержка между батчами | | `$InboxScanBatchDelaySeconds` | 3 | Задержка между батчами |
| `$ExcludeMailboxPatterns` | HealthMailbox*, … | Исключения | | `$ExcludeMailboxPatterns` | HealthMailbox*, … | Исключения |
| `$SkipInboxScanMailboxes` | `k.selezneva@kalinamall.ru` | Не вызывать `Get-InboxRule` (битый rule store) | | `$SkipInboxScanMailboxes` | `k.selezneva@example.com` | Не вызывать `Get-InboxRule` (битый rule store) |
Переопределение — в **`exchange_monitor.settings.ps1`**. Переопределение — в **`exchange_monitor.settings.ps1`**.
@@ -225,7 +225,7 @@ schtasks /Query /TN "RDP-Exchange-MailSecurity-Watchdog" /V /FO LIST
```text ```text
📧 Exchange: пересылка на внешний адрес 📧 Exchange: пересылка на внешний адрес
Тип: InboxRule | MailboxForwarding | TransportRule Тип: InboxRule | MailboxForwarding | TransportRule
Ящик: user@kalinamall.ru Ящик: user@example.com
Правило: … Правило: …
Куда: attacker@gmail.com (внешний) Куда: attacker@gmail.com (внешний)
Важность: Критическая | Высокая Важность: Критическая | Высокая
@@ -238,7 +238,7 @@ schtasks /Query /TN "RDP-Exchange-MailSecurity-Watchdog" /V /FO LIST
3. На Exchange: 3. На Exchange:
```powershell ```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\B26\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange powershell.exe -NoProfile -ExecutionPolicy Bypass -File "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-DomainMonitors.ps1" -Target Exchange
``` ```
## Устранение неполадок ## Устранение неполадок
+3 -3
View File
@@ -1,4 +1,4 @@
<# <#
.SYNOPSIS .SYNOPSIS
Мониторинг Exchange: очереди транспорта, пересылка на внешние адреса (Inbox rules + mailbox forwarding + transport rules). Мониторинг Exchange: очереди транспорта, пересылка на внешние адреса (Inbox rules + mailbox forwarding + transport rules).
.DESCRIPTION .DESCRIPTION
@@ -63,11 +63,11 @@ $ScanTransportRules = $true
# VIP: только перечисленные ящики и/или шаблоны (пилот перед полным сканом). # VIP: только перечисленные ящики и/или шаблоны (пилот перед полным сканом).
$VipMailboxesOnly = $false $VipMailboxesOnly = $false
$VipMailboxes = @() # точные PrimarySmtpAddress: user@domain.com $VipMailboxes = @() # точные PrimarySmtpAddress: user@domain.com
$VipMailboxPatterns = @() # wildcard: *@kalinamall.ru, director*, finance* $VipMailboxPatterns = @() # wildcard: *@example.com, director*, finance*
$ExcludeMailboxPatterns = @('HealthMailbox*', 'DiscoveryMailbox*', 'SystemMailbox*') $ExcludeMailboxPatterns = @('HealthMailbox*', 'DiscoveryMailbox*', 'SystemMailbox*')
# Skip Inbox rules scan (corrupt rule store / Get-InboxRule fails). Override in exchange_monitor.settings.ps1 # Skip Inbox rules scan (corrupt rule store / Get-InboxRule fails). Override in exchange_monitor.settings.ps1
$SkipInboxScanMailboxes = @( $SkipInboxScanMailboxes = @(
'k.selezneva@kalinamall.ru' 'broken-mailbox@example.com'
) )
$ScanDisabledInboxRulesWithExternalForward = $true # отключённые правила с внешней пересылкой $ScanDisabledInboxRulesWithExternalForward = $true # отключённые правила с внешней пересылкой
$SuppressAlertsOnFirstBaselineRun = $true # первый скан: baseline без всплеска алертов $SuppressAlertsOnFirstBaselineRun = $true # первый скан: baseline без всплеска алертов
+1 -1
View File
@@ -2,7 +2,7 @@
[CmdletBinding()] [CmdletBinding()]
param( param(
[string]$TaskName = "RDP-Login-Monitor-Deploy", [string]$TaskName = "RDP-Login-Monitor-Deploy",
[string]$DeployScriptPath = "\\B26\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1", [string]$DeployScriptPath = "\\dc.contoso.local\NETLOGON\RDP-login-monitor\Deploy-LoginMonitor.ps1",
[ValidateRange(5, 1440)][int]$RepeatMinutes = 60, [ValidateRange(5, 1440)][int]$RepeatMinutes = 60,
[switch]$RunNow [switch]$RunNow
) )
+147 -3
View File
@@ -90,7 +90,7 @@ $script:SkipLogDetailLimit = 15
# строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах). # строки ниже, если правки «мелкие» и вы не хотите менять отображаемую версию в логах).
# Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только # Рекомендация: при значимых релизах меняйте и $ScriptVersion, и version.txt одинаково; при только
# исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1). # исправлениях на шаре — достаточно поднять patch в version.txt (например 1.3.0.1).
$ScriptVersion = "2.0.36-SAC" $ScriptVersion = "2.0.38-SAC"
# Логи (все под InstallRoot) # Логи (все под InstallRoot)
$LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log" $LogFile = Join-Path $script:InstallRoot "Logs\login_monitor.log"
@@ -103,6 +103,8 @@ $MaxBackupDays = 31
# Heartbeat (файл; при отсутствии обновления > HeartbeatStaleAlertMultiplier × интервал — оповещение) # Heartbeat (файл; при отсутствии обновления > HeartbeatStaleAlertMultiplier × интервал — оповещение)
$HeartbeatInterval = 14400 $HeartbeatInterval = 14400
# Окно (мин) для определения «старт после перезагрузки ОС» (LastBootUpTime + System 41/1074/6005/6008/6009).
$StartupRebootDetectMinutes = 5
# Инвентаризация железа/ПО для SAC (agent.inventory); интервал опроса, сек (12 ч). # Инвентаризация железа/ПО для SAC (agent.inventory); интервал опроса, сек (12 ч).
$InventoryIntervalSec = 43200 $InventoryIntervalSec = 43200
$GetInventory = 1 $GetInventory = 1
@@ -1095,7 +1097,8 @@ function Send-RdpMonitorLifecycleNotification {
[Parameter(Mandatory = $true)][string]$SacSummary, [Parameter(Mandatory = $true)][string]$SacSummary,
[string]$SacTitle = '', [string]$SacTitle = '',
[string]$SacSeverity = 'info', [string]$SacSeverity = 'info',
[string]$EmailSubject = 'RDP Login Monitor' [string]$EmailSubject = 'RDP Login Monitor',
[hashtable]$SacDetailsExtra = @{}
) )
$title = if (-not [string]::IsNullOrWhiteSpace($SacTitle)) { $SacTitle } else { "RDP login monitor: $Lifecycle" } $title = if (-not [string]::IsNullOrWhiteSpace($SacTitle)) { $SacTitle } else { "RDP login monitor: $Lifecycle" }
@@ -1104,6 +1107,9 @@ function Send-RdpMonitorLifecycleNotification {
lifecycle = $Lifecycle lifecycle = $Lifecycle
trigger = $Trigger trigger = $Trigger
} }
foreach ($dk in @($SacDetailsExtra.Keys)) {
$sacDetails[$dk] = $SacDetailsExtra[$dk]
}
if (-not [string]::IsNullOrWhiteSpace($plainBody)) { if (-not [string]::IsNullOrWhiteSpace($plainBody)) {
$sacDetails.notification_body = $plainBody $sacDetails.notification_body = $plainBody
} }
@@ -2447,6 +2453,110 @@ function Send-RdpMonitorSacHeartbeat {
} }
} }
function Get-RdpMonitorSystemEventShortLabel {
param([int]$Id)
switch ($Id) {
41 { return 'Kernel-Power: unexpected reboot' }
1074 { return 'User32: planned shutdown/restart' }
6005 { return 'EventLog: service started' }
6008 { return 'EventLog: previous shutdown unexpected' }
6009 { return 'EventLog: OS version at startup' }
default { return "System ID $Id" }
}
}
function Get-RdpMonitorStartupCause {
param([int]$WindowMinutes = 5)
if ($WindowMinutes -lt 1) { $WindowMinutes = 5 }
$now = Get-Date
$since = $now.AddMinutes(-$WindowMinutes)
$bootTime = $null
$uptimeMin = $null
try {
$os = Get-CimInstance Win32_OperatingSystem -ErrorAction Stop
$bootTime = $os.LastBootUpTime
if ($null -ne $bootTime) {
$uptimeMin = ($now - $bootTime).TotalMinutes
}
} catch {
Write-Log "WARN: StartupCause: Win32_OperatingSystem недоступен: $($_.Exception.Message)"
}
$rebootEventIds = @(41, 1074, 6005, 6008, 6009)
$events = @()
$eventQueryStart = $since
# После ребута монитор может стартовать позже окна (5 мин): тогда берём System с LastBootUpTime (до 60 мин).
if ($null -ne $bootTime -and $null -ne $uptimeMin -and $uptimeMin -le 60 -and $bootTime -lt $eventQueryStart) {
$eventQueryStart = $bootTime
}
try {
$events = @(Get-WinEvent -FilterHashtable @{
LogName = 'System'
Id = $rebootEventIds
StartTime = $eventQueryStart
} -MaxEvents 15 -ErrorAction Stop | Sort-Object TimeCreated)
} catch {
if ($_.Exception -and $_.Exception.Message -notmatch 'No events were found|NoMatchingEventsFound') {
Write-Log "WARN: StartupCause: чтение журнала System: $($_.Exception.Message)"
}
}
$bootRecent = ($null -ne $uptimeMin -and $uptimeMin -le $WindowMinutes)
$hasRebootEvents = ($events.Count -gt 0)
$bootEventsRecent = ($hasRebootEvents -and $null -ne $uptimeMin -and $uptimeMin -le 60)
if ($bootRecent -or $bootEventsRecent) {
return [pscustomobject]@{
Cause = 'os_reboot'
WindowMinutes = $WindowMinutes
BootTime = $bootTime
UptimeMinutes = if ($null -ne $uptimeMin) { [math]::Round($uptimeMin, 1) } else { $null }
SystemEvents = @($events | ForEach-Object {
[pscustomobject]@{
TimeCreated = $_.TimeCreated
Id = $_.Id
ProviderName = $_.ProviderName
MessageShort = (Get-RdpMonitorSystemEventShortLabel -Id $_.Id)
}
})
}
}
return [pscustomobject]@{
Cause = 'process_start'
WindowMinutes = $WindowMinutes
BootTime = $bootTime
UptimeMinutes = if ($null -ne $uptimeMin) { [math]::Round($uptimeMin, 1) } else { $null }
SystemEvents = @()
}
}
function Format-RdpMonitorStartupCauseLogLine {
param([Parameter(Mandatory = $true)]$StartupCause)
if ($StartupCause.Cause -eq 'os_reboot') {
$parts = [System.Collections.Generic.List[string]]::new()
[void]$parts.Add('Старт монитора после перезагрузки ОС')
if ($null -ne $StartupCause.UptimeMinutes) {
[void]$parts.Add("uptime $($StartupCause.UptimeMinutes) мин")
}
if ($StartupCause.BootTime) {
[void]$parts.Add("LastBootUpTime=$($StartupCause.BootTime.ToString('dd.MM.yyyy HH:mm:ss'))")
}
if ($StartupCause.SystemEvents.Count -gt 0) {
$evSumm = ($StartupCause.SystemEvents | ForEach-Object {
"$($_.TimeCreated.ToString('dd.MM.yyyy HH:mm:ss')) ID$($_.Id) ($($_.MessageShort))"
}) -join '; '
[void]$parts.Add("System: $evSumm")
}
return ($parts -join '; ') + '.'
}
$uptimeStr = if ($null -ne $StartupCause.UptimeMinutes) { "$($StartupCause.UptimeMinutes) мин" } else { '?' }
return "Старт монитора: перезагрузка ОС за последние $($StartupCause.WindowMinutes) мин не обнаружена (uptime $uptimeStr) — перезапуск процесса или задачи планировщика."
}
function Send-Heartbeat { function Send-Heartbeat {
param([switch]$IsStartup = $false) param([switch]$IsStartup = $false)
@@ -2492,6 +2602,14 @@ function Send-Heartbeat {
} }
if ($IsStartup) { if ($IsStartup) {
$windowMin = 5
if (Get-Variable -Name StartupRebootDetectMinutes -Scope Script -ErrorAction SilentlyContinue) {
$w = (Get-Variable -Name StartupRebootDetectMinutes -Scope Script -ValueOnly)
if ($null -ne $w -and [int]$w -gt 0) { $windowMin = [int]$w }
}
$startupCause = Get-RdpMonitorStartupCause -WindowMinutes $windowMin
Write-Log (Format-RdpMonitorStartupCauseLogLine -StartupCause $startupCause)
$message = "<b>✅ Мониторинг логинов ЗАПУЩЕН</b>`r`n" $message = "<b>✅ Мониторинг логинов ЗАПУЩЕН</b>`r`n"
$message += "🏷️ Версия скрипта: $(ConvertTo-TelegramHtml $ScriptVersion)" $message += "🏷️ Версия скрипта: $(ConvertTo-TelegramHtml $ScriptVersion)"
$upd = Get-DeployUpdateMarker $upd = Get-DeployUpdateMarker
@@ -2500,10 +2618,18 @@ function Send-Heartbeat {
$message += " (обновлён $(ConvertTo-TelegramHtml $upd.UpdatedAt))" $message += " (обновлён $(ConvertTo-TelegramHtml $upd.UpdatedAt))"
$lifecycleTrigger = 'deploy_recycle' $lifecycleTrigger = 'deploy_recycle'
Set-DeployUpdateMarkerPendingOff -Marker $upd Set-DeployUpdateMarkerPendingOff -Marker $upd
} elseif ($startupCause.Cause -eq 'os_reboot') {
$lifecycleTrigger = 'os_reboot'
} elseif ($startupCause.Cause -eq 'process_start') {
$lifecycleTrigger = 'process_start'
} }
$message += "`r`n" $message += "`r`n"
$message += "🖥️ Сервер: $hHost`r`n" $message += "🖥️ Сервер: $hHost`r`n"
$message += "🕐 Время запуска: $timestamp" $message += "🕐 Время запуска: $timestamp"
if ($startupCause.Cause -eq 'os_reboot') {
$causePlain = Format-RdpMonitorStartupCauseLogLine -StartupCause $startupCause
$message += "`r`n🔄 $(ConvertTo-TelegramHtml $causePlain)"
}
if ($script:OsInstallKindLabel) { if ($script:OsInstallKindLabel) {
$message += "`r`n💻 <b>Тип установки:</b> $(ConvertTo-TelegramHtml $script:OsInstallKindLabel)" $message += "`r`n💻 <b>Тип установки:</b> $(ConvertTo-TelegramHtml $script:OsInstallKindLabel)"
} }
@@ -2554,10 +2680,28 @@ function Send-Heartbeat {
$message += " IP из IIS не заданы (<code>ExchangeIisLogPath</code> пуст)." $message += " IP из IIS не заданы (<code>ExchangeIisLogPath</code> пуст)."
} }
} }
$sacStartupExtra = @{
startup_cause = $startupCause.Cause
}
if ($null -ne $startupCause.UptimeMinutes) {
$sacStartupExtra.uptime_minutes = $startupCause.UptimeMinutes
}
if ($startupCause.BootTime) {
$sacStartupExtra.last_boot_up_time = $startupCause.BootTime.ToString('o')
}
if ($startupCause.SystemEvents.Count -gt 0) {
$sacStartupExtra.system_event_ids = @($startupCause.SystemEvents | ForEach-Object { $_.Id }) -join ','
}
Send-RdpMonitorLifecycleNotification -Lifecycle 'started' -Trigger $lifecycleTrigger ` Send-RdpMonitorLifecycleNotification -Lifecycle 'started' -Trigger $lifecycleTrigger `
-TelegramHtmlMessage $message -EmailSubject 'RDP Login Monitor: запуск' ` -TelegramHtmlMessage $message -EmailSubject 'RDP Login Monitor: запуск' `
-SacTitle 'RDP login monitor started' ` -SacTitle 'RDP login monitor started' `
-SacSummary "Мониторинг запущен на $(Get-MonitorServerLabelWithIp), версия $ScriptVersion" -SacSummary $(if ($startupCause.Cause -eq 'os_reboot') {
"Мониторинг запущен после перезагрузки ОС на $(Get-MonitorServerLabelWithIp), версия $ScriptVersion"
} else {
"Мониторинг запущен на $(Get-MonitorServerLabelWithIp), версия $ScriptVersion"
}) `
-SacDetailsExtra $sacStartupExtra
Write-Log "Отправлено уведомление о запуске скрипта (каналы: $notifyChain)" Write-Log "Отправлено уведомление о запуске скрипта (каналы: $notifyChain)"
Send-RdpMonitorSacHeartbeat -Timestamp $timestamp Send-RdpMonitorSacHeartbeat -Timestamp $timestamp
} else { } else {
+5 -5
View File
@@ -29,11 +29,11 @@ $QueueMessageCountThreshold = 150
# --- Пилот VIP (рекомендуется для первого запуска) --- # --- Пилот VIP (рекомендуется для первого запуска) ---
# $VipMailboxesOnly = $true # $VipMailboxesOnly = $true
# $VipMailboxes = @( # $VipMailboxes = @(
# 'director@kalinamall.ru', # 'director@example.com',
# 'cfo@kalinamall.ru' # 'cfo@example.com'
# ) # )
# $VipMailboxPatterns = @( # $VipMailboxPatterns = @(
# '*@kalinamall.ru' # опционально: все ящики домена из Get-Mailbox # '*@example.com' # опционально: все ящики домена из Get-Mailbox
# ) # )
# Первый ночной скан: не слать сотни алертов по уже существующим пересылкам # Первый ночной скан: не слать сотни алертов по уже существующим пересылкам
@@ -46,9 +46,9 @@ $QueueMessageCountThreshold = 150
# $SendInboxScanSummary = $true # $SendInboxScanSummary = $true
# Удалённый EMS (если скрипт не на Exchange) # Удалённый EMS (если скрипт не на Exchange)
# $ExchangeServerFqdn = 'fifth.kalinamall.ru' # $ExchangeServerFqdn = 'mail.example.com'
# Не сканировать Inbox rules (битое хранилище правил / Watson на Get-InboxRule) # Не сканировать Inbox rules (битое хранилище правил / Watson на Get-InboxRule)
# $SkipInboxScanMailboxes = @( # $SkipInboxScanMailboxes = @(
# 'k.selezneva@kalinamall.ru' # 'k.selezneva@example.com'
# ) # )
+12 -10
View File
@@ -9,9 +9,8 @@
#> #>
# --- Telegram (или DPAPI Base64 через Encrypt-DpapiForRdpMonitor.ps1) --- # --- Telegram (или DPAPI Base64 через Encrypt-DpapiForRdpMonitor.ps1) ---
# Закрытое зеркало Gitea — доверенный инстанс; в публичном GitHub используйте example без секретов. $TelegramBotToken = 'YOUR_BOT_TOKEN'
$TelegramBotToken = '8239219522:AAEyOZX3cwNfgGOMDkf-mgjTIuoaOh5gF7I' $TelegramChatID = 'YOUR_CHAT_ID'
$TelegramChatID = '2843230'
# $TelegramBotTokenProtectedB64 = '' # $TelegramBotTokenProtectedB64 = ''
# $TelegramChatIDProtectedB64 = '' # $TelegramChatIDProtectedB64 = ''
@@ -30,13 +29,13 @@ $NotifyOrder = 'tg'
# --- Подпись сервера в Telegram и SAC (host.display_name); пусто = $env:COMPUTERNAME --- # --- Подпись сервера в Telegram и SAC (host.display_name); пусто = $env:COMPUTERNAME ---
# $ServerDisplayName = 'UNMS Kalina' # $ServerDisplayName = 'UNMS Kalina'
# --- Явный IPv4 хоста для SAC (опционально; иначе автоопределение) --- # --- Явный IPv4 хоста для SAC (опционально; иначе автоопределение) ---
# $ServerIPv4 = '192.168.160.57' # $ServerIPv4 = '10.0.0.10'
# --- 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 = 'fallback' $UseSAC = 'fallback'
$SacUrl = 'https://sac.kalinamall.ru' $SacUrl = 'https://sac.example.com'
$SacApiKey = 'sac_UkOsAT3UWiQS54KK5OJPBDCSucysQDrKFju28wmYiz8' $SacApiKey = 'sac_CHANGE_ME'
# $SacSpoolDir = 'C:\ProgramData\RDP-login-monitor\sac-spool' # $SacSpoolDir = 'C:\ProgramData\RDP-login-monitor\sac-spool'
# $SacTimeoutSec = 12 # $SacTimeoutSec = 12
# $SacTlsSkipVerify = $false # $SacTlsSkipVerify = $false
@@ -48,6 +47,9 @@ $DailyReportEnabled = 1
# --- Heartbeat SAC (agent.heartbeat): интервал в секундах; 14400 = 4 ч --- # --- Heartbeat SAC (agent.heartbeat): интервал в секундах; 14400 = 4 ч ---
$HeartbeatInterval = 14400 $HeartbeatInterval = 14400
# Окно (мин): LastBootUpTime + System 41/1074/6005/6008/6009 → «старт после перезагрузки ОС»
$StartupRebootDetectMinutes = 5
# --- Инвентаризация железа/ПО для SAC (agent.inventory, раз в 12 ч) --- # --- Инвентаризация железа/ПО для SAC (agent.inventory, раз в 12 ч) ---
$GetInventory = $true $GetInventory = $true
@@ -63,7 +65,7 @@ $GetInventory = $true
# --- Узкое исключение шумовых сетевых логонов (LogonType=3, Advapi) --- # --- Узкое исключение шумовых сетевых логонов (LogonType=3, Advapi) ---
$IgnoreAdvapiNetworkLogonSourceIps = @( $IgnoreAdvapiNetworkLogonSourceIps = @(
'192.168.160.57' '10.0.0.1'
) )
# --- Exchange noise filter: 4624 + LogonType=3 + IP='-' (часто Outlook/почтовые клиенты) --- # --- Exchange noise filter: 4624 + LogonType=3 + IP='-' (часто Outlook/почтовые клиенты) ---
# Включайте на почтовом сервере, если нужен только полезный интерактивный сигнал. # Включайте на почтовом сервере, если нужен только полезный интерактивный сигнал.
@@ -76,9 +78,9 @@ $MaxBackupDays = 31
# --- Блокировка учётной записи AD (4740) + IP из IIS ActiveSync --- # --- Блокировка учётной записи AD (4740) + IP из IIS ActiveSync ---
# Мониторинг включается только на КД с именем $LockoutMonitorDomainController. # Мониторинг включается только на КД с именем $LockoutMonitorDomainController.
$LockoutMonitorDomainController = 'K6A-DC3' $LockoutMonitorDomainController = 'DC01'
$NetBiosDomainName = 'B26' $NetBiosDomainName = 'CONTOSO'
$ExchangeIisLogPath = '\\fifth.kalinamall.ru\c$\inetpub\logs\LogFiles\W3SVC1' $ExchangeIisLogPath = '\\mail.example.com\c$\inetpub\logs\LogFiles\W3SVC1'
$ExchangeServerHostForIisExclude = '' $ExchangeServerHostForIisExclude = ''
$ExchangeIisLogTailLines = 5000 $ExchangeIisLogTailLines = 5000
$ExchangeIisLogMinutesBeforeLockout = 30 $ExchangeIisLogMinutesBeforeLockout = 30
-20
View File
@@ -1,20 +0,0 @@
<#
.SYNOPSIS
Push main to kalinamall only (skip public GitHub origin).
#>
[CmdletBinding()]
param(
[string]$Branch = 'main'
)
Set-StrictMode -Version Latest
$ErrorActionPreference = 'Stop'
$repoRoot = Split-Path -Parent $PSScriptRoot
Push-Location -LiteralPath $repoRoot
try {
git push kalinamall $Branch
Write-Host "Pushed to kalinamall/$Branch (origin/GitHub skipped intentionally)."
} finally {
Pop-Location
}
+1 -1
View File
@@ -1,6 +1,6 @@
<# <#
.SYNOPSIS .SYNOPSIS
Smoke/autotests for RDP-login-monitor deploy and SAC paths (kalinamall internal). Smoke/autotests for RDP-login-monitor deploy and SAC paths.
.EXAMPLE .EXAMPLE
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tools\Run-RdpMonitorTests.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File tools\Run-RdpMonitorTests.ps1
#> #>
+1 -1
View File
@@ -3,7 +3,7 @@
Просмотр недавних 4624 с полями для диагностики RDP-login-monitor. Просмотр недавних 4624 с полями для диагностики RDP-login-monitor.
.EXAMPLE .EXAMPLE
.\Show-Rdp4624Recent.ps1 .\Show-Rdp4624Recent.ps1
.\Show-Rdp4624Recent.ps1 -Minutes 30 -User papatramp .\Show-Rdp4624Recent.ps1 -Minutes 30 -User jdoe
#> #>
[CmdletBinding()] [CmdletBinding()]
param( param(
+1 -1
View File
@@ -11,7 +11,7 @@ $sample303 = @'
</System> </System>
<UserData> <UserData>
<EventInfo xmlns="aag"> <EventInfo xmlns="aag">
<Username>B26\TSA</Username> <Username>CONTOSO\TSA</Username>
<IpAddress>95.154.72.73</IpAddress> <IpAddress>95.154.72.73</IpAddress>
<Resource>192.168.164.43</Resource> <Resource>192.168.164.43</Resource>
<BytesReceived>1991</BytesReceived> <BytesReceived>1991</BytesReceived>
-24
View File
@@ -1,24 +0,0 @@
# Autotests (kalinamall only)
Каталог `tools/tests/` и `tools/Run-RdpMonitorTests.ps1`**внутренние** smoke-тесты.
## Запуск
```powershell
powershell.exe -NoProfile -ExecutionPolicy Bypass -File tools\Run-RdpMonitorTests.ps1
```
Перед push правок `Deploy-LoginMonitor.ps1` / `Login_Monitor.ps1` / `RdpMonitor-TaskQuery.ps1`.
## Git remotes
- **kalinamall** — публиковать можно (`git push kalinamall main`)
- **GitHub (origin)****не пушить** коммиты с этими тестами на публичный remote
После работы с тестами:
```powershell
git push kalinamall main
```
На `origin` (GitHub) не выполнять push, если в коммите есть `tools/tests/` или `tools/Run-RdpMonitorTests.ps1`.
+8 -21
View File
@@ -4,7 +4,7 @@
.DESCRIPTION .DESCRIPTION
Dlya servera publikatsii (napr. DC3). Po umolchaniyu GitHub (github.com/PTah). Dlya servera publikatsii (napr. DC3). Po umolchaniyu GitHub (github.com/PTah).
Na zakrytom zerkale ukazhite -GitUrl URL vashego Gitea. Na zakrytom zerkale ukazhite -GitUrl URL vashego Gitea.
Posle fetch: vsegda reset --hard na kalinamall/main (bez merge), zatem clean -fd. Posle fetch: vsegda reset --hard na vetku upstream (bez merge), zatem clean -fd.
Kopiruyutsya: polnyj spisok v Docs/deploy-netlogon-publish.md. Kopiruyutsya: polnyj spisok v Docs/deploy-netlogon-publish.md.
.EXAMPLE .EXAMPLE
powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\soft\update-rdp-monitor.ps1 powershell.exe -NoProfile -ExecutionPolicy Bypass -File C:\soft\update-rdp-monitor.ps1
@@ -14,8 +14,8 @@
[CmdletBinding(SupportsShouldProcess = $true)] [CmdletBinding(SupportsShouldProcess = $true)]
param( param(
[string]$RepoPath = 'C:\Soft\Git\RDP-login-monitor', [string]$RepoPath = 'C:\Soft\Git\RDP-login-monitor',
[string]$NetlogonDest = '\\b26\NETLOGON\RDP-login-monitor', [string]$NetlogonDest = '\\dc.contoso.local\NETLOGON\RDP-login-monitor',
[string]$GitUrl = 'https://git.kalinamall.ru/PapaTramp/RDP-login-monitor.git', [string]$GitUrl = 'https://github.com/PTah/RDP-login-monitor.git',
[string]$GitBranch = 'main', [string]$GitBranch = 'main',
[string]$LogFile = 'C:\soft\Logs\update-rdp-monitor.log', [string]$LogFile = 'C:\soft\Logs\update-rdp-monitor.log',
[switch]$SkipGitClean [switch]$SkipGitClean
@@ -112,38 +112,25 @@ function Ensure-GitRepository {
function Get-ConfiguredGitRemoteName { function Get-ConfiguredGitRemoteName {
$names = @(Invoke-GitCommand -Arguments @('remote') | ForEach-Object { "$_".Trim() } | Where-Object { $_ }) $names = @(Invoke-GitCommand -Arguments @('remote') | ForEach-Object { "$_".Trim() } | Where-Object { $_ })
if ($names.Count -eq 0) { return $null } if ($names.Count -eq 0) { return $null }
if ('kalinamall' -in $names) { return 'kalinamall' }
foreach ($n in $names) {
$url = (& git -C $RepoPath remote get-url $n 2>$null)
if ($url -match 'git\.kalinamall\.ru') { return $n }
}
if ('origin' -in $names) { return 'origin' } if ('origin' -in $names) { return 'origin' }
return $names[0] return $names[0]
} }
function Ensure-GitKalinamallRemote { function Ensure-GitUpstreamRemote {
$name = Get-ConfiguredGitRemoteName $name = Get-ConfiguredGitRemoteName
if ($null -ne $name) { if ($null -ne $name) {
$url = (& git -C $RepoPath remote get-url $name 2>$null) $url = (& git -C $RepoPath remote get-url $name 2>$null)
if ($url -match 'git\.kalinamall\.ru') {
Write-UpdateLog "Using remote: $name ($url)" Write-UpdateLog "Using remote: $name ($url)"
return $name return $name
} }
Write-UpdateLog "Remote $name is not kalinamall ($url); adding kalinamall -> $GitUrl" Write-UpdateLog "No remotes; adding origin -> $GitUrl"
} else { Invoke-GitCommand -Arguments @('remote', 'add', 'origin', $GitUrl)
Write-UpdateLog "No remotes; adding kalinamall -> $GitUrl" return 'origin'
}
if ('kalinamall' -in @(& git -C $RepoPath remote 2>$null)) {
Invoke-GitCommand -Arguments @('remote', 'set-url', 'kalinamall', $GitUrl)
return 'kalinamall'
}
Invoke-GitCommand -Arguments @('remote', 'add', 'kalinamall', $GitUrl)
return 'kalinamall'
} }
function Update-Repository { function Update-Repository {
Ensure-GitRepository Ensure-GitRepository
$remote = Ensure-GitKalinamallRemote $remote = Ensure-GitUpstreamRemote
Invoke-GitCommand -Arguments @('fetch', '--prune', $remote, $GitBranch) Invoke-GitCommand -Arguments @('fetch', '--prune', $remote, $GitBranch)
$upstream = "${remote}/${GitBranch}" $upstream = "${remote}/${GitBranch}"
+1 -1
View File
@@ -1 +1 @@
2.0.36-SAC 2.0.38-SAC