feat(deploy): 补齐凭据加密接入迁移和密钥备份恢复
Test deployment public URL (Linux) / test-linux (push) Canceled after 0s
Test start.ps1 (Windows) / test-windows (push) Canceled after 0s
Test deployment public URL (Linux) / test-linux (pull_request) Canceled after 0s
Test start.ps1 (Windows) / test-windows (pull_request) Canceled after 0s
Test deployment public URL (Linux) / test-linux (push) Canceled after 0s
Test start.ps1 (Windows) / test-windows (push) Canceled after 0s
Test deployment public URL (Linux) / test-linux (pull_request) Canceled after 0s
Test start.ps1 (Windows) / test-windows (pull_request) Canceled after 0s
首次安装默认生成独立加密密钥,更新旧部署保留原配置,通过显式开关进入迁移窗口。增加生产迁移包装入口和完整密钥环备份恢复工具,并说明旧镜像升级、严格迁移、轮换及还原流程。 已通过 Bash 安全环境及密钥备份回归;对应 PowerShell 5.1 和 7 脚本已在 Windows 原生环境各通过 49 项验收。宁波服务器验收尚未执行。
This commit is contained in:
@@ -55,6 +55,48 @@ function Initialize-SecurityEnv {
|
||||
|
||||
$content = Get-Content $Path -Raw -Encoding UTF8
|
||||
if ($null -eq $content) { $content = "" }
|
||||
$active = Get-EnvValue $content 'CONFIG_CREDENTIAL_ENCRYPTION_ACTIVE_KEY_ID'
|
||||
$ringText = Get-EnvValue $content 'CONFIG_CREDENTIAL_ENCRYPTION_KEYRING'
|
||||
$legacy = Get-EnvValue $content 'CONFIG_CREDENTIAL_ALLOW_LEGACY_PLAINTEXT'
|
||||
if ($legacy -and $legacy -notin @('true','false')) { throw 'Credential legacy flag must be true/false' }
|
||||
if (-not $active -and -not $ringText) {
|
||||
if ($Mode -ne 'new' -and $legacy -eq 'false') { throw 'Credential encryption key missing; restore the original configuration' }
|
||||
if ($Mode -eq 'new' -or $env:DEPLOY_ENABLE_CREDENTIAL_ENCRYPTION -eq 'true') {
|
||||
$bytes = New-Object byte[] 32
|
||||
$rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
|
||||
try { $rng.GetBytes($bytes) } finally { $rng.Dispose() }
|
||||
$active = 'v1'
|
||||
$ringText = '{"v1":"' + [Convert]::ToBase64String($bytes) + '"}'
|
||||
$content = Set-EnvValue $content 'CONFIG_CREDENTIAL_ENCRYPTION_ACTIVE_KEY_ID' $active
|
||||
$content = Set-EnvValue $content 'CONFIG_CREDENTIAL_ENCRYPTION_KEYRING' ("'" + $ringText + "'")
|
||||
Write-Host ' [OK] Initialized independent credential encryption key (value omitted)'
|
||||
} elseif ($legacy -eq 'false') {
|
||||
throw 'Credential encryption key missing; restore the original configuration'
|
||||
} else {
|
||||
Write-Host ' [INFO] Existing deployment retains legacy compatibility; opt in using DEPLOY_ENABLE_CREDENTIAL_ENCRYPTION=true'
|
||||
}
|
||||
}
|
||||
if ($active -or $ringText) {
|
||||
try {
|
||||
if ($active -notmatch '^[A-Za-z0-9_-]{1,64}$') { throw 'invalid' }
|
||||
$normalized = $ringText -replace '\s', ''
|
||||
if ($ringText -notmatch '^\{\s*("[A-Za-z0-9_-]{1,64}"\s*:\s*"[A-Za-z0-9+/]{43}="\s*,\s*)*"[A-Za-z0-9_-]{1,64}"\s*:\s*"[A-Za-z0-9+/]{43}="\s*\}$') { throw 'invalid' }
|
||||
$ids = New-Object 'System.Collections.Generic.Dictionary[string,bool]' ([System.StringComparer]::Ordinal)
|
||||
foreach ($match in [regex]::Matches($normalized, '"([A-Za-z0-9_-]+)":"([A-Za-z0-9+/]+=)"')) {
|
||||
$id = $match.Groups[1].Value; $encoded = $match.Groups[2].Value
|
||||
if ($ids.ContainsKey($id)) { throw 'duplicate' }
|
||||
$key = [Convert]::FromBase64String($encoded)
|
||||
if ($key.Length -ne 32 -or [Convert]::ToBase64String($key) -cne $encoded) { throw 'invalid' }
|
||||
$ids[$id] = $true
|
||||
}
|
||||
if (-not $ids.ContainsKey($active)) { throw 'invalid' }
|
||||
} catch { throw 'Credential keyring invalid or incomplete; restore original keys (values omitted)' }
|
||||
if (-not $legacy) {
|
||||
if ($Mode -eq 'new') { $legacy = 'false' } else { $legacy = 'true' }
|
||||
$content = Set-EnvValue $content 'CONFIG_CREDENTIAL_ALLOW_LEGACY_PLAINTEXT' $legacy
|
||||
}
|
||||
if ($legacy -notin @('true', 'false')) { throw 'Credential legacy flag must be true/false' }
|
||||
}
|
||||
$definitions = @(
|
||||
@{ Key = "CONFIG_JWT_SECRET"; Legacy = "this is a very secret secret"; MinLength = 32 },
|
||||
@{ Key = "WS_AUTH_WS_TICKET_SECRET"; Legacy = ""; MinLength = 32 },
|
||||
@@ -102,4 +144,12 @@ function Initialize-SecurityEnv {
|
||||
$content,
|
||||
[System.Text.UTF8Encoding]::new($false)
|
||||
)
|
||||
if ($env:OS -eq 'Windows_NT') {
|
||||
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
|
||||
$acl = New-Object System.Security.AccessControl.FileSecurity
|
||||
$acl.SetAccessRuleProtection($true, $false)
|
||||
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, 'FullControl', 'Allow')
|
||||
$acl.AddAccessRule($rule)
|
||||
Set-Acl -LiteralPath $Path -AclObject $acl
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user