Files
insar-management-system-v2/scripts/sync_landsar_cluster_network_access.ps1
T

139 lines
4.4 KiB
PowerShell

param(
[string]$RepoRoot = (Resolve-Path (Join-Path $PSScriptRoot "..")).Path,
[string]$PostgresDataDir = "D:\PostgreSQLData",
[string]$PostgresServiceName = "postgresql-x64-17",
[string]$FirewallRuleName = "InSAR PostgreSQL 5432 LandSAR Cluster",
[int]$PostgresPort = 5432
)
$ErrorActionPreference = "Stop"
function Read-DotEnvValue {
param(
[string]$Path,
[string]$Name
)
if (-not (Test-Path -LiteralPath $Path)) {
return ""
}
$line = Get-Content -LiteralPath $Path |
Where-Object { $_ -match "^\s*$([regex]::Escape($Name))\s*=" } |
Select-Object -Last 1
if (-not $line) {
return ""
}
$value = ($line -split "=", 2)[1].Trim()
if (($value.StartsWith('"') -and $value.EndsWith('"')) -or ($value.StartsWith("'") -and $value.EndsWith("'"))) {
$value = $value.Substring(1, $value.Length - 2)
}
return $value
}
function Normalize-WorkerAddress {
param([string]$Raw)
$value = $Raw.Trim()
if (-not $value) {
return $null
}
if ($value -match "/") {
$parts = $value -split "/", 2
$ip = $parts[0]
$prefix = [int]$parts[1]
if ($prefix -lt 0 -or $prefix -gt 32) {
throw "Invalid CIDR prefix: $value"
}
} else {
$ip = $value
$prefix = 32
}
$parsed = $null
if (-not [System.Net.IPAddress]::TryParse($ip, [ref]$parsed)) {
throw "Invalid IP address: $value"
}
if ($parsed.AddressFamily -ne [System.Net.Sockets.AddressFamily]::InterNetwork) {
throw "Only IPv4 addresses are supported for LandSAR cluster workers: $value"
}
return "$ip/$prefix"
}
$envPath = Join-Path $RepoRoot ".env"
$allowedRaw = Read-DotEnvValue -Path $envPath -Name "LANDSAR_CLUSTER_ALLOWED_WORKER_IPS"
if (-not $allowedRaw) {
throw "LANDSAR_CLUSTER_ALLOWED_WORKER_IPS is empty. Set it in .env, for example: LANDSAR_CLUSTER_ALLOWED_WORKER_IPS=192.168.1.6"
}
$allowed = @()
foreach ($part in ($allowedRaw -split "[,;]")) {
$normalized = Normalize-WorkerAddress $part
if ($normalized -and ($allowed -notcontains $normalized)) {
$allowed += $normalized
}
}
if (-not $allowed) {
throw "No valid LandSAR cluster worker IPs found in LANDSAR_CLUSTER_ALLOWED_WORKER_IPS."
}
$hbaPath = Join-Path $PostgresDataDir "pg_hba.conf"
if (-not (Test-Path -LiteralPath $hbaPath)) {
throw "pg_hba.conf not found: $hbaPath"
}
$timestamp = Get-Date -Format "yyyyMMdd_HHmmss"
Copy-Item -LiteralPath $hbaPath -Destination "$hbaPath.bak_$timestamp"
$begin = "# BEGIN InSAR LandSAR cluster workers"
$end = "# END InSAR LandSAR cluster workers"
$content = Get-Content -LiteralPath $hbaPath
$newContent = New-Object System.Collections.Generic.List[string]
$inside = $false
foreach ($line in $content) {
if ($line -eq $begin) {
$inside = $true
continue
}
if ($line -eq $end) {
$inside = $false
continue
}
if (-not $inside) {
$newContent.Add($line)
}
}
$newContent.Add("")
$newContent.Add($begin)
foreach ($address in $allowed) {
$newContent.Add(("host insar_management all {0,-20} scram-sha-256" -f $address))
}
$newContent.Add($end)
Set-Content -LiteralPath $hbaPath -Value $newContent -Encoding ASCII
$pgCtl = "C:\Program Files\PostgreSQL\17\bin\pg_ctl.exe"
if (Test-Path -LiteralPath $pgCtl) {
& $pgCtl reload -D $PostgresDataDir | Out-Host
} else {
Restart-Service -Name $PostgresServiceName
}
$remoteAddresses = $allowed | ForEach-Object { ($_ -split "/", 2)[0] }
$rule = Get-NetFirewallRule -DisplayName $FirewallRuleName -ErrorAction SilentlyContinue
if (-not $rule) {
New-NetFirewallRule `
-DisplayName $FirewallRuleName `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalPort $PostgresPort `
-RemoteAddress $remoteAddresses `
-Profile Any | Out-Null
} else {
$rule | Set-NetFirewallRule -Enabled True -Direction Inbound -Action Allow -Profile Any
$rule | Get-NetFirewallAddressFilter | Set-NetFirewallAddressFilter -RemoteAddress $remoteAddresses
$rule | Get-NetFirewallPortFilter | Set-NetFirewallPortFilter -Protocol TCP -LocalPort $PostgresPort
}
Write-Host "LandSAR cluster network access synced."
Write-Host ("Allowed workers: " + ($allowed -join ", "))
Write-Host "PostgreSQL hba: $hbaPath"
Write-Host "Firewall rule: $FirewallRuleName"