Create VaultService NestJS module for OpenBao Transit #353

Closed
opened 2026-02-07 17:11:40 +00:00 by jason.woltje · 0 comments
Owner

Phase 2b - OpenBao Integration

Problem

The codebase needs a NestJS service that wraps OpenBao Transit API for encrypt/decrypt operations, with graceful fallback to the existing AES-256-GCM CryptoService when OpenBao is unavailable (local dev, CI).

Requirements

  1. Create VaultModule (global) and VaultService
  2. Authenticate via AppRole (credentials from init volume or env vars)
  3. Encrypt/decrypt via Transit API with named keys
  4. Auto-detect ciphertext format: vault:v1:... (Transit) vs aes:... (AES fallback)
  5. Fall back to CryptoService when OpenBao is not available
  6. Token auto-renewal at 50% TTL
  7. Health check for monitoring
  8. Migrate Account encryption middleware from Phase 1 to use VaultService

Implementation Notes

  • Use native fetch() for HTTP calls to OpenBao (no external Vault client library needed)
  • TransitKey enum: CREDENTIALS, ACCOUNT_TOKENS, FEDERATION, LLM_CONFIG
  • Transit encrypt: POST /v1/transit/encrypt/{key} with base64-encoded plaintext
  • Transit decrypt: POST /v1/transit/decrypt/{key} returns base64-encoded plaintext
  • VaultService wraps CryptoService as fallback, not replaces it
  • On module init: attempt AppRole login. If fails, log warning and set fallback mode.
  • Account encryption middleware updated to inject VaultService instead of CryptoService directly

Files

  • apps/api/src/vault/vault.module.ts (new)
  • apps/api/src/vault/vault.service.ts (new)
  • apps/api/src/vault/vault.service.spec.ts (new)
  • apps/api/src/vault/vault.health.ts (new)
  • apps/api/src/vault/vault.constants.ts (new - TransitKey enum)
  • apps/api/src/app.module.ts (modify - import VaultModule)
  • apps/api/src/prisma/account-encryption.middleware.ts (modify - use VaultService)
  • .env.example (modify - add OPENBAO_ROLE_ID, OPENBAO_SECRET_ID)

Acceptance Criteria

  • VaultService encrypts/decrypts via OpenBao Transit API
  • Falls back to CryptoService when OpenBao unavailable
  • AppRole authentication with auto-renewal
  • Health check endpoint reports OpenBao status
  • Account encryption middleware uses VaultService
  • Existing aes:-prefixed ciphertext remains decryptable
  • Unit tests with mocked Transit API
  • Integration test with real OpenBao container (optional)

Dependencies

  • Depends on: OpenBao Docker setup
  • Depends on: Account token encryption middleware (Phase 1c)
  • Blocks: User credential model and API (Phase 3)

Refs #346

## Phase 2b - OpenBao Integration ### Problem The codebase needs a NestJS service that wraps OpenBao Transit API for encrypt/decrypt operations, with graceful fallback to the existing AES-256-GCM CryptoService when OpenBao is unavailable (local dev, CI). ### Requirements 1. Create VaultModule (global) and VaultService 2. Authenticate via AppRole (credentials from init volume or env vars) 3. Encrypt/decrypt via Transit API with named keys 4. Auto-detect ciphertext format: vault:v1:... (Transit) vs aes:... (AES fallback) 5. Fall back to CryptoService when OpenBao is not available 6. Token auto-renewal at 50% TTL 7. Health check for monitoring 8. Migrate Account encryption middleware from Phase 1 to use VaultService ### Implementation Notes - Use native fetch() for HTTP calls to OpenBao (no external Vault client library needed) - TransitKey enum: CREDENTIALS, ACCOUNT_TOKENS, FEDERATION, LLM_CONFIG - Transit encrypt: POST /v1/transit/encrypt/{key} with base64-encoded plaintext - Transit decrypt: POST /v1/transit/decrypt/{key} returns base64-encoded plaintext - VaultService wraps CryptoService as fallback, not replaces it - On module init: attempt AppRole login. If fails, log warning and set fallback mode. - Account encryption middleware updated to inject VaultService instead of CryptoService directly ### Files - apps/api/src/vault/vault.module.ts (new) - apps/api/src/vault/vault.service.ts (new) - apps/api/src/vault/vault.service.spec.ts (new) - apps/api/src/vault/vault.health.ts (new) - apps/api/src/vault/vault.constants.ts (new - TransitKey enum) - apps/api/src/app.module.ts (modify - import VaultModule) - apps/api/src/prisma/account-encryption.middleware.ts (modify - use VaultService) - .env.example (modify - add OPENBAO_ROLE_ID, OPENBAO_SECRET_ID) ### Acceptance Criteria - [ ] VaultService encrypts/decrypts via OpenBao Transit API - [ ] Falls back to CryptoService when OpenBao unavailable - [ ] AppRole authentication with auto-renewal - [ ] Health check endpoint reports OpenBao status - [ ] Account encryption middleware uses VaultService - [ ] Existing aes:-prefixed ciphertext remains decryptable - [ ] Unit tests with mocked Transit API - [ ] Integration test with real OpenBao container (optional) ### Dependencies - Depends on: OpenBao Docker setup - Depends on: Account token encryption middleware (Phase 1c) - Blocks: User credential model and API (Phase 3) Refs #346
jason.woltje added this to the M9-CredentialSecurity (0.0.9) milestone 2026-02-07 17:11:40 +00:00
jason.woltje added the securityapiapip1 labels 2026-02-07 17:11:40 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaic/stack#353