feat(#353): Create VaultService NestJS module for OpenBao Transit
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
Implements secure credential encryption using OpenBao Transit API with automatic fallback to AES-256-GCM when OpenBao is unavailable. Features: - AppRole authentication with automatic token renewal at 50% TTL - Transit encrypt/decrypt with 4 named keys - Automatic fallback to CryptoService when OpenBao unavailable - Auto-detection of ciphertext format (vault:v1: vs AES) - Request timeout protection (5s default) - Health indicator for monitoring - Backward compatible with existing AES-encrypted data Security: - ERROR-level logging for fallback - Proper error propagation (no silent failures) - Request timeouts prevent hung operations - Secure credential file reading Migrations: - Account encryption middleware uses VaultService - Uses TransitKey.ACCOUNT_TOKENS for OAuth tokens - Backward compatible with existing encrypted data Tests: 56 tests passing (36 VaultService + 20 middleware) Closes #353 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,20 +1,21 @@
|
||||
import { Injectable, Logger, OnModuleDestroy, OnModuleInit } from "@nestjs/common";
|
||||
import { PrismaClient } from "@prisma/client";
|
||||
import { CryptoService } from "../federation/crypto.service";
|
||||
import { VaultService } from "../vault/vault.service";
|
||||
import { registerAccountEncryptionMiddleware } from "./account-encryption.middleware";
|
||||
|
||||
/**
|
||||
* Prisma service that manages database connection lifecycle
|
||||
* Extends PrismaClient to provide connection management and health checks
|
||||
*
|
||||
* IMPORTANT: CryptoService is required (not optional) because it will throw
|
||||
* if ENCRYPTION_KEY is not configured, providing fail-fast behavior.
|
||||
* IMPORTANT: VaultService is required (not optional) for encryption/decryption
|
||||
* of sensitive Account tokens. It automatically falls back to AES-256-GCM when
|
||||
* OpenBao is unavailable.
|
||||
*/
|
||||
@Injectable()
|
||||
export class PrismaService extends PrismaClient implements OnModuleInit, OnModuleDestroy {
|
||||
private readonly logger = new Logger(PrismaService.name);
|
||||
|
||||
constructor(private readonly cryptoService: CryptoService) {
|
||||
constructor(private readonly vaultService: VaultService) {
|
||||
super({
|
||||
log: process.env.NODE_ENV === "development" ? ["query", "info", "warn", "error"] : ["error"],
|
||||
});
|
||||
@@ -29,8 +30,8 @@ export class PrismaService extends PrismaClient implements OnModuleInit, OnModul
|
||||
this.logger.log("Database connection established");
|
||||
|
||||
// Register Account token encryption middleware
|
||||
// CryptoService constructor will have already validated ENCRYPTION_KEY exists
|
||||
registerAccountEncryptionMiddleware(this, this.cryptoService);
|
||||
// VaultService provides OpenBao Transit encryption with AES-256-GCM fallback
|
||||
registerAccountEncryptionMiddleware(this, this.vaultService);
|
||||
this.logger.log("Account encryption middleware registered");
|
||||
} catch (error) {
|
||||
this.logger.error("Failed to connect to database", error);
|
||||
|
||||
Reference in New Issue
Block a user