

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á.

# Crie funções Lambda para avaliar recursos para Lambda Hooks
<a name="lambda-hooks-create-lambda-function"></a>

CloudFormation O Lambda Hooks permite que você CloudFormation avalie e AWS API Cloud Control opere com base em seu próprio código personalizado. Seu Hook pode impedir que uma operação continue, ou emitir um aviso para o chamador e permitir que a operação continue. Ao criar um Lambda Hook, você pode configurá-lo para interceptar e avaliar as seguintes operações: CloudFormation 
+ Operações de recurso
+ Operações de empilhamento
+ Alterar as operações do conjunto

**Topics**
+ [

## Desenvolvendo um Lambda Hook
](#lambda-hooks-create-lambda-function-develop)
+ [

## Avaliando as operações de recursos com Lambda Hooks
](#lambda-hooks-create-lambda-function-resource)
+ [

## Avaliação de operações de pilha com Lambda Hooks
](#lambda-hooks-create-lambda-function-stack)
+ [

## Avaliando as operações do conjunto de alterações com Lambda Hooks
](#lambda-hooks-create-lambda-function-change-set)

## Desenvolvendo um Lambda Hook
<a name="lambda-hooks-create-lambda-function-develop"></a>

Quando Hooks invocam seu Lambda, ele espera até 30 segundos para que o Lambda avalie a entrada. O Lambda retornará uma resposta JSON que indica se o Hook foi bem-sucedido ou falhou.

**Topics**
+ [

### Solicitar entrada
](#lambda-hooks-create-lambda-function-request-input)
+ [

### Entrada de resposta
](#lambda-hooks-create-lambda-function-request-response)
+ [

### Exemplos
](#lambda-hooks-create-lambda-function-request-example)

### Solicitar entrada
<a name="lambda-hooks-create-lambda-function-request-input"></a>

A entrada passada para sua função Lambda depende da operação de destino do Hook (exemplos: pilha, recurso ou conjunto de alterações). 

### Entrada de resposta
<a name="lambda-hooks-create-lambda-function-request-response"></a>

Para se comunicar com Hooks se sua solicitação foi bem-sucedida ou falhou, sua função Lambda precisa retornar uma resposta JSON.

A seguir está um exemplo da forma da resposta que Hooks espera:

```
{ 
  "Status do gancho": "SUCCESS" or "FAILED" or "IN_PROGRESS", 
  "errorCode": "NonCompliant" or "InternalFailure"
  "message": String, 
  "clientRequestToken": String,
  "Contexto de retorno de chamada": None, 
  "callbackDelaySeconds": Integer,
  "anotações": [
    {
      "annotationName": String,
      "status": "PASSED" or "FAILED" or "SKIPPED",
      "statusMessage": String,
      "remediationMessage": String,
      "remediationLink": String,
      "severityLevel": "INFORMATIONAL" or "LOW" or "MEDIUM" or "HIGH" or "CRITICAL"
    }
  ]
}
```

Status do gancho  <a name="lambda-hook-response-hookstatus"></a>
O status do Hook. Este é um campo obrigatório.  
*Valores válidos*: (`SUCCESS`\$1 `FAILED` \$1`IN_PROGRESS`)  
Um gancho pode retornar `IN_PROGRESS` 3 vezes. Se nenhum resultado for retornado, o Hook falhará. Para um Lambda Hook, isso significa que sua função Lambda pode ser invocada até 3 vezes.

errorCode  <a name="lambda-hook-response-errorcode"></a>
Mostra se a operação foi avaliada e determinada como inválida ou se ocorreram erros no Hook, impedindo a avaliação. Esse campo é obrigatório se o Hook falhar.  
*Valores válidos*: (`NonCompliant`\$1`InternalFailure`)

message  <a name="lambda-hook-response-message"></a>
A mensagem para o chamador informando por que o Hook foi bem-sucedido ou falhou.  
Ao avaliar CloudFormation as operações, esse campo é truncado para 4096 caracteres.  
Ao avaliar as operações da Cloud Control API, esse campo é truncado para 1024 caracteres.

clientRequestToken  <a name="lambda-hook-response-clientrequesttoken"></a>
O token de solicitação que foi fornecido como entrada para a solicitação do Hook. Este é um campo obrigatório.

Contexto de retorno de chamada  <a name="lambda-hook-response-callbackcontext"></a>
Se você indicar que `hookStatus` é, `IN_PROGRESS` você passa um contexto adicional que é fornecido como entrada quando a função Lambda é invocada novamente.

callbackDelaySeconds  <a name="lambda-hook-response-callbackdelayseconds"></a>
Quanto tempo os Hooks devem esperar para invocar esse Hook novamente.

anotações  <a name="lambda-hook-response-annotations"></a>
Uma variedade de objetos de anotação que fornecem mais detalhes e orientações de remediação.     
Nome da anotação  
Um identificador para a anotação.  
status  
O status de invocação do Hook. Isso é útil quando as anotações representam uma lógica com avaliação de aprovação/reprovação semelhante a uma regra do Guard.   
*Valores válidos*: (`PASSED`\$1 `FAILED` \$1`SKIPPED`)  
statusMessage  
Explicação do status específico.  
Mensagem de remediação  
Sugestão para corrigir um `FAILED` status. Por exemplo, se um recurso não tiver criptografia, você pode indicar como adicionar criptografia à configuração do recurso.  
Link de remediação  
Um URL HTTP para orientação adicional sobre remediação.  
severityLevel  
Define o risco relativo associado a qualquer violação desse tipo. Ao atribuir níveis de severidade aos resultados da invocação do Hook, você pode consultar a [estrutura de AWS Security Hub CSPM severidade](https://docs.aws.amazon.com/securityhub/latest/userguide/asff-required-attributes.html#Severity) como um exemplo de como estruturar categorias de severidade significativas.   
*Valores válidos*: (`INFORMATIONAL`\$1 `LOW` \$1 `MEDIUM` \$1 `HIGH` \$1`CRITICAL`)

### Exemplos
<a name="lambda-hooks-create-lambda-function-request-example"></a>

Veja a seguir um exemplo de resposta bem-sucedida:

```
{ 
  "hookStatus": "SUCCESS",
  "message": "compliant",
  "clientRequestToken": "123avjdjk31"  
}
```

Veja a seguir um exemplo de falha na resposta:

```
{ 
  "hookStatus": "FAILED",
  "errorCode": "NonCompliant",
  "message": "S3 Bucket Versioning must be enabled.",
  "clientRequestToken": "123avjdjk31"
 }
```

## Avaliando as operações de recursos com Lambda Hooks
<a name="lambda-hooks-create-lambda-function-resource"></a>

Sempre que você cria, atualiza ou exclui um recurso, isso é considerado uma operação de recurso. Por exemplo, se você executar a atualização de uma CloudFormation pilha que cria um novo recurso, você concluiu uma operação de recurso. Quando você cria, atualiza ou exclui um recurso usando a Cloud Control API, isso também é considerado uma operação de recurso. Você pode configurar seu CloudFormation Lambda Hook para destinos `RESOURCE` e `CLOUD_CONTROL` operações na configuração do Hook`TargetOperations`.

**nota**  
O manipulador `delete` Hook só é invocado quando um recurso é excluído usando um gatilho de operação da Cloud Control API `delete-resource` ou. CloudFormation `delete-stack`

**Topics**
+ [

### Sintaxe de entrada de recursos do Lambda Hook
](#lambda-hooks-create-lambda-function-resource-input)
+ [

### Exemplo de entrada de alteração de recursos do Lambda Hook
](#lambda-hooks-create-lambda-function-resource-example)
+ [

### Exemplo de função Lambda para operações de recursos
](#lambda-hooks-create-lambda-function-resource-example-function)

### Sintaxe de entrada de recursos do Lambda Hook
<a name="lambda-hooks-create-lambda-function-resource-input"></a>

Quando seu Lambda for invocado para uma operação de recurso, você receberá uma entrada JSON contendo as propriedades do recurso, as propriedades propostas e o contexto em torno da invocação do Hook.

Veja a seguir um exemplo de formato da entrada JSON:

```
{
    "awsAccountId": String,
    "stackId": String,
    "changeSetId": String,
    "hookTypeName": String,
    "hookTypeVersion": String,
    "hookModel": {
        "LambdaFunction": String
    },
    "actionInvocationPoint": "CREATE_PRE_PROVISION" or "UPDATE_PRE_PROVISION" or "DELETE_PRE_PROVISION"
    "requestData": {
        "targetName": String,
        "targetType": String,
        "targetLogicalId": String,
        "targetModel": {
            "resourceProperties": {...},
            "previousResourceProperties": {...}
        }
    },
    "requestContext": {
        "invocação": 1,
        "Contexto de retorno de chamada": null
    }
}
```

`awsAccountId`  <a name="lambda-hook-resource-awsaccountid"></a>
O ID do Conta da AWS que contém o recurso que está sendo avaliado.

`stackId`  <a name="lambda-hook-resource-stackid"></a>
O ID da pilha da CloudFormation qual essa operação faz parte. Esse campo estará vazio se o chamador for a Cloud Control API.

`changeSetId`  <a name="lambda-hook-resource-changesetid"></a>
O ID do conjunto de alterações que iniciou a invocação do Hook. Esse valor ficará vazio se a alteração do recurso tiver sido iniciada pela Cloud Control API ou pelas `delete-stack` operações `create-stack``update-stack`, ou.

`hookTypeName`  <a name="lambda-hook-resource-hooktypename"></a>
O nome do Hook que está funcionando.

`hookTypeVersion`  <a name="lambda-hook-resource-hooktypeversion"></a>
A versão do Hook que está sendo executada.

`hookModel`  <a name="lambda-hook-resource-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-resource-hookmodel-lambdafunction"></a>
O ARN atual do Lambda invocado pelo Hook.

`actionInvocationPoint`  <a name="lambda-hook-resource-actioninvocationpoint"></a>
O ponto exato na lógica de provisionamento em que o Hook é executado.  
*Valores válidos*: (`CREATE_PRE_PROVISION`\$1 `UPDATE_PRE_PROVISION` \$1`DELETE_PRE_PROVISION`)

`requestData`  <a name="lambda-hook-resource-requestdata"></a>  
`targetName`  <a name="lambda-hook-resource-requestdata-targetname"></a>
O tipo de alvo que está sendo avaliado, por exemplo,`AWS::S3::Bucket`.  
`targetType`  <a name="lambda-hook-resource-requestdata-targettype"></a>
O tipo de alvo que está sendo avaliado, por exemplo`AWS::S3::Bucket`. Para recursos provisionados com a Cloud Control API, esse valor será. `RESOURCE`  
`targetLogicalId`  <a name="lambda-hook-resource-requestdata-targetlogicalid"></a>
O ID lógico do recurso que está sendo avaliado. Se a origem da invocação do Hook for CloudFormation, esse será o ID lógico do recurso definido em seu CloudFormation modelo. Se a origem dessa invocação do Hook for a Cloud Control API, esse será um valor construído.  
`targetModel`  <a name="lambda-hook-resource-requestdata-targetmodel"></a>  
`resourceProperties`  <a name="lambda-hook-resource-requestdata-targetmodel-resourceproperties"></a>
As propriedades propostas do recurso que está sendo modificado. Se o recurso estiver sendo excluído, esse valor ficará vazio.   
`previousResourceProperties`  <a name="lambda-hook-resource-requestdata-targetmodel-previousresourceproperties"></a>
As propriedades atualmente associadas ao recurso que está sendo modificado. Se o recurso estiver sendo criado, esse valor ficará vazio.

`requestContext`  <a name="lambda-hook-resource-requestcontext"></a>  
invocação  <a name="lambda-hook-resource-requestcontext-invocation"></a>
A tentativa atual de executar o Hook.   
Contexto de retorno de chamada  <a name="lambda-hook-resource-requestcontext-callbackcontext"></a>
Se o Hook foi configurado para `IN_PROGRESS` e `callbackContext` foi devolvido, ele estará aqui após a reinvocação.

### Exemplo de entrada de alteração de recursos do Lambda Hook
<a name="lambda-hooks-create-lambda-function-resource-example"></a>

O exemplo de entrada a seguir mostra um Lambda Hook que receberá a definição do `AWS::DynamoDB::Table` recurso a ser atualizado, em que o `ReadCapacityUnits` of `ProvisionedThroughput` é alterado de 3 para 10. Esses são os dados disponíveis para a Lambda para avaliação.

```
{
    "awsAccountId": "123456789012",
    "stackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/MyStack/1a2345b6-0000-00a0-a123-00abc0abc000",
    "hookTypeName": "my::lambda::resourcehookfunction",
    "hookTypeVersion": "00000008",
    "hookModel": {
        "LambdaFunction": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction"
    },
    "actionInvocationPoint": "UPDATE_PRE_PROVISION",
    "requestData": {
        "targetName": "AWS::DynamoDB::Table",
        "targetType": "AWS::DynamoDB::Table",
        "targetLogicalId": "DDBTable",
        "targetModel": {
            "resourceProperties": {
                "AttributeDefinitions": [
                    {
                        "AttributeType": "S",
                        "AttributeName": "Album"
                    },
                    {
                        "AttributeType": "S",
                        "AttributeName": "Artist"
                    }
                ],
                "ProvisionedThroughput": {
                    "WriteCapacityUnits": 5,
                    "ReadCapacityUnits": 10
                },
                "KeySchema": [
                    {
                        "KeyType": "HASH",
                        "AttributeName": "Album"
                    },
                    {
                        "KeyType": "RANGE",
                        "AttributeName": "Artist"
                    }
                ]
            },
            "previousResourceProperties": {
                "AttributeDefinitions": [
                    {
                        "AttributeType": "S",
                        "AttributeName": "Album"
                    },
                    {
                        "AttributeType": "S",
                        "AttributeName": "Artist"
                    }
                ],
                "ProvisionedThroughput": {
                    "WriteCapacityUnits": 5,
                    "ReadCapacityUnits": 5
                },
                "KeySchema": [
                    {
                        "KeyType": "HASH",
                        "AttributeName": "Album"
                    },
                    {
                        "KeyType": "RANGE",
                        "AttributeName": "Artist"
                    }
                ]
            }
        }
    },
    "requestContext": {
        "invocation": 1,
        "callbackContext": null
    }    
}
```

Para ver todas as propriedades disponíveis para o tipo de recurso, consulte [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-table.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-dynamodb-table.html).

### Exemplo de função Lambda para operações de recursos
<a name="lambda-hooks-create-lambda-function-resource-example-function"></a>

Veja a seguir uma função simples que falha em qualquer atualização de recurso para o DynamoDB, que tenta definir `ReadCapacity` o `ProvisionedThroughput` of como algo maior que 10. Se o Hook for bem-sucedido, a mensagem “ReadCapacity está configurado corretamente” será exibida para o chamador. Se a solicitação falhar na validação, o Hook falhará com o status “ReadCapacity não pode ser maior que 10”.

------
#### [ Node.js ]

```
export const handler = async (event, context) => {
    var targetModel = event?.requestData?.targetModel;
    var targetName = event?.requestData?.targetName;
    var response = {
        "hookStatus": "SUCCESS",
        "message": "ReadCapacity is correctly configured.",
        "clientRequestToken": event.clientRequestToken
    };

    if (targetName == "AWS::DynamoDB::Table") {
        var readCapacity = targetModel?.resourceProperties?.ProvisionedThroughput?.ReadCapacityUnits;
        if (readCapacity > 10) {
            response.hookStatus = "FAILED";
            response.errorCode = "NonCompliant";
            response.message = "ReadCapacity must be cannot be more than 10.";
        }
    }
    return response;
};
```

------
#### [ Python ]

```
import json
                            
def lambda_handler(event, context):
    # Using dict.get() for safe access to nested dictionary values
    request_data = event.get('requestData', {})
    target_model = request_data.get('targetModel', {})
    target_name = request_data.get('targetName', '')
    
    response = {
        "hookStatus": "SUCCESS",
        "message": "ReadCapacity is correctly configured.",
        "clientRequestToken": event.get('clientRequestToken')
    }
    
    if target_name == "AWS::DynamoDB::Table":
        # Safely navigate nested dictionary
        resource_properties = target_model.get('resourceProperties', {})
        provisioned_throughput = resource_properties.get('ProvisionedThroughput', {})
        read_capacity = provisioned_throughput.get('ReadCapacityUnits')
        
        if read_capacity and read_capacity > 10:
            response['hookStatus'] = "FAILED"
            response['errorCode'] = "NonCompliant"
            response['message'] = "ReadCapacity must be cannot be more than 10."
    
    return response
```

------

## Avaliação de operações de pilha com Lambda Hooks
<a name="lambda-hooks-create-lambda-function-stack"></a>

Sempre que você cria, atualiza ou exclui uma pilha com um novo modelo, você pode configurar seu CloudFormation Lambda Hook para começar avaliando o novo modelo e potencialmente impedir que a operação da pilha continue. Você pode configurar seu CloudFormation Lambda Hook para direcionar `STACK` operações na configuração do Hook`TargetOperations`.

**Topics**
+ [

### Sintaxe de entrada da pilha Lambda Hook
](#lambda-hooks-create-lambda-function-stack-input)
+ [

### Exemplo de entrada de alteração de pilha do Lambda Hook
](#lambda-hooks-create-lambda-function-stack-example)
+ [

### Exemplo de função Lambda para operações de pilha
](#lambda-hooks-create-lambda-function-stack-example-function)

### Sintaxe de entrada da pilha Lambda Hook
<a name="lambda-hooks-create-lambda-function-stack-input"></a>

Quando seu Lambda for invocado para uma operação de pilha, você receberá uma solicitação JSON contendo o contexto de invocação do Hook e o contexto da solicitação. `actionInvocationPoint` Devido ao tamanho dos CloudFormation modelos e ao tamanho limitado de entrada aceito pelas funções do Lambda, os modelos reais são armazenados em um objeto Amazon S3. A entrada do `requestData` inclui uma URL resignada do Amazon S3 para outro objeto, que contém a versão atual e anterior do modelo.

Veja a seguir um exemplo de formato da entrada JSON:

```
{
    "clientRequesttoken": String,
    "awsAccountId": String,
    "stackID": String,
    "changeSetId": String,
    "hookTypeName": String,
    "hookTypeVersion": String,
    "hookModel": {
        "LambdaFunction":String
    },
    "actionInvocationPoint": "CREATE_PRE_PROVISION" or "UPDATE_PRE_PROVISION" or "DELETE_PRE_PROVISION"
    "requestData": {
        "targetName": "STACK",
        "targetType": "STACK",
        "targetLogicalId": String,
        "payload": String (S3 Presigned URL)
    },
    "requestContext": {
        "invocation": Integer,
        "callbackContext": String
    }
}
```

`clientRequesttoken`  <a name="lambda-hook-stack-clientrequesttoken"></a>
O token de solicitação que foi fornecido como entrada para a solicitação do Hook. Este é um campo obrigatório.

`awsAccountId`  <a name="lambda-hook-stack-awsaccountid"></a>
O ID do Conta da AWS que contém a pilha que está sendo avaliada.

`stackID`  <a name="lambda-hook-stack-stackid"></a>
O ID da pilha. CloudFormation 

`changeSetId`  <a name="lambda-hook-stack-changesetid"></a>
O ID do conjunto de alterações que iniciou a invocação do Hook. Esse valor ficará vazio se a alteração da pilha tiver sido iniciada pela Cloud Control API ou pelas `delete-stack` operações `create-stack``update-stack`, ou.

`hookTypeName`  <a name="lambda-hook-stack-hooktypename"></a>
O nome do Hook que está funcionando.

`hookTypeVersion`  <a name="lambda-hook-stack-hooktypeversion"></a>
A versão do Hook que está sendo executada.

`hookModel`  <a name="lambda-hook-stack-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-stack-hookmodel-lambdafunction"></a>
O ARN atual do Lambda invocado pelo Hook.

`actionInvocationPoint`  <a name="lambda-hook-stack-actioninvocationpoint"></a>
O ponto exato na lógica de provisionamento em que o Hook é executado.  
*Valores válidos*: (`CREATE_PRE_PROVISION`\$1 `UPDATE_PRE_PROVISION` \$1`DELETE_PRE_PROVISION`)

`requestData`  <a name="lambda-hook-stack-requestdata"></a>  
`targetName`  <a name="lambda-hook-stack-requestdata-targetname"></a>
Esse valor será `STACK`.  
`targetType`  <a name="lambda-hook-stack-requestdata-targettype"></a>
Esse valor será `STACK`.  
`targetLogicalId`  <a name="lambda-hook-stack-requestdata-targetlogicalid"></a>
O nome da pilha.  
`payload`  <a name="lambda-hook-stack-requestdata-payload"></a>
A URL pré-assinada do Amazon S3 contendo um objeto JSON com as definições de modelo atuais e anteriores.

`requestContext`  <a name="lambda-hook-stack-requestcontext"></a>
Se o Hook estiver sendo invocado novamente, esse objeto será definido.    
`invocation`  <a name="lambda-hook-stack-requestcontext-invocation"></a>
A tentativa atual de executar o Hook.  
`callbackContext`  <a name="lambda-hook-stack-requestcontext-callbackcontext"></a>
Se o Hook foi configurado `IN_PROGRESS` e `callbackContext` foi devolvido, ele estará aqui após a reinvocação.

A `payload` propriedade nos dados da solicitação é uma URL que seu código precisa buscar. Depois de receber a URL, você obtém um objeto com o seguinte esquema:

```
{
    "template": String,
    "previousTemplate": String
}
```

`template`  <a name="lambda-hook-stack-payload-template"></a>
O CloudFormation modelo completo que foi fornecido para `create-stack` ou`update-stack`. Ela pode ser uma string JSON ou YAML, dependendo do que foi fornecido. CloudFormation  
Nas `delete-stack` operações, esse valor estará vazio.

`previousTemplate`  <a name="lambda-hook-stack-payload-previoustemplate"></a>
O CloudFormation modelo anterior. Ela pode ser uma string JSON ou YAML, dependendo do que foi fornecido. CloudFormation  
Nas `delete-stack` operações, esse valor estará vazio.

### Exemplo de entrada de alteração de pilha do Lambda Hook
<a name="lambda-hooks-create-lambda-function-stack-example"></a>

Veja a seguir um exemplo de entrada de alteração de pilha. O Hook está avaliando uma alteração que atualiza o `ObjectLockEnabled` para true e adiciona uma fila do Amazon SQS:

```
{
    "clientRequestToken": "f8da6d11-b23f-48f4-814c-0fb6a667f50e",
    "awsAccountId": "123456789012",
    "stackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/MyStack/1a2345b6-0000-00a0-a123-00abc0abc000",
    "changeSetId": null,
    "hookTypeName": "my::lambda::stackhook",
    "hookTypeVersion": "00000008",
    "hookModel": {
        "LambdaFunction": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction"
    },
    "actionInvocationPoint": "UPDATE_PRE_PROVISION",
    "requestData": {
        "targetName": "STACK",
        "targetType": "STACK",
        "targetLogicalId": "my-cloudformation-stack",
        "payload": "https://s3......"
    },
    "requestContext": {
        "invocation": 1,
        "callbackContext": null
    }
}
```

Este é um exemplo `payload` do`requestData`:

```
{
    "template": "{\"Resources\":{\"S3Bucket\":{\"Type\":\"AWS::S3::Bucket\",\"Properties\":{\"ObjectLockEnabled\":true}},\"SQSQueue\":{\"Type\":\"AWS::SQS::Queue\",\"Properties\":{\"QueueName\":\"NewQueue\"}}}}",
    "previousTemplate": "{\"Resources\":{\"S3Bucket\":{\"Type\":\"AWS::S3::Bucket\",\"Properties\":{\"ObjectLockEnabled\":false}}}}"
}
```

### Exemplo de função Lambda para operações de pilha
<a name="lambda-hooks-create-lambda-function-stack-example-function"></a>

O exemplo a seguir é uma função simples que baixa a carga útil da operação de pilha, analisa o modelo JSON e retorna. `SUCCESS`

------
#### [ Node.js ]

```
export const handler = async (event, context) => {
    var targetType = event?.requestData?.targetType;
    var payloadUrl = event?.requestData?.payload;
    
    var response = {
        "hookStatus": "SUCCESS",
        "message": "Stack update is compliant",
        "clientRequestToken": event.clientRequestToken
    };
    try {
        const templateHookPayloadRequest = await fetch(payloadUrl);
        const templateHookPayload = await templateHookPayloadRequest.json()
        if (templateHookPayload.template)  {
            // Do something with the template templateHookPayload.template
            // JSON or YAML
        }
        if (templateHookPayload.previousTemplate) {
            // Do something with the template templateHookPayload.previousTemplate
            // JSON or YAML        
        }        
    } catch (error) {
        console.log(error);
        response.hookStatus = "FAILED";
        response.message = "Failed to evaluate stack operation.";
        response.errorCode = "InternalFailure";
    }
    return response;
};
```

------
#### [ Python ]

Para usar o Python, você precisará importar a `requests` biblioteca. Para fazer isso, você precisará incluir a biblioteca em seu pacote de implantação ao criar sua função Lambda. Para obter mais informações, consulte [Criação de um pacote de implantação .zip com dependências](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies) no Guia do *AWS Lambda desenvolvedor*.

```
import json
import requests

def lamnbda_handler(event, context):
    # Safely access nested dictionary values
    request_data = event.get('requestData', {})
    target_type = request_data.get('targetType')
    payload_url = request_data.get('payload')
    
    response = {
        "hookStatus": "SUCCESS",
        "message": "Stack update is compliant",
        "clientRequestToken": event.get('clientRequestToken')
    }
    
    try:
        # Fetch the payload
        template_hook_payload_request = requests.get(payload_url)
        template_hook_payload_request.raise_for_status()  # Raise an exception for bad responses
        template_hook_payload = template_hook_payload_request.json()
        
        if 'template' in template_hook_payload:
            # Do something with the template template_hook_payload['template']
            # JSON or YAML
            pass
        
        if 'previousTemplate' in template_hook_payload:
            # Do something with the template template_hook_payload['previousTemplate']
            # JSON or YAML
            pass

    except Exception as error:
        print(error)
        response['hookStatus'] = "FAILED"
        response['message'] = "Failed to evaluate stack operation."
        response['errorCode'] = "InternalFailure"
    
    return response
```

------

## Avaliando as operações do conjunto de alterações com Lambda Hooks
<a name="lambda-hooks-create-lambda-function-change-set"></a>

Sempre que criar um conjunto de alterações, você pode configurar seu CloudFormation Lambda Hook para avaliar primeiro o novo conjunto de alterações e potencialmente bloquear sua execução. Você pode configurar seu CloudFormation Lambda Hook para direcionar `CHANGE_SET` operações na configuração do Hook`TargetOperations`.

**Topics**
+ [

### Sintaxe de entrada do conjunto de alterações do Lambda Hook
](#lambda-hooks-create-lambda-function-change-set-input)
+ [

### Exemplo de entrada de alteração do conjunto de alterações do Lambda Hook
](#lambda-hooks-create-lambda-function-change-set-example)
+ [

### Exemplo de função Lambda para operações de conjunto de alterações
](#lambda-hooks-create-lambda-function-change-set-example-function)

### Sintaxe de entrada do conjunto de alterações do Lambda Hook
<a name="lambda-hooks-create-lambda-function-change-set-input"></a>

A entrada para as operações do conjunto de alterações é semelhante às operações de pilha, mas a carga útil do `requestData` também inclui uma lista de alterações de recursos introduzidas pelo conjunto de alterações.

Veja a seguir um exemplo de formato da entrada JSON:

```
{
    "clientRequesttoken": String,
    "awsAccountId": String,
    "stackID": String,
    "changeSetId": String,
    "hookTypeName": String,
    "hookTypeVersion": String,
    "hookModel": {
        "LambdaFunction":String
    },
    "requestData": {
        "targetName": "CHANGE_SET",
        "targetType": "CHANGE_SET",
        "targetLogicalId": String,
        "payload": String (S3 Presigned URL)
    },
    "requestContext": {
        "invocation": Integer,
        "callbackContext": String
    }
}
```

`clientRequesttoken`  <a name="lambda-hook-change-set-clientrequesttoken"></a>
O token de solicitação que foi fornecido como entrada para a solicitação do Hook. Este é um campo obrigatório.

`awsAccountId`  <a name="lambda-hook-change-set-awsaccountid"></a>
O ID do Conta da AWS que contém a pilha que está sendo avaliada.

`stackID`  <a name="lambda-hook-change-set-stackid"></a>
O ID da pilha. CloudFormation 

`changeSetId`  <a name="lambda-hook-change-set-changesetid"></a>
O ID do conjunto de alterações que iniciou a invocação do Hook.

`hookTypeName`  <a name="lambda-hook-change-set-hooktypename"></a>
O nome do Hook que está funcionando.

`hookTypeVersion`  <a name="lambda-hook-change-set-hooktypeversion"></a>
A versão do Hook que está sendo executada.

`hookModel`  <a name="lambda-hook-change-set-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-change-set-hookmodel-lambdafunction"></a>
O ARN atual do Lambda invocado pelo Hook.

`requestData`  <a name="lambda-hook-change-set-requestdata"></a>  
`targetName`  <a name="lambda-hook-change-set-requestdata-targetname"></a>
Esse valor será `CHANGE_SET`.  
`targetType`  <a name="lambda-hook-change-set-requestdata-targettype"></a>
Esse valor será `CHANGE_SET`.  
`targetLogicalId`  <a name="lambda-hook-change-set-requestdata-targetlogicalid"></a>
O conjunto de alterações ARN..  
`payload`  <a name="lambda-hook-change-set-requestdata-payload"></a>
A URL pré-assinada do Amazon S3 contendo um objeto JSON com o modelo atual, bem como uma lista das alterações introduzidas por esse conjunto de alterações.

`requestContext`  <a name="lambda-hook-change-set-requestcontext"></a>
Se o Hook estiver sendo invocado novamente, esse objeto será definido.    
`invocation`  <a name="lambda-hook-change-set-requestcontext-invocation"></a>
A tentativa atual de executar o Hook.  
`callbackContext`  <a name="lambda-hook-change-set-requestcontext-callbackcontext"></a>
Se o Hook foi configurado `IN_PROGRESS` e `callbackContext` foi devolvido, ele estará aqui após a reinvocação.

A `payload` propriedade nos dados da solicitação é uma URL que seu código precisa buscar. Depois de receber a URL, você obtém um objeto com o seguinte esquema:

```
{
    "template": String,
    "changedResources": [
        {
            "action": String,
            "beforeContext": JSON String,
            "afterContext": JSON String,
            "lineNumber": Integer,
            "logicalResourceId": String,
            "resourceType": String
        }
    ]
}
```

`template`  <a name="lambda-hook-change-set-payload-template"></a>
O CloudFormation modelo completo que foi fornecido para `create-stack` ou`update-stack`. Ela pode ser uma string JSON ou YAML, dependendo do que foi fornecido. CloudFormation

`changedResources`  <a name="lambda-hook-change-set-payload-changed-resources"></a>
Uma lista dos recursos alterados.    
`action`  <a name="lambda-hook-change-set-payload-changed-resources-action"></a>
O tipo de alteração aplicada ao recurso.  
*Valores válidos*: (`CREATE`\$1 `UPDATE` \$1`DELETE`)  
`beforeContext`  <a name="lambda-hook-change-set-payload-changed-resources-beforecontext"></a>
Uma string JSON das propriedades do recurso antes da alteração. Esse valor é nulo quando o recurso está sendo criado. Todos os valores booleanos e numéricos nessa string JSON são STRINGS.  
`afterContext`  <a name="lambda-hook-change-set-payload-changed-resources-aftercontext"></a>
Uma string JSON das propriedades dos recursos se esse conjunto de alterações for executado. Esse valor é nulo quando o recurso está sendo excluído. Todos os valores booleanos e numéricos nessa string JSON são STRINGS.  
`lineNumber`  <a name="lambda-hook-change-set-payload-changed-resources-linenumber"></a>
O número da linha no modelo que causou essa alteração. Se a ação for, `DELETE` esse valor será nulo.   
`logicalResourceId`  <a name="lambda-hook-change-set-payload-changed-resources-logicalresourceid"></a>
O ID lógico do recurso que está sendo alterado.  
`resourceType`  <a name="lambda-hook-change-set-payload-changed-resources-resourcetype"></a>
O tipo de recurso que está sendo alterado.

### Exemplo de entrada de alteração do conjunto de alterações do Lambda Hook
<a name="lambda-hooks-create-lambda-function-change-set-example"></a>

Veja a seguir um exemplo de entrada de alteração do conjunto de alterações. No exemplo a seguir, você pode ver as alterações introduzidas pelo conjunto de alterações. A primeira alteração é excluir uma fila chamada. `CoolQueue` A segunda mudança é adicionar uma nova fila chamada`NewCoolQueue`. A última alteração é uma atualização do`DynamoDBTable`.

```
{
    "clientRequestToken": "f8da6d11-b23f-48f4-814c-0fb6a667f50e",
    "awsAccountId": "123456789012",
    "stackId": "arn:aws:cloudformation:us-west-2:123456789012:stack/MyStack/1a2345b6-0000-00a0-a123-00abc0abc000",
    "changeSetId": "arn:aws:cloudformation:us-west-2:123456789012:changeSet/SampleChangeSet/1a2345b6-0000-00a0-a123-00abc0abc000",
    "hookTypeName": "my::lambda::changesethook",
    "hookTypeVersion": "00000008",
    "hookModel": {
        "LambdaFunction": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction"
    },
    "actionInvocationPoint": "CREATE_PRE_PROVISION",
    "requestData": {
        "targetName": "CHANGE_SET",
        "targetType": "CHANGE_SET",
        "targetLogicalId": "arn:aws:cloudformation:us-west-2:123456789012:changeSet/SampleChangeSet/1a2345b6-0000-00a0-a123-00abc0abc000",
        "payload": "https://s3......"
    },
    "requestContext": {
        "invocation": 1,
        "callbackContext": null
    }
}
```

Este é um exemplo `payload` do`requestData.payload`:

```
{
  template: 'Resources:\n' +
    '  DynamoDBTable:\n' +
    '    Type: AWS::DynamoDB::Table\n' +
    '    Properties:\n' +
    '      AttributeDefinitions:\n' +
    '        - AttributeName: "PK"\n' +
    '          AttributeType: "S"\n' +
    '      BillingMode: "PAY_PER_REQUEST"\n' +
    '      KeySchema:\n' +
    '        - AttributeName: "PK"\n' +
    '          KeyType: "HASH"\n' +
    '      PointInTimeRecoverySpecification:\n' +
    '        PointInTimeRecoveryEnabled: false\n' +
    '  NewSQSQueue:\n' +
    '    Type: AWS::SQS::Queue\n' +
    '    Properties:\n' +
    '      QueueName: "NewCoolQueue"',
  changedResources: [
    {
      logicalResourceId: 'SQSQueue',
      resourceType: 'AWS::SQS::Queue',
      action: 'DELETE',
      lineNumber: null,
      beforeContext: '{"Properties":{"QueueName":"CoolQueue"}}',
      afterContext: null
    },
    {
      logicalResourceId: 'NewSQSQueue',
      resourceType: 'AWS::SQS::Queue',
      action: 'CREATE',
      lineNumber: 14,
      beforeContext: null,
      afterContext: '{"Properties":{"QueueName":"NewCoolQueue"}}'
    },
    {
      logicalResourceId: 'DynamoDBTable',
      resourceType: 'AWS::DynamoDB::Table',
      action: 'UPDATE',
      lineNumber: 2,
      beforeContext: '{"Properties":{"BillingMode":"PAY_PER_REQUEST","AttributeDefinitions":[{"AttributeType":"S","AttributeName":"PK"}],"KeySchema":[{"KeyType":"HASH","AttributeName":"PK"}]}}',
      afterContext: '{"Properties":{"BillingMode":"PAY_PER_REQUEST","PointInTimeRecoverySpecification":{"PointInTimeRecoveryEnabled":"false"},"AttributeDefinitions":[{"AttributeType":"S","AttributeName":"PK"}],"KeySchema":[{"KeyType":"HASH","AttributeName":"PK"}]}}'
    }
  ]
}
```

### Exemplo de função Lambda para operações de conjunto de alterações
<a name="lambda-hooks-create-lambda-function-change-set-example-function"></a>

O exemplo a seguir é uma função simples que baixa a carga útil da operação do conjunto de alterações, percorre cada alteração e, em seguida, imprime as propriedades antes e depois antes de retornar a. `SUCCESS`

------
#### [ Node.js ]

```
export const handler = async (event, context) => {
    var payloadUrl = event?.requestData?.payload;    
    var response = {
        "hookStatus": "SUCCESS",
        "message": "Change set changes are compliant",
        "clientRequestToken": event.clientRequestToken
    };
    try {
        const changeSetHookPayloadRequest = await fetch(payloadUrl);
        const changeSetHookPayload = await changeSetHookPayloadRequest.json();
        const changes = changeSetHookPayload.changedResources || [];
        for(const change of changes) {
            var beforeContext = {};
            var afterContext = {};
            if(change.beforeContext) {
                beforeContext = JSON.parse(change.beforeContext);
            }
            if(change.afterContext) {
                afterContext = JSON.parse(change.afterContext);
            }
            console.log(beforeContext)
            console.log(afterContext)
            // Evaluate Change here
        }
    } catch (error) {
        console.log(error);
        response.hookStatus = "FAILED";
        response.message = "Failed to evaluate change set operation.";
        response.errorCode = "InternalFailure";
    }
    return response;
};
```

------
#### [ Python ]

Para usar o Python, você precisará importar a `requests` biblioteca. Para fazer isso, você precisará incluir a biblioteca em seu pacote de implantação ao criar sua função Lambda. Para obter mais informações, consulte [Criação de um pacote de implantação .zip com dependências](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies) no Guia do *AWS Lambda desenvolvedor*.

```
import json
import requests

def lambda_handler(event, context):
    payload_url = event.get('requestData', {}).get('payload')
    response = {
        "hookStatus": "SUCCESS",
        "message": "Change set changes are compliant",
        "clientRequestToken": event.get('clientRequestToken')
    }

    try:
        change_set_hook_payload_request = requests.get(payload_url)
        change_set_hook_payload_request.raise_for_status()  # Raises an HTTPError for bad responses
        change_set_hook_payload = change_set_hook_payload_request.json()
        
        changes = change_set_hook_payload.get('changedResources', [])
        
        for change in changes:
            before_context = {}
            after_context = {}
            
            if change.get('beforeContext'):
                before_context = json.loads(change['beforeContext'])
            
            if change.get('afterContext'):
                after_context = json.loads(change['afterContext'])
            
            print(before_context)
            print(after_context)
            # Evaluate Change here

    except requests.RequestException as error:
        print(error)
        response['hookStatus'] = "FAILED"
        response['message'] = "Failed to evaluate change set operation."
        response['errorCode'] = "InternalFailure"
    except json.JSONDecodeError as error:
        print(error)
        response['hookStatus'] = "FAILED"
        response['message'] = "Failed to parse JSON payload."
        response['errorCode'] = "InternalFailure"

    return response
```

------