如何使用node.js和aws-sdk从lambda访问aws参数存储 [英] How to access the aws parameter store from a lambda using node.js and aws-sdk

查看:77
本文介绍了如何使用node.js和aws-sdk从lambda访问aws参数存储的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆