

本文属于机器翻译版本。若本译文内容与英语原文存在差异，则一律以英文原文为准。

# Lambda 挂钩
<a name="lambda-hooks"></a>

要在您的账户中使用 AWS Lambda 挂钩，您必须先为要使用该挂钩的账户和区域*激活*挂钩。激活 Hook 后，它可以在激活该挂钩的账户和区域的堆栈操作中使用。

激活 Lambda 挂钩时， CloudFormation 会在账户的注册表中为已激活的挂钩创建一个条目作为私有挂钩。这允许您设置 Hook 包含的任何配置属性。配置属性定义了如何为给定 AWS 账户 和区域配置挂钩。

**Topics**
+ [AWS CLI 用于使用 Lambda 挂钩的命令](#commonly-used-commands-lambda-hooks)
+ [创建 Lambda 函数来评估 Lambda 挂钩的资源](lambda-hooks-create-lambda-function.md)
+ [准备创建 Lambda 挂钩](lambda-hooks-prepare-to-create-hook.md)
+ [在您的账户中激活 Lambda 挂钩](lambda-hooks-activate-hooks.md)
+ [查看您账户中 Lambda 挂钩的日志](lambda-hooks-view-logs.md)
+ [删除账户中的 Lambda 挂钩](lambda-hooks-delete-hooks.md)

## AWS CLI 用于使用 Lambda 挂钩的命令
<a name="commonly-used-commands-lambda-hooks"></a>

使用 Lambda 挂钩的 AWS CLI 命令包括：
+ [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/activate-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/activate-type.html)启动 Lambda 挂钩的激活过程。
+ [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/set-type-configuration.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/set-type-configuration.html)为账户中的 Hook 指定配置数据。
+ [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-types.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/list-types.html)列出你账户中的 Hook。
+ [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/describe-type.html)返回有关特定 Hook 或特定 Hook 版本的详细信息，包括当前配置数据。
+ [https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deactivate-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deactivate-type.html)从您的账户中移除之前激活的 Hook。

# 创建 Lambda 函数来评估 Lambda 挂钩的资源
<a name="lambda-hooks-create-lambda-function"></a>

CloudFormation Lambda Hooks 允许您对自己的自定义代码进行评估 CloudFormation 和 AWS 云端控制 API 操作。您的 Hook 可以阻止操作继续进行，或者向调用者发出警告并允许操作继续进行。创建 Lambda 挂钩时，可以将其配置为拦截和评估以下操作： CloudFormation 
+ 资源操作
+ 堆栈操作
+ 更改集合操作

**Topics**
+ [开发 Lambda 挂钩](#lambda-hooks-create-lambda-function-develop)
+ [使用 Lambda 挂钩评估资源操作](#lambda-hooks-create-lambda-function-resource)
+ [使用 Lambda 挂钩评估堆栈操作](#lambda-hooks-create-lambda-function-stack)
+ [使用 Lambda 挂钩评估变更集操作](#lambda-hooks-create-lambda-function-change-set)

## 开发 Lambda 挂钩
<a name="lambda-hooks-create-lambda-function-develop"></a>

当 Hook 调用你的 Lambda 时，它将等待长达 30 秒钟让 Lambda 评估输入。Lambda 将返回一个 JSON 响应，指示挂钩是成功还是失败。

**Topics**
+ [请求输入](#lambda-hooks-create-lambda-function-request-input)
+ [响应输入](#lambda-hooks-create-lambda-function-request-response)
+ [示例](#lambda-hooks-create-lambda-function-request-example)

### 请求输入
<a name="lambda-hooks-create-lambda-function-request-input"></a>

传递给 Lambda 函数的输入取决于 Hook 目标操作（例如：堆栈、资源或更改集）。

### 响应输入
<a name="lambda-hooks-create-lambda-function-request-response"></a>

为了在您的请求成功或失败时与 Hook 进行通信，您的 Lambda 函数需要返回 JSON 响应。

以下是 Hooks 期望的响应的示例形状：

```
{ 
  "挂钩状态": "SUCCESS" or "FAILED" or "IN_PROGRESS", 
  "errorCode": "NonCompliant" or "InternalFailure"
  "message": String, 
  "clientRequestToken": String,
  "回调上下文": None, 
  "callbackDelaySeconds": Integer,
  "annotations": [
    {
      "annotationName": String,
      "status": "PASSED" or "FAILED" or "SKIPPED",
      "statusMessage": String,
      "remediationMessage": String,
      "remediationLink": String,
      "severityLevel": "INFORMATIONAL" or "LOW" or "MEDIUM" or "HIGH" or "CRITICAL"
    }
  ]
}
```

挂钩状态  <a name="lambda-hook-response-hookstatus"></a>
挂钩的状态。此字段为必填字段。  
*有效值*：(`SUCCESS`\$1 `FAILED` \$1`IN_PROGRESS`)  
Hook 可以返回 `IN_PROGRESS` 3 次。如果未返回任何结果，Hook 将失败。对于 Lambda 挂钩，这意味着您的 Lambda 函数最多可以被调用 3 次。

errorCode  <a name="lambda-hook-response-errorcode"></a>
显示操作是否经过评估并被确定为无效，或者挂钩内是否发生了错误，从而阻止了评估。如果挂钩失败，则此字段为必填字段。  
*有效值*：(`NonCompliant`\$1`InternalFailure`)

message  <a name="lambda-hook-response-message"></a>
给调用者的消息，说明挂钩成功或失败的原因。  
计算 CloudFormation 操作时，此字段被截断为 4096 个字符。  
在评估 Cloud Control API 操作时，此字段被截断为 1024 个字符。

clientRequestToken  <a name="lambda-hook-response-clientrequesttoken"></a>
作为 Hook 请求的输入而提供的请求令牌。此字段为必填字段。

回调上下文  <a name="lambda-hook-response-callbackcontext"></a>
如果您指明`hookStatus`是，则`IN_PROGRESS`会传递一个额外的上下文，该上下文在重新调用 Lambda 函数时作为输入提供。

callbackDelaySeconds  <a name="lambda-hook-response-callbackdelayseconds"></a>
Hook 应该等多久才能再次调用这个 Hook。

annotations  <a name="lambda-hook-response-annotations"></a>
一系列注释对象，可提供更多详细信息和补救指导。    
注释名称  
注释的标识符。  
status  
Hook 调用状态。当注解表示逻辑时，这会很有用，其通过/失败评估与防护规则类似。  
*有效值*：(`PASSED`\$1 `FAILED` \$1`SKIPPED`)  
statusMessage  
具体状态的解释。  
补救消息  
关于修复`FAILED`状态的建议。例如，如果资源缺少加密，则可以说明如何为资源配置添加加密。  
修正链接  
用于获取更多补救指南的 HTTP 网址。  
severityLevel  
定义与任何此类违规行为相关的相对风险。在为 Hook 调用结果分配严重性级别时，您可以参考 AWS Security Hub CSPM [严重性框架](https://docs.aws.amazon.com/securityhub/latest/userguide/asff-required-attributes.html#Severity)，以此作为如何构建有意义的严重性类别的示例。  
*有效值*：(`INFORMATIONAL`\$1 `LOW` \$1 `MEDIUM` \$1 `HIGH` \$1`CRITICAL`)

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

以下是成功响应的示例：

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

以下是响应失败的示例：

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

## 使用 Lambda 挂钩评估资源操作
<a name="lambda-hooks-create-lambda-function-resource"></a>

每当您创建、更新或删除资源时，都被视为资源操作。例如，如果您运行更新 CloudFormation 堆栈以创建新资源，则表示您已完成资源操作。当您使用 Cloud Control API 创建、更新或删除资源时，这也被视为资源操作。您可以将 CloudFormation Lambda 挂钩配置为目标`RESOURCE`和挂钩`TargetOperations`配置中的`CLOUD_CONTROL`操作。

**注意**  
只有在使用 Cloud Control API `delete-resource` 中的操作触发器删除资源时，才会调用 `delete` Hook 处理程序 CloudFormation `delete-stack`。

**Topics**
+ [Lambda Hook 资源输入语法](#lambda-hooks-create-lambda-function-resource-input)
+ [Lambda Hook 资源变更输入示例](#lambda-hooks-create-lambda-function-resource-example)
+ [用于资源操作的 Lambda 函数示例](#lambda-hooks-create-lambda-function-resource-example-function)

### Lambda Hook 资源输入语法
<a name="lambda-hooks-create-lambda-function-resource-input"></a>

当您的 Lambda 被调用进行资源操作时，您将收到一个 JSON 输入，其中包含资源属性、建议的属性以及与 Hook 调用相关的上下文。

以下是 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": {
        "调用": 1,
        "回调上下文": null
    }
}
```

`awsAccountId`  <a name="lambda-hook-resource-awsaccountid"></a>
 AWS 账户 包含正在评估的资源的 ID。

`stackId`  <a name="lambda-hook-resource-stackid"></a>
此操作所属 CloudFormation 堆栈的堆栈 ID。如果调用方是云控制 API，则此字段为空。

`changeSetId`  <a name="lambda-hook-resource-changesetid"></a>
启动 Hook 调用的更改集的 ID。如果资源变更是由云控制 API 或、或`delete-stack`操作启动的，则此值为`create-stack`空。`update-stack`

`hookTypeName`  <a name="lambda-hook-resource-hooktypename"></a>
正在运行的 Hook 的名称。

`hookTypeVersion`  <a name="lambda-hook-resource-hooktypeversion"></a>
正在运行的 Hook 的版本。

`hookModel`  <a name="lambda-hook-resource-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-resource-hookmodel-lambdafunction"></a>
挂钩调用的当前 Lambda ARN。

`actionInvocationPoint`  <a name="lambda-hook-resource-actioninvocationpoint"></a>
配置逻辑中挂钩运行的确切位置。  
*有效值*：(`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>
正在评估的目标类型，例如`AWS::S3::Bucket`。  
`targetType`  <a name="lambda-hook-resource-requestdata-targettype"></a>
例如，正在评估的目标类型`AWS::S3::Bucket`。对于使用云控制 API 置备的资源，此值将`RESOURCE`为。  
`targetLogicalId`  <a name="lambda-hook-resource-requestdata-targetlogicalid"></a>
正在评估的资源的逻辑 ID。如果 Hook 调用的来源是 CloudFormation，则这将是 CloudFormation 模板中定义的逻辑资源 ID。如果此 Hook 调用的来源是 Cloud Control API，则这将是一个构造值。  
`targetModel`  <a name="lambda-hook-resource-requestdata-targetmodel"></a>  
`resourceProperties`  <a name="lambda-hook-resource-requestdata-targetmodel-resourceproperties"></a>
正在修改的资源的建议属性。如果要删除资源，则此值将为空。  
`previousResourceProperties`  <a name="lambda-hook-resource-requestdata-targetmodel-previousresourceproperties"></a>
当前与正在修改的资源关联的属性。如果正在创建资源，则此值将为空。

`requestContext`  <a name="lambda-hook-resource-requestcontext"></a>  
调用  <a name="lambda-hook-resource-requestcontext-invocation"></a>
当前执行挂钩的尝试。  
回调上下文  <a name="lambda-hook-resource-requestcontext-callbackcontext"></a>
如果 Hookwas 设置为`IN_PROGRESS`，并且`callbackContext`已返回，则它将在重新调用后出现在这里。

### Lambda Hook 资源变更输入示例
<a name="lambda-hooks-create-lambda-function-resource-example"></a>

以下示例输入显示了一个 Lambda 挂钩，它将接收要更新的`AWS::DynamoDB::Table`资源定义，其中 of `ReadCapacityUnits` 从 3 更改`ProvisionedThroughput`为 10。这是 Lambda 可用于评估的数据。

```
{
    "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
    }    
}
```

要查看该资源类型的所有可用属性，请参见[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)。

### 用于资源操作的 Lambda 函数示例
<a name="lambda-hooks-create-lambda-function-resource-example-function"></a>

以下是一个简单的函数，它会让 DynamoDB 的任何资源更新失败，DynamoDB 会尝试将 of 设置为`ReadCapacity`大于 `ProvisionedThroughput` 10 的值。如果挂接成功，则将向呼叫者显示消息 “ReadCapacity 配置正确”。如果请求验证失败，则挂钩将失败，状态为 “ReadCapacity 不能超过 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
```

------

## 使用 Lambda 挂钩评估堆栈操作
<a name="lambda-hooks-create-lambda-function-stack"></a>

每当您使用新模板创建、更新或删除堆栈时，都可以将您的 CloudFormation Lambda Hook 配置为从评估新模板开始，并可能阻止堆栈操作继续进行。您可以将 CloudFormation Lambda 挂钩配置为挂钩配置中的`STACK`操作目标。`TargetOperations`

**Topics**
+ [Lambda Hook 堆栈输入语法](#lambda-hooks-create-lambda-function-stack-input)
+ [Lambda Hook 堆栈更改输入示例](#lambda-hooks-create-lambda-function-stack-example)
+ [用于堆栈操作的 Lambda 函数示例](#lambda-hooks-create-lambda-function-stack-example-function)

### Lambda Hook 堆栈输入语法
<a name="lambda-hooks-create-lambda-function-stack-input"></a>

当为堆栈操作调用 Lambda 时，您将收到一个包含 Hook 调用上下文和请求上下文的 JSON 请求。`actionInvocationPoint`由于 CloudFormation 模板的大小以及 Lambda 函数接受的输入大小有限，因此实际模板存储在 Amazon S3 对象中。的输入`requestData`包括指向另一个对象的 Amazon S3 签名 URL，其中包含当前和以前的模板版本。

以下是 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>
作为 Hook 请求的输入而提供的请求令牌。此字段为必填字段。

`awsAccountId`  <a name="lambda-hook-stack-awsaccountid"></a>
 AWS 账户 包含正在评估的堆栈的 ID。

`stackID`  <a name="lambda-hook-stack-stackid"></a>
堆栈的堆 CloudFormation 栈 ID。

`changeSetId`  <a name="lambda-hook-stack-changesetid"></a>
启动 Hook 调用的更改集的 ID。如果堆栈变更是由云控制 API 或、或`delete-stack`操作启动的，则此值为`create-stack`空。`update-stack`

`hookTypeName`  <a name="lambda-hook-stack-hooktypename"></a>
正在运行的 Hook 的名称。

`hookTypeVersion`  <a name="lambda-hook-stack-hooktypeversion"></a>
正在运行的 Hook 的版本。

`hookModel`  <a name="lambda-hook-stack-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-stack-hookmodel-lambdafunction"></a>
挂钩调用的当前 Lambda ARN。

`actionInvocationPoint`  <a name="lambda-hook-stack-actioninvocationpoint"></a>
配置逻辑中挂钩运行的确切位置。  
*有效值*：(`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>
这个值将是 `STACK`。  
`targetType`  <a name="lambda-hook-stack-requestdata-targettype"></a>
这个值将是 `STACK`。  
`targetLogicalId`  <a name="lambda-hook-stack-requestdata-targetlogicalid"></a>
堆栈名称。  
`payload`  <a name="lambda-hook-stack-requestdata-payload"></a>
Amazon S3 预签名 URL，其中包含一个包含当前和之前模板定义的 JSON 对象。

`requestContext`  <a name="lambda-hook-stack-requestcontext"></a>
如果正在重新调用 Hook，则将设置此对象。    
`invocation`  <a name="lambda-hook-stack-requestcontext-invocation"></a>
当前执行挂钩的尝试。  
`callbackContext`  <a name="lambda-hook-stack-requestcontext-callbackcontext"></a>
如果 Hook 设置为`IN_PROGRESS`并`callbackContext`已返回，则它将在重新调用时出现在这里。

请求数据中的`payload`属性是您的代码需要获取的 URL。收到网址后，您将获得一个包含以下架构的对象：

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

`template`  <a name="lambda-hook-stack-payload-template"></a>
提供给`create-stack`或的完整 CloudFormation 模板`update-stack`。它可以是 JSON 或 YAML 字符串，具体取决于提供的内容。 CloudFormation  
在`delete-stack`操作中，此值将为空。

`previousTemplate`  <a name="lambda-hook-stack-payload-previoustemplate"></a>
之前的 CloudFormation 模板。它可以是 JSON 或 YAML 字符串，具体取决于提供的内容。 CloudFormation  
在`delete-stack`操作中，此值将为空。

### Lambda Hook 堆栈更改输入示例
<a name="lambda-hooks-create-lambda-function-stack-example"></a>

以下是堆栈变更输入的示例。Hook 正在评估一项更改，该更改`ObjectLockEnabled`将更新为 true，并添加了一个 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
    }
}
```

以下是以下`payload`示例`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}}}}"
}
```

### 用于堆栈操作的 Lambda 函数示例
<a name="lambda-hooks-create-lambda-function-stack-example-function"></a>

以下示例是一个简单的函数，它下载堆栈操作有效负载，解析模板 JSON 并返回`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 ]

要使用 Python，你需要导入该`requests`库。为此，您需要在创建 Lambda 函数时将该库包含在部署包中。有关更多信息，请参阅《*AWS Lambda 开发人员指南》*中的[创建带有依赖项的.zip 部署包](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies)。

```
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
```

------

## 使用 Lambda 挂钩评估变更集操作
<a name="lambda-hooks-create-lambda-function-change-set"></a>

每当您创建更改集时，都可以将您的 CloudFormation Lambda Hook 配置为首先评估新的更改集并可能阻止其执行。您可以将 CloudFormation Lambda 挂钩配置为挂钩配置中的`CHANGE_SET`操作目标。`TargetOperations`

**Topics**
+ [Lambda 挂钩更改集输入语法](#lambda-hooks-create-lambda-function-change-set-input)
+ [示例 Lambda 挂钩更改集更改输入](#lambda-hooks-create-lambda-function-change-set-example)
+ [用于变更集操作的 Lambda 函数示例](#lambda-hooks-create-lambda-function-change-set-example-function)

### Lambda 挂钩更改集输入语法
<a name="lambda-hooks-create-lambda-function-change-set-input"></a>

变更集操作的输入与堆栈操作类似，但是的有效载荷`requestData`还包括变更集引入的资源变更列表。

以下是 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>
作为 Hook 请求的输入而提供的请求令牌。此字段为必填字段。

`awsAccountId`  <a name="lambda-hook-change-set-awsaccountid"></a>
 AWS 账户 包含正在评估的堆栈的 ID。

`stackID`  <a name="lambda-hook-change-set-stackid"></a>
堆栈的堆 CloudFormation 栈 ID。

`changeSetId`  <a name="lambda-hook-change-set-changesetid"></a>
启动 Hook 调用的更改集的 ID。

`hookTypeName`  <a name="lambda-hook-change-set-hooktypename"></a>
正在运行的 Hook 的名称。

`hookTypeVersion`  <a name="lambda-hook-change-set-hooktypeversion"></a>
正在运行的 Hook 的版本。

`hookModel`  <a name="lambda-hook-change-set-hookmodel"></a>  
`LambdaFunction`  <a name="lambda-hook-change-set-hookmodel-lambdafunction"></a>
挂钩调用的当前 Lambda ARN。

`requestData`  <a name="lambda-hook-change-set-requestdata"></a>  
`targetName`  <a name="lambda-hook-change-set-requestdata-targetname"></a>
这个值将是 `CHANGE_SET`。  
`targetType`  <a name="lambda-hook-change-set-requestdata-targettype"></a>
这个值将是 `CHANGE_SET`。  
`targetLogicalId`  <a name="lambda-hook-change-set-requestdata-targetlogicalid"></a>
更改集合 ARN...  
`payload`  <a name="lambda-hook-change-set-requestdata-payload"></a>
Amazon S3 预签名 URL，其中包含带有当前模板的 JSON 对象，以及此更改集引入的更改列表。

`requestContext`  <a name="lambda-hook-change-set-requestcontext"></a>
如果正在重新调用 Hook，则将设置此对象。    
`invocation`  <a name="lambda-hook-change-set-requestcontext-invocation"></a>
当前执行挂钩的尝试。  
`callbackContext`  <a name="lambda-hook-change-set-requestcontext-callbackcontext"></a>
如果 Hook 设置为`IN_PROGRESS`并`callbackContext`已返回，则它将在重新调用时出现在这里。

请求数据中的`payload`属性是您的代码需要获取的 URL。收到网址后，您将获得一个包含以下架构的对象：

```
{
    "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>
提供给`create-stack`或的完整 CloudFormation 模板`update-stack`。它可以是 JSON 或 YAML 字符串，具体取决于提供的内容。 CloudFormation

`changedResources`  <a name="lambda-hook-change-set-payload-changed-resources"></a>
已更改的资源列表。    
`action`  <a name="lambda-hook-change-set-payload-changed-resources-action"></a>
应用于资源的更改类型。  
*有效值*：(`CREATE`\$1 `UPDATE` \$1`DELETE`)  
`beforeContext`  <a name="lambda-hook-change-set-payload-changed-resources-beforecontext"></a>
更改前资源属性的 JSON 字符串。创建资源时，此值为空。此 JSON 字符串中的所有布尔值和数字值均为字符串。  
`afterContext`  <a name="lambda-hook-change-set-payload-changed-resources-aftercontext"></a>
如果执行此更改集，则为资源属性的 JSON 字符串。删除资源时，此值为空。此 JSON 字符串中的所有布尔值和数字值均为字符串。  
`lineNumber`  <a name="lambda-hook-change-set-payload-changed-resources-linenumber"></a>
模板中导致此更改的行号。如果操作是，则`DELETE`此值将为空。  
`logicalResourceId`  <a name="lambda-hook-change-set-payload-changed-resources-logicalresourceid"></a>
正在更改的资源的逻辑资源 ID。  
`resourceType`  <a name="lambda-hook-change-set-payload-changed-resources-resourcetype"></a>
正在更改的资源类型。

### 示例 Lambda 挂钩更改集更改输入
<a name="lambda-hooks-create-lambda-function-change-set-example"></a>

以下是更改集更改输入的示例。在以下示例中，您可以看到变更集引入的更改。第一个更改是删除名为的队列`CoolQueue`。第二个更改是添加一个名为的新队列`NewCoolQueue`。最后一项更改是对的更新`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
    }
}
```

以下是以下`payload`示例`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"}]}}'
    }
  ]
}
```

### 用于变更集操作的 Lambda 函数示例
<a name="lambda-hooks-create-lambda-function-change-set-example-function"></a>

以下示例是一个简单的函数，它下载更改集操作有效负载，循环浏览每个更改，然后在返回 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 ]

要使用 Python，你需要导入该`requests`库。为此，您需要在创建 Lambda 函数时将该库包含在部署包中。有关更多信息，请参阅《*AWS Lambda 开发人员指南》*中的[创建带有依赖项的.zip 部署包](https://docs.aws.amazon.com/lambda/latest/dg/python-package.html#python-package-create-dependencies)。

```
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
```

------

# 准备创建 Lambda 挂钩
<a name="lambda-hooks-prepare-to-create-hook"></a>

在创建 Lambda 挂钩之前，必须完成以下先决条件：
+ 您必须已经创建了一个 Lambda 函数。有关更多信息，请参阅[为挂钩创建 Lambda 函数](lambda-hooks-create-lambda-function.md)。
+ 创建 Hook 的用户或角色必须具有足够的权限才能激活 Hook。有关更多信息，请参阅 [为 CloudFormation Hook 授予 IAM 权限](grant-iam-permissions-for-hooks.md)。
+ 要使用 AWS CLI 或软件开发工具包创建 Lambda 挂钩，您必须手动创建具有 IAM 权限的执行角色和允许 CloudFormation 调用 Lambda 挂钩的信任策略。

## 为 Lambda 挂钩创建执行角色
<a name="lambda-hooks-create-execution-role"></a>

Hook 使用执行角色来获得在你中调用该 Hook 所需的权限 AWS 账户。

如果您从中创建 Lambda Hook，则可以自动创建此角色 AWS 管理控制台；否则，您必须自己创建此角色。

以下部分向您展示如何设置创建 Lambda 挂钩的权限。

### 所需的权限
<a name="lambda-hooks-execution-role-permissions"></a>

按照《IAM 用户指南》**中[使用自定义信任策略创建角色](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create_for-custom.html)的指导，使用自定义信任策略创建角色。

然后，完成以下步骤来设置您的权限：

1. 将以下最低权限策略附加到您要用于创建 Lambda 挂钩的 IAM 角色。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Action": "lambda:InvokeFunction",
         "Resource": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction"
       }
     ]
   }
   ```

------

1. 通过向角色添加信任策略，授予您的 Hook 代入该角色的权限。以下显示了您可以使用的信任策略示例。

------
#### [ JSON ]

****  

   ```
   {
     "Version":"2012-10-17",		 	 	 
     "Statement": [
       {
         "Effect": "Allow",
         "Principal": {
           "Service": [
             "hooks.cloudformation.amazonaws.com"
           ]
         },
         "Action": "sts:AssumeRole"
       }
     ]
   }
   ```

------

# 在您的账户中激活 Lambda 挂钩
<a name="lambda-hooks-activate-hooks"></a>

以下主题向您展示了如何在您的账户中激活 Lambda Hook，从而使其在激活该挂钩的账户和区域中可用。

**Topics**
+ [激活 Lambda 挂钩（控制台）](#lambda-hooks-activate-hook-console)
+ [激活 Lambda 挂钩 ()AWS CLI](#lambda-hooks-activate-hooks-cli)
+ [相关资源](#related-resources-lambda-hooks)

## 激活 Lambda 挂钩（控制台）
<a name="lambda-hooks-activate-hook-console"></a>

**激活 Lambda 挂钩以在您的账户中使用**

1. 登录 AWS 管理控制台 并在 [https://console.aws.amazon.com/cloudformat](https://console.aws.amazon.com/cloudformation/) ion 上打开 CloudFormation 控制台。

1. 在屏幕顶部的导航栏上，选择要创建 Hook in AWS 区域 的位置。

1. 如果您*尚未*为挂钩创建 Lambda 函数，请执行以下操作：
   + 打开 Lambda 控制台的[函数](https://console.aws.amazon.com/lambda/home#/functions)页面。
   + 创建您将用于此 Hook 的 Lambda 函数，然后返回此过程。有关更多信息，请参阅 [创建 Lambda 函数来评估 Lambda 挂钩的资源](lambda-hooks-create-lambda-function.md)。

   如果您已经创建了 Lambda 函数，请继续执行下一步。

1. 在左侧的导航窗格中，选择 **Hook**。

1. 在 “**挂钩**” 页面上，选择 “**创建挂钩**”，然后选择 “**使用 Lambda**”。

1. 在 **Hook 名称**中，选择以下选项之一：
   + 提供一个简短的描述性名称，该名称将在之后`Private::Lambda::`添加。例如，如果输入*`MyTestHook`*，则完整的 Hook 名称变为`Private::Lambda::MyTestHook`。
   + 使用以下格式提供完整的 Hook 名称（也称为别名）：`Provider::ServiceName::HookName`

1. 对于 **Lambda 函数**，请提供用于此挂钩的 Lambda 函数。您可以使用：
   + 不带后缀的完整亚马逊资源名称 (ARN)。
   + 带有版本或别名后缀的合格 ARN。

1. 对于 **Hook 目标**，请选择要评估的内容：
   + **堆栈**-在用户创建、更新或删除堆栈时评估堆栈模板。
   + **资源**-在用户更新堆栈时评估各个资源的变化。
   + **更改集**-在用户创建更改集时评估计划的更新。
   + **云控制 API** — 评估由[云控制 AP](https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/what-is-cloudcontrolapi.html) I 启动的创建、更新或删除操作。

1. 在 “**操作**” 中，选择哪些操作（创建、更新、删除）将调用您的 Hook。

1. 对于**挂钩模式**，选择挂钩调用的 Lambda 函数返回响应时挂钩的响应方式：`FAILED`
   + **警告**-向用户发出警告，但允许继续执行操作。这对于非关键验证或信息检查很有用。
   + **失败**-阻止操作继续进行。这有助于执行严格的合规或安全政策。

1. 对于**执行角色**，请选择挂钩担任的用于调用您的 Lambda 函数的 IAM 角色。您可以 CloudFormation 允许自动为您创建执行角色，也可以指定已创建的角色。

1. 选择**下一步**。

1. （可选）对于 **Hook 过滤器**，请执行以下操作：

   1. 在**资源筛选器**中，指定哪些资源类型可以调用 Hook。这样可以确保仅针对相关资源调用 Hook。

   1. 在**筛选条件**中，选择应用堆栈名称和堆栈角色筛选器的逻辑：
      + **所有堆栈名称和堆栈角色** — 只有当所有指定的过滤器都匹配时，才会调用 Hook。
      + **任何堆栈名称和堆栈角色** — 如果指定的过滤器中至少有一个匹配，就会调用 Hook。
**注意**  
对于 Cloud Control API 操作，所有**堆栈名称**和**堆栈角色**筛选器都将被忽略。

   1. 对于**堆栈名称**，在 Hook 调用中包含或排除特定堆栈。
      + 对于 “**包含**”，指定要包含的堆栈名称。当你想要瞄准一小部分特定的堆栈时，使用此选项。只有此列表中指定的堆栈才会调用 Hook。
      + 对于**排除**，请指定要排除的堆栈名称。当你想在大多数堆栈上调用 Hook 但排除一些特定的堆栈时，请使用此选项。除此处列出的堆栈外，所有堆栈都将调用 Hook。

   1. 对于**堆栈角色**，请根据其关联的 IAM 角色在 Hook 调用中包含或排除特定堆栈。
      + 对于 **Inc** lude，指定一个或多个 IAM 角色 ARNs 来定位与这些角色关联的堆栈。只有由这些角色启动的堆栈操作才会调用 Hook。
      + 对于**排除， ARNs 为要排除**的堆栈指定一个或多个 IAM 角色。Hook 将在除指定角色启动的堆栈之外的所有堆栈上调用。

1. 选择**下一步**。

1. 在 “**查看并激活**” 页面上，查看您的选择。要进行更改，请在相关部分选择**编辑**。

1. 准备好继续操作时，选择 “**激活挂钩**”。

## 激活 Lambda 挂钩 ()AWS CLI
<a name="lambda-hooks-activate-hooks-cli"></a>

在继续操作之前，请确认您已创建 Lambda 函数和将用于此 Hook 的执行角色。有关更多信息，请参阅[创建 Lambda 函数来评估 Lambda 挂钩的资源](lambda-hooks-create-lambda-function.md)和[为 Lambda 挂钩创建执行角色](lambda-hooks-prepare-to-create-hook.md#lambda-hooks-create-execution-role)。

**激活 Lambda 挂钩以在您的账户中使用 ()AWS CLI**

1. 要开始激活 Hook，请使用以下[https://docs.aws.amazon.com/cli/latest/reference/cloudformation/activate-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/activate-type.html)命令，用您的特定值替换占位符。此命令授权 Hook 使用您的 AWS 账户指定执行角色。

   ```
   aws cloudformation activate-type --type HOOK \
     --type-name AWS::Hooks::LambdaHook \
     --publisher-id aws-hooks \
     --execution-role-arn arn:aws:iam::123456789012:role/my-execution-role \
     --type-name-alias Private::Lambda::MyTestHook \
     --region us-west-2
   ```

1. 要完成激活 Hook，必须使用 JSON 配置文件对其进行配置。

   使用**cat**命令创建具有以下结构的 JSON 文件。有关更多信息，请参阅 [挂钩配置架构语法参考](hook-configuration-schema.md)。

   ```
   $ cat > config.json
   {
     "CloudFormationConfiguration": {
       "HookConfiguration": {
         "HookInvocationStatus": "ENABLED",
         "TargetOperations": [
           "CLOUD_CONTROL"
         ],
         "FailureMode": "WARN",
         "Properties": {
           "LambdaFunction": "arn:aws:lambda:us-west-2:123456789012:function:MyFunction"
         },
         "TargetFilters": {
           "Actions": [
             "CREATE",
             "UPDATE",
             "DELETE"
           ]
         }
       }
     }
   }
   ```
   + `HookInvocationStatus`：设置`ENABLED`为可启用挂钩。
   + `TargetOperations`：指定 Hook 将评估的操作。
   + `FailureMode`：设置为 `FAIL` 或 `WARN`。
   + `LambdaFunction`：指定 Lambda 函数的 ARN。
   + `TargetFilters`：指定将调用 Hook 的操作类型。

1. 使用以下[https://docs.aws.amazon.com/cli/latest/reference/cloudformation/set-type-configuration.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/set-type-configuration.html)命令以及您创建的 JSON 文件来应用配置。用您的特定值替换占位符。

   ```
   aws cloudformation set-type-configuration \
     --configuration file://config.json \
     --type-arn "arn:aws:cloudformation:us-west-2:123456789012:type/hook/MyTestHook" \
     --region us-west-2
   ```

## 相关资源
<a name="related-resources-lambda-hooks"></a>

我们提供了模板示例，您可以使用这些示例来了解如何在 CloudFormation 堆栈模板中声明 Lambda Hook。有关更多信息，请参阅《AWS CloudFormation 用户指南》**中的 [https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-lambdahook.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-cloudformation-lambdahook.html)。

# 查看您账户中 Lambda 挂钩的日志
<a name="lambda-hooks-view-logs"></a>

使用 Lambda 挂钩时，可以在 Lambda 控制台中找到您的验证输出报告日志文件。

## 在 Lambda 控制台中查看 Lambda 挂钩日志
<a name="lambda-hooks-view-logs-console"></a>

**查看 Lambda 挂钩输出日志文件**

1. 登录 Lambda 控制台。

1. 在屏幕顶部的导航栏中，选择您的 AWS 区域。

1. 选择**函数**。

1. 选择所需的 Lambda 函数。

1. 选择**测试**选项卡。

1. 选择 **L CloudWatch ogs 实时跟踪**

1. 选择下拉菜单并选择要查看的日志组。

1. 选择**启动**。日志将显示在 Log **CloudWatch s Live Trail** 窗口中。根据您的喜好**，选择 “按列****查看” 或 “以纯文本形式**查看”。
   + 您可以通过在 “添加筛选器**模式” 字段中添加更多筛选器来向结果中添加更多过滤器**。此字段允许您筛选结果，使其仅包含与指定模式匹配的事件。

有关查看 Lambda 函数日志的更多信息，请参阅[查看 Lambda 函数的 CloudWatch 日志](https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs-view.html)。

# 删除账户中的 Lambda 挂钩
<a name="lambda-hooks-delete-hooks"></a>

当您不再需要已激活的 Lambda 挂钩时，请使用以下步骤将其从您的账户中删除。

要暂时禁用 Hook 而不是将其删除，请参阅[禁用和启用 CloudFormation Hook](hooks-disable-enable.md)。

**Topics**
+ [删除您账户中的 Lambda 挂钩（控制台）](#lambda-hooks-delete-hook-console)
+ [删除您账户中的 Lambda 挂钩 ()AWS CLI](#lambda-hooks-delete-hook-cli)

## 删除您账户中的 Lambda 挂钩（控制台）
<a name="lambda-hooks-delete-hook-console"></a>

**删除账户中的 Lambda 挂钩**

1. 登录 AWS 管理控制台 并在 [https://console.aws.amazon.com/cloudformat](https://console.aws.amazon.com/cloudformation/) ion 上打开 CloudFormation 控制台。

1. 在屏幕顶部的导航栏上，选择 Hook 所在 AWS 区域 的位置。

1. 从导航窗格中选择 **Hooks**。

1. 在**挂钩**页面上，找到要删除的 Lambda 挂钩。

1. 选中挂钩旁边的复选框并选择**删除**。

1. 当系统提示您确认时，键入挂钩名称以确认删除指定的挂钩，然后选择 **Delete**。

## 删除您账户中的 Lambda 挂钩 ()AWS CLI
<a name="lambda-hooks-delete-hook-cli"></a>

**注意**  
在删除挂钩之前，必须先将其禁用。有关更多信息，请参阅 [在您的账户中禁用并启用挂钩 (AWS CLI)](hooks-disable-enable.md#hooks-disable-enable-cli)。

使用以下[https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deactivate-type.html](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deactivate-type.html)命令停用 Hook，这会将其从您的帐户中删除。用您的特定值替换占位符。

```
aws cloudformation deactivate-type \
  --type-arn "arn:aws:cloudformation:us-west-2:123456789012:type/hook/MyTestHook" \
  --region us-west-2
```