HashiCorp Vault provides a complete HTTP API for managing secrets, encryption keys, database credentials, and access policies. The open-source version is free and gives you enterprise-grade secrets management.
Why Use the Vault API?
- Centralize all secrets in one secure location
- Rotate database credentials automatically
- Encrypt sensitive data without managing keys
- Audit every secret access with detailed logs
Getting Started
# Start Vault in dev mode
vault server -dev
export VAULT_ADDR='http://127.0.0.1:8200'
export VAULT_TOKEN='your-root-token'
# Store a secret
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
-X POST "$VAULT_ADDR/v1/secret/data/myapp/config" \
-d '{"data": {"db_password": "supersecret", "api_key": "abc123"}}' | jq .
# Read a secret
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/secret/data/myapp/config" | jq '.data.data'
Python Client
import requests
class VaultClient:
def __init__(self, addr='http://127.0.0.1:8200', token=None):
self.addr = addr
self.headers = {'X-Vault-Token': token}
def read_secret(self, path):
resp = requests.get(f"{self.addr}/v1/secret/data/{path}", headers=self.headers)
if resp.status_code == 200:
return resp.json()['data']['data']
return None
def write_secret(self, path, data):
resp = requests.post(
f"{self.addr}/v1/secret/data/{path}",
json={'data': data},
headers=self.headers
)
return resp.json()
def delete_secret(self, path):
resp = requests.delete(f"{self.addr}/v1/secret/data/{path}", headers=self.headers)
return resp.status_code == 204
def list_secrets(self, path):
resp = requests.request('LIST', f"{self.addr}/v1/secret/metadata/{path}", headers=self.headers)
if resp.status_code == 200:
return resp.json()['data']['keys']
return []
# Usage
vault = VaultClient(token='your-root-token')
# Store application secrets
vault.write_secret('myapp/production', {
'database_url': 'postgres://prod-server:5432/mydb',
'redis_url': 'redis://prod-cache:6379',
'stripe_key': 'sk_live_xxxxx',
'jwt_secret': 'my-jwt-signing-key'
})
# Read secrets in your app
config = vault.read_secret('myapp/production')
print(f"DB: {config['database_url']}")
Dynamic Database Credentials
# Enable database secrets engine
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
-X POST "$VAULT_ADDR/v1/sys/mounts/database" \
-d '{"type": "database"}'
# Configure PostgreSQL connection
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
-X POST "$VAULT_ADDR/v1/database/config/mydb" \
-d '{
"plugin_name": "postgresql-database-plugin",
"connection_url": "postgresql://{{username}}:{{password}}@localhost:5432/mydb",
"allowed_roles": ["readonly", "readwrite"],
"username": "vault_admin",
"password": "admin_password"
}'
# Create a role
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
-X POST "$VAULT_ADDR/v1/database/roles/readonly" \
-d '{
"db_name": "mydb",
"creation_statements": ["CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '\''{{password}}'\'' VALID UNTIL '\''{{expiration}}'\'' INHERIT; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";"],
"default_ttl": "1h",
"max_ttl": "24h"
}'
# Get temporary credentials (auto-expire in 1 hour!)
curl -s -H "X-Vault-Token: $VAULT_TOKEN" \
"$VAULT_ADDR/v1/database/creds/readonly" | jq '{username: .data.username, password: .data.password, ttl: .lease_duration}'
Encryption as a Service
import base64
def encrypt(vault, plaintext, key_name='my-key'):
encoded = base64.b64encode(plaintext.encode()).decode()
resp = requests.post(
f"{vault.addr}/v1/transit/encrypt/{key_name}",
json={'plaintext': encoded},
headers=vault.headers
)
return resp.json()['data']['ciphertext']
def decrypt(vault, ciphertext, key_name='my-key'):
resp = requests.post(
f"{vault.addr}/v1/transit/decrypt/{key_name}",
json={'ciphertext': ciphertext},
headers=vault.headers
)
encoded = resp.json()['data']['plaintext']
return base64.b64decode(encoded).decode()
# Encrypt sensitive data
ciphertext = encrypt(vault, 'SSN: 123-45-6789')
print(f"Encrypted: {ciphertext}")
# Decrypt when needed
plaintext = decrypt(vault, ciphertext)
print(f"Decrypted: {plaintext}")
Application Integration Pattern
import os
from functools import lru_cache
class AppConfig:
def __init__(self):
self.vault = VaultClient(
addr=os.environ.get('VAULT_ADDR', 'http://127.0.0.1:8200'),
token=os.environ.get('VAULT_TOKEN')
)
self._env = os.environ.get('APP_ENV', 'development')
@lru_cache(maxsize=1)
def get_config(self):
return self.vault.read_secret(f'myapp/{self._env}')
@property
def database_url(self):
return self.get_config()['database_url']
@property
def redis_url(self):
return self.get_config()['redis_url']
def refresh(self):
self.get_config.cache_clear()
config = AppConfig()
print(config.database_url)
Real-World Use Case
A healthcare company stored 500+ database passwords in a shared spreadsheet. After a security audit, they migrated to Vault with dynamic credentials. Every application now gets unique, time-limited database credentials that auto-expire. When an employee leaves, no password rotation needed — their Vault token is simply revoked.
What You Can Build
- Secrets management platform for your organization
- Dynamic credential system with auto-rotation
- Encryption service for sensitive data at rest
- PKI infrastructure for internal TLS certificates
- Access audit system tracking who accessed what secrets
Need custom security automation? I build DevOps tools and infrastructure solutions.
Email me: spinov001@gmail.com
Check out my developer tools: https://apify.com/spinov001
Top comments (0)