在 NestJS 中使用 AWS SSM Parameter Store 进行 TypeORM 配置

Using AWS SSM Parameter Store for TypeORM config in NestJS

我在 AWS Lambda 上有一个简单的 NestJS 应用程序 运行。我正在使用 AWS SSM Parameter Store 来保存数据库连接信息和凭证。当我导入 TypeORM 时,我使用已经从商店检索到的参数。

现在我只是在导入了 TypeORM 的 AppModule 中检索参数。我确定有更好的方法可以做到这一点,但我不确定它会是什么。自定义提供商?某种设置服务?我不认为我当前的解决方案非常可靠,并且没有很好的错误处理。

唯一的要求是我在运行时而不是在构建或部署时检索 SSM 参数。任何建议

这是我目前正在做的事情:

import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { TypeOrmModule } from '@nestjs/typeorm';
import { ThingyModule } from 'thingy/thingy.module';
import * as awsParamStore from 'aws-param-store';

const ssmParams = awsParamStore.getParametersByPathSync('/myapp/prod', {region: (process.env['AWS_DEFAULT_REGION'] ? process.env['AWS_DEFAULT_REGION'] : 'us-east-2')}); 
const ssmMap = ssmParams.reduce(function(map, obj) {
  map[obj.Name] = obj.Value;
  return map;
}, {});

@Module({
  imports: [
    TypeOrmModule.forRoot({
      type: 'postgres',
      host: ssmMap['/myapp/prod/db/host'],
      port: 5432,
      username: ssmMap['/myapp/prod/db/username'],
      password: ssmMap['/myapp/prod/db/password'],
      database: 'postgres',
      entities: [__dirname + '/**/*.entity{.ts,.js}'],
      synchronize: true,
    }),
    ThingyModule
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

之前已使用 AWS CLI 创建参数:

// aws ssm put-parameter --type String --name /myapp/prod/db/username --value postgres --region us-east-2
// aws ssm put-parameter --type String --name /myapp/prod/db/password --value supRCkrit --region us-east-2
// aws ssm put-parameter --type String --name /myapp/prod/db/host --value localhost --region us-east-2

我们可以使用异步提供程序来做到这一点。

来自工作项目的示例:

创建异步提供程序:

import * as AWS from 'aws-sdk';
import { Parameter } from 'aws-sdk/clients/ssm';

export const ssmProvider = {
  provide: 'AWS_SSM',
  useFactory: async (): Promise<Parameter[]> => {
    const ssmClient = new AWS.SSM({
      endpoint: 'endpoint',
      region: 'us-west-2',
    });
    const result = await ssmClient
      .getParametersByPath({
        Path: '/ssm/path',
        Recursive: true,
      })
      .promise();
    return result?.Parameters;
  },
};

然后我们可以使用此提供程序来注入值。

例如在配置服务中注入 AWS SSM 参数:

export class ConfigModule {
  static register(options: ConfigModuleOptions): DynamicModule {
    return {
      global: true,
      module: ConfigModule,
      providers: [
        ssmProvider,
        {
          provide: CONFIG_OPTIONS,
          useValue: options,
        },
        ConfigService,
      ],
      exports: [ConfigService],
    };
  }
}

并且在配置服务构造函数中:

constructor(
    @Inject(CONFIG_OPTIONS) options: ConfigOptions,
    @Inject('AWS_SSM') awsParameters: Parameter[],
  ) {}

编辑:提供在应用程序启动时加载 aws 参数存储参数的服务的 NPM 包:

param-store-service