

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

# 编写 Guard 规则来评估防护挂钩的资源
<a name="guard-hooks-write-rules"></a>

AWS CloudFormation Guard 是一种开源的通用域特定语言 (DSL)，可用于创 policy-as-code作。本主题介绍如何使用 Guard 编写示例规则，这些规则可以在 Guard Hook 中运行以自动评估 CloudFormation 和 AWS 云端控制 API 操作。它还将重点关注你的守卫规则可用的不同类型的输入，具体取决于你的 Guard Hook 的运行时间。可以将 Guard Hook 配置为在以下类型的操作期间运行：
+ 资源操作
+ 堆栈操作
+ 更改集合操作

有关编写 Guard 规则的更多信息，请参阅[编写 AWS CloudFormation Guard 规则](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html)

**Topics**
+ [资源操作守卫规则](#guard-hooks-write-rules-resource-operations)
+ [堆栈操作防护规则](#guard-hooks-write-rules-stack-operations)
+ [更改集合操作守卫规则](#guard-hooks-write-rules-change-set-operations)

## 资源操作守卫规则
<a name="guard-hooks-write-rules-resource-operations"></a>

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

**Topics**
+ [守卫资源输入语法](#guard-hooks-write-rules-resource-operations-input)
+ [示例 Guard 资源操作输入](#guard-hooks-write-rules-resource-operations-example)
+ [资源变更防护规则](#guard-hooks-rules-resource-changes)

### 守卫资源输入语法
<a name="guard-hooks-write-rules-resource-operations-input"></a>

Guard 资源输入是可供您的 Guard 规则评估的数据。

以下是资源输入的示例形状：

```
HookContext:
  AWSAccountID: String
  StackId: String
  HookTypeName: String
  HookTypeVersion: String
  InvocationPoint: [CREATE_PRE_PROVISION, UPDATE_PRE_PROVISION, DELETE_PRE_PROVISION]
  TargetName: String
  TargetType: RESOURCE
  TargetLogicalId: String
  ChangeSetId: String
Resources:
  {ResourceLogicalID}:
    ResourceType: {ResourceType}
    ResourceProperties:
        {ResourceProperties}
Previous:
  ResourceLogicalID:
    ResourceType: {ResourceType}
    ResourceProperties:
        {PreviousResourceProperties}
```

`HookContext`  <a name="guard-hook-resource-hookcontext"></a>  
`AWSAccountID`  <a name="guard-hook-resource-awsaccountid"></a>
 AWS 账户 包含正在评估的资源的 ID。  
`StackId`  <a name="guard-hook-resource-stackid"></a>
作为资源操作一部分的 CloudFormation 堆栈的堆栈 ID。如果调用方是云控制 API，则该值为空。  
`HookTypeName`  <a name="guard-hook-resource-hooktypename"></a>
正在运行的 Hook 的名称。  
`HookTypeVersion`  <a name="guard-hook-resource-hooktypeversion"></a>
正在运行的 Hook 的版本。  
`InvocationPoint`  <a name="guard-hook-resource-invocationpoint"></a>
配置逻辑中挂钩运行的确切位置。  
*有效值*：(`CREATE_PRE_PROVISION`\$1 `UPDATE_PRE_PROVISION` \$1`DELETE_PRE_PROVISION`)  
`TargetName`  <a name="guard-hook-resource-targetname"></a>
正在评估的目标类型，例如`AWS::S3::Bucket`。  
`TargetType`  <a name="guard-hook-resource-targettype"></a>
例如，正在评估的目标类型`AWS::S3::Bucket`。对于使用云控制 API 置备的资源，此值将`RESOURCE`为。  
`TargetLogicalId`  <a name="guard-hook-resource-targetlogicalid"></a>
正在评估`TargetLogicalId`的资源的。如果 Hook 的来源是 CloudFormation，则这将是资源的逻辑 ID（也称为逻辑名称）。如果 Hook 的起源是 Cloud Control API，则这将是一个构造值。  
`ChangeSetId`  <a name="guard-hook-resource-changesetid"></a>
为导致 Hook 调用而执行的更改集 ID。如果资源变更是由 Cloud Control API 或、或`delete-stack`操作启动的 `create-stack``update-stack`，则此值为空。

`Resources`  <a name="guard-hook-resource-resources"></a>  
`ResourceLogicalID`  <a name="guard-hook-resource-current-resourcelogicalid"></a>
当操作由启动时 CloudFormation，`ResourceLogicalID`就是 CloudFormation 模板中资源的逻辑 ID。  
当操作由 Cloud Control API 启动时，`ResourceLogicalID`是资源类型、名称、操作 ID 和请求 ID 的组合。  
`ResourceType`  <a name="guard-hook-resource-current-resourcetype"></a>
资源的类型名称（例如：`AWS::S3::Bucket`）。  
`ResourceProperties`  <a name="guard-hook-resource-current-resourceproperties"></a>
正在修改的资源的建议属性。当 Guard Hook 针对 CloudFormation 资源变化运行时，任何函数、参数和转换都将得到完全解析。如果要删除资源，则此值将为空。

`Previous`  <a name="guard-hook-resource-previous"></a>  
`ResourceLogicalID`  <a name="guard-hook-resource-previous-resourcelogicalid"></a>
当操作由启动时 CloudFormation，`ResourceLogicalID`就是 CloudFormation 模板中资源的逻辑 ID。  
当操作由 Cloud Control API 启动时，`ResourceLogicalID`是资源类型、名称、操作 ID 和请求 ID 的组合。  
`ResourceType`  <a name="guard-hook-resource-previous-resourcetype"></a>
资源的类型名称（例如：`AWS::S3::Bucket`）。  
`ResourceProperties`  <a name="guard-hook-resource-previous-resourceproperties"></a>
与正在修改的资源相关的当前属性。如果要删除资源，则此值将为空。

### 示例 Guard 资源操作输入
<a name="guard-hooks-write-rules-resource-operations-example"></a>

以下示例输入显示了一个 Guard Hook，它将接收要更新的`AWS::S3::Bucket`资源定义。这是 Guard 可用于评估的数据。

```
HookContext:
  AwsAccountId: "123456789012"
  StackId: "arn:aws:cloudformation:us-west-2:123456789012:stack/MyStack/1a2345b6-0000-00a0-a123-00abc0abc000"
  HookTypeName: org::s3policy::hook
  HookTypeVersion: "00001"
  InvocationPoint: UPDATE_PRE_PROVISION
  TargetName: AWS::S3::Bucket
  TargetType: RESOURCE
  TargetLogicalId: MyS3Bucket
  ChangeSetId: ""
Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket
      ObjectLockEnabled: true
Previous:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket
      ObjectLockEnabled: false
```

要查看该资源类型的所有可用属性，请参见[https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html](https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-s3-bucket.html)。

### 资源变更防护规则
<a name="guard-hooks-rules-resource-changes"></a>

当 Guard Hook 评估资源变化时，它首先下载使用该挂钩配置的所有规则。然后根据资源输入对这些规则进行评估。如果有任何规则的评估失败，Hook 就会失败。如果没有失败，Hook 就会通过。

以下示例是一条防护规则，用于评估该`ObjectLockEnabled`属性是否`true`适用于任何`AWS::S3::Bucket`资源类型。

```
let s3_buckets_default_lock_enabled = Resources.*[ Type == 'AWS::S3::Bucket']

rule S3_BUCKET_DEFAULT_LOCK_ENABLED when %s3_buckets_default_lock_enabled !empty {
  %s3_buckets_default_lock_enabled.Properties.ObjectLockEnabled exists
  %s3_buckets_default_lock_enabled.Properties.ObjectLockEnabled == true
  <<
    Violation: S3 Bucket ObjectLockEnabled must be set to true.
    Fix: Set the S3 property ObjectLockEnabled parameter to true.
  >>
}
```

当此规则针对以下输入运行时，它将失败，因为该`ObjectLockEnabled`属性未设置为`true`。

```
Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket 
      ObjectLockEnabled: false
```

当此规则针对以下输入运行时，它将通过，因为设置`ObjectLockEnabled`为`true`。

```
Resources:
  MyS3Bucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: amzn-s3-demo-bucket
      ObjectLockEnabled: true
```

当 Hook 失败时，失败的规则将传播回我们的 Cloud Con CloudFormation trol API。如果已为 Guard Hook 配置了日志存储桶，则将在那里提供其他规则反馈。此额外反馈包括`Violation`和`Fix`信息。

## 堆栈操作防护规则
<a name="guard-hooks-write-rules-stack-operations"></a>

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

**Topics**
+ [防护堆栈输入语法](#guard-hooks-write-rules-stack-operations-input)
+ [示例 Guard 堆栈操作输入](#guard-hooks-write-rules-stack-operations-example)
+ [堆栈变更的保护规则](#guard-hooks-rules-stack-changes)

### 防护堆栈输入语法
<a name="guard-hooks-write-rules-stack-operations-input"></a>

Guard 堆栈操作的输入为您的 Guard 规则提供了要评估的完整 CloudFormation模板。

以下是堆栈输入的示例形状：

```
HookContext:
  AWSAccountID: String
  StackId: String
  HookTypeName: String
  HookTypeVersion: String
  InvocationPoint: [CREATE_PRE_PROVISION, UPDATE_PRE_PROVISION, DELETE_PRE_PROVISION]
  TargetName: String
  TargetType:STACK
  ChangeSetId: String
{Proposed CloudFormation Template}
Previous:
    {CloudFormation Template}
```

`HookContext`  <a name="guard-hook-stack-hookcontext"></a>  
`AWSAccountID`  <a name="guard-hook-stack-awsaccountid"></a>
 AWS 账户 包含资源的的 ID。  
`StackId`  <a name="guard-hook-stack-stackid"></a>
作为堆栈操作一部分的 CloudFormation 堆栈的堆栈 ID。  
`HookTypeName`  <a name="guard-hook-stack-hooktypename"></a>
正在运行的 Hook 的名称。  
`HookTypeVersion`  <a name="guard-hook-stack-hooktypeversion"></a>
正在运行的 Hook 的版本。  
`InvocationPoint`  <a name="guard-hook-stack-invocationpoint"></a>
配置逻辑中挂钩运行的确切位置。  
*有效值*：(`CREATE_PRE_PROVISION`\$1 `UPDATE_PRE_PROVISION` \$1`DELETE_PRE_PROVISION`)  
`TargetName`  <a name="guard-hook-stack-targetname"></a>
正在评估的堆栈的名称。  
`TargetType`  <a name="guard-hook-stack-targettype"></a>
当作为堆栈级 Hook 运行`STACK`时，此值将为。  
`ChangeSetId`  <a name="guard-hook-stack-changesetid"></a>
为导致 Hook 调用而执行的更改集 ID。如果堆栈操作由、或`delete-stack`操作启动 `create-stack``update-stack`，则此值为空。

`Proposed CloudFormation Template`  <a name="guard-hook-stack-template-current-template"></a>
传递给 CloudFormation`create-stack`或`update-stack`操作的完整 CloudFormation 模板值。这包括诸如`Resources``Outputs`、和之类的内容`Properties`。它可以是 JSON 或 YAML 字符串，具体取决于提供的内容。 CloudFormation  
在`delete-stack`操作中，此值将为空。

`Previous`  <a name="guard-hook-stack-template-previous-template"></a>
上次成功部署的 CloudFormation 模板。如果正在创建或删除堆栈，则此值为空。  
在`delete-stack`操作中，此值将为空。

**注意**  
提供的模板是传递给堆`update`栈操作`create`的模板。删除堆栈时，不提供模板值。

### 示例 Guard 堆栈操作输入
<a name="guard-hooks-write-rules-stack-operations-example"></a>

以下示例输入显示了将接收完整模板和先前部署的模板的 Guard Hook。此示例中的模板使用 JSON 格式。

```
HookContext:
  AwsAccountId: 123456789012
  StackId: "arn:aws:cloudformation:us-west-2:123456789012:stack/MyStack/1a2345b6-0000-00a0-a123-00abc0abc000"
  HookTypeName: org::templatechecker::hook
  HookTypeVersion: "00001"
  InvocationPoint: UPDATE_PRE_PROVISION
  TargetName: MyStack
  TargetType: CHANGE_SET
  TargetLogicalId: arn:aws:cloudformation:us-west-2:123456789012:changeSet/SampleChangeSet/1a2345b6-0000-00a0-a123-00abc0abc000
  ChangeSetId: arn:aws:cloudformation:us-west-2:123456789012:changeSet/SampleChangeSet/1a2345b6-0000-00a0-a123-00abc0abc000
Resources: {
   "S3Bucket": {
        "Type": "AWS::S3::Bucket",
        "Properties": {
           "BucketEncryption": {
               "ServerSideEncryptionConfiguration": [ 
                {"ServerSideEncryptionByDefault": 
                    {"SSEAlgorithm": "aws:kms", 
                      "KMSMasterKeyID": "KMS-KEY-ARN" }, 
                      "BucketKeyEnabled": true } 
                ] 
           }
        }
}
Previous: {
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "S3Bucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {}
        }
    }
}
```

### 堆栈变更的保护规则
<a name="guard-hooks-rules-stack-changes"></a>

当 Guard Hook 评估堆栈更改时，它首先下载使用该挂钩配置的所有规则。然后根据资源输入对这些规则进行评估。如果有任何规则的评估失败，Hook 就会失败。如果没有失败，Hook 就会通过。

以下示例是一条 Guard 规则，用于评估是否有任何`AWS::S3::Bucket`资源类型包含名为的属性`BucketEncryption`，且该属性`SSEAlgorithm`设置为`aws:kms`或`AES256`。

```
let s3_buckets_s3_default_encryption = Resources.*[ Type == 'AWS::S3::Bucket']

rule S3_DEFAULT_ENCRYPTION_KMS when %s3_buckets_s3_default_encryption !empty {
  %s3_buckets_s3_default_encryption.Properties.BucketEncryption exists
  %s3_buckets_s3_default_encryption.Properties.BucketEncryption.ServerSideEncryptionConfiguration[*].ServerSideEncryptionByDefault.SSEAlgorithm in ["aws:kms","AES256"]
  <<
    Violation: S3 Bucket default encryption must be set.
    Fix: Set the S3 Bucket property BucketEncryption.ServerSideEncryptionConfiguration.ServerSideEncryptionByDefault.SSEAlgorithm to either "aws:kms" or "AES256"
  >>
}
```

当规则针对以下模板运行时，它会运行的`fail`。

```
AWSTemplateFormatVersion: 2010-09-09
Description: S3 bucket without default encryption
Resources:
  EncryptedS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub 'encryptedbucket-${AWS::Region}-${AWS::AccountId}'
```

当规则针对以下模板运行时，它会运行的`pass`。

```
AWSTemplateFormatVersion: 2010-09-09
Description: S3 bucket with default encryption using SSE-KMS with an S3 Bucket Key
Resources:
  EncryptedS3Bucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub 'encryptedbucket-${AWS::Region}-${AWS::AccountId}'
      BucketEncryption:
        ServerSideEncryptionConfiguration:
          - ServerSideEncryptionByDefault:
              SSEAlgorithm: 'aws:kms'
              KMSMasterKeyID: KMS-KEY-ARN
            BucketKeyEnabled: true
```

## 更改集合操作守卫规则
<a name="guard-hooks-write-rules-change-set-operations"></a>

创建 CloudFormation 变更集后，您可以将 Guard Hook 配置为评估模板和变更集中提出的更改，以阻止变更集的执行。

**Topics**
+ [防护变更集输入语法](#guard-hooks-write-rules-change-set-operations-input)
+ [示例：防护变更集操作输入](#guard-hooks-write-rules-change-set-operations-example)
+ [变更集操作的保护规则](#guard-hooks-rules-change-set-operations)

### 防护变更集输入语法
<a name="guard-hooks-write-rules-change-set-operations-input"></a>

Guard 更改集输入是可供您的 Guard 规则评估的数据。

以下是更改集输入的示例形状：

```
HookContext:
  AWSAccountID: String
  StackId: String
  HookTypeName: String
  HookTypeVersion: String
  InvocationPoint: [CREATE_PRE_PROVISION, UPDATE_PRE_PROVISION, DELETE_PRE_PROVISION]
  TargetName: CHANGE_SET
  TargetType:CHANGE_SET
  TargetLogicalId:ChangeSet ID
  ChangeSetId: String
{Proposed CloudFormation Template}
Previous:
  {CloudFormation Template}
Changes: [{ResourceChange}]
```

`ResourceChange`模型语法为：

```
logicalResourceId: String 
resourceType: String
action: CREATE, UPDATE, DELETE
LineNumber: Number
在上下文之前: JSON String
AfterCon: JSON String
```

`HookContext`  <a name="guard-hook-change-set-hookcontext"></a>  
`AWSAccountID`  <a name="guard-hook-change-set-awsaccountid"></a>
 AWS 账户 包含资源的的 ID。  
`StackId`  <a name="guard-hook-change-set-stackid"></a>
作为堆栈操作一部分的 CloudFormation 堆栈的堆栈 ID。  
`HookTypeName`  <a name="guard-hook-change-set-hooktypename"></a>
正在运行的 Hook 的名称。  
`HookTypeVersion`  <a name="guard-hook-change-set-hooktypeversion"></a>
正在运行的 Hook 的版本。  
`InvocationPoint`  <a name="guard-hook-change-set-invocationpoint"></a>
配置逻辑中挂钩运行的确切位置。  
*有效值*：(`CREATE_PRE_PROVISION`\$1 `UPDATE_PRE_PROVISION` \$1`DELETE_PRE_PROVISION`)  
`TargetName`  <a name="guard-hook-change-set-targetname"></a>
正在评估的堆栈的名称。  
`TargetType`  <a name="guard-hook-change-set-targettype"></a>
当作为更改集级别的 Hook 运行`CHANGE_SET`时，将使用此值。  
`TargetLogicalId`  <a name="guard-hook-change-set-targetlogicalid"></a>
该值将是变更集的 ARN。  
`ChangeSetId`  <a name="guard-hook-change-set-changesetid"></a>
为导致 Hook 调用而执行的更改集 ID。如果堆栈操作由、或`delete-stack`操作启动 `create-stack``update-stack`，则此值为空。

`Proposed CloudFormation Template`  <a name="guard-hook-change-set-current-template"></a>
为`create-change-set`操作提供的完整 CloudFormation 模板。它可以是 JSON 或 YAML 字符串，具体取决于提供的内容。 CloudFormation

`Previous`  <a name="guard-hook-change-set-previous-template"></a>
上次成功部署的 CloudFormation 模板。如果正在创建或删除堆栈，则此值为空。

`Changes`  <a name="guard-hook-change-set-changes"></a>
`Changes`模型。这列出了资源更改。

更改    
logicalResourceId  <a name="guard-hook-change-set-change-logicalresourceid"></a>
已更改资源的逻辑资源名称。  
resourceType  <a name="guard-hook-change-set-change-resourcetype"></a>
将要更改的资源类型。  
action  <a name="guard-hook-change-set-change-action"></a>
对资源执行的操作类型。  
*有效值*：(`CREATE`\$1 `UPDATE` \$1`DELETE`)  
LineNumber  <a name="guard-hook-change-set-change-linenumber"></a>
模板中与变更相关的行号。  
在上下文之前  <a name="guard-hook-change-set-change-beforecontext"></a>
更改前资源属性的 JSON 字符串：  

```
{"properties": {"property1": "value"}}
```  
AfterCon  <a name="guard-hook-change-set-change-aftercontext"></a>
更改后资源属性的 JSON 字符串：  

```
{"properties": {"property1": "new value"}}
```

### 示例：防护变更集操作输入
<a name="guard-hooks-write-rules-change-set-operations-example"></a>

以下示例输入显示了将接收完整模板的 Guard Hook、之前部署的模板和资源更改列表。此示例中的模板使用 JSON 格式。

```
HookContext:
  AwsAccountId: "00000000"
  StackId: MyStack
  HookTypeName: org::templatechecker::hook
  HookTypeVersion: "00001"
  InvocationPoint: UPDATE_PRE_PROVISION
  TargetName: my-example-stack
  TargetType:STACK
  TargetLogicalId: arn...:changeSet/change-set
  ChangeSetId: ""
Resources: {
    "S3Bucket": {
       "Type": "AWS::S3::Bucket",
       "Properties": {
           "BucketName": "amzn-s3-demo-bucket",
           "VersioningConfiguration":{
              "Status": "Enabled"
            }                
         }
    }
Previous: {
    "AWSTemplateFormatVersion": "2010-09-09",
    "Resources": {
        "S3Bucket": {
            "Type": "AWS::S3::Bucket",
            "Properties": {
                "BucketName": "amzn-s3-demo-bucket",
                "VersioningConfiguration":{
                  "Status": "Suspended"
                }
            }
        }
    }
}
Changes: [
  {
    "logicalResourceId": "S3Bucket",
    "resourceType": "AWS::S3::Bucket",
    "action": "UPDATE",
    "lineNumber": 5,
    "beforeContext": "{\"Properties\":{\"VersioningConfiguration\":{\"Status\":\"Suspended\"}}}",
    "afterContext": "{\"Properties\":{\"VersioningConfiguration\":{\"Status\":\"Enabled\"}}}"
  }
]
```

### 变更集操作的保护规则
<a name="guard-hooks-rules-change-set-operations"></a>

以下示例是一条防护规则，用于评估对 Amazon S3 存储桶的更改，并确保该规则未`VersionConfiguration`被禁用。

```
let s3_buckets_changing = Changes[resourceType == 'AWS::S3::Bucket']

rule S3_VERSIONING_STAY_ENABLED when %s3_buckets_changing !empty {
    let afterContext = json_parse(%s3_buckets_changing.afterContext)
    when %afterContext.Properties.VersioningConfiguration.Status !empty {
        %afterContext.Properties.VersioningConfiguration.Status == 'Enabled'
    }
}
```