Add phase 5 secure credential vault

This commit is contained in:
A R R R Associates
2026-07-23 14:44:02 +05:30
parent d113db0d20
commit 1b9f555dcf
16 changed files with 442 additions and 0 deletions
+41
View File
@@ -0,0 +1,41 @@
from __future__ import annotations
import base64
import hashlib
import hmac
from cryptography.fernet import Fernet, InvalidToken
from app.core.settings import get_settings
class VaultCryptoError(RuntimeError):
pass
def _master_key() -> bytes:
settings = get_settings()
raw = (getattr(settings, "VAULT_MASTER_KEY", "") or settings.SECRET_KEY or "").strip()
if not raw or raw == "change-me-to-a-long-random-string":
raise VaultCryptoError("VAULT_MASTER_KEY must be configured with a strong production secret before using the credential vault.")
return raw.encode("utf-8")
def _fernet(tenant_id: int) -> Fernet:
digest = hmac.new(_master_key(), f"audit-firm-vault:tenant:{tenant_id}:v1".encode(), hashlib.sha256).digest()
return Fernet(base64.urlsafe_b64encode(digest))
def encrypt_value(tenant_id: int, value: str | None) -> str | None:
if value is None or value == "":
return None
return _fernet(tenant_id).encrypt(value.encode("utf-8")).decode("ascii")
def decrypt_value(tenant_id: int, token: str | None) -> str:
if not token:
return ""
try:
return _fernet(tenant_id).decrypt(token.encode("ascii")).decode("utf-8")
except InvalidToken as exc:
raise VaultCryptoError("The credential could not be decrypted with the configured vault key.") from exc