CodePark/ questions / Secrets, config & KMS
START PRACTICINGPRACTICE
Backend question · Cloud & AWS › Secrets, config & KMS

How should a NestJS service load secrets and configuration from AWS at runtime? Explain what this provider does and how you would improve it.

{
  provide: "DB_CREDS",
  inject: [SecretsManagerClient],
  useFactory: async (sm: SecretsManagerClient) => {
    const res = await sm.send(new GetSecretValueCommand({
      SecretId: process.env.DB_SECRET_ID,
    }));
    return JSON.parse(res.SecretString!);
  },
}

Load the secret once at startup with an async provider, and make the parsed credentials injectable. An async factory is a provider function that NestJS awaits during bootstrap (app startup) before the app starts.

Why this provider is safe:

  • The secret ID comes from an environment variable. This is fine, because the ID itself is not secret.
  • The SDK client gets its permission from the task role or execution role, so no access keys are needed.
  • Nothing sensitive is baked into the Docker image.

Improvements:

  • Cache the value. Refresh it from time to time, or when authentication fails. Then rotation does not break running tasks.
  • Fail fast with a clear error if the secret is missing.
  • Never log the secret value.
  • Grant secretsmanager:GetSecretValue only on that one secret's ARN (its unique AWS ID). This is least privilege.

On Lambda, fetch the secret outside the handler function and cache it across invocations. Or use the AWS Parameters and Secrets Lambda Extension. Plain config that is not secret can come from environment variables or Parameter Store in the same way.

  • Fetch the secret at startup with an async provider; the secret ID can be an environment variable.
  • Credentials come from the IAM role, not from access keys.
  • Cache and refresh the value so the app keeps working after rotation.
  • Fail fast, never log values, and allow access only to the one secret's ARN.
  • On Lambda, cache outside the handler or use the Parameters and Secrets extension.