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.
Python code
55 linesimport 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
{
"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
- Use `secrets.token_urlsafe(12)` for cryptographically secure passwords
- 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
More from Auth & security at scale
- ACME LetsEncrypt Mock Challenge Server in Python medium
- AES GCM encryption and decryption in Python medium
- Build a Mock OIDC Userinfo Endpoint in Python with Flask easy
- ChaCha20-Poly1305 mock in Python medium
- ECDH key agreement in Python with cryptography medium
- Enforce TLS 1.2 Minimum in Python easy
Keep learning
Related tutorials and quizzes for this topic.