diff --git a/src/lib/db/aws-iam.ts b/src/lib/db/aws-iam.ts new file mode 100644 index 0000000000..143c4d8ac0 --- /dev/null +++ b/src/lib/db/aws-iam.ts @@ -0,0 +1,31 @@ +import { Signer } from '@aws-sdk/rds-signer'; +import type { IDBOption } from '../types/option.js'; + +type PasswordResolver = () => Promise; + +export const getDBPasswordResolver = (db: IDBOption): PasswordResolver => { + if (db.awsIamAuth) { + if (!db.awsRegion) + throw new Error( + 'AWS_REGION is required when DATABASE_AWS_IAM=true', + ); + + const signer = new Signer({ + region: db.awsRegion, + hostname: db.host, + port: db.port, + username: db.user, + }); + return async () => { + console.log('[AWS RDS SIGNER] Getting token...'); + const token = await signer.getAuthToken(); + console.log(`[AWS RDS SIGNER] Got token: ${token}`); + return token; + }; + } + + return async () => db.password; +}; + +export const getDBPassword = (db: IDBOption): Promise => + getDBPasswordResolver(db)(); diff --git a/src/lib/db/db-pool.ts b/src/lib/db/db-pool.ts index 2321d65285..92b7058354 100644 --- a/src/lib/db/db-pool.ts +++ b/src/lib/db/db-pool.ts @@ -2,8 +2,7 @@ import type { Knex } from 'knex'; import knexpkg from 'knex'; const { knex } = knexpkg; import type { IUnleashConfig } from '../types/option.js'; - -import { Signer } from '@aws-sdk/rds-signer'; +import { getDBPasswordResolver } from './aws-iam.js'; export function createDb({ db, @@ -11,53 +10,19 @@ export function createDb({ }: Pick): Knex { const logger = getLogger('db-pool.js'); - const { - host, - port, - user, - database, - ssl, - applicationName, - password, - awsIamAuth, - awsRegion, - pool, - } = db; - - let resolvedPassword: string | (() => Promise) | undefined = - password; - - if (awsIamAuth) { - if (!awsRegion) { - throw new Error( - 'AWS_REGION is required when DATABASE_AWS_IAM=true', - ); - } - const signer = new Signer({ - region: awsRegion, - hostname: host, - port, - username: user, - }); - - resolvedPassword = async () => signer.getAuthToken(); - } - - const connection = { - host, - port, - user, - database, - ssl, - application_name: applicationName, - password: resolvedPassword, - }; + logger.info( + `createDb: iam=${Boolean(db.awsIamAuth)} host=${db.host} port=${db.port} db=${db.database} user=${db.user} ssl=${Boolean(db.ssl)}`, + ); return knex({ client: 'pg', version: db.version, - connection, - pool, + connection: { + ...db, + application_name: db.applicationName, + password: getDBPasswordResolver(db), + }, + pool: db.pool, searchPath: db.schema, asyncStackTraces: true, log: { diff --git a/src/lib/types/option.ts b/src/lib/types/option.ts index 4d1ad8bcbf..d87a368665 100644 --- a/src/lib/types/option.ts +++ b/src/lib/types/option.ts @@ -20,7 +20,7 @@ export interface ISSLOption { export interface IDBOption { user: string; - password?: string; + password: string; host: string; port: number; database: string;