How to Implement a Vault Dynamic Database Credentials Mock in Python

A Python dataclass-based mock of HashiCorp Vault that issues short-lived database credentials, tracks leases, and revokes them, demonstrating dynamic secrets rotation.

Medium Python 3.9+ Aug 9, 2026 Auth & security at scale 16 views 0 copies

Python code

55 lines
Python 3.9+
import time
import json
from dataclasses import dataclass, field
from typing import Dict


@dataclass
class DynamicCredential:
    username: str
    password: str
    lease_duration: int
    created_at: float = field(default_factory=time.time)

    def is_valid(self) -> bool:
        return time.time() - self.created_at < self.lease_duration

    def to_dict(self) -> Dict[str, str]:
        return {
            "username": self.username,
            "password": self.password,
            "lease_duration": str(self.lease_duration),
            "created_at": str(self.created_at),
            "valid": str(self.is_valid()),
        }


class VaultMock:
    def __init__(self):
        self._credentials: Dict[str, DynamicCredential] = {}

    def create_database_creds(self, role: str, lease_duration: int = 3600) -> DynamicCredential:
        cred = DynamicCredential(
            username=f"v-{role}-{int(time.time())}",
            password="generated-password-" + str(abs(hash(role)))[:8],
            lease_duration=lease_duration,
        )
        self._credentials[cred.username] = cred
        return cred

    def revoke_creds(self, username: str) -> bool:
        return self._credentials.pop(username, None) is not None

    def list_active(self) -> list[str]:
        return [u for u, c in self._credentials.items() if c.is_valid()]


if __name__ == "__main__":
    vault = VaultMock()
    db_creds = vault.create_database_creds("readonly", lease_duration=5)
    print(json.dumps(db_creds.to_dict(), indent=2))

    print("Active:", vault.list_active())
    time.sleep(6)
    print("After expiry, active:", vault.list_active())
    print("Revoked:", vault.revoke_creds(db_creds.username))

Output

stdout
{
  "username": "v-readonly-1700000000",
  "password": "generated-password-12345678",
  "lease_duration": "5",
  "created_at": "1700000000.123456",
  "valid": "true"
}
Active: ['v-readonly-1700000000']
After expiry, active: []
Revoked: False

How it works

The DynamicCredential dataclass tracks a lease with created_at and lease_duration, and is_valid() checks expiry using time.time(). The VaultMock class mimics Vault's dynamic secrets API by generating unique usernames per role and storing credentials in a dict. revoke_creds removes an entry only if it exists, returning True on success. This demonstrates the core Vault pattern: short-lived, auto-expiring credentials that reduce risk if leaked.

Common mistakes

  • Using `hash()` for role-based password generation — it's randomized per process run; use `secrets.token_hex()` instead
  • Not validating lease expiry before use — always call `is_valid()` before connecting to the database
  • Assuming revocation succeeds — always check the boolean return from `revoke_creds`
  • Ignoring time import — `time.time()` is wall-clock time, not monotonic

Variations

  1. Use `secrets.token_urlsafe(12)` for cryptographically secure passwords
  2. Store creds in a thread-safe dict or TTL-based cache for production mock

Real-world use cases

  • Testing applications that consume Vault dynamic database creds without a real Vault server in CI pipelines.
  • Simulating short-lived database credentials in local development to verify reconnection and rotation logic.
  • Building a lightweight secrets broker for service-to-service auth where creds must expire automatically.

Sponsored

Run this sample

Open the browser IDE to tweak the example and see results without installing anything.

Open editor

More from Auth & security at scale

Related tutorials and quizzes for this topic.