#How to use ConfigModule for loading secrets asynchronously?

8 messages · Page 1 of 1 (latest)

silver rose
#

I read in the docs that the ConfigModule is used to load environment variables from a .env file. However, I was wondering if I can use it to either load environment variables if NODE_ENV is 'dev' or load secrets asynchronously from a cloud provider service, such as AWS SecretsManager.

In fact, I already tried this by making an asynchronous method that loads the secrets. Then, I made a custom module where I kind of override the ConfigService as such:

export const getConfig = async () => {
  if (process.env.NODE_ENV === 'dev') {
    Logger.log('Environment variables', configDev);

    return new ConfigService(configDev);
  }

  const secrets = loadSecrets(); // loading secrets from SecretsManager

  return new ConfigService(secrets);
};

@Module({
  providers: [
    {
      provide: ConfigService,
      useFactory: getConfig,
    },
  ],
  exports: [ConfigService],
})
export class CustomConfigModule {}

I am importing this module in the top-level AppModule and in any other module that needs access to those secrets. The problem now is that if I try to load environment variables from a .env file when running the application in the DEV environment it does not work anymore (mostly because I do not have the ConfigModule declared anywhere anymore).

Has anyone ever tried this? Or does anyone have any idea on how to solve this? Any help is greatly appreciated!

dusky lintel
#

You may want to use the load option in ConfigModule.forRoot. Here you can provide functions (sync or async) that pass config values to ConfigService:

const getConfig = async () => {
  if (process.env.NODE_ENV === 'dev') {
    Logger.log('Environment variables', configDev);
    return configDev;
  }
  
  const secrets = await loadSecrets();
  return secrets;
};

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [getConfig],
    }),
  ],
})
export class AppModule {}
silver rose
#

@dusky lintel I tried it this way but I would get only undefined values when trying to retrieve the environment variables from the .env file.

dusky lintel
#

Do you retrieve the configDev directly from .env or do you mean NODE_ENV is undefined?

dusky lintel
#

because the .env should always overwrite the loaded config if not disabled

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [getConfig],
      ignoreEnvFile: process.env.NODE_ENV === 'prod',
    }),
  ],
})
export class AppModule {}

this would default to .env variables in NODE_ENV != prod

silver rose
#

If I import this code above directly into the load function. For example:

import configDev from './utils/config.dev';

@Module({
  imports: [
    ConfigModule.forRoot({
      load: [configDev]
    })
  ]
})

Then this works. And my guess is because it is not an asynchronous operation like getConfig.