Exemplos de funções do AWS Lambda para regras do AWS Config (Node.js) - AWS Config

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Exemplos de funções do AWS Lambda para regras do AWS Config (Node.js)

O AWS Lambda executa funções em resposta a eventos publicados por serviços da AWS. A função de umAWS ConfigA regra personalizada do Lambda recebe um evento publicado pelaAWS Confige, em seguida, a função usa os dados que recebe do evento e recuperados doAWS ConfigAPI para avaliar a conformidade da regra. As operações em uma função para uma regra Config diferem conforme a avaliação seja acionada por alterações de configuração ou acionada periodicamente.

Para obter informações sobre padrões comuns emAWS Lambdafunções do de exemplo, consulteModelo de programaçãonaAWS LambdaGuia do desenvolvedor do.

Exemplo de função para avaliações acionadas por alterações de configuração

O AWS Config chamará uma função como a do exemplo a seguir, quando detectar a alteração de configuração de um recurso dentro do escopo de uma regra personalizada.

Se você usar o console do AWS Config para criar uma regra que esteja associada a uma função, como neste exemplo, escolha Configuration changes (Alterações da configuração) como o tipo de trigger. Se você usar a API do AWS Config ou a AWS CLI para criar a regra, defina o atributo MessageType para ConfigurationItemChangeNotification e OversizedConfigurationItemChangeNotification. Essas configurações habilitam sua regra para ser acionada sempre que o AWS Config gerar um item de configuração ou um item de configuração superdimensionado como resultado de uma mudança de recurso.

Este exemplo avalia seus recursos e verifica se as instâncias correspondem ao tipo de recurso AWS::EC2::Instance. A regra é acionada quando o AWS Config gera um item de configuração ou uma notificação de item de configuração superdimensionado.

'use strict'; const aws = require('aws-sdk'); const config = new aws.ConfigService(); // 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. function getConfiguration(resourceType, resourceId, configurationCaptureTime, callback) { config.getResourceConfigHistory({ resourceType, resourceId, laterTime: new Date(configurationCaptureTime), limit: 1 }, (err, data) => { if (err) { callback(err, null); } const configurationItem = data.configurationItems[0]; callback(null, configurationItem); }); } // 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. function getConfigurationItem(invokingEvent, callback) { checkDefined(invokingEvent, 'invokingEvent'); if (isOverSizedChangeNotification(invokingEvent.messageType)) { const configurationItemSummary = checkDefined(invokingEvent.configurationItemSummary, 'configurationItemSummary'); 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. exports.handler = (event, context, callback) => { checkDefined(event, 'event'); const invokingEvent = JSON.parse(event.invokingEvent); const ruleParameters = JSON.parse(event.ruleParameters); getConfigurationItem(invokingEvent, (err, configurationItem) => { if (err) { callback(err); } let compliance = 'NOT_APPLICABLE'; const putEvaluationsRequest = {}; if (isApplicable(configurationItem, event)) { // Invoke the compliance checking function. compliance = evaluateChangeNotificationCompliance(configurationItem, ruleParameters); } // Initializes the request that contains the evaluation results. putEvaluationsRequest.Evaluations = [ { ComplianceResourceType: configurationItem.resourceType, ComplianceResourceId: configurationItem.resourceId, ComplianceType: compliance, OrderingTimestamp: configurationItem.configurationItemCaptureTime, }, ]; putEvaluationsRequest.ResultToken = event.resultToken; // Sends the evaluation results to AWS Config. config.putEvaluations(putEvaluationsRequest, (error, data) => { if (error) { callback(error, null); } else if (data.FailedEvaluations.length > 0) { // Ends the function if evaluation results are not successfully reported to AWS Config. callback(JSON.stringify(data), null); } else { callback(null, data); } }); }); };
Operações de função

A função executa as seguintes operações em tempo de execução:

  1. A função é executada quando o AWS Lambda passa o objeto event para a função handler. Neste exemplo, a função aceita o opcionalcallbackparâmetro, que ele usa para retornar informações para o chamador.AWS Lambdatambém passa umcontextobjeto, que contém informações e métodos que a função pode usar enquanto é executada. Observe que nas versões mais recentes do Lambda, o contexto não é mais usado.

  2. A função verifica se messageType para o evento é um item de configuração ou um item de configuração superdimensionado, e, em seguida, retorna o item de configuração.

  3. O handler chama a função isApplicable para determinar se o recurso foi excluído.

  4. O manipulador chama a função evaluateChangeNotificationCompliance e transmite os objetos configurationItem e ruleParameters e que o AWS Config publicou no evento.

    A função primeiro avalia se o recurso é uma instância EC2. Se o recurso não é uma instância EC2, a função retorna um valor de compatibilidade de NOT_APPLICABLE.

    Em seguida, a função avalia se o atributo instanceType no item de configuração é igual ao valor de parâmetro desiredInstanceType. Se os valores são iguais, a função retornará COMPLIANT. Se os valores não são iguais, a função retornará NON_COMPLIANT.

  5. O manipulador prepara o envio dos resultados da avaliação para o AWS Config, inicializando o objeto putEvaluationsRequest. Este objeto inclui o parâmetro Evaluations, que identifica o resultado de compatibilidade, o tipo de recurso e o ID do recurso que foi avaliado. O objeto putEvaluationsRequest também inclui o token de resultado do evento, que identifica a regra e o evento para o AWS Config.

  6. O manipulador envia os resultados da avaliação para o AWS Config, transmitindo o objeto para o método putEvaluations do cliente config.

Exemplo de função para avaliações periódicas

O AWS Config chamará uma função como a do exemplo a seguir para avaliações periódicas. As avaliações periódicas ocorrem com a frequência que você especifica ao definir a regra em AWS Config.

Se você usar o console do AWS Config para criar uma regra que esteja associada a uma função, como neste exemplo, escolha Periodic (Periódico) como o tipo de trigger. Se você usar a API do AWS Config ou a AWS CLI para criar a regra, defina o atributo MessageType como ScheduledNotification.

Este exemplo verifica se o número total de um recurso especificado excede o máximo especificado.

var aws = require('aws-sdk'), // Loads the AWS SDK for JavaScript. config = new aws.ConfigService(), // Constructs a service object to use the aws.ConfigService class. COMPLIANCE_STATES = { COMPLIANT : 'COMPLIANT', NON_COMPLIANT : 'NON_COMPLIANT', NOT_APPLICABLE : 'NOT_APPLICABLE' }; // Receives the event and context from AWS Lambda. exports.handler = function(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), noOfResources = 0; if (isScheduledNotification(invokingEvent)) { countResourceTypes(ruleParameters.applicableResourceType, "", noOfResources, function(err, count) { if (err === null) { var putEvaluationsRequest; // Initializes the request that contains the evaluation results. putEvaluationsRequest = { Evaluations : [ { // Applies the evaluation result to the AWS account published in the event. ComplianceResourceType : 'AWS::::Account', ComplianceResourceId : event.accountId, ComplianceType : evaluateCompliance(ruleParameters.maxCount, count), OrderingTimestamp : new Date() } ], ResultToken : event.resultToken }; // Sends the evaluation results to AWS Config. config.putEvaluations(putEvaluationsRequest, function(err, data) { if (err) { callback(err, null); } else { if (data.FailedEvaluations.length > 0) { // Ends the function execution if evaluation results are not successfully reported callback(JSON.stringify(data)); } callback(null, data); } }); } 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 whether the compliance conditions for the rule are violated. function evaluateCompliance(maxCount, actualCount) { if (actualCount > maxCount) { return COMPLIANCE_STATES.NON_COMPLIANT; } else { return COMPLIANCE_STATES.COMPLIANT; } } // Counts the applicable resources that belong to the AWS account. function countResourceTypes(applicableResourceType, nextToken, count, callback) { config.listDiscoveredResources({resourceType : applicableResourceType, nextToken : nextToken}, function(err, data) { if (err) { callback(err, null); } else { count = count + data.resourceIdentifiers.length; if (data.nextToken !== undefined && data.nextToken != null) { countResourceTypes(applicableResourceType, data.nextToken, count, callback); } callback(null, count); } }); return count; }
Operações de função

A função executa as seguintes operações em tempo de execução:

  1. A função é executada quando o AWS Lambda passa o objeto event para a função handler. Neste exemplo, a função aceita o opcionalcallbackparâmetro, que ele usa para retornar informações para o chamador.AWS Lambdatambém passa umcontextobjeto, que contém informações e métodos que a função pode usar enquanto é executada. Observe que nas versões mais recentes do Lambda, o contexto não é mais usado.

  2. Para contar os recursos do tipo especificado, o handler chama a função countResourceTypes e passa o parâmetro applicableResourceType que recebeu do evento. A função countResourceTypes chama o método listDiscoveredResources do cliente config, que retorna uma lista de identificadores para os recursos aplicáveis. A função usa o comprimento da lista para determinar o número de recursos aplicáveis e retorna essa contagem para o handler.

  3. O manipulador prepara o envio dos resultados da avaliação para o AWS Config, inicializando o objeto putEvaluationsRequest. Esse objeto inclui oEvaluationsparâmetro, que identifica o resultado da conformidade e oConta da AWSque foi publicado no evento. Você pode usar o parâmetro Evaluations para aplicar o resultado a qualquer tipo de recurso que tenha suporte no AWS Config. O objeto putEvaluationsRequest também inclui o token de resultado do evento, que identifica a regra e o evento para o AWS Config.

  4. Dentro do objeto putEvaluationsRequest, o handler chama a função evaluateCompliance. Esta função testa se o número de recursos aplicáveis excede o máximo atribuído ao parâmetro maxCount, que foi fornecido pelo evento. Se o número de recursos excede o máximo, a função retorna NON_COMPLIANT. Se o número de recursos não excede o máximo, a função retorna COMPLIANT.

  5. O manipulador envia os resultados da avaliação para o AWS Config, transmitindo o objeto para o método putEvaluations do cliente config.