Build local product stack with Vault-managed secrets (#42)

This commit is contained in:
Stephan D committed 2026-09-12 21:04:42 +02:00
1 parent 8e2ef7aa88
commit 184a3be413
32 files changed
+1191 -10

No files matched your search

+72
View File
@@ -0,0 +1,72 @@
"""Integration checks against this project's running stack; never print secrets."""
import json
import ssl
import urllib.request
from bootstrap import compose, mongo
from vault import STATE
def require(condition, message):
if not condition:
raise RuntimeError(message)
def database_access(vault):
for role, database, forbidden in [('bff', 'sxchnge', 'sxchnge_notifications'),
('notifications', 'sxchnge_notifications', 'sxchnge')]:
lease = vault.call('database/creds/' + role)
credentials = lease['data']
auth = 'db.getSiblingDB("admin").auth(' + json.dumps(credentials['username']) + ',' + json.dumps(credentials['password']) + ');'
try:
result = compose('exec', '-T', 'mongo', 'mongosh', '--quiet', '--file', '/dev/stdin', capture=True,
input=auth + 'const own=db.getSiblingDB(' + json.dumps(database) + '); own.local_smoke.insertOne({_id:"vault-check"}); own.local_smoke.deleteOne({_id:"vault-check"});\n'
'let denied=false; try { db.getSiblingDB(' + json.dumps(forbidden) + ').runCommand({find:"local_smoke",filter:{}}); } catch(e) { denied=e.code===13; } if(!denied) throw new Error("cross-database access allowed"); print("scope-ok");')
require('scope-ok' in result, 'Mongo service scope check failed')
renewed = vault.call('sys/leases/renew', {'lease_id': lease['lease_id'], 'increment': '1h'})
require(renewed['lease_duration'] > 0, 'Mongo lease renewal failed')
finally:
vault.call('sys/leases/revoke', {'lease_id': lease['lease_id']})
admin = vault.kv('bootstrap/mongo')['password']
result = mongo('print(admin.getUser(' + json.dumps(credentials['username']) + ')===null)', admin)
require('true' in result, 'Revoked Mongo user still exists')
print('PASS: database-plugin issuance, separate database permissions, lease renewal and revocation')
def policies(vault):
for service in ['bff', 'notifications', 'nats']:
root = STATE / 'agents' / service
login = vault.call('auth/approle/login', {'role_id': (root / 'role-id').read_text(),
'secret_id': (root / 'secret-id').read_text()})
token = login['auth']['client_token']
try:
result = vault.call('sys/capabilities', {'token': token, 'paths': ['kv/data/bootstrap/mongo', 'sys/init']})['data']
require(all(result[path] == ['deny'] for path in ['kv/data/bootstrap/mongo', 'sys/init']), 'Service can access bootstrap credentials')
finally:
vault.call('auth/token/revoke', {'token': token})
print('PASS: service identities cannot read bootstrap credentials')
def infrastructure(vault):
status = compose('ps', '--format', 'json', capture=True)
rows = [json.loads(line) for line in status.splitlines() if line.strip()]
infra = {r['Service']: r for r in rows if r['Service'] in {'vault', 'mongo', 'nats'}}
require(set(infra) == {'vault', 'mongo', 'nats'}, 'Expected Vault, Mongo and NATS')
require(all(r['Health'] == 'healthy' for r in infra.values()), 'Infrastructure is unhealthy')
print('PASS: Vault, Mongo replica set and NATS JetStream are healthy')
policies(vault)
database_access(vault)
def verify(vault):
status = compose('ps', '--format', 'json', capture=True)
rows = [json.loads(line) for line in status.splitlines() if line.strip()]
require({r['Service'] for r in rows} == {'vault', 'mongo', 'nats', 'notifications', 'bff', 'frontend'}, 'Expected six running services')
require(all(r['Health'] == 'healthy' for r in rows), 'Some services are unhealthy')
context = ssl.create_default_context(cafile=str(STATE / 'ca.pem'))
for path in ['/', '/api/v1/health']:
with urllib.request.urlopen('https://localhost:5126' + path, context=context, timeout=10) as response:
require(response.status == 200, 'Frontend or BFF health failed')
print('PASS: all six services healthy; frontend and proxied BFF use verified TLS')
infrastructure(vault)
print('Resend credentials are configured; no live email sent by this check')