7 votes

Comment accéder au magasin de paramètres aws à partir d'une lambda en utilisant node.js et aws-sdk

J'ai créé un modèle de formation lambda et cloud qui donne à un lambda l'accès au magasin de paramètres et au gestionnaire de secrets. Lorsque je teste la lambda, j'ai les fonctions suivantes en dehors de la fonction 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 est instancié en tant que var servmgr = new AWS.SSM();

Lorsque j'appelle cette fonction à partir de la fonction export.handler, je le fais comme suit :

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

let endpointResult = getParameterFromStore(myFirstParam);

Dans la lambda, la fonction récupère le paramètre défini à l'extérieur de la fonction export.handler mais enveloppé dans une promesse.

Lorsque j'exécute/teste cette lambda, l'objet retourné est toujours indéfini... Je récupère Parameters[] mais aucune valeur.

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":[]}

Comment renvoyer les valeurs des paramètres à une lambda au moment de l'exécution ?

mise à jour

Sur la base de la suggestion/réponse de Thales, j'ai simplifié le lambda en le limitant à ceci :

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

Dans mes tests, je vois toujours un tableau vide renvoyé :

### endpoint path: {"Parameters":[]}

J'ai également déplacé la fonction dans le callback en tant que

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

Même résultat ... tableau vide. Y a-t-il d'autres choses à essayer ?

12voto

Thales Minussi Points 5277

En effet, votre getParameterFromStore revient avant que votre then() est exécuté, donc parameterResult es undefined . Si vous ne voulez pas trop modifier votre code, je renverrais la Promesse que vous avez créée, comme ceci :

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

} ;

Enfin, sur le client de votre fonction, vous pouvez obtenir le résultat comme suit :

const myFirstParam =  { Path : '/myPath/Service/servicesEndpoint'}
getParameterFromStore(myFirstParam).then(console.log)

Cependant, lorsque vous codez en NodeJS, je vous recommande vivement d'utiliser async/await à la place, ce qui vous permettra d'échapper à l'enfer des promesses (changer promesse après promesse afin d'obtenir quelque chose de "synchrone").

Lorsque vous utilisez async/await, vous pouvez concevoir votre code comme s'il était synchrone. Voici une version remaniée de votre exemple, utilisant async/await ainsi que des fonctions fléchées :

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

EDITAR : Après que l'OP a résolu le premier problème, j'ai créé un exemple fonctionnel de mon côté. Il s'est avéré que la façon dont le PO invoquait l'API était incorrecte.

Voici l'exemple complet :

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

L'esprit Name qui doit être fourni dans le cadre de l'appel API à la méthode ServiceManager.getAttribute.

Cet attribut est indiqué dans le document officiel documents

Je l'ai fait moi-même et voici le résultat dans les Logs de CloudWatch :

enter image description here

Comme vous pouvez le constater, la valeur a été renvoyée avec succès.

J'espère que cela vous aidera !

1voto

Aziz Zoaib Points 66

Si votre lambda est déployé sur un VPC, assurez-vous que le groupe de sécurité y est attaché et que le trafic sortant est autorisé. Il sera en mesure d'accéder automatiquement au magasin de paramètres.

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

1voto

Mim Armand Points 409

Une solution plus simple serait la suivante :

const getParameterFromStore = (params) => servmgr.getParametersByPath(params).promise();

const myFirstParam =  { Path : '/myPath/Service'};
getParameterFromStore(myFirstParam).then(console.log);

Comme vous pouvez le voir, le SDK lui-même fournit des fonctionnalités utilitaires que vous pouvez utiliser en fonction de vos besoins pour une utilisation asynchrone ou synchrone.

J'espère que cela vous aidera.

  • m

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X