feat: encrypt sensitive values in app.yaml with AES-256-GCM
Passwords and secrets from deploy fields (type: password/secret) are now encrypted at rest in app.yaml using a per-node 32-byte key. Values stored as ENC:base64(nonce+ciphertext), decrypted transparently for docker-compose and web UI. Key included in infra backup bundle for disaster recovery. Existing plaintext values migrated automatically on startup. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -26,6 +26,7 @@ type InfraBackup struct {
|
||||
|
||||
ResticPassword string `json:"restic_password,omitempty"`
|
||||
CrossDrivePassword string `json:"cross_drive_password,omitempty"`
|
||||
EncryptionKeyB64 string `json:"encryption_key_b64,omitempty"`
|
||||
}
|
||||
|
||||
// InfraStack identifies a deployed app for disaster recovery.
|
||||
@@ -42,6 +43,7 @@ func BuildInfraBackup(
|
||||
controllerYAMLPath string,
|
||||
settingsPath string,
|
||||
resticPasswordFile string,
|
||||
encryptionKeyFile string,
|
||||
systemDataPath string,
|
||||
sett *settings.Settings,
|
||||
stackProvider backup.StackDataProvider,
|
||||
@@ -75,6 +77,15 @@ func BuildInfraBackup(
|
||||
logger.Printf("[WARN] Infra backup: could not read restic password file: %v", err)
|
||||
}
|
||||
|
||||
// Read encryption key for app.yaml secrets (important but non-fatal)
|
||||
if encryptionKeyFile != "" {
|
||||
if data, err := os.ReadFile(encryptionKeyFile); err == nil {
|
||||
ib.EncryptionKeyB64 = base64.StdEncoding.EncodeToString(data)
|
||||
} else if !os.IsNotExist(err) {
|
||||
logger.Printf("[WARN] Infra backup: could not read encryption key file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Collect disk layout from fstab + blkid
|
||||
ib.DiskLayout = collectDiskLayout(systemDataPath)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user