HashiCorp Vault Integration
HashiCorp Vault Integration
Section titled “HashiCorp Vault Integration”DBCrust provides seamless integration with HashiCorp Vault for dynamic database credentials, eliminating the need to store passwords in configuration files or environment variables. This guide covers setup, configuration, and advanced usage patterns.
🔐 Why Vault Integration?
Section titled “🔐 Why Vault Integration?”Dynamic database credentials provide significant security benefits:
- ✅ No stored passwords - Credentials are generated on-demand
- ✅ Automatic rotation - Credentials expire and rotate automatically
- ✅ Audit trail - All access is logged in Vault
- ✅ Fine-grained permissions - Role-based access control
- ✅ Compliance ready - Meets enterprise security requirements
🚀 Quick Start
Section titled “🚀 Quick Start”Prerequisites
Section titled “Prerequisites”- HashiCorp Vault server running and accessible
- Database secrets engine configured
- Vault authentication (token, userpass, LDAP, etc.)
Basic Connection
Section titled “Basic Connection”# Set Vault environment variablesexport VAULT_ADDR="https://vault.company.com"export VAULT_TOKEN="your-vault-token"
# Connect using Vault URL schemedbcrust vault://database-role@database/postgres-prod
# Interactive connection (prompts for role and database)dbcrust vault://Vault URL Format
Section titled “Vault URL Format”vault://[role]@[mount-point]/[database-name]Components:
role(optional): Vault role namemount-point(optional): Database secrets engine mount point (default: “database”)database-name(optional): Database configuration name in Vault
Examples:
# Full specificationdbcrust vault://app-readonly@database/postgres-prod
# Use default mount pointdbcrust vault://app-readonly/postgres-prod
# Interactive selectiondbcrust vault://app-readonlydbcrust vault://🛠️ Configuration
Section titled “🛠️ Configuration”Environment Variables
Section titled “Environment Variables”# Requiredexport VAULT_ADDR="https://vault.company.com"
# Authentication (choose one)export VAULT_TOKEN="your-token" # Token authexport VAULT_USERNAME="your-username" # Userpass authexport VAULT_PASSWORD="your-password" # Userpass auth
# Optionalexport VAULT_NAMESPACE="your-namespace" # Vault Enterpriseexport VAULT_MOUNT_POINT="database" # Default mount pointexport VAULT_SKIP_VERIFY="false" # Skip TLS verificationDBCrust Configuration
Section titled “DBCrust Configuration”[vault]addr = "https://vault.company.com"mount_point = "database" # Default secrets engine mountauth_method = "token" # "token", "userpass", "ldap"timeout = 30 # Request timeout in secondsnamespace = "" # Vault Enterprise namespace
# Credential Caching (recommended for performance)vault_credential_cache_enabled = truevault_cache_renewal_threshold = 0.25 # Renew when 25% TTL remainingvault_cache_min_ttl_seconds = 300 # Minimum 5 minutes TTL required
# TLS Configurationtls_skip_verify = false # Don't skip TLS verificationtls_ca_cert = "" # Path to CA certificatetls_client_cert = "" # Path to client certificatetls_client_key = "" # Path to client private keyAuthentication Methods
Section titled “Authentication Methods”Token Authentication
Section titled “Token Authentication”export VAULT_ADDR="https://vault.company.com"export VAULT_TOKEN="s.abc123def456..."
dbcrust vault://app-role@database/postgres-mainUsername/Password Authentication
Section titled “Username/Password Authentication”export VAULT_ADDR="https://vault.company.com"export VAULT_USERNAME="your-username"export VAULT_PASSWORD="your-password"
# DBCrust automatically authenticates with Vaultdbcrust vault://app-role@database/postgres-mainLDAP Authentication
Section titled “LDAP Authentication”[vault]addr = "https://vault.company.com"auth_method = "ldap"export VAULT_ADDR="https://vault.company.com"export VAULT_USERNAME="your-ldap-username"export VAULT_PASSWORD="your-ldap-password"
dbcrust vault://app-role@database/postgres-main🎯 Credential Caching
Section titled “🎯 Credential Caching”DBCrust intelligently caches Vault credentials to improve performance and reduce Vault API calls.
How Caching Works
Section titled “How Caching Works”- First connection: DBCrust fetches credentials from Vault
- Encryption: Credentials encrypted with AES-256-GCM using your Vault token
- Storage: Cached in
~/.config/dbcrust/vault_credentials.enc - Reuse: Subsequent connections use cached credentials if still valid
- Renewal: Automatically refreshes when approaching expiration
- Security: Cache is tied to your Vault token - invalid if token changes
Cache Configuration
Section titled “Cache Configuration”[vault]vault_credential_cache_enabled = true
# Renew credentials when 25% of TTL remainsvault_cache_renewal_threshold = 0.25
# Only cache credentials with at least 5 minutes TTLvault_cache_min_ttl_seconds = 300Cache Management Commands
Section titled “Cache Management Commands”# Show cache status\vc
# Clear all cached credentials\vcc
# Force refresh specific role credentials\vcr app-readonly
# Show expired credentials\vceExample cache status output:
Vault Credential Cache Status:=============================
app-readonly@database/postgres-prod: ✅ Valid until: 2024-01-15 16:30:00 UTC (45 minutes remaining) 📍 Database: postgres-prod 🔄 Will renew at: 2024-01-15 16:18:45 UTC
app-writer@database/postgres-main: ⚠️ Expires soon: 2024-01-15 14:45:00 UTC (5 minutes remaining) 📍 Database: postgres-main 🔄 Auto-renewal in progress...
Cache file: ~/.config/dbcrust/vault_credentials.enc (2.1 KB)Encryption: AES-256-GCM🏗️ Vault Setup
Section titled “🏗️ Vault Setup”Database Secrets Engine
Section titled “Database Secrets Engine”Configure the database secrets engine in Vault:
# Enable database secrets enginevault secrets enable database
# Configure PostgreSQL connectionvault write database/config/postgres-prod \ plugin_name=postgresql-database-plugin \ connection_url="postgresql://vault@postgres.company.com:5432/postgres?sslmode=require" \ allowed_roles="app-readonly,app-writer,admin"
# Configure MySQL connectionvault write database/config/mysql-analytics \ plugin_name=mysql-database-plugin \ connection_url="{{username}}:{{password}}@tcp(mysql.company.com:3306)/" \ allowed_roles="analytics-readonly,analytics-writer"Role Configuration
Section titled “Role Configuration”Create roles with appropriate permissions:
# Read-only role for applicationvault write database/roles/app-readonly \ db_name=postgres-prod \ creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' IN ROLE readonly;" \ default_ttl="1h" \ max_ttl="24h"
# Writer role for applicationvault write database/roles/app-writer \ db_name=postgres-prod \ creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' IN ROLE app_writer;" \ default_ttl="2h" \ max_ttl="8h"
# Admin role for DBAsvault write database/roles/admin \ db_name=postgres-prod \ creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}' SUPERUSER;" \ default_ttl="30m" \ max_ttl="2h"Policy Configuration
Section titled “Policy Configuration”Create Vault policies for role access:
# Create policy for developersvault policy write developers - <<EOF# Allow reading credentials for app rolespath "database/creds/app-readonly" { capabilities = ["read"]}
path "database/creds/app-writer" { capabilities = ["read"]}EOF
# Create policy for DBAsvault policy write dbas - <<EOF# Allow reading all database credentialspath "database/creds/*" { capabilities = ["read"]}EOF🎨 Real-World Examples
Section titled “🎨 Real-World Examples”Django Application Setup
Section titled “Django Application Setup”Production Django setup with different roles:
import osfrom dbcrust import get_vault_credentials
# Get database credentials from Vaultif os.getenv('USE_VAULT', 'false').lower() == 'true': db_creds = get_vault_credentials('app-writer', 'database', 'django-prod')
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'django_prod', 'USER': db_creds['username'], 'PASSWORD': db_creds['password'], 'HOST': 'postgres.company.com', 'PORT': '5432', } }else: # Fallback to environment variables for development DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': os.getenv('DB_NAME', 'django_dev'), 'USER': os.getenv('DB_USER', 'django'), 'PASSWORD': os.getenv('DB_PASSWORD'), 'HOST': os.getenv('DB_HOST', 'localhost'), 'PORT': os.getenv('DB_PORT', '5432'), } }Django management commands:
# Connect with appropriate roleexport USE_VAULT=true
# Read-only access for queriespython manage.py dbcrust vault://app-readonly@database/django-prod
# Writer access for migrationspython manage.py dbcrust vault://app-writer@database/django-prod
# Admin access for schema changespython manage.py dbcrust vault://admin@database/django-prodMulti-Environment Setup
Section titled “Multi-Environment Setup”# Development environmentexport VAULT_ADDR="https://vault-dev.company.com"dbcrust vault://dev-app@database/postgres-dev
# Staging environmentexport VAULT_ADDR="https://vault-staging.company.com"dbcrust vault://staging-app@database/postgres-staging
# Production environmentexport VAULT_ADDR="https://vault.company.com"dbcrust vault://app-readonly@database/postgres-prodAnalytics Workflow
Section titled “Analytics Workflow”# Data analysts get read-only access to analytics databasesdbcrust vault://analyst@analytics/data-warehouse
# Data engineers get writer access for ETLdbcrust vault://etl-writer@analytics/data-warehouse
# Data platform team gets admin accessdbcrust vault://admin@analytics/data-warehouseAutomated Scripts
Section titled “Automated Scripts”#!/usr/bin/env python3import dbcrustimport os
# Set Vault configurationos.environ['VAULT_ADDR'] = 'https://vault.company.com'os.environ['VAULT_TOKEN'] = os.environ.get('VAULT_TOKEN')
def run_daily_report(): """Generate daily analytics report using Vault credentials"""
# Connect using Vault credentials result = dbcrust.run_command( "vault://analytics-readonly@database/data-warehouse", """ SELECT date_trunc('day', created_at) as day, COUNT(*) as orders, SUM(amount) as revenue FROM orders WHERE created_at >= current_date - interval '7 days' GROUP BY day ORDER BY day; """ )
# Process results print("Daily Revenue Report:") print(result)
if __name__ == "__main__": run_daily_report()🔧 Advanced Configuration
Section titled “🔧 Advanced Configuration”Custom Mount Points
Section titled “Custom Mount Points”If your Vault setup uses custom mount points:
# Multiple database enginesdbcrust vault://app@postgres-engine/main-dbdbcrust vault://app@mysql-engine/analytics-dbdbcrust vault://app@mongodb-engine/logs-dbVault Namespaces (Enterprise)
Section titled “Vault Namespaces (Enterprise)”For Vault Enterprise with namespaces:
export VAULT_NAMESPACE="development"dbcrust vault://app@database/postgres-dev
export VAULT_NAMESPACE="production"dbcrust vault://app@database/postgres-prodCustom TTL Configuration
Section titled “Custom TTL Configuration”Request specific credential TTLs:
# Request 4-hour credentials (if role allows)dbcrust vault://app-writer@database/postgres-prod?ttl=4h
# Request maximum TTLdbcrust vault://admin@database/postgres-prod?ttl=maxConnection Retry Logic
Section titled “Connection Retry Logic”[vault]max_retries = 3retry_delay = 1000 # millisecondsbackoff_multiplier = 2
# Retry on these HTTP status codesretry_on_status = [500, 502, 503, 504]🚨 Troubleshooting
Section titled “🚨 Troubleshooting”Common Issues
Section titled “Common Issues”Vault Connection Problems
Section titled “Vault Connection Problems”# Test Vault connectivitycurl -s "$VAULT_ADDR/v1/sys/health" | jq
# Test authenticationvault auth -method=userpass username=yourname
# Test role accessvault read database/creds/app-readonlyPermission Denied
Section titled “Permission Denied”# Check your Vault token capabilitiesvault token lookup
# Check policy attachmentsvault token lookup -format=json | jq '.data.policies'
# Test specific path permissionsvault policy read your-policy-nameCredential Cache Issues
Section titled “Credential Cache Issues”# Clear cache and retry\vccdbcrust vault://app-readonly@database/postgres-prod
# Check cache file permissionsls -la ~/.config/dbcrust/vault_credentials.enc
# Enable debug loggingdbcrust --debug vault://app-readonly@database/postgres-prodSSL/TLS Problems
Section titled “SSL/TLS Problems”# Skip TLS verification (not recommended for production)export VAULT_SKIP_VERIFY=true
# Or specify CA certificateexport VAULT_CACERT=/path/to/ca.crtDebug Mode
Section titled “Debug Mode”Enable detailed Vault debugging:
# Enable Vault client debug loggingexport VAULT_LOG_LEVEL=debug
# Enable DBCrust debug loggingdbcrust --debug vault://app@database/postgres-prodHealth Checks
Section titled “Health Checks”Monitor Vault integration health:
# Check Vault server health\vault health
# Check credential cache status\vc
# Test credential renewal\vcr app-readonly🛡️ Security Best Practices
Section titled “🛡️ Security Best Practices”Token Security
Section titled “Token Security”# Use short-lived tokensvault auth -method=userpass username=yourname
# Renew tokens before expirationvault token renew
# Use token helpers for secure storagevault auth -method=awsNetwork Security
Section titled “Network Security”- Always use HTTPS for Vault connections
- Implement proper firewall rules
- Use VPN or private networks when possible
- Enable Vault audit logging
Role Design
Section titled “Role Design”- Follow principle of least privilege
- Use separate roles for different access levels
- Implement short TTLs for sensitive operations
- Regular role permission audits
Compliance
Section titled “Compliance”# Enable comprehensive logging for audits[logging]level = "info"file_output = truefile_path = "/var/log/dbcrust/audit.log"
[vault]log_credential_requests = truelog_cache_operations = true🔗 Integration Examples
Section titled “🔗 Integration Examples”CI/CD Pipelines
Section titled “CI/CD Pipelines”# GitHub Actionsname: Database Testson: [push, pull_request]
jobs: test: runs-on: ubuntu-latest env: VAULT_ADDR: ${{ secrets.VAULT_ADDR }} VAULT_ROLE_ID: ${{ secrets.VAULT_ROLE_ID }} VAULT_SECRET_ID: ${{ secrets.VAULT_SECRET_ID }}
steps: - uses: actions/checkout@v2
- name: Authenticate to Vault run: | vault write -field=token auth/approle/login \ role_id="$VAULT_ROLE_ID" \ secret_id="$VAULT_SECRET_ID" > /tmp/vault-token export VAULT_TOKEN=$(cat /tmp/vault-token)
- name: Run database tests run: | # Tests automatically use Vault credentials python -m pytest tests/database_tests.py
- name: Database migration check run: | dbcrust vault://ci-readonly@database/test-db \ --query "SELECT version()"Kubernetes Integration
Section titled “Kubernetes Integration”apiVersion: apps/v1kind: Deploymentmetadata: name: django-appspec: template: spec: serviceAccountName: django-vault-sa containers: - name: django image: django-app:latest env: - name: VAULT_ADDR value: "https://vault.company.com" - name: VAULT_ROLE value: "django-app" - name: DATABASE_URL value: "vault://app@database/django-prod"📚 See Also
Section titled “📚 See Also”- SSH Tunneling - Secure database connections
- Security Guide - Complete security practices
- Configuration Reference - All configuration options
- HashiCorp Vault Documentation - Official Vault docs