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>
52 lines
1.2 KiB
TypeScript
52 lines
1.2 KiB
TypeScript
/**
|
|
* Vault Health Indicator
|
|
*
|
|
* Health check for OpenBao connectivity and encryption status.
|
|
*/
|
|
|
|
import { Injectable } from "@nestjs/common";
|
|
import { VaultService } from "./vault.service";
|
|
|
|
export interface VaultHealthStatus {
|
|
status: "up" | "down";
|
|
available: boolean;
|
|
fallbackMode: boolean;
|
|
endpoint: string;
|
|
message?: string;
|
|
}
|
|
|
|
@Injectable()
|
|
export class VaultHealthIndicator {
|
|
constructor(private readonly vaultService: VaultService) {}
|
|
|
|
/**
|
|
* Check OpenBao health status
|
|
*
|
|
* @returns Health status object
|
|
*/
|
|
check(): VaultHealthStatus {
|
|
try {
|
|
const status = this.vaultService.getStatus();
|
|
|
|
return {
|
|
status: status.available ? "up" : "down",
|
|
available: status.available,
|
|
fallbackMode: status.fallbackMode,
|
|
endpoint: status.endpoint,
|
|
message: status.available
|
|
? "OpenBao Transit encryption enabled"
|
|
: "Using fallback AES-256-GCM encryption",
|
|
};
|
|
} catch (error: unknown) {
|
|
const errorMsg = error instanceof Error ? error.message : "Unknown error";
|
|
return {
|
|
status: "down",
|
|
available: false,
|
|
fallbackMode: true,
|
|
endpoint: "unknown",
|
|
message: `Health check failed: ${errorMsg}`,
|
|
};
|
|
}
|
|
}
|
|
}
|