如何使用 node.js 和 aws-sdk 从 lambda 访问 aws 参数存储
How to access the aws parameter store from a lambda using node.js and aws-sdk
我创建了一个 lambda 和云形成模板,它授予 lambda 访问参数存储和机密管理器的权限。当我测试 lambda 时,我在 export.handler 函数之外有以下函数:
function getParameterFromStore(param){
let promise = new Promise(function(resolve, reject){
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, function(err, data){
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
} else {
resolve(data);
}
});
});
let parameterResult = promise.then(function(result){
console.log('---- result: '+ JSON.stringify(result));
return result;
});
return parameterResult;
};
servmgr
实例化为 var servmgr = new AWS.SSM();
当我从 export.handler 函数调用此函数时,我这样做:
myFirstParam = { Path : '/myPath/Service/servicesEndpoint'};
let endpointResult = getParameterFromStore(myFirstParam);
在 lambda 中,我让函数检索在 export.handler 函数 bt 之外定义的参数,这些参数被包裹在一个 promise 中。
当我 run/test 这个 lambda 返回的对象总是未定义的...我得到 Parameters[] 但没有值。
2019-02-20T21:42:41.340Z 2684fe88-d552-4560-a477-6761f2de6717 ++ /myPath/Service/serviceEndpoint
2019-02-20T21:42:41.452Z 2684fe88-d552-4560-a477-6761f2de6717 ---- result: {"Parameters":[]}
如何在 运行 时将参数值返回给 lambda?
更新
基于 Thales 的 suggestion/answer,我将 lambda 简化为:
const getParameterFromStoreAsync = (param) => {
return new Promise((resolve, reject) => {
servmgr.getParametersByPath(param, (err, data) => {
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
}
return resolve(data);
});
});
};
exports.handler = async(event, ctx, callback) => {
console.log('INFO[lambda]: Event: [' + JSON.stringify(event, null, 2) + ']');
console.log('this is the event' + JSON.stringify(event));
sfdcEndPointParam = { Path : '/PartnerBanking/Service/SfdcEndpoint'};
let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);
console.log('### endpoint path: ' + JSON.stringify(myendpoint));
done = ()=>{}
callback(null, done());
};
我仍然看到在我的测试中返回了一个空数组:
### endpoint path: {"Parameters":[]}
我也将函数移到了回调中
exports.handler = (event,ctx, callback){
done = async()=>{
console.log('this is the event' + JSON.stringify(event));
sfdcEndPointParam = { Path : '/PartnerBanking/Service/SfdcEndpoint'};
let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);
console.log('### endpoint path: ' + JSON.stringify(myendpoint));}
}
callback(null, done());
相同的结果...空数组。还有什么要尝试的吗?
这是因为你的 getParameterFromStore
return 在你的 then()
代码执行之前,因此 parameterResult
是 undefined
。如果您不想过多更改代码,我会 return 您创建的 Promise,如下所示:
function getParameterFromStore(param){
return new Promise(function(resolve, reject){
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, function(err, data){
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
} else {
resolve(data);
}
});
});
};
最后,在您函数的客户端上,您可以获得如下结果:
const myFirstParam = { Path : '/myPath/Service/servicesEndpoint'}
getParameterFromStore(myFirstParam).then(console.log)
然而,当在 NodeJS 中编码时,我强烈建议您改用 async/await,这样您就可以摆脱 Promise 地狱(在 Promise 之后更改 Promise 以实现某些目标 "synchronously" )
使用 async/await 时,您可以将代码设计为同步的。这是您的示例的重构版本,使用 async/await 以及箭头函数:
const getParameterFromStore = param => {
return new Promise((resolve, reject) => {
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, (err, data) => {
if (err) {
console.log('Error getting parameter: ' + err, err.stack)
return reject(err);
}
return resolve(data);
});
})
}
exports.handler = async (event) => {
const endpointResult = await getParameterFromStore(event.someAttributeFromTheEventThatYouWantToUse)
console.log(endpointResult)
};
编辑:OP 解决了第一个问题后,我自己创建了一个工作示例。事实证明,OP 调用 API 的方式不正确。
这是完整的工作示例:
'use strict';
const AWS = require('aws-sdk')
AWS.config.update({
region: 'us-east-1'
})
const parameterStore = new AWS.SSM()
const getParam = param => {
return new Promise((res, rej) => {
parameterStore.getParameter({
Name: param
}, (err, data) => {
if (err) {
return rej(err)
}
return res(data)
})
})
}
module.exports.get = async (event, context) => {
const param = await getParam('MyTestParameter')
console.log(param);
return {
statusCode: 200,
body: JSON.stringify(param)
};
};
注意 Name
属性,它必须作为对 ServiceManager.getAttribute 方法的 API 调用的一部分提供。
这个属性在官方有说明docs
我自己有 运行 这是 CloudWatch Logs 中的输出:
如您所见,值 return 已成功编辑。
希望对您有所帮助!
如果您的 lambda 部署在 VPC 上,请确保已附加安全组并允许出站流量。它将能够自动访问参数存储。
https://aws.amazon.com/premiumsupport/knowledge-center/lambda-vpc-parameter-store/
一个更简单的解决方案是:
const getParameterFromStore = (params) => servmgr.getParametersByPath(params).promise();
const myFirstParam = { Path : '/myPath/Service'};
getParameterFromStore(myFirstParam).then(console.log);
As you can see, the SDK itself provides utility functinality that you can use depending on your needs to use in an async or syncronious fashion.
希望对您有所帮助。
我创建了一个 lambda 和云形成模板,它授予 lambda 访问参数存储和机密管理器的权限。当我测试 lambda 时,我在 export.handler 函数之外有以下函数:
function getParameterFromStore(param){
let promise = new Promise(function(resolve, reject){
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, function(err, data){
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
} else {
resolve(data);
}
});
});
let parameterResult = promise.then(function(result){
console.log('---- result: '+ JSON.stringify(result));
return result;
});
return parameterResult;
};
servmgr
实例化为 var servmgr = new AWS.SSM();
当我从 export.handler 函数调用此函数时,我这样做:
myFirstParam = { Path : '/myPath/Service/servicesEndpoint'};
let endpointResult = getParameterFromStore(myFirstParam);
在 lambda 中,我让函数检索在 export.handler 函数 bt 之外定义的参数,这些参数被包裹在一个 promise 中。
当我 run/test 这个 lambda 返回的对象总是未定义的...我得到 Parameters[] 但没有值。
2019-02-20T21:42:41.340Z 2684fe88-d552-4560-a477-6761f2de6717 ++ /myPath/Service/serviceEndpoint
2019-02-20T21:42:41.452Z 2684fe88-d552-4560-a477-6761f2de6717 ---- result: {"Parameters":[]}
如何在 运行 时将参数值返回给 lambda?
更新
基于 Thales 的 suggestion/answer,我将 lambda 简化为:
const getParameterFromStoreAsync = (param) => {
return new Promise((resolve, reject) => {
servmgr.getParametersByPath(param, (err, data) => {
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
}
return resolve(data);
});
});
};
exports.handler = async(event, ctx, callback) => {
console.log('INFO[lambda]: Event: [' + JSON.stringify(event, null, 2) + ']');
console.log('this is the event' + JSON.stringify(event));
sfdcEndPointParam = { Path : '/PartnerBanking/Service/SfdcEndpoint'};
let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);
console.log('### endpoint path: ' + JSON.stringify(myendpoint));
done = ()=>{}
callback(null, done());
};
我仍然看到在我的测试中返回了一个空数组:
### endpoint path: {"Parameters":[]}
我也将函数移到了回调中
exports.handler = (event,ctx, callback){
done = async()=>{
console.log('this is the event' + JSON.stringify(event));
sfdcEndPointParam = { Path : '/PartnerBanking/Service/SfdcEndpoint'};
let myendpoint = await getParameterFromStoreAsync(sfdcEndPointParam);
console.log('### endpoint path: ' + JSON.stringify(myendpoint));}
}
callback(null, done());
相同的结果...空数组。还有什么要尝试的吗?
这是因为你的 getParameterFromStore
return 在你的 then()
代码执行之前,因此 parameterResult
是 undefined
。如果您不想过多更改代码,我会 return 您创建的 Promise,如下所示:
function getParameterFromStore(param){
return new Promise(function(resolve, reject){
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, function(err, data){
if(err){
reject(console.log('Error getting parameter: ' + err, err.stack));
} else {
resolve(data);
}
});
});
};
最后,在您函数的客户端上,您可以获得如下结果:
const myFirstParam = { Path : '/myPath/Service/servicesEndpoint'}
getParameterFromStore(myFirstParam).then(console.log)
然而,当在 NodeJS 中编码时,我强烈建议您改用 async/await,这样您就可以摆脱 Promise 地狱(在 Promise 之后更改 Promise 以实现某些目标 "synchronously" )
使用 async/await 时,您可以将代码设计为同步的。这是您的示例的重构版本,使用 async/await 以及箭头函数:
const getParameterFromStore = param => {
return new Promise((resolve, reject) => {
console.log('++ ' + param.Path);
servmgr.getParametersByPath(param, (err, data) => {
if (err) {
console.log('Error getting parameter: ' + err, err.stack)
return reject(err);
}
return resolve(data);
});
})
}
exports.handler = async (event) => {
const endpointResult = await getParameterFromStore(event.someAttributeFromTheEventThatYouWantToUse)
console.log(endpointResult)
};
编辑:OP 解决了第一个问题后,我自己创建了一个工作示例。事实证明,OP 调用 API 的方式不正确。
这是完整的工作示例:
'use strict';
const AWS = require('aws-sdk')
AWS.config.update({
region: 'us-east-1'
})
const parameterStore = new AWS.SSM()
const getParam = param => {
return new Promise((res, rej) => {
parameterStore.getParameter({
Name: param
}, (err, data) => {
if (err) {
return rej(err)
}
return res(data)
})
})
}
module.exports.get = async (event, context) => {
const param = await getParam('MyTestParameter')
console.log(param);
return {
statusCode: 200,
body: JSON.stringify(param)
};
};
注意 Name
属性,它必须作为对 ServiceManager.getAttribute 方法的 API 调用的一部分提供。
这个属性在官方有说明docs
我自己有 运行 这是 CloudWatch Logs 中的输出:
如您所见,值 return 已成功编辑。
希望对您有所帮助!
如果您的 lambda 部署在 VPC 上,请确保已附加安全组并允许出站流量。它将能够自动访问参数存储。
https://aws.amazon.com/premiumsupport/knowledge-center/lambda-vpc-parameter-store/
一个更简单的解决方案是:
const getParameterFromStore = (params) => servmgr.getParametersByPath(params).promise();
const myFirstParam = { Path : '/myPath/Service'};
getParameterFromStore(myFirstParam).then(console.log);
As you can see, the SDK itself provides utility functinality that you can use depending on your needs to use in an async or syncronious fashion.
希望对您有所帮助。