I want to get a secret in my aws L@E function, and in the code I must set a region to my SecretManager instance
// Create a Secrets Manager client
const client = new AWS.SecretsManager({
region: "us-east-1", // mandatory param
});
but I know that SecretManager also has multi-region support so i don’t understand how it work together with the L@E function. how can I know on runtime what is the best region to use? and also what happens if there is a downtime in one region? in addition to caching the secrets via lambda global variables, is it possible also to optimize the SecretManager usage?
I tried using the process.env.AWS_REGION
env variable, but its not supported
In case someone encounters this issue in the future, I got an answer from AWS support. There is no way to tell what is the "best" region to use on runtime via L@E. To protect against region downtime, the best practice is to try accessing a SecretManager instance from a primary region and have a fallback region (where it has been replicated) in case of an error.
const AWS = require('aws-sdk');
const name = "app-api-key";
const primarySecretManager = new AWS.SecretsManager({
region: 'us-east-1',
});
const fallbackSecretManager = new AWS.SecretsManager({
region: "us-east-2",
});
const getSecrets = async () => {
let secrets;
try {
secrets = await getSecretsInternal(primarySecretManager)
} catch (e) {
secrets = await getSecretsInternal(fallbackSecretManager)
}
return secrets
}
const getSecretsInternal = async client => {
return new Promise((resolve, reject) => {
client.getSecretValue({ SecretId: name }, (err, data) => {
if (err) {
switch (err.code) {
case 'DecryptionFailureException':
console.error(`Secrets Manager can't decrypt the protected secret text using the provided KMS key.`)
break
case 'InternalServiceErrorException':
console.error(`An error occurred on the server side.`)
break
case 'InvalidParameterException':
console.error(`You provided an invalid value for a parameter.`)
break
case 'InvalidRequestException':
console.error(`You provided a parameter value that is not valid for the current state of the resource.`)
break
case 'ResourceNotFoundException':
console.error(`We can't find the resource that you asked for.`)
break
}
console.error(err)
reject(err)
return
}
// Decrypts secret using the associated KMS CMK.
// Depending on whether the secret is a string or binary, one of these fields will be populated.
let secrets;
if ('SecretString' in data) {
secrets = data.SecretString;
} else {
const buff = new Buffer(data.SecretBinary, 'base64');
secrets = buff.toString('ascii');
}
resolve(JSON.parse(secrets))
})
})
}
module.exports = {
getSecrets,
}