Security Configuration
Code Search provides security features to protect sensitive data like API tokens stored in the database.
Token Encryption at Rest
Section titled “Token Encryption at Rest”Connection tokens (GitHub, GitLab, Gitea, Bitbucket) can be encrypted before being stored in the database using AES-256-GCM encryption.
Why Encrypt Tokens?
Section titled “Why Encrypt Tokens?”- Database compromise protection: If your database is compromised, encrypted tokens are useless without the encryption key
- Compliance requirements: Many security standards require encryption of sensitive data at rest
- Defense in depth: Adds an extra layer of security beyond database access controls
Enabling Encryption
Section titled “Enabling Encryption”Set the encryption key via environment variable (recommended):
export CS_SECURITY_ENCRYPTION_KEY="your-secret-encryption-key-here"Or in your config.yaml:
security: encryption_key: "your-secret-encryption-key-here"Key Requirements
Section titled “Key Requirements”- Any string is valid: The key is hashed using SHA-256 to derive a 32-byte AES-256 key
- Recommended length: Use at least 32 characters for security
- Cryptographically random: Use a secure random generator for production keys
Generate a secure key:
# Using OpenSSLopenssl rand -base64 32
# Using /dev/urandomhead -c 32 /dev/urandom | base64
# Using Pythonpython3 -c "import secrets; print(secrets.token_urlsafe(32))"How It Works
Section titled “How It Works”- On write: When a connection is created or updated, the token is encrypted with AES-256-GCM and prefixed with
enc: - On read: When fetching a connection, the token is decrypted in memory before use
- Detection: Encrypted values have an
enc:prefix, allowing Code Search to distinguish them from plaintext
Backwards Compatibility
Section titled “Backwards Compatibility”Token encryption is fully backwards compatible:
| Scenario | Behavior |
|---|---|
| No encryption key set | Tokens stored/read as plaintext (existing behavior) |
| Encryption key set, existing plaintext tokens | Plaintext tokens continue to work, new tokens are encrypted |
| Encryption key set, token updated | Token is encrypted on save |
This allows gradual migration without disrupting existing deployments.
Kubernetes Deployment
Section titled “Kubernetes Deployment”Store the encryption key as a Kubernetes secret:
# Generate a secure keyENCRYPTION_KEY=$(openssl rand -base64 32)
# Create the secretkubectl create secret generic code-search-encryption \ --namespace code-search \ --from-literal=CS_SECURITY_ENCRYPTION_KEY="$ENCRYPTION_KEY"Reference in your deployment:
apiVersion: apps/v1kind: Deploymentmetadata: name: code-search-apispec: template: spec: containers: - name: api envFrom: - secretRef: name: code-search-encryptionOr with the Helm chart:
extraEnvVars: - name: CS_SECURITY_ENCRYPTION_KEY valueFrom: secretKeyRef: name: code-search-encryption key: CS_SECURITY_ENCRYPTION_KEYDocker Compose
Section titled “Docker Compose”services: api: image: ghcr.io/techquestsdev/code-search-api:latest environment: CS_SECURITY_ENCRYPTION_KEY: ${ENCRYPTION_KEY} # Or use Docker secrets secrets: - encryption_key
secrets: encryption_key: file: ./secrets/encryption_key.txtKey Rotation
Section titled “Key Rotation”Currently, key rotation requires re-creating connections:
- Export your connection configurations (without tokens)
- Set the new encryption key
- Re-create connections with fresh tokens
Verifying Encryption
Section titled “Verifying Encryption”You can verify tokens are encrypted by checking the database directly:
-- Encrypted tokens start with "enc:"SELECT name, CASE WHEN token LIKE 'enc:%' THEN 'encrypted' ELSE 'plaintext' END as statusFROM connections;Troubleshooting
Section titled “Troubleshooting”Tokens not being encrypted
Section titled “Tokens not being encrypted”-
Verify the encryption key is set:
Terminal window echo $CS_SECURITY_ENCRYPTION_KEY -
Check logs for encryption status on startup:
INFO Token encryption enabled -
Update existing connections to trigger encryption (tokens are encrypted on save)
Decryption errors
Section titled “Decryption errors”If you see decryption errors in logs:
- Wrong key: Ensure the same key is used across all API and indexer instances
- Key changed: If the key was rotated, old encrypted tokens won’t decrypt
- Corrupted data: Check database for corrupted token values
For backwards compatibility, decryption errors fall back to using the raw value, so existing plaintext tokens continue to work.
Environment Variable Reference
Section titled “Environment Variable Reference”| Variable | Description | Default |
|---|---|---|
CS_SECURITY_ENCRYPTION_KEY | AES-256-GCM encryption key for tokens | - (disabled) |
Best Practices
Section titled “Best Practices”- Always encrypt in production: Enable token encryption for any production deployment
- Use secrets management: Store the encryption key in a secrets manager (Vault, AWS Secrets Manager, etc.)
- Same key everywhere: Ensure API and indexer use the same encryption key
- Backup the key: Store the encryption key securely in case of disaster recovery
- Rotate tokens, not just keys: Regularly rotate the underlying API tokens with your code hosts
Next Steps
Section titled “Next Steps”- Secrets Management - Loading secrets from files
- Environment Variables - Complete environment variable reference
- Kubernetes Deployment - Deploy securely on Kubernetes