如何将 AWS Secret Manager 与 Nodejs Lambda 结合使用



我试图包装示例代码片段以在函数中获取机密,然后调用它,但它似乎不起作用。我怀疑我正在异步调用它,我需要同步调用它?我只想要一个可以调用的函数来获取机密值并将其放入变量中。

这是函数:

//outside exports.handler = (event, context, callback) => {
function getSecret(secretName) {
// Load the AWS SDK
var AWS = require('aws-sdk'),
region = process.env.AWS_REGION,
secretName = secretName,
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.
client.getSecretValue({SecretId: secretName}, 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) {
return data.SecretString;
} else {
let buff = new Buffer(data.SecretBinary, 'base64');
return buff.toString('ascii');
}
}
});
}

那我叫它

// inside exports.handler = (event, context, callback) => {
var secret = getSecret('mySecret')
console.log('mysecret: ' + secret )

秘密变量始终undefined

编辑:异步仅适用于承诺,所以我不得不使我的函数异步并返回一个承诺:

async function mySecrets(secretName) {
// Load the AWS SDK
var AWS = require('aws-sdk'),
region = process.env.AWS_REGION,
secretName = secretName,
secret,
decodedBinarySecret;
// Create a Secrets Manager client
var client = new AWS.SecretsManager({
region: region
});
return new Promise((resolve,reject)=>{
client.getSecretValue({SecretId: secretName}, function(err, data) {
// 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.
if (err) {
reject(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) {
resolve(data.SecretString);
} else {
let buff = new Buffer(data.SecretBinary, 'base64');
resolve(buff.toString('ascii'));
}
}
});
});
}
.....
// inside handler
exports.handler = async (event) => {
....
var value = await mySecrets('mysecret')

您需要等待异步调用完成。

在您的主处理程序中,您将拥有类似以下内容的内容:

// inside your main handler
exports.handler =  async function(event, context) {
var secret = await getSecret('mySecret')
console.log('mysecret: ' + secret )
return ...
}

有一种更简单的方法可以从秘密管理器读取它。

let secretManager = new SecretsManager({ region: 'region-name' });
const data = await secretManager.getSecretValue({ SecretId: 'secretid' }).promise();
console.log(`data is: ${JSON.stringify(data)}`);

如果有人需要解决此问题,这是一个更简单的示例:

const result = await client
.getSecretValue({
SecretId: AWSConfig.secretName,
})
.promise();
const parsedResult = JSON.parse(result.SecretString);

aws-sdk提供了两种从 API 获取值的方法。您可以使用本机回调机制(如上所示),也可以改为在调用链末端使用.promise()将 API 调用转换为其 promise 等效项。

例如

const data = await secretManager.getSecret({ SecretId }).promise();

如果你正在使用await那么你的函数需要像所有调用它的函数一样async,除非他们选择使用 Promise 的then/catch等。

我创建了一个同步解决方案,你可以在这里找到:https://github.com/jwerre/secrets

使用此包,您可以在特定命名空间中加载所有机密,如下所示:

const config = require('@jwerre/secrets').configSync({
region: 'us-east-1',
env: 'production',
namespace: 'my-namespace',
});

这将检索您的所有秘密,这些秘密可能不完全是您想要的。如果你想要一个秘密,你可以这样做:

const config = require('@jwerre/secrets').secretSync({
region: 'us-west-2'
id: '/my-co/apis/'
});

更好的方法是在异步 lambda 函数中执行此操作

示例key:val => password:rootPassword

const secret = await secretClient.getSecretValue({SecretId: 'SecretKeyName'}).promise().then((data) => {
return JSON.parse(data.SecretString);
})

然后作为secret.password访问它。

注意:环绕try/catch块以自动处理错误。

最新更新