diff --git a/.env.demo b/.env.demo index a686298f1..83d2fe9e4 100644 --- a/.env.demo +++ b/.env.demo @@ -382,4 +382,8 @@ 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= +BAO_URL= +BAO_SECRET_PATH= +BAO_ROLE_ID= +BAO_SECRET_ID= HIDE_EXPERIMENTAL_OIDC_CONTROLLERS=false diff --git a/apps/agent-provisioning/src/main.ts b/apps/agent-provisioning/src/main.ts index 6b3e2963c..f02b18dd2 100644 --- a/apps/agent-provisioning/src/main.ts +++ b/apps/agent-provisioning/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(AgentProvisioningModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/agent-service/src/main.ts b/apps/agent-service/src/main.ts index c949023a5..f992d5b96 100644 --- a/apps/agent-service/src/main.ts +++ b/apps/agent-service/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(AgentServiceModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/api-gateway/src/main.ts b/apps/api-gateway/src/main.ts index d7934ae78..b8b8a9895 100755 --- a/apps/api-gateway/src/main.ts +++ b/apps/api-gateway/src/main.ts @@ -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 { + await loadConfigSecrets(); + try { if (otelSDK) { await otelSDK.start(); diff --git a/apps/cloud-wallet/src/main.ts b/apps/cloud-wallet/src/main.ts index a411b0700..1da37b7ec 100644 --- a/apps/cloud-wallet/src/main.ts +++ b/apps/cloud-wallet/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(CloudWalletModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/connection/src/main.ts b/apps/connection/src/main.ts index c98e3ea74..10ee34ff8 100644 --- a/apps/connection/src/main.ts +++ b/apps/connection/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(ConnectionModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/ecosystem/src/main.ts b/apps/ecosystem/src/main.ts index ebb2a53df..71fed8e97 100644 --- a/apps/ecosystem/src/main.ts +++ b/apps/ecosystem/src/main.ts @@ -1,3 +1,5 @@ +import * as dotenv from 'dotenv'; + import { MicroserviceOptions, Transport } from '@nestjs/microservices'; import { CommonConstants } from '@credebl/common/common.constant'; @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(EcosystemModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/geo-location/src/main.ts b/apps/geo-location/src/main.ts index 84800754f..9e16df13e 100644 --- a/apps/geo-location/src/main.ts +++ b/apps/geo-location/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(GeoLocationModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/issuance/src/main.ts b/apps/issuance/src/main.ts index b69e8e57c..9d137b58d 100644 --- a/apps/issuance/src/main.ts +++ b/apps/issuance/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(IssuanceModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/ledger/src/main.ts b/apps/ledger/src/main.ts index 022dffa76..b25a6a6b0 100644 --- a/apps/ledger/src/main.ts +++ b/apps/ledger/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(LedgerModule, { transport: Transport.NATS, options: getNatsOptions(CommonConstants.LEDGER_SERVICE, process.env.LEDGER_NKEY_SEED, process.env.NATS_CREDS_FILE) diff --git a/apps/notification/src/main.ts b/apps/notification/src/main.ts index 64d505ed7..892524c40 100644 --- a/apps/notification/src/main.ts +++ b/apps/notification/src/main.ts @@ -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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(NotificationModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/oid4vc-issuance/src/main.ts b/apps/oid4vc-issuance/src/main.ts index 68aa19bbf..4e9702a07 100644 --- a/apps/oid4vc-issuance/src/main.ts +++ b/apps/oid4vc-issuance/src/main.ts @@ -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 { + await loadConfigSecrets(); + if (!process.env.STATUS_LIST_HOST) { logger.warn('STATUS_LIST_HOST is not configured. Revocable SD-JWT flow will be disabled.'); } diff --git a/apps/oid4vc-verification/src/main.ts b/apps/oid4vc-verification/src/main.ts index 667a31102..2303643e6 100644 --- a/apps/oid4vc-verification/src/main.ts +++ b/apps/oid4vc-verification/src/main.ts @@ -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(); const logger = new Logger(); async function bootstrap(): Promise { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(Oid4vpModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/organization/src/main.ts b/apps/organization/src/main.ts index 8ec4de9d2..625c4f59c 100644 --- a/apps/organization/src/main.ts +++ b/apps/organization/src/main.ts @@ -1,16 +1,23 @@ +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 { NestFactory } from '@nestjs/core'; +import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; import { OrganizationModule } from './organization.module'; -import { MicroserviceOptions, Transport } from '@nestjs/microservices'; // import { nkeyAuthenticator } from 'nats'; 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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(OrganizationModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/user/src/main.ts b/apps/user/src/main.ts index 01411c446..cd3d9ad77 100644 --- a/apps/user/src/main.ts +++ b/apps/user/src/main.ts @@ -1,3 +1,5 @@ +import * as dotenv from 'dotenv'; + import { MicroserviceOptions, Transport } from '@nestjs/microservices'; import { CommonConstants } from '@credebl/common/common.constant'; @@ -7,10 +9,14 @@ import { NestFactory } from '@nestjs/core'; import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; import { UserModule } from './user.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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(UserModule, { transport: Transport.NATS, options: getNatsOptions(CommonConstants.USER_SERVICE, process.env.USER_NKEY_SEED, process.env.NATS_CREDS_FILE) diff --git a/apps/utility/src/main.ts b/apps/utility/src/main.ts index fcf71b53a..07d9bfa10 100644 --- a/apps/utility/src/main.ts +++ b/apps/utility/src/main.ts @@ -1,15 +1,22 @@ +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 { NestFactory } from '@nestjs/core'; -import { MicroserviceOptions, Transport } from '@nestjs/microservices'; -import { getNatsOptions } from '@credebl/common/nats.config'; -import { UtilitiesModule } from './utilities.module'; -import { CommonConstants } from '@credebl/common/common.constant'; import NestjsLoggerServiceAdapter from '@credebl/logger/nestjsLoggerServiceAdapter'; +import { UtilitiesModule } from './utilities.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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(UtilitiesModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/verification/src/main.ts b/apps/verification/src/main.ts index 0195a8ee1..5fe2fd73d 100644 --- a/apps/verification/src/main.ts +++ b/apps/verification/src/main.ts @@ -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 { VerificationModule } from './verification.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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(VerificationModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/webhook/src/main.ts b/apps/webhook/src/main.ts index 07ca3bcea..a7cc3bb61 100644 --- a/apps/webhook/src/main.ts +++ b/apps/webhook/src/main.ts @@ -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 { WebhookModule } from '../src/webhook.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 { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(WebhookModule, { transport: Transport.NATS, options: getNatsOptions( diff --git a/apps/x509/src/main.ts b/apps/x509/src/main.ts index eb77bb520..b181e45fd 100644 --- a/apps/x509/src/main.ts +++ b/apps/x509/src/main.ts @@ -1,13 +1,20 @@ -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 { X509Module } from './x509.module'; +import { getNatsOptions } from '@credebl/common/nats.config'; +import { loadConfigSecrets } from '@credebl/config/secret-storage/secrets-loader'; + +dotenv.config(); async function bootstrap(): Promise { + await loadConfigSecrets(); const app = await NestFactory.createMicroservice(X509Module, { transport: Transport.NATS, options: getNatsOptions(CommonConstants.X509_SERVICE, process.env.X509_NKEY_SEED, process.env.NATS_CREDS_FILE) diff --git a/libs/common/src/common.constant.ts b/libs/common/src/common.constant.ts index 011ef9780..9613ed454 100644 --- a/libs/common/src/common.constant.ts +++ b/libs/common/src/common.constant.ts @@ -443,6 +443,12 @@ export enum CommonConstants { OIDC_VERIFIER_SESSION_RESPONSE_GET_BY_ID = 'get-oid4vp-verifier-session-response-id', OIDC_VERIFIER_SESSION_AUTH_RESPONSE_VERIFY = 'verify-oid4vp-verifier-session-auth-response', + // BAO_STORAGE_PATH + CREDEBL_RESEND_API_KEY_PATH = 'secret/data/credebl_resend_api_key', + CREDEBL_SMTP_CONFIG_PATH = 'secret/data/credebl_smtp_config', + CREDEBL_SENDGRID_API_KEY_PATH = 'secret/data/credebl_sendgrid_api_key', + CREDEBL_AWS_KEY_PATH = 'secret/data/credebl_aws_keys', + //X509 X509_CREATE_CERTIFICATE = 'create-x509-certificate', X509_IMPORT_CERTIFICATE = 'import-x509-certificate', @@ -451,7 +457,9 @@ export enum CommonConstants { // Storage Types STORAGE_TYPE_AWS = 'aws', STORAGE_TYPE_LOCAL = 'local', - STORAGE_TYPE_RUSTFS = 'rustfs' + STORAGE_TYPE_RUSTFS = 'rustfs', + + OPENBAO_REQUEST_TIMEOUT = 10000 } export const MICRO_SERVICE_NAME = Symbol('MICRO_SERVICE_NAME'); export const ATTRIBUTE_NAME_REGEX = /\['(.*?)'\]/; diff --git a/libs/common/src/resend-helper-file.ts b/libs/common/src/resend-helper-file.ts index 4d0326bd8..9950ee96a 100644 --- a/libs/common/src/resend-helper-file.ts +++ b/libs/common/src/resend-helper-file.ts @@ -1,26 +1,21 @@ -import * as dotenv from 'dotenv'; - +import { CommonConstants } from './common.constant'; import { EmailDto } from './dtos/email.dto'; import { Logger } from '@nestjs/common'; import { Resend } from 'resend'; - -dotenv.config(); - -const emailProvider = process.env.EMAIL_PROVIDER; -const apiKey = process.env.RESEND_API_KEY; - -let resend: Resend | null = null; - -if ('resend' === emailProvider) { - if (!apiKey) { - throw new Error('Missing RESEND_API_KEY in environment variables.'); - } - resend = new Resend(apiKey); -} +import { fetchSecrets } from './utils/secretLoader.util'; export const sendWithResend = async (emailDto: EmailDto): Promise => { try { - const response = await resend.emails.send({ + const secretPath = CommonConstants.CREDEBL_RESEND_API_KEY_PATH; + const secrets = await fetchSecrets(secretPath); + const apiKey = secrets.RESEND_API_KEY ?? process.env.RESEND_API_KEY; + + if (!apiKey) { + throw new Error('Missing RESEND_API_KEY in secret payload.'); + } + + const client = new Resend(apiKey); + const response = await client.emails.send({ from: emailDto.emailFrom, to: emailDto.emailTo, subject: emailDto.emailSubject, @@ -28,7 +23,6 @@ export const sendWithResend = async (emailDto: EmailDto): Promise => { html: emailDto.emailHtml, attachments: emailDto.emailAttachments }); - return Boolean(response.data?.id); } catch (error) { Logger.error('Error while sending email with Resend', error); diff --git a/libs/common/src/send-grid-helper-file.ts b/libs/common/src/send-grid-helper-file.ts index 3ae07faf1..01e3f666d 100644 --- a/libs/common/src/send-grid-helper-file.ts +++ b/libs/common/src/send-grid-helper-file.ts @@ -1,14 +1,22 @@ -import * as dotenv from 'dotenv'; import * as sendgrid from '@sendgrid/mail'; +import { CommonConstants } from './common.constant'; import { EmailDto } from './dtos/email.dto'; - -dotenv.config(); - -sendgrid.setApiKey(process.env.SENDGRID_API_KEY); +import { Logger } from '@nestjs/common'; +import { fetchSecrets } from './utils/secretLoader.util'; export const sendWithSendGrid = async (EmailDto: EmailDto): Promise => { try { + const secretPath = CommonConstants.CREDEBL_SENDGRID_API_KEY_PATH; + const secrets = await fetchSecrets(secretPath); + const apiKey = secrets.SENDGRID_API_KEY ?? process.env.SENDGRID_API_KEY; + + if (!apiKey) { + throw new Error('Missing SENDGRID_API_KEY in secret payload.'); + } + + sendgrid.setApiKey(apiKey); + const msg = { to: EmailDto.emailTo, from: EmailDto.emailFrom, @@ -22,6 +30,7 @@ export const sendWithSendGrid = async (EmailDto: EmailDto): Promise => .then(() => true) .catch(() => false); } catch (error) { + Logger.error('Error while sending email with SendGrid', error); return false; } }; diff --git a/libs/common/src/smtp-helper-file.ts b/libs/common/src/smtp-helper-file.ts index be0559e0a..1f629ad67 100644 --- a/libs/common/src/smtp-helper-file.ts +++ b/libs/common/src/smtp-helper-file.ts @@ -1,47 +1,40 @@ -import * as dotenv from 'dotenv'; import * as nodemailer from 'nodemailer'; +import { CommonConstants } from './common.constant'; import { EmailDto } from './dtos/email.dto'; import { Logger } from '@nestjs/common'; - -dotenv.config(); - -const emailProvider = process.env.EMAIL_PROVIDER?.toLowerCase(); - -let transporter: nodemailer.Transporter | null = null; - -if ('smtp' === emailProvider) { - const { SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS } = process.env; - - if (!SMTP_HOST || !SMTP_PORT || !SMTP_USER || !SMTP_PASS) { - throw new Error('Missing SMTP configuration. Required: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS'); - } - - const port = Number(SMTP_PORT); - - if (!Number.isInteger(port) || 0 >= port) { - throw new Error(`Invalid SMTP_PORT value: "${SMTP_PORT}". Must be a valid number.`); - } - - transporter = nodemailer.createTransport({ - host: SMTP_HOST, - port: Number(SMTP_PORT), - secure: 465 === Number(SMTP_PORT), - auth: { - user: SMTP_USER, - pass: SMTP_PASS - }, - requireTLS: 587 === Number(SMTP_PORT) - }); -} +import { fetchSecrets } from './utils/secretLoader.util'; export const sendWithSMTP = async (emailDto: EmailDto): Promise => { - if (!transporter) { - Logger.error('SMTP email provider is not initialized'); - return false; - } - try { + const secretPath = CommonConstants.CREDEBL_SMTP_CONFIG_PATH; + const secrets = await fetchSecrets(secretPath); + const smtpHost = secrets.SMTP_HOST ?? process.env.SMTP_HOST; + const smtpPort = secrets.SMTP_PORT ?? process.env.SMTP_PORT; + const smtpUser = secrets.SMTP_USER ?? process.env.SMTP_USER; + const smtpPass = secrets.SMTP_PASS ?? process.env.SMTP_PASS; + + if (!smtpHost || !smtpPort || !smtpUser || !smtpPass) { + throw new Error('Missing SMTP configuration. Required: SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS'); + } + + const port = Number(smtpPort); + + if (!Number.isInteger(port) || 0 >= port) { + throw new Error(`Invalid SMTP_PORT value: "${smtpPort}". Must be a valid number.`); + } + + const transporter = nodemailer.createTransport({ + host: smtpHost, + port, + secure: 465 === port, + auth: { + user: smtpUser, + pass: smtpPass + }, + requireTLS: 587 === port + }); + await transporter.sendMail({ from: emailDto.emailFrom, to: emailDto.emailTo, diff --git a/libs/common/src/utils/secretLoader.util.ts b/libs/common/src/utils/secretLoader.util.ts new file mode 100644 index 000000000..63cd53352 --- /dev/null +++ b/libs/common/src/utils/secretLoader.util.ts @@ -0,0 +1,28 @@ +import { TtlCache } from './ttl-cache.util'; +import { getSecretProvider } from 'libs/config/src/secret-storage/secrets-loader'; + +const CACHE_TTL_MS = 10 * 60 * 1000; + +const secretCaches = new Map>>(); + +export async function fetchSecrets(secretPath: string): Promise> { + if ('true' !== process.env.ENABLE_BAO?.trim()?.toLowerCase()) { + return {}; + } + let cache = secretCaches.get(secretPath); + if (!cache) { + cache = new TtlCache>(CACHE_TTL_MS); + secretCaches.set(secretPath, cache); + } + return cache.get(async () => { + const providerType = process.env.SECRETS_PROVIDER?.trim(); + if (!providerType) { + return {}; + } + const provider = getSecretProvider(providerType); + if (!provider) { + return {}; + } + return provider.loadSecrets({ customPath: secretPath }); + }); +} diff --git a/libs/common/src/utils/ttl-cache.util.ts b/libs/common/src/utils/ttl-cache.util.ts new file mode 100644 index 000000000..5574ea441 --- /dev/null +++ b/libs/common/src/utils/ttl-cache.util.ts @@ -0,0 +1,38 @@ +export class TtlCache { + private value: T | null = null; + private timer: ReturnType | null = null; + private readonly ttlMs: number; + + constructor(ttlMs: number) { + this.ttlMs = ttlMs; + } + + async get(fetchFn: () => Promise): Promise { + if (null !== this.value) { + this.refreshTimer(); + return this.value; + } + + this.value = await fetchFn(); + this.refreshTimer(); + return this.value; + } + + clear(): void { + this.value = null; + if (this.timer) { + clearTimeout(this.timer); + this.timer = null; + } + } + + private refreshTimer(): void { + if (this.timer) { + clearTimeout(this.timer); + } + this.timer = setTimeout(() => { + this.clear(); + }, this.ttlMs); + this.timer.unref(); + } +} diff --git a/libs/config/src/index.ts b/libs/config/src/index.ts index 8d518dbf6..e5e70bc39 100644 --- a/libs/config/src/index.ts +++ b/libs/config/src/index.ts @@ -1,3 +1,4 @@ export * from './config.service'; export * from './config.module'; -export * from './global-config.module'; \ No newline at end of file +export * from './global-config.module'; +export { loadConfigSecrets } from './secret-storage/secrets-loader'; diff --git a/libs/config/src/secret-storage/openbao.provider.ts b/libs/config/src/secret-storage/openbao.provider.ts new file mode 100644 index 000000000..2bffbe7fd --- /dev/null +++ b/libs/config/src/secret-storage/openbao.provider.ts @@ -0,0 +1,97 @@ +import { CommonConstants } from '@credebl/common/common.constant'; +import { Logger } from '@nestjs/common'; +import { SecretProvider } from './secret-provider.interface'; + +async function fetchWithTimeout(url: string, options: RequestInit, timeoutMs: number): Promise { + const controller = new AbortController(); + const timeoutId = setTimeout(() => controller.abort(), timeoutMs); + try { + const response = await fetch(url, { ...options, signal: controller.signal }); + return response; + } finally { + clearTimeout(timeoutId); + } +} + +export class OpenBaoProvider implements SecretProvider { + readonly name = 'OpenBao'; + private readonly logger = new Logger(OpenBaoProvider.name); + + isEnabled(): boolean { + return 'true' === process.env.ENABLE_BAO?.trim()?.toLowerCase(); + } + + async loadSecrets(options?: { customPath?: string }): Promise> { + const baoUrl = process.env.BAO_URL; + const secretPath = options?.customPath || process.env.BAO_SECRET_PATH; + const roleId = process.env.BAO_ROLE_ID; + const secretId = process.env.BAO_SECRET_ID; + if (!baoUrl || !secretPath || !roleId || !secretId) { + throw new Error('BAO_URL, BAO_SECRET_PATH, BAO_ROLE_ID, and BAO_SECRET_ID must be set.'); + } + this.logger.log(`Fetching secrets from ${baoUrl}/v1/${secretPath}`); + this.logger.log(`Authenticating with AppRole at ${baoUrl}/v1/auth/approle/login`); + // --- Authentication --- + let authResponse: Response; + try { + authResponse = await fetchWithTimeout( + `${baoUrl}/v1/auth/approle/login`, + { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + // eslint-disable-next-line camelcase + body: JSON.stringify({ role_id: roleId, secret_id: secretId }) + }, + CommonConstants.OPENBAO_REQUEST_TIMEOUT + ); + } catch (error) { + if (error instanceof DOMException && 'AbortError' === error.name) { + throw new Error('OpenBao authentication request timed out.'); + } + throw error; + } + if (!authResponse.ok) { + throw new Error(`Authentication failed: Status ${authResponse.status}`); + } + + const authData = await authResponse.json(); + const baoToken = authData.auth?.client_token; + + if (!baoToken) { + throw new Error('Failed to retrieve client token from OpenBao.'); + } + this.logger.log(`Fetching secrets from ${baoUrl}/v1/${secretPath}`); + // --- Fetch Secrets --- + let response: Response; + try { + response = await fetchWithTimeout( + `${baoUrl}/v1/${secretPath}`, + { + method: 'GET', + headers: { + 'X-Vault-Token': baoToken, + 'Content-Type': 'application/json' + } + }, + CommonConstants.OPENBAO_REQUEST_TIMEOUT + ); + } catch (error) { + if (error instanceof DOMException && 'AbortError' === error.name) { + throw new Error('OpenBao secrets fetch request timed out.'); + } + throw error; + } + if (!response.ok) { + throw new Error(`Fetch failed: Status ${response.status}`); + } + + const result = await response.json(); + const secrets = result.data?.data; + this.logger.log('Successfully fetched secrets from OpenBao'); + if (!secrets || 'object' !== typeof secrets || Array.isArray(secrets)) { + throw new Error('Unexpected secrets payload structure.'); + } + + return secrets as Record; + } +} diff --git a/libs/config/src/secret-storage/secret-provider.interface.ts b/libs/config/src/secret-storage/secret-provider.interface.ts new file mode 100644 index 000000000..f982c868a --- /dev/null +++ b/libs/config/src/secret-storage/secret-provider.interface.ts @@ -0,0 +1,13 @@ +export interface SecretProvider { + /** + * A human-readable name used for logging purposes (e.g., 'AWS Secrets Manager') + */ + name: string; + + /** + * Fetches the secrets from the external service and returns them + * as a flat key-value object of strings. + * * @returns A promise resolving to Record + */ + loadSecrets(options?: Record): Promise>; +} diff --git a/libs/config/src/secret-storage/secrets-loader.ts b/libs/config/src/secret-storage/secrets-loader.ts new file mode 100644 index 000000000..8c7d6c23b --- /dev/null +++ b/libs/config/src/secret-storage/secrets-loader.ts @@ -0,0 +1,66 @@ +import { Logger } from '@nestjs/common'; +import { OpenBaoProvider } from './openbao.provider'; +import { SecretProvider } from './secret-provider.interface'; + +const FORBIDDEN_KEYS = new Set(['__proto__', 'constructor', 'prototype']); +const logger = new Logger('SecretsLoader'); + +/** + * Factory function to get the requested secret provider + */ +export function getSecretProvider(providerType: string): SecretProvider | null { + switch (providerType.toLowerCase()) { + case 'openbao': + return new OpenBaoProvider(); + + default: + return null; + } +} + +export async function loadConfigSecrets(): Promise { + if ('true' !== process.env.ENABLE_BAO?.trim()?.toLowerCase()) { + logger.log('OpenBao secrets management is disabled. Skipping remote secrets fetching.'); + return; + } + const providerType = process.env.SECRETS_PROVIDER?.trim(); + + if (!providerType) { + logger.log('SECRETS_PROVIDER not set. Skipping remote secrets fetching.'); + return; + } + + const provider = getSecretProvider(providerType); + + if (!provider) { + logger.warn( + `⚠️ Unsupported SECRETS_PROVIDER value "${providerType}". Falling back to local environment variables.` + ); + return; + } + + logger.log(`Secrets management enabled via [${provider.name}]. Fetching...`); + + try { + const secrets = await provider.loadSecrets(); + + for (const [key, value] of Object.entries(secrets)) { + if (FORBIDDEN_KEYS.has(key)) { + continue; + } + + Object.defineProperty(process.env, key, { + value: String(value), + enumerable: true, + configurable: true, + writable: true + }); + } + + logger.log(`Successfully injected secrets from ${provider.name} into process.env`); + } catch (error) { + const errorMessage = error instanceof Error ? error.message : String(error); + logger.error(`Critical Lifecycle Boot Failure (${provider.name}): ${errorMessage}`); + logger.error(`Failed to load secrets from ${provider.name}`); + } +} diff --git a/libs/enum/src/enum.ts b/libs/enum/src/enum.ts index e0ec32df2..5dab5c162 100755 --- a/libs/enum/src/enum.ts +++ b/libs/enum/src/enum.ts @@ -373,7 +373,8 @@ export enum X509ExtendedKeyUsage { export enum CredentialFormat { SdJwtVc = 'dc+sd-jwt', Mdoc = 'mso_mdoc', - JwtVcJsonLd = 'jwt_vc_json-ld' + JwtVcJsonLd = 'jwt_vc_json-ld', + LdpVc = 'ldp_vc' } export enum AttributeType { diff --git a/libs/storage/src/providers/base-s3-storage.provider.ts b/libs/storage/src/providers/base-s3-storage.provider.ts index 4403130d3..fbb55b9b3 100644 --- a/libs/storage/src/providers/base-s3-storage.provider.ts +++ b/libs/storage/src/providers/base-s3-storage.provider.ts @@ -6,20 +6,32 @@ import { RpcException } from '@nestjs/microservices'; import { S3 } from 'aws-sdk'; import { promisify } from 'node:util'; -export abstract class BaseS3StorageService implements IStorageService { - protected s3: S3; - protected s4: S3; - protected s3StoreObject: S3; +function extToMimeType(ext: string): string { + const mime: Record = { + png: 'image/png', + jpg: 'image/jpeg', + jpeg: 'image/jpeg', + gif: 'image/gif', + webp: 'image/webp', + svg: 'image/svg+xml', + bmp: 'image/bmp', + pdf: 'application/pdf', + csv: 'text/csv', + json: 'application/json', + txt: 'text/plain', + html: 'text/html', + xml: 'application/xml', + zip: 'application/zip', + doc: 'application/msword', + docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' + }; + return mime[ext.toLowerCase()] ?? 'application/octet-stream'; +} - constructor( - s3Config: Record, - s4Config: Record, - storeObjectConfig: Record - ) { - this.s3 = new S3(s3Config); - this.s4 = new S3(s4Config); - this.s3StoreObject = new S3(storeObjectConfig); - } +export abstract class BaseS3StorageService implements IStorageService { + protected abstract getS3Client(): Promise; + protected abstract getPublicS3Client(): Promise; + protected abstract getStoreObjectS3Client(): Promise; abstract getPublicUrl(bucketName: string, fileKey: string): string; @@ -31,8 +43,9 @@ export abstract class BaseS3StorageService implements IStorageService { encoding: string, pathAWS: string = '' ): Promise { + const s4 = await this.getPublicS3Client(); const timestamp = Date.now(); - const putObjectAsync = promisify(this.s4.putObject).bind(this.s4); + const putObjectAsync = promisify(s4.putObject).bind(s4); const fileKey = `${pathAWS}/${encodeURIComponent(filename)}-${timestamp}.${ext}`; try { await putObjectAsync({ @@ -40,7 +53,7 @@ export abstract class BaseS3StorageService implements IStorageService { Key: `${pathAWS}/${encodeURIComponent(filename)}-${timestamp}.${ext}`, Body: fileBuffer, ContentEncoding: encoding, - ContentType: `image/png` + ContentType: extToMimeType(ext) }); return this.getPublicUrl(bucketName, fileKey); } catch (error) { @@ -49,6 +62,7 @@ export abstract class BaseS3StorageService implements IStorageService { } async uploadCsvFile(key: string, body: unknown): Promise { + const s3 = await this.getS3Client(); let data: string; if ('string' === typeof body) { data = body; @@ -64,37 +78,40 @@ export abstract class BaseS3StorageService implements IStorageService { Body: data }; try { - await this.s3.upload(params).promise(); + await s3.upload(params).promise(); } catch (error) { throw new RpcException(error.response ? error.response : error); } } async getFile(key: string): Promise { + const s3 = await this.getS3Client(); const params: AWS.S3.GetObjectRequest = { Bucket: process.env.FILE_SHARING_BUCKET, Key: key }; try { - return this.s3.getObject(params).promise(); + return s3.getObject(params).promise(); } catch (error) { throw new RpcException(error.response ? error.response : error); } } async deleteFile(key: string): Promise { + const s3 = await this.getS3Client(); const params: AWS.S3.DeleteObjectRequest = { Bucket: process.env.FILE_SHARING_BUCKET, Key: key }; try { - await this.s3.deleteObject(params).promise(); + await s3.deleteObject(params).promise(); } catch (error) { throw new RpcException(error.response ? error.response : error); } } async storeObject(persistent: boolean, key: string, body: unknown): Promise { + const s3StoreObject = await this.getStoreObjectS3Client(); const objKey: string = persistent.valueOf() ? `persist/${key}` : `default/${key}`; const buf = Buffer.from(JSON.stringify(body)); const params: AWS.S3.PutObjectRequest = { @@ -106,7 +123,7 @@ export abstract class BaseS3StorageService implements IStorageService { }; try { - return await this.s3StoreObject.upload(params).promise(); + return await s3StoreObject.upload(params).promise(); } catch (error) { throw new RpcException(error.response ? error.response : error); } diff --git a/libs/storage/src/providers/rustfs-storage.provider.ts b/libs/storage/src/providers/rustfs-storage.provider.ts index c90287b95..9dee2d144 100644 --- a/libs/storage/src/providers/rustfs-storage.provider.ts +++ b/libs/storage/src/providers/rustfs-storage.provider.ts @@ -1,27 +1,30 @@ import { BaseS3StorageService } from './base-s3-storage.provider'; import { Injectable } from '@nestjs/common'; +import { S3 } from 'aws-sdk'; @Injectable() export class RustFsStorageService extends BaseS3StorageService { - constructor() { - const endpoint = process.env.RUSTFS_ENDPOINT || 'http://localhost:9000'; + private readonly endpoint = process.env.RUSTFS_ENDPOINT || 'http://localhost:9000'; + private readonly baseConfig = { + accessKeyId: process.env.RUSTFS_ACCESS_KEY_ID, + secretAccessKey: process.env.RUSTFS_SECRET_ACCESS_KEY, + endpoint: this.endpoint, + s3ForcePathStyle: true + }; - const baseConfig = { - accessKeyId: process.env.RUSTFS_ACCESS_KEY_ID, - secretAccessKey: process.env.RUSTFS_SECRET_ACCESS_KEY, - endpoint, - s3ForcePathStyle: true - }; + protected async getS3Client(): Promise { + return new S3({ ...this.baseConfig, region: process.env.AWS_REGION }); + } - const s3Config = { ...baseConfig, region: process.env.AWS_REGION }; - const s4Config = { ...baseConfig, region: process.env.AWS_PUBLIC_REGION }; - const storeObjectConfig = { ...baseConfig, region: process.env.AWS_S3_STOREOBJECT_REGION }; + protected async getPublicS3Client(): Promise { + return new S3({ ...this.baseConfig, region: process.env.AWS_PUBLIC_REGION }); + } - super(s3Config, s4Config, storeObjectConfig); + protected async getStoreObjectS3Client(): Promise { + return new S3({ ...this.baseConfig, region: process.env.AWS_S3_STOREOBJECT_REGION }); } getPublicUrl(bucketName: string, fileKey: string): string { - const endpoint = process.env.RUSTFS_ENDPOINT || 'http://localhost:9000'; - return `${endpoint}/${bucketName}/${fileKey}`; + return `${this.endpoint}/${bucketName}/${fileKey}`; } } diff --git a/libs/storage/src/providers/s3-storage.provider.ts b/libs/storage/src/providers/s3-storage.provider.ts index 546c82bdc..1fba7d5b0 100644 --- a/libs/storage/src/providers/s3-storage.provider.ts +++ b/libs/storage/src/providers/s3-storage.provider.ts @@ -1,28 +1,36 @@ import { BaseS3StorageService } from './base-s3-storage.provider'; +import { CommonConstants } from 'libs/common/src/common.constant'; import { Injectable } from '@nestjs/common'; +import { S3 } from 'aws-sdk'; +import { fetchSecrets } from '@credebl/common/utils/secretLoader.util'; @Injectable() export class S3StorageService extends BaseS3StorageService { - constructor() { - const s3Config = { - accessKeyId: process.env.AWS_ACCESS_KEY, - secretAccessKey: process.env.AWS_SECRET_KEY, + protected async getS3Client(): Promise { + const secrets = await fetchSecrets(CommonConstants.CREDEBL_AWS_KEY_PATH); + return new S3({ + accessKeyId: secrets.AWS_ACCESS_KEY ?? process.env.AWS_ACCESS_KEY, + secretAccessKey: secrets.AWS_SECRET_KEY ?? process.env.AWS_SECRET_KEY, region: process.env.AWS_REGION - }; + }); + } - const s4Config = { - accessKeyId: process.env.AWS_PUBLIC_ACCESS_KEY, - secretAccessKey: process.env.AWS_PUBLIC_SECRET_KEY, + protected async getPublicS3Client(): Promise { + const secrets = await fetchSecrets(CommonConstants.CREDEBL_AWS_KEY_PATH); + return new S3({ + accessKeyId: secrets.AWS_PUBLIC_ACCESS_KEY ?? process.env.AWS_PUBLIC_ACCESS_KEY, + secretAccessKey: secrets.AWS_PUBLIC_SECRET_KEY ?? process.env.AWS_PUBLIC_SECRET_KEY, region: process.env.AWS_PUBLIC_REGION - }; + }); + } - const storeObjectConfig = { - accessKeyId: process.env.AWS_S3_STOREOBJECT_ACCESS_KEY, - secretAccessKey: process.env.AWS_S3_STOREOBJECT_SECRET_KEY, + protected async getStoreObjectS3Client(): Promise { + const secrets = await fetchSecrets(CommonConstants.CREDEBL_AWS_KEY_PATH); + return new S3({ + accessKeyId: secrets.AWS_S3_STOREOBJECT_ACCESS_KEY ?? process.env.AWS_S3_STOREOBJECT_ACCESS_KEY, + secretAccessKey: secrets.AWS_S3_STOREOBJECT_SECRET_KEY ?? process.env.AWS_S3_STOREOBJECT_SECRET_KEY, region: process.env.AWS_S3_STOREOBJECT_REGION - }; - - super(s3Config, s4Config, storeObjectConfig); + }); } getPublicUrl(bucketName: string, fileKey: string): string {