Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .env.demo
Original file line number Diff line number Diff line change
Expand Up @@ -382,4 +382,18 @@ ADMIN_KEYCLOAK_SECRET=
# Add in case the keycloak id of the old platform client is changed and want to update all the users in database with the new admin client
PLATFORM_ADMIN_OLD_CLIENT_ID=

# --- OpenBao secret storage (PR #1679) ---
# Enable remote secrets fetching via OpenBao. Set to false to fall back to
# plain environment variables (default local behaviour).
ENABLE_BAO=true
# Secret provider: only 'openbao' is supported today
SECRETS_PROVIDER=openbao
# OpenBao server URL (docker-compose.openbao.yml maps 8200)
BAO_URL=http://127.0.0.1:8200
# Default KV v2 path fetched at boot and injected into process.env
BAO_SECRET_PATH=secret/data/credebl_resend_api_key
# AppRole credentials. Generate your own via: ./openbao-init.sh
# (values below are for the local 'openbao' container created by docker-compose.openbao.yml)
BAO_ROLE_ID=ca2a350b-1871-0851-8557-42b36aa9c623
BAO_SECRET_ID=3f0d8d45-c232-f5c1-2984-fe58e5144be8
HIDE_EXPERIMENTAL_OIDC_CONTROLLERS=false
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,54 @@ The `docker-compose.yml` file is available in the root folder.
docker-compose up
```

## OpenBao Secret Storage (Optional)

The platform can source the credentials used by email and file-storage integrations from an [OpenBao](https://openbao.org) server instead of plain environment variables. This is opt-in and disabled by default.

### • Run OpenBao using Docker Compose

```bash
docker compose -f docker-compose.openbao.yml up -d
```

This starts an OpenBao server on `http://127.0.0.1:8200` with file-backed storage persisted on a named volume. Server settings live in `config.hcl`.

### • Provision the server

OpenBao starts sealed and uninitialized. Run the one-shot provisioning script (idempotent — safe to re-run):

```bash
./openbao-init.sh
```

The script initializes and unseals the server, enables the KV v2 secrets engine at `secret/`, enables the AppRole auth method, creates a `credebl` role scoped to the `credebl_*` secret paths, stores the secret values found in the environment (e.g. `RESEND_API_KEY`, `SMTP_HOST`, `AWS_ACCESS_KEY`), and prints the values to copy into your env file:

```bash
BAO_URL=http://127.0.0.1:8200
BAO_SECRET_PATH=secret/data/credebl_resend_api_key
BAO_ROLE_ID=<generated>
BAO_SECRET_ID=<generated>
```

Keep the printed `BAO_UNSEAL_KEY` and `BAO_ROOT_TOKEN` safe — they are shown only once. On later runs, pass `BAO_ROOT_TOKEN` (and `BAO_SECRET_ID` to re-print it).

### • Configure the platform

Add the following to your `.env` (values are already present as placeholders in `.env.demo`):

```bash
ENABLE_BAO=true
SECRETS_PROVIDER=openbao
BAO_URL=http://127.0.0.1:8200
BAO_SECRET_PATH=secret/data/credebl_resend_api_key
BAO_ROLE_ID=<from openbao-init.sh>
BAO_SECRET_ID=<from openbao-init.sh>
```

At startup every microservice authenticates to OpenBao via AppRole, fetches the secrets at `BAO_SECRET_PATH`, and injects them into `process.env` before the NATS listener starts. Email and S3 integrations re-fetch their own credential paths on demand (e.g. `secret/data/credebl_smtp_config`, `secret/data/credebl_aws_keys`) with a 10-minute TTL cache.

Set `ENABLE_BAO=false` (or omit it) to fall back to local environment variables.

## Run CREDEBL Microservices

### • Install Dependencies
Expand Down
16 changes: 12 additions & 4 deletions apps/agent-provisioning/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,22 @@
import { NestFactory } from '@nestjs/core';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { AgentProvisioningModule } from './agent-provisioning.module';
import { getNatsOptions } from '@credebl/common/nats.config';
import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
Comment thread
sujitaw marked this conversation as resolved.
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AgentProvisioningModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
19 changes: 13 additions & 6 deletions apps/agent-service/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AgentServiceModule } from './agent-service.module';
import { AgentServiceService } from './agent-service.service';
import * as dotenv from 'dotenv';

import { IAgentSpinupDto, IUserRequestInterface } from './interface/agent-service.interface';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';

import { AgentServiceModule } from './agent-service.module';
import { AgentServiceService } from './agent-service.service';
import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Ledgers } from '@credebl/enum/enum';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(AgentServiceModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
3 changes: 3 additions & 0 deletions apps/api-gateway/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,13 @@ import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapt
import { UpdatableValidationPipe } from '@credebl/common/custom-overrideable-validation-pipe';
import * as useragent from 'express-useragent';
import { EcosystemSwaggerFilter } from './authz/guards/ecosystem-swagger.filter';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();

try {
if (otelSDK) {
await otelSDK.start();
Expand Down
15 changes: 11 additions & 4 deletions apps/cloud-wallet/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { NestFactory } from '@nestjs/core';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { CloudWalletModule } from './cloud-wallet.module';
import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';
import { CommonConstants } from '@credebl/common/common.constant';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(CloudWalletModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
15 changes: 11 additions & 4 deletions apps/connection/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { NestFactory } from '@nestjs/core';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { CommonConstants } from '@credebl/common/common.constant';
import { ConnectionModule } from './connection.module';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';
import { CommonConstants } from '@credebl/common/common.constant';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(ConnectionModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
6 changes: 6 additions & 0 deletions apps/ecosystem/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { CommonConstants } from '@credebl/common/common.constant';
Expand All @@ -8,10 +10,14 @@ import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
// import { nkeyAuthenticator } from 'nats';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(EcosystemModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
15 changes: 11 additions & 4 deletions apps/geo-location/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { CommonConstants } from '@credebl/common/common.constant';
import { GeoLocationModule } from './geo-location.module';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';
import { GeoLocationModule } from './geo-location.module';
import { CommonConstants } from '@credebl/common/common.constant';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
Comment thread
sujitaw marked this conversation as resolved.
const app = await NestFactory.createMicroservice<MicroserviceOptions>(GeoLocationModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
17 changes: 12 additions & 5 deletions apps/issuance/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { NestFactory } from '@nestjs/core';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { IssuanceModule } from '../src/issuance.module';
import { getNatsOptions } from '@credebl/common/nats.config';

import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { IssuanceModule } from '../src/issuance.module';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(IssuanceModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
17 changes: 12 additions & 5 deletions apps/ledger/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
import { NestFactory } from '@nestjs/core';
import { LedgerModule } from './ledger.module';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';

import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { LedgerModule } from './ledger.module';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(LedgerModule, {
transport: Transport.NATS,
options: getNatsOptions(CommonConstants.LEDGER_SERVICE, process.env.LEDGER_NKEY_SEED, process.env.NATS_CREDS_FILE)
Expand Down
15 changes: 11 additions & 4 deletions apps/notification/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,22 @@
import { NestFactory } from '@nestjs/core';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';

import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { NotificationModule } from '../src/notification.module';
import { getNatsOptions } from '@credebl/common/nats.config';
import { CommonConstants } from '@credebl/common/common.constant';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(NotificationModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
16 changes: 12 additions & 4 deletions apps/oid4vc-issuance/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
import { NestFactory } from '@nestjs/core';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';

import { CommonConstants } from '@credebl/common/common.constant';
import { HttpExceptionFilter } from 'libs/http-exception.filter';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { Oid4vcIssuanceModule } from './oid4vc-issuance.module';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();

if (!process.env.STATUS_LIST_HOST) {
logger.warn('STATUS_LIST_HOST is not configured. Revocable SD-JWT flow will be disabled.');
}
Expand Down
13 changes: 10 additions & 3 deletions apps/oid4vc-verification/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
import { NestFactory } from '@nestjs/core';
import { Logger } from '@nestjs/common';
import * as dotenv from 'dotenv';

import { MicroserviceOptions, Transport } from '@nestjs/microservices';
import { getNatsOptions } from '@credebl/common/nats.config';

import { CommonConstants } from '@credebl/common/common.constant';
import { Logger } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter';
import { Oid4vpModule } from './oid4vc-verification.module';
import { getNatsOptions } from '@credebl/common/nats.config';
import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader';

dotenv.config();

Comment thread
sujitaw marked this conversation as resolved.
const logger = new Logger();

async function bootstrap(): Promise<void> {
await loadConfigSecrets();
const app = await NestFactory.createMicroservice<MicroserviceOptions>(Oid4vpModule, {
transport: Transport.NATS,
options: getNatsOptions(
Expand Down
Loading