简体   繁体   中英

Access AWS Secrets Manager secret from AWS Lambda with JS

I created a secret in the AWS Secrets Manager. Trying the example code I got from the AWS Secret manager page does not yield any result. Below is the example code dumbly copied into a javascript AWS Lambda function.

In order to make it work, I had to add await at the beginning and .promise() to the API call.

Following the instruction on AWS Promises I only would need to add the await and promise() instead of using a callback function:

The AWS.Request.promise method provides a way to call a service operation and manage asynchronous flow instead of using callbacks

QUESTION: The example code already contains a callback, why do I need to add await and prommise ? What did I miss?


Example AWS Lambda function code:

exports.handler = async function(event, context, callback) {
    // Use this code snippet in your app.
    // If you need more information about configurations or implementing the sample code, visit the AWS docs:
    // https://aws.amazon.com/developers/getting-started/nodejs/

    // Load the AWS SDK
    var AWS = require('aws-sdk'),
        region = "eu-west-1",
        secretName = "MY_SUPER_SECRET",
        secret,
        decodedBinarySecret;

    // Create a Secrets Manager client
    var client = new AWS.SecretsManager({
        region: region
    });

    // In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
    // See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
    // We rethrow the exception by default.

    // ---> THIS await IS NEEDED TO MAKE IT WORK TOGETHER WITH THE promise() AT THE END
    await client.getSecretValue({SecretId: "MY_SUPER_SECRET"}, function(err, data) {
        if (err) {
            if (err.code === 'DecryptionFailureException')
                // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw err;
            else if (err.code === 'InternalServiceErrorException')
                // An error occurred on the server side.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw err;
            else if (err.code === 'InvalidParameterException')
                // You provided an invalid value for a parameter.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw err;
            else if (err.code === 'InvalidRequestException')
                // You provided a parameter value that is not valid for the current state of the resource.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw err;
            else if (err.code === 'ResourceNotFoundException')
                // We can't find the resource that you asked for.
                // Deal with the exception here, and/or rethrow at your discretion.
                throw err;
        }
        else {
            // Decrypts secret using the associated KMS CMK.
            // Depending on whether the secret is a string or binary, one of these fields will be populated.
            if ('SecretString' in data) {
                secret = data.SecretString;
                console.warn("secret")
                console.warn(secret)
            } else {
                let buff = new Buffer(data.SecretBinary, 'base64');
                decodedBinarySecret = buff.toString('ascii');
                console.warn("decodedBinarySecret")
                console.warn(decodedBinarySecret)
            }
        }
    
    // Your code goes here. 

    // ---> THIS promise IS NEEDED TO MAKE IT WORK TOGETHER WITH THE await AT THE BEGINING
    }).promise();
)    

If you're using .promise() on the aws-call you should not pass it a callback (see this for more details). Instead you handle the response (or error) after this promise has been fulfilled.

I would rewrite this as:

function getAwsSecretPromise() {
    return client.getSecretValue({
        SecretId: "MY_SUPER_SECRET"
    }).promise();
}

const rethrowErrorCodes = ['DecryptionFailureException', 'InternalServiceErrorException', 'InvalidParameterException', 'InvalidRequestException', 'ResourceNotFoundException']

exports.handler = async function (event, context, callback) {

    try {
        const data = await getAwsSecretPromise();
        if ('SecretString' in data) {
            secret = data.SecretString;
            console.warn("secret")
            console.warn(secret)
        } else {
            let buff = new Buffer(data.SecretBinary, 'base64');
            decodedBinarySecret = buff.toString('ascii');
            console.warn("decodedBinarySecret")
            console.warn(decodedBinarySecret)
        }

      // todo: do something with secret?
    } catch (err) {
        if (rethrowErrorCodes.some(errorCode => err.code === errorCode) {
            throw err;
        }            
        // todo: handle other errors?    
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM