DEV Community

Cover image for NestJS Configuration Secrets Made Easy with configify
Tom Melo
Tom Melo

Posted on • Edited on

NestJS Configuration Secrets Made Easy with configify

If you have been working with NestJS you are probably familiar with NestJS config module.

The config module handles multi environment configurations and allows users to extend the module by providing customized configurations(e.g.: loading secrets from AWS Secrets Manager).

Another module that attempts to make it easier to deal with configurations and secrets is the configify module. This module offers a decorator based config mapping and an out of the box integration with AWS Secrets Manager and Parameter Store.

In this post we will be taking a look on how to use the configify module.

Setup

Add the configify dependency to your project:

npm install --save @itgorillaz/configify
Enter fullscreen mode Exit fullscreen mode

You can then import the module in your application module:

@Module({
  imports: [ConfigifyModule.forRootAsync()],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}
Enter fullscreen mode Exit fullscreen mode

Mapping Configuration Files

By default, configify will lookup for a .env or an application.yml file located in the root folder of the project.

So let's define our .env file:

# database configuration
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=admin
DB_PASSWORD=${AWS_SECRETS_MANAGER_DB_PASSWORD}

# api client configuration
API_CLIENT_ID=1234
API_CLIENT_SECRET=${AWS_PARAMETER_STORE_API_CLIENT_SECRET}

# aws secrets manager
AWS_SECRETS_MANAGER_DB_PASSWORD=my-secret-id

# aws parameter store
AWS_PARAMETER_STORE_API_CLIENT_SECRET=/secret/name
Enter fullscreen mode Exit fullscreen mode

You can then define classes that will be mapped by the module according to your configuration file:

@Configuration()
export class DatabaseConfiguration {
  @Value('DB_HOST')
  host: string;

  @Value('DB_PORT', {
    parse: (value: any) => parseInt(value)
  })
  port: number;

  @Value('DB_USERNAME')
  username: string;

  @Value('DB_PASSWORD')
  password: string;
}
Enter fullscreen mode Exit fullscreen mode
@Configuration()
export class ApiClientConfiguration {
  @Value('API_CLIENT_ID')
  host: string;

  @Value('API_CLIENT_SECRET')
  username: string;
}
Enter fullscreen mode Exit fullscreen mode

By default, every environment variable prefixed with AWS_SECRETS_MANAGER, AWS_PARAMETER_STORE, aws-secrets-manager or aws-parameter-store will be considered a special attribute and the module will attempt to resolve it's remote value on AWS.

Dependency Injection

The module will make the instances of your configuration classes globally available to the application, so in order to use it you just need to declare the dependency in the class constructor:

export class AppService {
  private readonly LOGGER = new Logger(AppService.name);

  constructor(
    private readonly dbConfig: DatabaseConfiguration,
    private readonly apiConfig: ApiClientConfiguration,
  ) {
    this.LOGGER.log(JSON.stringify(dbConfig));
    this.LOGGER.log(JSON.stringify(apiConfig));
  }

}
Enter fullscreen mode Exit fullscreen mode

Module Options

You can provide your own instance of AWS Secrets Manager and Parameter Store client classes as well as override some other options offered by the module.

Check the module's repository for a detailed documentation.

Top comments (0)