93 lines
3.3 KiB
PowerShell
93 lines
3.3 KiB
PowerShell
function New-SecuritySecret {
|
|
$bytes = New-Object byte[] 48
|
|
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
|
|
try {
|
|
$rng.GetBytes($bytes)
|
|
} finally {
|
|
$rng.Dispose()
|
|
}
|
|
return [Convert]::ToBase64String($bytes)
|
|
}
|
|
|
|
function New-InitialAdminPassword {
|
|
$bytes = New-Object byte[] 10
|
|
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
|
|
try {
|
|
$rng.GetBytes($bytes)
|
|
} finally {
|
|
$rng.Dispose()
|
|
}
|
|
return ([BitConverter]::ToString($bytes) -replace "-", "").ToLowerInvariant()
|
|
}
|
|
|
|
function Get-EnvValue {
|
|
param([string]$Content, [string]$Key)
|
|
$match = [regex]::Match($Content, "(?m)^$([regex]::Escape($Key))=(.*)$")
|
|
if (-not $match.Success) { return "" }
|
|
$value = $match.Groups[1].Value.Trim()
|
|
if ($value.Length -ge 2) {
|
|
$first = $value.Substring(0, 1)
|
|
$last = $value.Substring($value.Length - 1, 1)
|
|
if (($first -eq "'" -and $last -eq "'") -or ($first -eq '"' -and $last -eq '"')) {
|
|
return $value.Substring(1, $value.Length - 2)
|
|
}
|
|
}
|
|
return $value
|
|
}
|
|
|
|
function Set-EnvValue {
|
|
param([string]$Content, [string]$Key, [string]$Value)
|
|
$pattern = "(?m)^$([regex]::Escape($Key))=.*(?:\r?\n)?"
|
|
$replacement = "$Key=$Value`r`n"
|
|
if ([regex]::IsMatch($Content, $pattern)) {
|
|
return [regex]::Replace($Content, $pattern, $replacement, 1)
|
|
}
|
|
if ($Content -and -not $Content.EndsWith("`n")) { $Content += "`r`n" }
|
|
return $Content + $replacement
|
|
}
|
|
|
|
function Initialize-SecurityEnv {
|
|
param(
|
|
[Parameter(Mandatory = $true)][string]$Path,
|
|
[ValidateSet("new", "upgrade")][string]$Mode = "upgrade"
|
|
)
|
|
if (-not (Test-Path $Path)) { throw "Environment file not found: $Path" }
|
|
|
|
$content = Get-Content $Path -Raw -Encoding UTF8
|
|
if ($null -eq $content) { $content = "" }
|
|
$definitions = @(
|
|
@{ Key = "CONFIG_JWT_SECRET"; Legacy = "this is a very secret secret"; MinLength = 32 }
|
|
)
|
|
if ($Mode -eq "new") {
|
|
$definitions += @(
|
|
@{ Key = "CONFIG_SECURITY_CONFIG_ENCRYPTION_KEY"; Legacy = ""; MinLength = 32 },
|
|
@{ Key = "CONFIG_OTP_HASH_SECRET"; Legacy = ""; MinLength = 32 },
|
|
@{ Key = "CONFIG_AUDIT_HASH_PEPPER"; Legacy = ""; MinLength = 32 },
|
|
@{ Key = "CONFIG_AUDIT_INTEGRITY_KEY"; Legacy = ""; MinLength = 32 }
|
|
)
|
|
}
|
|
|
|
foreach ($definition in $definitions) {
|
|
$current = Get-EnvValue $content $definition.Key
|
|
$needsInitialization = $current.Length -lt $definition.MinLength -or
|
|
($definition.Legacy -and $current -eq $definition.Legacy)
|
|
if (-not $needsInitialization) { continue }
|
|
$content = Set-EnvValue $content $definition.Key (New-SecuritySecret)
|
|
Write-Host " [OK] Initialized security secret: $($definition.Key)" -ForegroundColor Green
|
|
}
|
|
|
|
if ($Mode -eq "new") {
|
|
$adminPassword = Get-EnvValue $content "CONFIG_INITIAL_ADMIN_PASSWORD"
|
|
if ($adminPassword.Length -lt 12) {
|
|
$content = Set-EnvValue $content "CONFIG_INITIAL_ADMIN_PASSWORD" (New-InitialAdminPassword)
|
|
Write-Host " [OK] Initialized admin password: CONFIG_INITIAL_ADMIN_PASSWORD" -ForegroundColor Green
|
|
}
|
|
}
|
|
|
|
[System.IO.File]::WriteAllText(
|
|
(Resolve-Path $Path),
|
|
$content,
|
|
[System.Text.UTF8Encoding]::new($false)
|
|
)
|
|
}
|