feat(deploy): 补齐凭据加密接入迁移和密钥备份恢复

首次安装默认生成独立加密密钥,更新旧部署保留原配置,通过显式开关进入迁移窗口。增加生产迁移包装入口和完整密钥环备份恢复工具,并说明旧镜像升级、严格迁移、轮换及还原流程。

已通过 Bash 安全环境及密钥备份回归;对应 PowerShell 5.1 和 7 脚本已在 Windows 原生环境各通过 49 项验收。宁波服务器验收尚未执行。
This commit is contained in:
2026-10-12 22:24:16 +08:00
parent f59dd33097
commit 5cff1041a9
15 changed files with 563 additions and 0 deletions
+28
View File
@@ -0,0 +1,28 @@
#Requires -Version 5.1
param(
[ValidateSet('inventory','dry-run','apply','verify','finalize')][string]$Mode = 'inventory',
[Parameter(Mandatory=$true)][string]$ExpectedTarget
)
$ErrorActionPreference = 'Stop'
$root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
Set-Location $root
. (Join-Path $root 'scripts/Initialize-SecurityEnv.ps1')
Initialize-SecurityEnv -Path (Join-Path $root '.env') -Mode upgrade
$content = Get-Content (Join-Path $root '.env') -Raw
if (-not (Get-EnvValue $content 'CONFIG_CREDENTIAL_ENCRYPTION_KEYRING')) { throw 'Configure independent encryption keys and prepare database/queue backup before migrating' }
$checkpointDir = Join-Path $root 'data/credential-migration'
[System.IO.Directory]::CreateDirectory($checkpointDir) | Out-Null
if ($env:OS -eq 'Windows_NT') {
$identity = [System.Security.Principal.WindowsIdentity]::GetCurrent().User
$acl = New-Object System.Security.AccessControl.DirectorySecurity
$acl.SetAccessRuleProtection($true, $false)
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule($identity, 'FullControl', 'ContainerInherit,ObjectInherit', 'None', 'Allow')
$acl.AddAccessRule($rule)
Set-Acl -LiteralPath $checkpointDir -AclObject $acl
}
$toolArgs = @("--mode=$Mode", '--production=true', "--expected-target=$ExpectedTarget", '--batch-size=100', '--checkpoint=/credential-migration/checkpoint.json')
if ($Mode -eq 'finalize') { $toolArgs = @('--mode=verify', '--finalize=true', '--production=true', "--expected-target=$ExpectedTarget", '--batch-size=100') }
docker compose version *> $null
if ($LASTEXITCODE -eq 0) { docker compose run --rm --no-deps -v "${checkpointDir}:/credential-migration" easyai-server node /app/dist/credential-migrate.js @toolArgs }
else { docker-compose run --rm --no-deps -v "${checkpointDir}:/credential-migration" easyai-server node /app/dist/credential-migrate.js @toolArgs }
if ($LASTEXITCODE -ne 0) { throw 'Credential migration failed; preserve checkpoint and resolve configuration or concurrency conflicts' }