All files / proxy/utils/customer-variables/secrets-manager secrets-manager-variables.ts

86.95% Statements 20/23
100% Branches 7/7
100% Functions 5/5
86.95% Lines 20/23

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72  3x   3x 3x   3x             3x 38x           38x 38x   38x 7x 7x                     124x   124x       124x 102x     22x 22x                       38x 38x               38x      
import { CustomerVariableProvider, CustomerVariableType, CustomerVariableValue } from '../types'
import { SecretsManagerClient } from '@aws-sdk/client-secrets-manager'
import { CloudFrontRequest } from 'aws-lambda'
import { getHeaderValue } from '../../headers'
import { retrieveSecret } from './retrieve-secret'
import { NonNullableObject } from '../../types'
import { DEFAULT_REGION, SECRET_NAME_HEADER_KEY } from '../defaults'
 
interface SecretsInfo {
  secretName: string | null
  secretRegion: string | null
}
 
export class SecretsManagerVariables implements CustomerVariableProvider {
  readonly name = 'SecretsManagerVariables'
 
  private secretsInfo?: SecretsInfo
 
  private readonly secretsManager?: SecretsManagerClient
 
  constructor(private readonly request: CloudFrontRequest) {
    this.readSecretsInfoFromHeaders()
 
    if (SecretsManagerVariables.isValidSecretInfo(this.secretsInfo)) {
      try {
        this.secretsManager = new SecretsManagerClient({ region: this.secretsInfo.secretRegion })
      } catch (error) {
        console.error('Failed to create secrets manager', {
          error,
          secretsInfo: this.secretsInfo,
        })
      }
    }
  }
 
  async getVariable(variable: CustomerVariableType): Promise<CustomerVariableValue> {
    const secretsObject = await this.retrieveSecrets()
 
    return secretsObject?.[variable] ?? null
  }
 
  private async retrieveSecrets() {
    if (!this.secretsManager) {
      return null
    }
 
    try {
      return await retrieveSecret(this.secretsManager, this.secretsInfo!.secretName!)
    } catch (error) {
      console.error('Error retrieving secret from secrets manager', {
        error,
        secretsInfo: this.secretsInfo,
      })
 
      return null
    }
  }
 
  private readSecretsInfoFromHeaders() {
    if (!this.secretsInfo) {
      this.secretsInfo = {
        secretName: getHeaderValue(this.request, SECRET_NAME_HEADER_KEY),
        secretRegion: DEFAULT_REGION,
      }
    }
  }
 
  private static isValidSecretInfo(secretsInfo?: SecretsInfo): secretsInfo is NonNullableObject<SecretsInfo> {
    return Boolean(secretsInfo?.secretRegion && secretsInfo?.secretName)
  }
}