Encryption at Rest
Encryption at Rest
Section titled “Encryption at Rest”Configure encryption for sensitive data stored in the Mantis database.
Overview
Section titled “Overview”What is Encrypted
Section titled “What is Encrypted”Mantis encrypts sensitive data stored in PostgreSQL:
| Data Type | Encryption | Storage |
|---|---|---|
| Credentials | AES-256-GCM | Database |
| Secrets | AES-256-GCM | Database |
| API keys | Argon2 hash | Database |
| OAuth client secrets | AES-256-GCM | Database |
| Variable values | AES-256-GCM (if marked sensitive) | Database |
Encryption Architecture
Section titled “Encryption Architecture”Encryption Key Configuration
Section titled “Encryption Key Configuration”Generating an Encryption Key
Section titled “Generating an Encryption Key”# Generate 256-bit master keyopenssl rand -base64 32
# Example output:# K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=Configuration
Section titled “Configuration”The encryption configuration is a single base64-encoded 32-byte key under the
[encryption] table. There is no enabled toggle or algorithm selector — encryption is
always AES-256-GCM, and supplying a valid key is what enables credential encryption.
[encryption]key = "K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols="Environment Variable (Recommended)
Section titled “Environment Variable (Recommended)”Store the key as an environment variable instead of in the config file:
export MANTIS_ENCRYPTION_KEY="K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols="Key Management
Section titled “Key Management”Mantis uses the configured 32-byte key directly as the AES-256-GCM key — there is no key-derivation (HKDF) step and no per-record or per-data-type key hierarchy. A fresh random 96-bit nonce is generated for each encryption operation, so the same key safely encrypts many records. Rotating the key re-encrypts all existing records (see Key Rotation).
Encryption Details
Section titled “Encryption Details”AES-256-GCM
Section titled “AES-256-GCM”Mantis uses AES-256-GCM (Galois/Counter Mode):
| Property | Value |
|---|---|
| Algorithm | AES-256 |
| Mode | GCM (authenticated encryption) |
| Key size | 256 bits |
| IV size | 96 bits (12 bytes) |
| Tag size | 128 bits (16 bytes) |
Benefits:
- Authenticated encryption (integrity + confidentiality)
- Parallelizable encryption/decryption
- Hardware acceleration support (AES-NI)
Storage Format
Section titled “Storage Format”Encrypted values are stored as:
Base64(IV || Ciphertext || Tag)| Component | Size | Purpose |
|---|---|---|
| IV | 12 bytes | Initialization vector |
| Ciphertext | Variable | Encrypted data |
| Tag | 16 bytes | Authentication tag |
Configuring Sensitive Fields
Section titled “Configuring Sensitive Fields”Variable Encryption
Section titled “Variable Encryption”Mark a variable as sensitive when creating it through the REST API (or the Lens UI). A
variable created with variable_type: "sensitive" is encrypted at rest and its value is
masked on read:
curl -X POST "https://api.mantis.example.com/api/v1/variable-sets/$SET_ID/variables" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "DB_PASSWORD", "value": "supersecret123", "variable_type": "sensitive"}'Via Lens UI
Section titled “Via Lens UI”┌─────────────────────────────────────────────────────────────┐│ Create Variable │├─────────────────────────────────────────────────────────────┤│ ││ Name * ││ [DB_PASSWORD ] ││ ││ Value * ││ [•••••••••••••••• ] ││ ││ ☑ Sensitive (encrypt value at rest) ││ ││ Scope: ││ ○ Global ● Environment ○ Target ││ ││ [Cancel] [Create Variable] ││ │└─────────────────────────────────────────────────────────────┘Credential Storage
Section titled “Credential Storage”Storage backend credentials are always encrypted:
[storage.s3]access_key = "AKIAIOSFODNN7EXAMPLE"secret_key = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"# secret_key is automatically encrypted when storedDatabase Considerations
Section titled “Database Considerations”PostgreSQL Encryption
Section titled “PostgreSQL Encryption”In addition to application-level encryption, consider:
| Level | Method | Protection |
|---|---|---|
| Application | AES-256-GCM | Data at rest in DB |
| Database | pgcrypto extension | Additional layer |
| Storage | LUKS/dm-crypt | Disk encryption |
| Cloud | AWS RDS encryption | Managed encryption |
pgcrypto Extension
Section titled “pgcrypto Extension”Enable for additional database-level encryption:
CREATE EXTENSION IF NOT EXISTS pgcrypto;Transparent Data Encryption (TDE)
Section titled “Transparent Data Encryption (TDE)”For cloud deployments:
| Provider | Feature | Configuration |
|---|---|---|
| AWS RDS | Encryption at rest | Enable in RDS console |
| Azure | TDE | Enable in Azure portal |
| GCP | Cloud SQL encryption | Enabled by default |
API Key Hashing
Section titled “API Key Hashing”API keys are hashed with Argon2 before storage, using the library’s default Argon2
parameters. These parameters are not configurable — there is no [api_keys] configuration
section.
How API Keys Work
Section titled “How API Keys Work”Key Rotation
Section titled “Key Rotation”Master Key Rotation
Section titled “Master Key Rotation”Rotate the master key annually or if compromised:
# Generate new master keyNEW_KEY=$(openssl rand -base64 32)
# Run key rotation (re-encrypts all data)mantisctl key rotate \ --old-key "$OLD_KEY" \ --new-key "$NEW_KEY"
# Update configurationexport MANTIS_ENCRYPTION_KEY="$NEW_KEY"
# Restart servicessystemctl restart mandible thoraxRotation Process
Section titled “Rotation Process”See Key Rotation for detailed procedures.
Backup Considerations
Section titled “Backup Considerations”Encrypted Backups
Section titled “Encrypted Backups”Database backups contain encrypted data:
| Backup Type | Encryption Status |
|---|---|
| pg_dump | Data remains encrypted |
| File backup | Data remains encrypted |
| Snapshot | Data remains encrypted |
Master Key Backup
Section titled “Master Key Backup”Backup the master key securely:
- Store in separate secure location
- Use secrets management (Vault, AWS Secrets Manager)
- Document key recovery procedure
- Test key recovery periodically
Disaster Recovery
Section titled “Disaster Recovery”For disaster recovery, you need:
- Database backup
- Master key
- Configuration files
# Restore databasepg_restore -d mantis mantis_backup.dump
# Set master key (from secure backup)export MANTIS_ENCRYPTION_KEY="backed-up-key"
# Start servicessystemctl start mandible thoraxTroubleshooting
Section titled “Troubleshooting”Decryption Failures
Section titled “Decryption Failures”Problem: Decryption failed: authentication error (wrong key, AAD, or tampered data)
Causes:
- Wrong master key
- Corrupted data
- Data modified in database
Solution:
# Verify that all encrypted records decrypt with the configured key# (reads MANTIS_ENCRYPTION_KEY, or pass --key explicitly)mantisctl key verifyKey Misconfiguration
Section titled “Key Misconfiguration”Problem: SECURITY ERROR: Encryption key is not configured (missing key) or
SECURITY ERROR: Encryption key must be exactly 32 bytes (256 bits), got N bytes (wrong
length) or SECURITY ERROR: Encryption key is not valid base64 (encoding error).
Diagnosis:
# Check key format (should be base64)echo "$MANTIS_ENCRYPTION_KEY" | base64 -d | wc -c# Should output: 32Solution:
# Ensure key is properly formattedexport MANTIS_ENCRYPTION_KEY="$(cat /path/to/key | tr -d '\n')"Performance Impact
Section titled “Performance Impact”Encryption adds minimal overhead:
| Operation | Overhead |
|---|---|
| Encrypt | ~1ms per record |
| Decrypt | ~1ms per record |
| Batch operations | Parallelized |
If performance issues occur:
# Check for hardware accelerationgrep -m1 'aes' /proc/cpuinfo# Should show: aes (AES-NI support)Security Audit
Section titled “Security Audit”Verify Encrypted Data
Section titled “Verify Encrypted Data”Confirm that every encrypted record can be decrypted with the configured key. This is the primary integrity check after a key change or restore:
# Uses MANTIS_ENCRYPTION_KEY, or pass --key "<base64 key>"mantisctl key verifyTo generate a fresh key (for example before a rotation), use:
mantisctl key generateBest Practices
Section titled “Best Practices”1. Environment Variables for Keys
Section titled “1. Environment Variables for Keys”# Good: Environment variableexport MANTIS_ENCRYPTION_KEY="..."
# Bad: Configuration file# [encryption]# key = "..." # Don't do this!2. Secrets Management
Section titled “2. Secrets Management”Use a secrets manager:
| Tool | Integration |
|---|---|
| HashiCorp Vault | KV secrets engine |
| AWS Secrets Manager | IAM integration |
| Azure Key Vault | Managed identity |
| GCP Secret Manager | Service account |
Example with Vault:
export MANTIS_ENCRYPTION_KEY=$(vault kv get -field=key secret/mantis/encryption)3. Key Rotation Schedule
Section titled “3. Key Rotation Schedule”| Key Type | Rotation Period |
|---|---|
| Master key | Annually |
| After compromise | Immediately |
| After personnel change | As needed |
4. Layered Encryption
Section titled “4. Layered Encryption”Enable multiple layers:
[encryption]key = "<base64 32-byte key>" # Application-level AES-256-GCM
[database]url = "postgres://...?sslmode=verify-full" # TLS in transit
# Plus: Disk encryption on database server# Plus: Cloud provider encryption (RDS, etc.)5. Documentation
Section titled “5. Documentation”Maintain documentation for:
- Key storage location
- Key recovery procedure
- Rotation schedule
- Emergency contacts
Next Steps
Section titled “Next Steps”- Key Rotation - Detailed rotation procedures
- Security Overview - Overall security architecture
- Database Setup - Database configuration
