

本文為英文版的機器翻譯版本，如內容有任何歧義或不一致之處，概以英文版為準。

# 撰寫 Guard 規則來評估 Guard Hooks 的資源
<a name="guard-hooks-write-rules"></a>

AWS CloudFormation Guard 是一種開放原始碼和一般用途網域特定語言 (DSL)，可用來撰寫policy-as-code。本主題說明如何使用 Guard 撰寫可在 Guard Hook 中執行的範例規則，以自動評估 CloudFormation 和 AWS 雲端控制 API 操作。視您的 Guard Hook 執行時間而定，它也會專注於您的 Guard 規則可用的不同輸入類型。Guard Hook 可設定為在下列操作類型期間執行：
+ 資源操作
+ 堆疊操作
+ 變更集操作

如需撰寫 Guard 規則的詳細資訊，請參閱[撰寫 AWS CloudFormation Guard 規則](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html)

**Topics**
+ [資源操作 Guard 規則](#guard-hooks-write-rules-resource-operations)
+ [堆疊操作 Guard 規則](#guard-hooks-write-rules-stack-operations)
+ [變更集操作 Guard 規則](#guard-hooks-write-rules-change-set-operations)

## 資源操作 Guard 規則
<a name="guard-hooks-write-rules-resource-operations"></a>

每當您建立、更新或刪除資源時，即視為資源操作。例如，如果您執行更新建立新資源的 CloudFormation 堆疊，表示您已完成資源操作。當您使用 Cloud Control API 建立、更新或刪除資源時，這也被視為資源操作。您可以在 Guard Hook 的`TargetOperations`組態中，將 Guard Hook 設定為目標`RESOURCE`和`CLOUD_CONTROL`操作。當您的 Guard Hook 評估資源操作時，Guard 引擎會評估資源輸入。

**Topics**
+ [Guard 資源輸入語法](#guard-hooks-write-rules-resource-operations-input)
+ [Guard 資源操作輸入範例](#guard-hooks-write-rules-resource-operations-example)
+ [資源變更的防護規則](#guard-hooks-rules-resource-changes)

### Guard 資源輸入語法
<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>
正在執行的勾點名稱。  
`HookTypeVersion`  <a name="guard-hook-resource-hooktypeversion"></a>
正在執行的 Hook 版本。  
`InvocationPoint`  <a name="guard-hook-resource-invocationpoint"></a>
佈建邏輯中 Hook 執行的確切點。  
*有效值*： (`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`。對於使用 Cloud Control API 佈建的資源，此值將為 `RESOURCE`。  
`TargetLogicalId`  <a name="guard-hook-resource-targetlogicalid"></a>
正在評估`TargetLogicalId`的資源的 。如果 Hook 的原始伺服器是 CloudFormation，這將是資源的邏輯 ID （也稱為邏輯名稱）。如果勾點的原始伺服器是雲端控制 API，這會是建構值。  
`ChangeSetId`  <a name="guard-hook-resource-changesetid"></a>
為造成勾點調用而執行的變更集 ID。如果資源變更是由 Cloud Control API 或 `create-stack`、 `update-stack`或 `delete-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>

下列範例輸入顯示將接收要更新之`AWS::S3::Bucket`資源定義的 Guard Hook。這是可供 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 設定的所有規則。然後，這些規則會根據資源輸入進行評估。如果任何規則的評估失敗，勾點將會失敗。如果沒有失敗，勾點將會通過。

下列範例是 Guard 規則，評估 `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
```

當勾點失敗時，失敗的規則將傳播回 CloudFormation 或 Cloud Control API。如果已為 Guard Hook 設定記錄儲存貯體，則會在該處提供額外的規則意見回饋。此額外的意見回饋包括 `Violation`和 `Fix`資訊。

## 堆疊操作 Guard 規則
<a name="guard-hooks-write-rules-stack-operations"></a>

建立、更新或刪除 CloudFormation 堆疊時，您可以將 Guard Hook 設定為從評估新範本開始，並可能封鎖堆疊操作以繼續。您可以在 Guard Hook 的`TargetOperations`組態中將 Guard Hook 設定為目標`STACK`操作。

**Topics**
+ [Guard 堆疊輸入語法](#guard-hooks-write-rules-stack-operations-input)
+ [Guard 堆疊操作輸入範例](#guard-hooks-write-rules-stack-operations-example)
+ [堆疊變更的防護規則](#guard-hooks-rules-stack-changes)

### Guard 堆疊輸入語法
<a name="guard-hooks-write-rules-stack-operations-input"></a>

Guard 堆疊操作的輸入提供整個 CloudFormation 範本，供您的 Guard 規則評估。

以下是堆疊輸入的範例形狀：

```
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>
正在執行的勾點名稱。  
`HookTypeVersion`  <a name="guard-hook-stack-hooktypeversion"></a>
正在執行的 Hook 版本。  
`InvocationPoint`  <a name="guard-hook-stack-invocationpoint"></a>
佈建邏輯中 Hook 執行的確切點。  
*有效值*： (`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>
作為堆疊層級掛鉤執行`STACK`時，此值將為 。  
`ChangeSetId`  <a name="guard-hook-stack-changesetid"></a>
為造成勾點調用而執行的變更集 ID。如果堆疊操作是由 `create-stack`、 或 `delete-stack`操作啟動`update-stack`，則此值為空。

`Proposed CloudFormation Template`  <a name="guard-hook-stack-template-current-template"></a>
傳遞給 CloudFormation `create-stack`或 `update-stack`操作的完整 CloudFormation 範本值。這包括 `Resources`、 `Outputs`和 等物件`Properties`。根據提供給 CloudFormation 的內容，它可以是 JSON 或 YAML 字串。  
在 `delete-stack` 操作中，此值將為空。

`Previous`  <a name="guard-hook-stack-template-previous-template"></a>
上次成功部署的 CloudFormation 範本。如果正在建立或刪除堆疊，則此值為空。  
在 `delete-stack` 操作中，此值將為空。

**注意**  
提供的範本是傳遞至 `create`或 `update`堆疊操作的內容。刪除堆疊時，不會提供任何範本值。

### 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 設定的所有規則。然後，這些規則會根據資源輸入進行評估。如果任何規則的評估失敗，勾點將會失敗。如果沒有失敗，勾點將會通過。

下列範例是 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
```

## 變更集操作 Guard 規則
<a name="guard-hooks-write-rules-change-set-operations"></a>

建立 CloudFormation 變更集時，您可以設定 Guard Hook 來評估範本和變更集中提議的變更，以封鎖變更集執行。

**Topics**
+ [防護變更集輸入語法](#guard-hooks-write-rules-change-set-operations-input)
+ [範例 Guard 變更集操作輸入](#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
動作: CREATE, UPDATE, DELETE
lineNumber: Number
beforeContext: JSON String
afterContext: 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>
正在執行的勾點名稱。  
`HookTypeVersion`  <a name="guard-hook-change-set-hooktypeversion"></a>
正在執行的 Hook 版本。  
`InvocationPoint`  <a name="guard-hook-change-set-invocationpoint"></a>
佈建邏輯中 Hook 執行的確切點。  
*有效值*： (`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>
作為變更集層級掛鉤執行`CHANGE_SET`時，此值將為 。  
`TargetLogicalId`  <a name="guard-hook-change-set-targetlogicalid"></a>
此值將是變更集的 ARN。  
`ChangeSetId`  <a name="guard-hook-change-set-changesetid"></a>
為造成勾點調用而執行的變更集 ID。如果堆疊操作是由 `create-stack`、 或 `delete-stack`操作啟動`update-stack`，則此值為空。

`Proposed CloudFormation Template`  <a name="guard-hook-change-set-current-template"></a>
提供給 `create-change-set` 操作的完整 CloudFormation 範本。根據提供給 CloudFormation 的內容，它可以是 JSON 或 YAML 字串。

`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>
要變更的資源類型。  
動作  <a name="guard-hook-change-set-change-action"></a>
在資源上執行的操作類型。  
*有效值*： (`CREATE` \$1 `UPDATE` \$1 `DELETE`)  
lineNumber  <a name="guard-hook-change-set-change-linenumber"></a>
範本中與變更相關聯的行號。  
beforeContext  <a name="guard-hook-change-set-change-beforecontext"></a>
變更前資源屬性的 JSON 字串：  

```
{"properties": {"property1": "value"}}
```  
afterContext  <a name="guard-hook-change-set-change-aftercontext"></a>
變更後資源屬性的 JSON 字串：  

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

### 範例 Guard 變更集操作輸入
<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>

下列範例是 Guard 規則，可評估 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'
    }
}
```