Files
easyai/scripts/test-credential-keys.sh
easyai03 5cff1041a9
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
feat(deploy): 补齐凭据加密接入迁移和密钥备份恢复
首次安装默认生成独立加密密钥,更新旧部署保留原配置,通过显式开关进入迁移窗口。增加生产迁移包装入口和完整密钥环备份恢复工具,并说明旧镜像升级、严格迁移、轮换及还原流程。

已通过 Bash 安全环境及密钥备份回归;对应 PowerShell 5.1 和 7 脚本已在 Windows 原生环境各通过 49 项验收。宁波服务器验收尚未执行。
2026-10-12 22:24:16 +08:00

40 lines
2.8 KiB
Bash

#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# shellcheck source=scripts/init-security-env.sh
. "$SCRIPT_DIR/init-security-env.sh"
tmp_dir="$(mktemp -d)"; trap 'rm -rf "$tmp_dir"' EXIT
touch "$tmp_dir/.env"
write_env_value "$tmp_dir/.env" CONFIG_SECURITY_CONFIG_ENCRYPTION_KEY "original-master-with-dollar-\$1-and-backslash-\\"
write_env_value "$tmp_dir/.env" CONFIG_JWT_SECRET original-jwt-fallback
init_credential_encryption_env "$tmp_dir/.env" new > "$tmp_dir/log"
old_ring="$(read_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING)"
second="$(openssl rand -base64 32 | tr -d '\r\n')"
multi="${old_ring%\}},\"v2\":\"$second\"}"
write_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING "'$multi'"
write_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_ACTIVE_KEY_ID v2
write_env_value "$tmp_dir/.env" UNRELATED_CONFIG keep-me
bash "$SCRIPT_DIR/credential-keys.sh" export "$tmp_dir/keys.env" "$tmp_dir/.env" >> "$tmp_dir/log"
[ "$(read_env_value "$tmp_dir/keys.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING)" = "$multi" ]
if bash "$SCRIPT_DIR/credential-keys.sh" export "$tmp_dir/keys.env" "$tmp_dir/.env" >> "$tmp_dir/log" 2>&1; then exit 1; fi
write_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING "'$old_ring'"
write_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_ACTIVE_KEY_ID v1
bash "$SCRIPT_DIR/credential-keys.sh" restore "$tmp_dir/keys.env" "$tmp_dir/.env" >> "$tmp_dir/log"
[ "$(read_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING)" = "$multi" ]
[ "$(read_env_value "$tmp_dir/.env" CONFIG_CREDENTIAL_ENCRYPTION_ACTIVE_KEY_ID)" = v2 ]
[ "$(read_env_value "$tmp_dir/.env" UNRELATED_CONFIG)" = keep-me ]
[ "$(read_env_value "$tmp_dir/.env" CONFIG_JWT_SECRET)" = original-jwt-fallback ]
[ "$(read_env_value "$tmp_dir/.env" CONFIG_SECURITY_CONFIG_ENCRYPTION_KEY)" = "$(read_env_value "$tmp_dir/keys.env" CONFIG_SECURITY_CONFIG_ENCRYPTION_KEY)" ]
cp "$tmp_dir/.env" "$tmp_dir/before"
cp "$tmp_dir/keys.env" "$tmp_dir/bad.env"
write_env_value "$tmp_dir/bad.env" CONFIG_CREDENTIAL_ENCRYPTION_KEYRING '{}'
if bash "$SCRIPT_DIR/credential-keys.sh" restore "$tmp_dir/bad.env" "$tmp_dir/.env" >> "$tmp_dir/log" 2>&1; then exit 1; fi
cmp -s "$tmp_dir/.env" "$tmp_dir/before"
touch "$tmp_dir/legacy.env"
if bash "$SCRIPT_DIR/credential-keys.sh" export "$tmp_dir/missing.env" "$tmp_dir/legacy.env" >> "$tmp_dir/log" 2>&1; then exit 1; fi
[ ! -e "$tmp_dir/missing.env" ]
if grep -Fq "$second" "$tmp_dir/log"; then exit 1; fi
if stat -f '%Lp' "$tmp_dir/keys.env" > /dev/null 2>&1; then permission="$(stat -f '%Lp' "$tmp_dir/keys.env")"; else permission="$(stat -c '%a' "$tmp_dir/keys.env")"; fi
[ "$permission" = 600 ]
echo 'Credential key backup/restore self-test passed (rotation, preservation, refusal, permissions, logs).'