#!/bin/bash # 为本地 .env 初始化持久化安全密钥。只处理空值和已知历史默认值, # 已存在的自定义值保持不变;数据库中的 JWT 轮转配置仍由后端优先使用。 generate_security_secret() { if command -v openssl >/dev/null 2>&1; then openssl rand -base64 48 | tr -d '\r\n' return fi if [ -r /dev/urandom ]; then od -An -N48 -tx1 /dev/urandom | tr -d ' \r\n' return fi echo "❌ 无法生成安全随机值:需要 openssl 或 /dev/urandom" >&2 return 1 } generate_initial_admin_password() { if command -v openssl >/dev/null 2>&1; then # 10 random bytes encoded as hexadecimal: exactly 20 alphanumeric characters. openssl rand -hex 10 | tr -d '\r\n' return fi if [ -r /dev/urandom ]; then od -An -N10 -tx1 /dev/urandom | tr -d ' \r\n' return fi echo "❌ 无法生成初始管理员密码:需要 openssl 或 /dev/urandom" >&2 return 1 } read_env_value() { local file="$1" local key="$2" local value value="$(awk -v key="$key" 'index($0, key "=") == 1 { print substr($0, length(key) + 2); exit }' "$file")" value="$(printf '%s' "$value" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')" case "$value" in \"*\") value="${value#\"}"; value="${value%\"}" ;; \'*\') value="${value#\'}"; value="${value%\'}" ;; esac printf '%s' "$value" } write_env_value() { local file="$1" local key="$2" local value="$3" local tmp tmp="$(mktemp "${file}.tmp.XXXXXX")" awk -v key="$key" -v value="$value" ' BEGIN { replaced = 0 } index($0, key "=") == 1 { if (!replaced) { print key "=" value replaced = 1 } next } { print } END { if (!replaced) print key "=" value } ' "$file" > "$tmp" chmod 600 "$tmp" mv "$tmp" "$file" } ensure_security_secret() { local file="$1" local key="$2" local legacy_value="${3:-}" local minimum_length="${4:-32}" local current current="$(read_env_value "$file" "$key")" if [ "${#current}" -ge "$minimum_length" ] && { [ -z "$legacy_value" ] || [ "$current" != "$legacy_value" ]; }; then return 0 fi write_env_value "$file" "$key" "$(generate_security_secret)" echo " ✓ 已初始化安全密钥: ${key}" } ensure_initial_admin_password() { local file="$1" local current current="$(read_env_value "$file" "CONFIG_INITIAL_ADMIN_PASSWORD")" if [ "${#current}" -ge 12 ]; then return 0 fi write_env_value "$file" "CONFIG_INITIAL_ADMIN_PASSWORD" "$(generate_initial_admin_password)" echo " ✓ 已初始化管理员密码: CONFIG_INITIAL_ADMIN_PASSWORD" } init_security_env() { local file="${1:-.env}" local mode="${2:-upgrade}" if [ ! -f "$file" ]; then echo "❌ 环境配置文件不存在: $file" >&2 return 1 fi if [ "$mode" != "new" ] && [ "$mode" != "upgrade" ]; then echo "❌ 安全环境初始化模式无效: $mode(仅支持 new/upgrade)" >&2 return 1 fi ensure_security_secret "$file" "CONFIG_JWT_SECRET" "this is a very secret secret" if [ "$mode" = "new" ]; then ensure_security_secret "$file" "CONFIG_SECURITY_CONFIG_ENCRYPTION_KEY" ensure_security_secret "$file" "CONFIG_OTP_HASH_SECRET" ensure_security_secret "$file" "CONFIG_AUDIT_HASH_PEPPER" ensure_security_secret "$file" "CONFIG_AUDIT_INTEGRITY_KEY" ensure_initial_admin_password "$file" fi chmod 600 "$file" } if [ "${BASH_SOURCE[0]}" = "$0" ]; then init_security_env "${1:-.env}" "${2:-upgrade}" fi