Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Exemples de AWS Lambda fonctions pour AWS Config les règles (Node.js)
AWS Lambda exécute des fonctions en réponse à des événements publiés par les AWS services. La fonction d'une règle Lambda AWS Config personnalisée reçoit un événement publié par AWS Config, puis utilise les données qu'elle reçoit de l'événement et qu'elle extrait de l' AWS Config API pour évaluer la conformité de la règle. Les opérations dans une fonction pour une règle de configuration varient selon qu'il s'agisse d'une évaluation déclenchée par des changements de configuration ou de façon périodique.
Pour plus d'informations sur les modèles courants au sein des AWS Lambda fonctions, voir Modèle de programmation dans le Guide du AWS Lambda développeur.
Table des matières
Exemple de fonction pour des évaluations déclenchées par des changements de configuration
AWS Config invoquera une fonction comme dans l'exemple suivant lorsqu'elle détecte un changement de configuration pour une ressource comprise dans le champ d'application d'une règle personnalisée.
Si vous utilisez la AWS Config console pour créer une règle associée à une fonction comme dans cet exemple, choisissez Configuration changes comme type de déclencheur. Si vous utilisez l' AWS Config API ou AWS CLI pour créer la règle, définissez l'MessageType
attribut sur ConfigurationItemChangeNotification
etOversizedConfigurationItemChangeNotification
. Ces paramètres permettent à votre règle d'être déclenchée chaque fois qu'un élément de configuration ou un élément de configuration surdimensionné est AWS Config généré à la suite d'un changement de ressource.
Cet exemple évalue vos ressources et vérifie si les instances correspondent au type de ressource, AWS::EC2::Instance
. La règle est déclenchée quand AWS Config
génère un élément de configuration ou une notification d'élément de configuration surdimensionné.
'use strict'; import { ConfigServiceClient, GetResourceConfigHistoryCommand, PutEvaluationsCommand } from "@aws-sdk/client-config-service"; const configClient = new ConfigServiceClient({}); // Helper function used to validate input function checkDefined(reference, referenceName) { if (!reference) { throw new Error(`Error: ${referenceName} is not defined`); } return reference; } // Check whether the message type is OversizedConfigurationItemChangeNotification, function isOverSizedChangeNotification(messageType) { checkDefined(messageType, 'messageType'); return messageType === 'OversizedConfigurationItemChangeNotification'; } // Get the configurationItem for the resource using the getResourceConfigHistory API. async function getConfiguration(resourceType, resourceId, configurationCaptureTime, callback) { const input = { resourceType, resourceId, laterTime: new Date(configurationCaptureTime), limit: 1 }; const command = new GetResourceConfigHistoryCommand(input); await configClient.send(command).then( (data) => { callback(null, data.configurationItems[0]); }, (error) => { callback(error, null); } ); } // Convert the oversized configuration item from the API model to the original invocation model. function convertApiConfiguration(apiConfiguration) { apiConfiguration.awsAccountId = apiConfiguration.accountId; apiConfiguration.ARN = apiConfiguration.arn; apiConfiguration.configurationStateMd5Hash = apiConfiguration.configurationItemMD5Hash; apiConfiguration.configurationItemVersion = apiConfiguration.version; apiConfiguration.configuration = JSON.parse(apiConfiguration.configuration); if ({}.hasOwnProperty.call(apiConfiguration, 'relationships')) { for (let i = 0; i < apiConfiguration.relationships.length; i++) { apiConfiguration.relationships[i].name = apiConfiguration.relationships[i].relationshipName; } } return apiConfiguration; } // Based on the message type, get the configuration item either from the configurationItem object in the invoking event or with the getResourceConfigHistory API in the getConfiguration function. async function getConfigurationItem(invokingEvent, callback) { checkDefined(invokingEvent, 'invokingEvent'); if (isOverSizedChangeNotification(invokingEvent.messageType)) { const configurationItemSummary = checkDefined(invokingEvent.configurationItemSummary, 'configurationItemSummary'); await getConfiguration(configurationItemSummary.resourceType, configurationItemSummary.resourceId, configurationItemSummary.configurationItemCaptureTime, (err, apiConfigurationItem) => { if (err) { callback(err); } const configurationItem = convertApiConfiguration(apiConfigurationItem); callback(null, configurationItem); }); } else { checkDefined(invokingEvent.configurationItem, 'configurationItem'); callback(null, invokingEvent.configurationItem); } } // Check whether the resource has been deleted. If the resource was deleted, then the evaluation returns not applicable. function isApplicable(configurationItem, event) { checkDefined(configurationItem, 'configurationItem'); checkDefined(event, 'event'); const status = configurationItem.configurationItemStatus; const eventLeftScope = event.eventLeftScope; return (status === 'OK' || status === 'ResourceDiscovered') && eventLeftScope === false; } // In this example, the resource is compliant if it is an instance and its type matches the type specified as the desired type. // If the resource is not an instance, then this resource is not applicable. function evaluateChangeNotificationCompliance(configurationItem, ruleParameters) { checkDefined(configurationItem, 'configurationItem'); checkDefined(configurationItem.configuration, 'configurationItem.configuration'); checkDefined(ruleParameters, 'ruleParameters'); if (configurationItem.resourceType !== 'AWS::EC2::Instance') { return 'NOT_APPLICABLE'; } else if (ruleParameters.desiredInstanceType === configurationItem.configuration.instanceType) { return 'COMPLIANT'; } return 'NON_COMPLIANT'; } // Receives the event and context from AWS Lambda. export const handler = async (event, context) => { checkDefined(event, 'event'); const invokingEvent = JSON.parse(event.invokingEvent); const ruleParameters = JSON.parse(event.ruleParameters); await getConfigurationItem(invokingEvent, async (err, configurationItem) => { let compliance = 'NOT_APPLICABLE'; let annotation = ''; const putEvaluationsRequest = {}; if (isApplicable(configurationItem, event)) { // Invoke the compliance checking function. compliance = evaluateChangeNotificationCompliance(configurationItem, ruleParameters); if (compliance === "NON_COMPLIANT") { annotation = "This is an annotation describing why the resource is not compliant."; } } // Initializes the request that contains the evaluation results. if (annotation) { putEvaluationsRequest.Evaluations = [ { ComplianceResourceType: configurationItem.resourceType, ComplianceResourceId: configurationItem.resourceId, ComplianceType: compliance, OrderingTimestamp: new Date(configurationItem.configurationItemCaptureTime), Annotation: annotation }, ]; } else { putEvaluationsRequest.Evaluations = [ { ComplianceResourceType: configurationItem.resourceType, ComplianceResourceId: configurationItem.resourceId, ComplianceType: compliance, OrderingTimestamp: new Date(configurationItem.configurationItemCaptureTime), }, ]; } putEvaluationsRequest.ResultToken = event.resultToken; // Sends the evaluation results to AWS Config. await configClient.send(new PutEvaluationsCommand(putEvaluationsRequest)); }); };
Opérations de la fonction
La fonction effectue les opérations suivantes lors de l'exécution :
-
La fonction s'exécute lorsque AWS Lambda l'
event
objet est transmis à lahandler
fonction. Dans cet exemple, la fonction accepte lecallback
paramètre facultatif, qu'elle utilise pour renvoyer des informations à l'appelant. AWS Lambda transmet également uncontext
objet contenant des informations et des méthodes que la fonction peut utiliser pendant son exécution. Sachez que le contexte n'est plus utilisé dans les nouvelles versions de Lambda. -
La fonction vérifie si le
messageType
pour l'événement est un élément de configuration ou un élément de configuration surdimensionné, puis renvoie l'élément de configuration. -
Le gestionnaire appelle la fonction
isApplicable
afin de déterminer si la ressource a été supprimée.Note
Les règles signalant les ressources supprimées doivent renvoyer le résultat de l'évaluation
NOT_APPLICABLE
afin d'éviter des évaluations de règles inutiles. -
Le gestionnaire appelle la
evaluateChangeNotificationCompliance
fonction et transmet lesruleParameters
objetsconfigurationItem
et AWS Config publiés lors de l'événement.La fonction commence par évaluer si la ressource est une instance EC2. Si la ressource n'est pas une instance EC2, la fonction renvoie la valeur de conformité
NOT_APPLICABLE
.La fonction évalue ensuite si l'attribut
instanceType
de l'élément de configuration est égal à la valeur du paramètredesiredInstanceType
. Si les valeurs sont égales, la fonction renvoieCOMPLIANT
. Si les valeurs ne sont pas égales, la fonction renvoieNON_COMPLIANT
. -
Le gestionnaire se prépare à envoyer les résultats de l'évaluation à AWS Config en initialisant l'
putEvaluationsRequest
objet. Cet objet comprend le paramètreEvaluations
qui identifie le résultat de la conformité, le type et l'ID de la ressource qui a été évaluée. L'putEvaluationsRequest
objet inclut également le jeton de résultat de l'événement, qui identifie la règle et l'événement pour AWS Config. -
Le gestionnaire envoie les résultats de l'évaluation à AWS Config en transmettant l'objet à la
putEvaluations
méthode duconfig
client.
Exemple de fonction pour des évaluations périodiques
AWS Config invoquera une fonction comme dans l'exemple suivant pour les évaluations périodiques. Des évaluations périodiques se produisent à la fréquence que vous spécifiez lorsque vous définissez la règle dans AWS Config.
Si vous utilisez la AWS Config console pour créer une règle associée à une fonction comme dans cet exemple, choisissez Périodique comme type de déclencheur. Si vous utilisez l' AWS Config API ou AWS CLI pour créer la règle, définissez l'MessageType
attribut surScheduledNotification
.
Cet exemple vérifie si le nombre total d'une ressource donnée dépasse le maximum spécifié.
'use strict'; import { ConfigServiceClient, ListDiscoveredResourcesCommand, PutEvaluationsCommand } from "@aws-sdk/client-config-service"; const configClient = new ConfigServiceClient({}); // Receives the event and context from AWS Lambda. export const handler = async (event, context, callback) => { // Parses the invokingEvent and ruleParameters values, which contain JSON objects passed as strings. var invokingEvent = JSON.parse(event.invokingEvent), ruleParameters = JSON.parse(event.ruleParameters), numberOfResources = 0; if (isScheduledNotification(invokingEvent) && hasValidRuleParameters(ruleParameters, callback)) { await countResourceTypes(ruleParameters.applicableResourceType, "", numberOfResources, async function (err, count) { if (err === null) { var putEvaluationsRequest; const compliance = evaluateCompliance(ruleParameters.maxCount, count); var annotation = ''; if (compliance === "NON_COMPLIANT") { annotation = "Description of why the resource is not compliant."; } // Initializes the request that contains the evaluation results. if (annotation) { putEvaluationsRequest = { Evaluations: [{ // Applies the evaluation result to the AWS account published in the event. ComplianceResourceType: 'AWS::::Account', ComplianceResourceId: event.accountId, ComplianceType: compliance, OrderingTimestamp: new Date(), Annotation: annotation }], ResultToken: event.resultToken }; } else { putEvaluationsRequest = { Evaluations: [{ // Applies the evaluation result to the AWS account published in the event. ComplianceResourceType: 'AWS::::Account', ComplianceResourceId: event.accountId, ComplianceType: compliance, OrderingTimestamp: new Date() }], ResultToken: event.resultToken }; } // Sends the evaluation results to AWS Config. try { await configClient.send(new PutEvaluationsCommand(putEvaluationsRequest)); } catch (e) { callback(e, null); } } else { callback(err, null); } }); } else { console.log("Invoked for a notification other than Scheduled Notification... Ignoring."); } }; // Checks whether the invoking event is ScheduledNotification. function isScheduledNotification(invokingEvent) { return (invokingEvent.messageType === 'ScheduledNotification'); } // Checks the rule parameters to see if they are valid function hasValidRuleParameters(ruleParameters, callback) { // Regular express to verify that applicable resource given is a resource type const awsResourcePattern = /^AWS::(\w*)::(\w*)$/; const isApplicableResourceType = awsResourcePattern.test(ruleParameters.applicableResourceType); // Check to make sure the maxCount in the parameters is an integer const maxCountIsInt = !isNaN(ruleParameters.maxCount) && parseInt(Number(ruleParameters.maxCount)) == ruleParameters.maxCount && !isNaN(parseInt(ruleParameters.maxCount, 10)); if (!isApplicableResourceType) { callback("The applicableResourceType parameter is not a valid resource type.", null); } if (!maxCountIsInt) { callback("The maxCount parameter is not a valid integer.", null); } return isApplicableResourceType && maxCountIsInt; } // Checks whether the compliance conditions for the rule are violated. function evaluateCompliance(maxCount, actualCount) { if (actualCount > maxCount) { return "NON_COMPLIANT"; } else { return "COMPLIANT"; } } // Counts the applicable resources that belong to the AWS account. async function countResourceTypes(applicableResourceType, nextToken, count, callback) { const input = { resourceType: applicableResourceType, nextToken: nextToken }; const command = new ListDiscoveredResourcesCommand(input); try { const response = await configClient.send(command); count = count + response.resourceIdentifiers.length; if (response.nextToken !== undefined && response.nextToken != null) { countResourceTypes(applicableResourceType, response.nextToken, count, callback); } callback(null, count); } catch (e) { callback(e, null); } return count; }
Opérations de la fonction
La fonction effectue les opérations suivantes lors de l'exécution :
-
La fonction s'exécute lorsque AWS Lambda l'
event
objet est transmis à lahandler
fonction. Dans cet exemple, la fonction accepte lecallback
paramètre facultatif, qu'elle utilise pour renvoyer des informations à l'appelant. AWS Lambda transmet également uncontext
objet contenant des informations et des méthodes que la fonction peut utiliser pendant son exécution. Sachez que le contexte n'est plus utilisé dans les nouvelles versions de Lambda. -
Pour compter les ressources du type spécifié, le gestionnaire appelle la fonction
countResourceTypes
et il transmet le paramètreapplicableResourceType
qu'il a reçu de l'événement. La fonctioncountResourceTypes
appelle la méthodelistDiscoveredResources
du clientconfig
, qui retourne une liste d'identificateurs pour les ressources applicables. La fonction utilise la longueur de cette liste pour déterminer le nombre de ressources applicables, et elle retourne ce nombre au gestionnaire. -
Le gestionnaire se prépare à envoyer les résultats de l'évaluation à AWS Config en initialisant l'
putEvaluationsRequest
objet. Cet objet inclut leEvaluations
paramètre, qui identifie le résultat de conformité et celui Compte AWS qui a été publié lors de l'événement. Vous pouvez utiliser le paramètreEvaluations
pour appliquer le résultat à n'importe quel type de ressource pris en charge par AWS Config. L'putEvaluationsRequest
objet inclut également le jeton de résultat de l'événement, qui identifie la règle et l'événement pour AWS Config. -
Au sein de l'objet
putEvaluationsRequest
, le gestionnaire appelle la fonctionevaluateCompliance
. Cette fonction teste si le nombre de ressources applicables dépasse le maximum attribué au paramètremaxCount
fourni par l'événement. Si le nombre maximum de ressources est dépassé, la fonction renvoieNON_COMPLIANT
. Si le nombre maximum de ressources n'est pas dépassé, la fonction renvoieCOMPLIANT
. -
Le gestionnaire envoie les résultats de l'évaluation à AWS Config en transmettant l'objet à la
putEvaluations
méthode duconfig
client.