web-dev-qa-db-ja.com

node.jsとaws-sdkを使用してラムダからawsパラメータストアにアクセスする方法

パラメーターストアとシークレットマネージャーへのラムダアクセスを許可するラムダとクラウド形成テンプレートを作成しました。ラムダをテストすると、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;
};
_

servmgrvar servmgr = new AWS.SSM();としてインスタンス化されます

この関数をexport.handler関数から呼び出すときは、次のようにします。

_myFirstParam =  { Path : '/myPath/Service/servicesEndpoint'};

let endpointResult = getParameterFromStore(myFirstParam);
_

ラムダでは、export.handler関数の外側で定義されたパラメーターを関数が取得し、プロミスにラップします。

このラムダを実行/テストすると、返されるオブジェクトは常に未定義です... 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":[]}
_

実行時にパラメーター値をラムダに返すにはどうすればよいですか?

更新

タレスからの提案/回答に基づいて、ラムダをこれだけに単純化しました:

_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());
_

同じ結果...空の配列。他に試すことはありますか?

3
rlcrews

これは、getParameterFromStorethen()コードが実行される前に戻るため、parameterResultundefinedになるためです。コードをあまり変更したくない場合は、次のように、作成した約束を返します。

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 Hellをエスケープできるようになります(Promiseの後にPromiseを実行して、「同期的に」何かを実現します)。

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)
};

[〜#〜] edit [〜#〜]: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)
  };
};

ServiceManager.getAttributeメソッドへのAPI呼び出しの一部として提供する必要があるName属性に注意してください。

この属性は公式 docs に記載されています

これを自分で実行しました。CloudWatchLogsの出力は次のとおりです。

enter image description here

ご覧のとおり、値は正常に返されました。

お役に立てれば!

6
Thales Minussi

ラムダがVPCにデプロイされている場合は、セキュリティグループがそれに接続されており、送信トラフィックが許可されていることを確認してください。パラメータストアに自動的にアクセスできるようになります。

https://aws.Amazon.com/premiumsupport/knowledge-center/lambda-vpc-parameter-store/

0
Aziz Zoaib