-
Notifications
You must be signed in to change notification settings - Fork 13
Description
Problem
The AES-256 encryption key used to encrypt sensitive data (client secrets, SMTP passwords, etc.) is currently generated during database
seeding and stored in plaintext in the settings table (aes_encryption_key column).
This creates a security concern: if the database is compromised, an attacker obtains both the encrypted data AND the key to decrypt it,
rendering the encryption ineffective.
Current flow:
Database compromise → attacker gets encrypted client secrets + AES key → full decryption possible
Current Implementation
The key is generated in database_seeder.go and stored in the database:
// database_seeder.go:63
encryptionKey := securecookie.GenerateRandomKey(32)
// database_seeder.go:357
settings := &models.Settings{
AESEncryptionKey: encryptionKey, // stored in DB
}
Meanwhile, goiabada-setup already generates other secrets externally (session keys, OAuth client secret) and passes them via environment
variables — but the AES key is not handled this way.
Proposed Solution
Align AES encryption key handling with the existing pattern used for session keys:
- Add to goiabada-setup — Generate GOIABADA_AES_ENCRYPTION_KEY alongside other secrets
- Add to Config struct — Include AESEncryptionKey field in goiabada-setup/main.go
- Update output templates — Add the env var to docker-compose, Kubernetes manifests, and .env files
- Add to core config — Read GOIABADA_AES_ENCRYPTION_KEY in src/core/config/config.go
- Modify database seeder — Accept key from config instead of generating it
- Remove from database — Drop aes_encryption_key column from settings table
Changes Required
src/cmd/goiabada-setup/main.go:
// Add to credential generation (around line 601)
aesEncryptionKey := generateHexKey(32)
printSuccess("AES encryption key generated")
// Add to Config struct
type Config struct {
// ... existing fields ...
AESEncryptionKey string
}
Output templates (docker-compose, k8s, .env):
GOIABADA_AES_ENCRYPTION_KEY: ${config.AESEncryptionKey}
src/core/config/config.go:
AESEncryptionKey string env:"GOIABADA_AES_ENCRYPTION_KEY"
src/core/data/database_seeder.go:
- Remove encryptionKey := securecookie.GenerateRandomKey(32)
- Accept key from config/parameter instead
Migration for Existing Installations
Add startup validation with three scenarios:
| DB Key | Env Var | Result |
|---|---|---|
| Exists | Not set | Fail — require migration |
| Exists | Set, matches | OK — continue startup |
| Exists | Set, different | Fail — key mismatch error |
| Empty/null | Set | OK — new installation pattern |
| Empty/null | Not set | Fail — key required |
Scenario 1: DB key exists, env var not set
MIGRATION REQUIRED
Detected AES encryption key in database but GOIABADA_AES_ENCRYPTION_KEY
environment variable is not set.
Starting with this version, the AES encryption key must be provided via
environment variable for improved security.
To migrate, run:
goiabada-authserver --export-aes-key
This will output the key from your database. Add it to your environment:
GOIABADA_AES_ENCRYPTION_KEY=
Then restart the server.
Scenario 2: DB key exists, env var set but DIFFERENT
FATAL: AES ENCRYPTION KEY MISMATCH
The GOIABADA_AES_ENCRYPTION_KEY environment variable does not match the key
stored in the database.
Using the wrong key will cause decryption failures for existing encrypted
data (client secrets, SMTP passwords, etc.).
To resolve:
1. If migrating from DB key: run 'goiabada-authserver --export-aes-key'
and use the output as your GOIABADA_AES_ENCRYPTION_KEY value.
2. If intentionally rotating keys: this requires re-encrypting all
existing secrets, which is not yet supported.
Server cannot start with mismatched keys.
Add CLI flag: --export-aes-key
- Connects to database
- Reads aes_encryption_key from settings
- Outputs hex-encoded key to stdout
- Exits
Security Benefit
Database compromise → attacker gets encrypted data only → decryption not possible without env var
Implementation Checklist
- Add AESEncryptionKey to goiabada-setup Config struct and generation
- Update generateDockerCompose() to include the env var
- Update generateKubernetesManifests() to include the env var in Secret
- Update generateEnvFile() to include the env var
- Add GOIABADA_AES_ENCRYPTION_KEY to src/core/config/config.go
- Modify DatabaseSeeder to accept key from config
- Add --export-aes-key CLI flag to authserver
- Add startup validation:
- Fail if DB key exists but env var missing
- Fail if DB key exists and env var differs (key mismatch)
- Pass if keys match or new installation
- Create database migration to remove aes_encryption_key column (future release)
- Update documentation
References
- Setup wizard: src/cmd/goiabada-setup/main.go
- Database seeder: src/core/data/database_seeder.go:63
- Settings model: src/core/models/settings.go:25
- Encryption utility: src/core/encryption/encryption.go
- Documentation: site/src/content/docs/getting-started/setup-wizard.md