DEV Community

Alex Spinov
Alex Spinov

Posted on

HashiCorp Vault Has a Free API: Here's How to Use It for Secrets Management

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'
Enter fullscreen mode Exit fullscreen mode

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']}")
Enter fullscreen mode Exit fullscreen mode

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}'
Enter fullscreen mode Exit fullscreen mode

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}")
Enter fullscreen mode Exit fullscreen mode

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)
Enter fullscreen mode Exit fullscreen mode

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)