14 KiB
Configuration Encryption System
This document describes the configuration encryption system that allows you to securely store sensitive configuration values using AES-256-GCM encryption.
Overview
The configuration encryption system provides:
- AES-256-GCM encryption for sensitive configuration values
- Automatic key generation and management via
.kfile - Simple syntax - encrypted values start with
@ - Automatic decryption during configuration loading
- CLI tools for managing encrypted values
- Environment variable support alongside encryption
How It Works
- Key Storage: A 256-bit encryption key is stored in a
.kfile in your project root - Value Encryption: Sensitive values are encrypted and prefixed with
@ - Automatic Decryption: During config loading,
@prefixed values are automatically decrypted - Fallback Support: You can still use environment variables alongside encrypted values
Quick Start
1. Generate Encryption Key
# Generate a new encryption key
cargo run --bin config_crypto_tool generate-key
# Or use the interactive mode
cargo run --bin config_crypto_tool interactive
This creates a .k file in your project root containing a base64-encoded 256-bit encryption key.
2. Encrypt Sensitive Values
# Encrypt a database password
cargo run --bin config_crypto_tool encrypt "my_secret_password"
# Output: @AbCdEf123456...
# Encrypt an API key
cargo run --bin config_crypto_tool encrypt "sk-1234567890abcdef"
# Output: @XyZ789AbCdEf...
3. Use in Configuration
# config.prod.toml
[database]
url = "postgresql://user:@AbCdEf123456...@localhost:5432/mydb"
[session]
secret = "@XyZ789AbCdEf..."
[oauth.google]
client_secret = "@GhI012JkLmNo..."
[email]
sendgrid_api_key = "@PqR345StUvWx..."
4. Verify Configuration
# Verify encryption key works
cargo run --bin config_crypto_tool verify
# Show decrypted values (for debugging)
cargo run --bin config_crypto_tool show-decrypted -c config.prod.toml
Security Features
Key Management
- Automatic Generation: Keys are generated using cryptographically secure random number generation
- File Permissions: Key files are created with restrictive permissions (0600 on Unix systems)
- Key Rotation: Support for safely rotating encryption keys
- Backup Support: Automatic backup during key rotation
Encryption Details
- Algorithm: AES-256-GCM (Galois/Counter Mode)
- Key Size: 256 bits (32 bytes)
- Nonce: 96 bits (12 bytes), randomly generated for each encryption
- Authentication: Built-in authentication and integrity verification
- Encoding: Base64 encoding for text representation
Security Best Practices
- Keep
.kfile secure: Never commit to version control - Backup encryption keys: Store backups in secure location
- Use proper file permissions: Ensure only authorized users can read the key
- Regular key rotation: Rotate keys periodically in production
- Environment separation: Use different keys for different environments
Configuration Integration
Automatic Decryption
The configuration system automatically decrypts values during loading:
use server::config::Config;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Load configuration - encrypted values are automatically decrypted
let config = Config::load()?;
// These values are now decrypted and ready to use
println!("Database URL: {}", config.database.url);
println!("Session secret: {}", config.session.secret);
Ok(())
}
Mixed Approach
You can combine encrypted values with environment variables:
# config.prod.toml
[database]
url = "${DATABASE_URL}" # Environment variable
[session]
secret = "@encrypted_session_secret" # Encrypted value
[oauth.google]
client_id = "${GOOGLE_CLIENT_ID}" # Environment variable
client_secret = "@encrypted_google_secret" # Encrypted value
Precedence Order
- Environment variables (highest priority)
- Encrypted values (decrypted during loading)
- Plain text values (lowest priority)
CLI Tools
config_crypto_tool
The main CLI tool for managing encrypted configuration values:
# Basic commands
cargo run --bin config_crypto_tool generate-key # Generate new key
cargo run --bin config_crypto_tool encrypt "value" # Encrypt a value
cargo run --bin config_crypto_tool decrypt "@..." # Decrypt a value
cargo run --bin config_crypto_tool verify # Verify key works
# Key management
cargo run --bin config_crypto_tool key-info # Show key information
cargo run --bin config_crypto_tool rotate-key --confirm # Rotate key
# Configuration file operations
cargo run --bin config_crypto_tool find-encrypted -c config.toml
cargo run --bin config_crypto_tool show-decrypted -c config.toml
cargo run --bin config_crypto_tool encrypt-config -c config.toml -k "secret,api_key"
# Interactive mode
cargo run --bin config_crypto_tool interactive
Command Examples
Encrypting Multiple Values
# Encrypt database password
DB_PASSWORD=$(cargo run --bin config_crypto_tool encrypt "my_db_password")
# Encrypt API key
API_KEY=$(cargo run --bin config_crypto_tool encrypt "sk-1234567890")
# Update configuration file
cargo run --bin config_crypto_tool encrypt-config \
-c config.prod.toml \
-k "session.secret,oauth.google.client_secret,email.sendgrid_api_key" \
--backup
Finding Encrypted Values
# Find all encrypted values in a config file
cargo run --bin config_crypto_tool find-encrypted -c config.prod.toml
# Show configuration with decrypted values (for debugging)
cargo run --bin config_crypto_tool show-decrypted -c config.prod.toml
Environment Setup
Development Environment
# Generate development key
cargo run --bin config_crypto_tool generate-key
# Encrypt development secrets
DEV_SECRET=$(cargo run --bin config_crypto_tool encrypt "dev-secret-key")
# config.dev.toml
[session]
secret = "@dev_encrypted_secret" # Use encrypted value
[database]
url = "postgresql://dev:dev@localhost:5432/dev_db" # Plain text for dev
Production Environment
# Generate production key (on production server)
cargo run --bin config_crypto_tool generate-key
# Encrypt production secrets
PROD_SECRET=$(cargo run --bin config_crypto_tool encrypt "prod-secret-key-2024")
SENDGRID_KEY=$(cargo run --bin config_crypto_tool encrypt "SG.xyz123...")
# config.prod.toml
[session]
secret = "@prod_encrypted_secret"
[email]
sendgrid_api_key = "@encrypted_sendgrid_key"
File Structure
project/
├── .k # Encryption key file (DO NOT COMMIT)
├── config.dev.toml # Development config
├── config.prod.toml # Production config (with encrypted values)
├── .env # Environment variables
├── .gitignore # Must include .k file
└── docs/
└── ENCRYPTION.md # This documentation
.gitignore Setup
CRITICAL: Always add the .k file to your .gitignore:
# Encryption key file - NEVER COMMIT
.k
.k.backup
# Environment files
.env
.env.local
.env.production
# Backup files
*.backup
Deployment
Docker Deployment
# Dockerfile
FROM rust:1.75 as builder
# Copy source code
COPY . .
# Build application
RUN cargo build --release
FROM debian:bookworm-slim
# Copy binary
COPY --from=builder /app/target/release/server /usr/local/bin/server
# Copy configuration
COPY config.prod.toml /app/config.toml
# Encryption key should be mounted as volume or secret
VOLUME ["/app/.k"]
WORKDIR /app
CMD ["server"]
# docker-compose.yml
version: '3.8'
services:
app:
build: .
volumes:
- ./secrets/.k:/app/.k:ro # Mount key file
environment:
- ROOT_PATH=/app
- ENVIRONMENT=production
Kubernetes Deployment
# secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: app-encryption-key
type: Opaque
data:
.k: <base64-encoded-key-file-content>
---
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: app
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
volumeMounts:
- name: encryption-key
mountPath: /app/.k
subPath: .k
readOnly: true
env:
- name: ROOT_PATH
value: /app
volumes:
- name: encryption-key
secret:
secretName: app-encryption-key
Migration Guide
From Environment Variables
-
Backup current configuration:
cp config.prod.toml config.prod.toml.backup -
Generate encryption key:
cargo run --bin config_crypto_tool generate-key -
Encrypt sensitive values:
# Encrypt each sensitive value SESSION_SECRET_ENC=$(cargo run --bin config_crypto_tool encrypt "$SESSION_SECRET") API_KEY_ENC=$(cargo run --bin config_crypto_tool encrypt "$API_KEY") -
Update configuration:
# Before session.secret = "${SESSION_SECRET}" # After session.secret = "@encrypted_session_secret" -
Test configuration:
cargo run --bin config_crypto_tool verify cargo run --bin config_crypto_tool show-decrypted -c config.prod.toml
From Plain Text
Use the automated encryption tool:
# Encrypt specific keys in configuration file
cargo run --bin config_crypto_tool encrypt-config \
-c config.prod.toml \
-k "session.secret,oauth.google.client_secret,email.sendgrid_api_key" \
--backup
Troubleshooting
Common Issues
Key File Not Found
Error: Encryption key file not found
Solution: Generate a new key file:
cargo run --bin config_crypto_tool generate-key
Decryption Failed
Error: Failed to decrypt value
Possible causes:
- Wrong encryption key
- Corrupted encrypted value
- Key file was rotated without re-encrypting values
Solution:
- Verify key works:
cargo run --bin config_crypto_tool verify - Re-encrypt the value:
cargo run --bin config_crypto_tool encrypt "original_value"
Permission Denied
Error: Failed to read encryption key file: Permission denied
Solution: Fix file permissions:
chmod 600 .k
Configuration Validation Failed
Error: Configuration validation failed
Solution: Check if all encrypted values are properly decrypted:
cargo run --bin config_crypto_tool show-decrypted -c config.toml
Debug Mode
Enable debug logging to see encryption/decryption operations:
RUST_LOG=debug cargo run --bin config_crypto_tool verify
Recovery Procedures
Lost Encryption Key
If you lose the .k file:
- Generate new key:
cargo run --bin config_crypto_tool generate-key - Re-encrypt all values: You'll need to re-encrypt all
@prefixed values - Update configuration: Replace old encrypted values with new ones
Corrupted Key File
If the key file is corrupted:
- Check if backup exists: Look for
.k.backup - Restore from backup:
cp .k.backup .k - If no backup: Generate new key and re-encrypt all values
Best Practices
Development
- Use separate keys for development and production
- Keep development keys in team-shared secure location
- Use plain text for non-sensitive development values
- Test encryption/decryption regularly
Production
- Generate keys on production systems
- Use proper file permissions (0600)
- Regularly rotate encryption keys
- Monitor key file integrity
- Backup keys securely
- Use encrypted values for all sensitive data
Key Management
- Never commit
.kfiles to version control - Backup keys in secure, separate location
- Use different keys for different environments
- Rotate keys regularly (quarterly/yearly)
- Monitor key file access and modifications
- Have key recovery procedures documented
Security Considerations
- Principle of least privilege: Only necessary personnel should have access to keys
- Secure backup: Store key backups in encrypted, secure locations
- Audit trail: Log key access and usage
- Environment separation: Never use production keys in development
- Regular security review: Periodically review and update encryption practices
Advanced Usage
Programmatic Usage
use server::config::encryption::ConfigEncryption;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Initialize encryption
let encryption = ConfigEncryption::new(".")?;
// Encrypt a value
let encrypted = encryption.encrypt("my_secret_value")?;
println!("Encrypted: {}", encrypted);
// Decrypt a value
let decrypted = encryption.decrypt(&encrypted)?;
println!("Decrypted: {}", decrypted);
// Check if value is encrypted
if ConfigEncryption::is_encrypted(&encrypted) {
println!("Value is encrypted");
}
Ok(())
}
Custom Integration
use server::config::{Config, ConfigError};
// Custom configuration loader with encryption
pub fn load_config_with_encryption() -> Result<Config, ConfigError> {
let mut config = Config::load()?;
// Verify encryption key
config.verify_encryption_key()?;
// Additional custom decryption logic
// ...
Ok(config)
}
Support and Maintenance
Regular Maintenance
- Weekly: Check key file integrity
- Monthly: Review encrypted values
- Quarterly: Consider key rotation
- Annually: Security audit and update procedures
Monitoring
Monitor these metrics in production:
- Key file access patterns
- Decryption success/failure rates
- Configuration loading times
- Security events related to encryption
Updates
When updating the encryption system:
- Test in development environment
- Backup current keys and configurations
- Update gradually with rollback plan
- Monitor for issues after deployment
For additional support, refer to the main configuration documentation and security guidelines.