如何使用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){让诺言=新的承诺(function(resolve,reject){console.log('++'+ param.Path);servmgr.getParametersByPath(param,function(err,data){如果(错误){reject(console.log('错误获取参数:'+ err,err.stack));} 别的 {解析(数据);}});});让parameterResult = promise.then(function(result){console.log('----结果:'+ JSON.stringify(result));返回结果;});返回parameterResult;};
servmgr
实例化为 var servmgr = new AWS.SSM();
当我从export.handler函数调用此函数时,我这样做是:
myFirstParam = {路径:'/myPath/Service/servicesEndpoint'};让endpointResult = getParameterFromStore(myFirstParam);
在lambda中,我有一个函数来检索在promise中包装的export.handler函数bt之外定义的参数.
当我运行/测试此lambda时,返回的对象始终是未定义的……我得到Parameters [],但没有值.
<代码> 2019-02-20T21:42:41.340Z 2684fe88-d552-4560-a477-6761f2de6717 ++/myPath/Service/serviceEndpoint2019-02-20T21:42:41.452Z 2684fe88-d552-4560-a477-6761f2de6717 ----结果:{"Parameters":[]}
如何在运行时将参数值返回给lambda?
更新
基于Thales的建议/答案,我将lambda简化为:
const getParameterFromStoreAsync =(param)=>{返回新的Promise((resolve,reject)=> {servmgr.getParametersByPath(param,(err,data)=> {如果(错误){reject(console.log('错误获取参数:'+ err,err.stack));}返回resolve(data);});});};Exports.handler =异步(事件,ctx,回调)=>{console.log('INFO [lambda]:Event:['+ JSON.stringify(event,null,2)+']');console.log('这是事件'+ JSON.stringify(event));sfdcEndPointParam = {路径:'/PartnerBanking/Service/SfdcEndpoint'};让myendpoint =等待getParameterFromStoreAsync(sfdcEndPointParam);console.log('###端点路径:'+ JSON.stringify(myendpoint));完成=()=> {}callback(null,done());};
我仍然看到测试中返回了一个空数组:
###端点路径:{"Parameters":[]}
我也将函数移到了回调中
exports.handler =(event,ctx,callback){完成= async()=> {console.log('这是事件'+ JSON.stringify(event));sfdcEndPointParam = {路径:'/PartnerBanking/Service/SfdcEndpoint'};让myendpoint =等待getParameterFromStoreAsync(sfdcEndPointParam);console.log('###端点路径:'+ JSON.stringify(myendpoint));}}callback(null,done());
相同结果...空数组.还有其他尝试吗?
这是因为您的 getParameterFromStore
在执行 then()
代码之前返回,因此parameterResult
是 undefined
.如果您不想太多更改代码,我将返回您创建的Promise,如下所示:
function getParameterFromStore(param){返回新的Promise(函数(解决,拒绝){console.log('++'+ param.Path);servmgr.getParametersByPath(param,function(err,data){如果(错误){reject(console.log('错误获取参数:'+ err,err.stack));} 别的 {解析(数据);}});});
};
最后,在函数的客户端上,您可以得到如下结果:
const myFirstParam = {路径:'/myPath/Service/servicesEndpoint'}getParameterFromStore(myFirstParam).then(console.log)
但是,在NodeJS中进行编码时,我强烈建议您改用
如您所见,该值已成功返回.
希望这会有所帮助!
I've created a lambda and cloud formation template which grants a lambda access to the parameter store and secrets manager. When I test the lambda I have the following functions outside of the export.handler function:
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
is instantiated as var servmgr = new AWS.SSM();
When I call this function from the export.handler function I do so as:
myFirstParam = { Path : '/myPath/Service/servicesEndpoint'};
let endpointResult = getParameterFromStore(myFirstParam);
In the lambda I have the function retrieve the parameter defined outside of the export.handler function bt wrapped in a promise.
When I run/test this lambda the object returned is always undefined... I get Parameters[] back but no values.
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":[]}
How do you get parameter values returned back to a lambda at run time?
update
based upon the suggestion/answer from Thales I've simplified the lambda to just this:
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());
};
I am still seeing an empty array being returned in my tests:
### endpoint path: {"Parameters":[]}
I've also moved the function into the callback as
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());
Same result ... empty array. Any additional things to try?
This is because your getParameterFromStore
returns before your then()
code is executed, thus parameterResult
is undefined
. If you don't want to change your code too much, I would return the Promise you create, like this:
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);
}
});
});
};
And finally, on your function's client, you can get the result like this:
const myFirstParam = { Path : '/myPath/Service/servicesEndpoint'}
getParameterFromStore(myFirstParam).then(console.log)
When coding in NodeJS, however, I highly recommend you use async/await instead, so you'll be able to escape the Promise Hell (chaninig Promise after Promise in order to achieve something "synchronously")
When using async/await, you can design your code as though it was synchronous. Here's a refactored version of your example, using async/await as well as arrow functions:
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)
};
EDIT: After the OP fixed the first issue, I created a working example on my own. It turned out that the way the OP was invoking the API was incorrect.
Here's the full working example:
'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)
};
};
Mind the Name
attribute which must be provided as part of the API call to the ServiceManager.getAttribute method.
This attribute is stated in the official docs
I have run this myself and here's the output in CloudWatch Logs:
As you can see, the value was returned successfully.
Hope this helps!
这篇关于如何使用node.js和aws-sdk从lambda访问aws参数存储的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!