

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

# 在 Guard 規則中指派和參考變數
<a name="variables"></a>

您可以在 AWS CloudFormation Guard 規則檔案中指派變數，以存放要在 Guard 規則中參考的資訊。Guard 支援一次性變數指派。變數會延遲評估，這表示 Guard 只會在規則執行時評估變數。

**Topics**
+ [指派變數](#assigning-variables)
+ [參考變數](#referencing-variables)
+ [變數範圍](#variable-scope)
+ [Guard 規則檔案中的變數範例](#variables-examples)

## 指派變數
<a name="assigning-variables"></a>

使用 `let`關鍵字來初始化和指派變數。最佳實務是針對變數名稱使用蛇案例。變數可以存放查詢產生的靜態常值或動態屬性。在下列範例中， 變數會`ecs_task_definition_task_role_arn`存放靜態字串值 `arn:aws:iam:123456789012:role/my-role-name`。

```
let ecs_task_definition_task_role_arn = 'arn:aws:iam::123456789012:role/my-role-name'
```

在下列範例中， 變數會`ecs_tasks`儲存查詢的結果，以搜尋範本中的所有`AWS::ECS::TaskDefinition` CloudFormation 資源。您可以在撰寫規則時參考 `ecs_tasks` 來存取這些資源的相關資訊。

```
let ecs_tasks = Resources.*[
    Type == 'AWS::ECS::TaskDefinition'
]
```

## 參考變數
<a name="referencing-variables"></a>

使用 `%`字首來參考變數。

根據 中的`ecs_task_definition_task_role_arn`變數範例[指派變數](#assigning-variables)，您可以在 Guard 規則子句的 `query|value literal`區段`ecs_task_definition_task_role_arn`中參考 。使用該參考可確保為 CloudFormation 範本中任何`AWS::ECS::TaskDefinition`資源的 `TaskDefinitionArn` 屬性指定的值是靜態字串值 `arn:aws:iam:123456789012:role/my-role-name`。

```
Resources.*.Properties.TaskDefinitionArn == %ecs_task_definition_role_arn
```

根據 中的`ecs_tasks`變數範例[指派變數](#assigning-variables)，您可以在查詢`ecs_tasks`中參考 （例如 %ecs\$1tasks.Properties)。首先，Guard 會評估變數，`ecs_tasks`然後使用傳回的值來周遊階層。如果變數`ecs_tasks`解析為非字串值，則 Guard 會擲回錯誤。

**注意**  
目前，Guard 不支援在自訂錯誤訊息內參考變數。

## 變數範圍
<a name="variable-scope"></a>

範圍是指規則檔案中定義的變數可見性。變數名稱只能在範圍內使用一次。有三個層級可以宣告變數，或三個可能的變數範圍：
+ **檔案層級** – 通常在規則檔案頂端宣告，您可以在規則檔案內的所有規則中使用檔案層級變數。它們對整個檔案可見。

  在下列範例規則檔案中，變數 `ecs_task_definition_task_role_arn`和 `ecs_task_definition_execution_role_arn` 會在檔案層級初始化。

  ```
  let ecs_task_definition_task_role_arn = 'arn:aws:iam::123456789012:role/my-task-role-name'
  let ecs_task_definition_execution_role_arn = 'arn:aws:iam::123456789012:role/my-execution-role-name'
  
  rule check_ecs_task_definition_task_role_arn
  {
      Resources.*.Properties.TaskRoleArn == %ecs_task_definition_task_role_arn
  }
  
  rule check_ecs_task_definition_execution_role_arn
  {
      Resources.*.Properties.ExecutionRoleArn == %ecs_task_definition_execution_role_arn
  }
  ```
+ **規則層級** – 在規則中宣告，規則層級變數僅對該特定規則可見。規則以外的任何參考都會導致錯誤。

  在下列範例規則檔案中，變數 `ecs_task_definition_task_role_arn`和 `ecs_task_definition_execution_role_arn` 會在規則層級初始化。`ecs_task_definition_task_role_arn` 只能在`check_ecs_task_definition_task_role_arn`具名規則中參考 。您只能在`check_ecs_task_definition_execution_role_arn`具名規則中參考 `ecs_task_definition_execution_role_arn`變數。

  ```
  rule check_ecs_task_definition_task_role_arn
  {
      let ecs_task_definition_task_role_arn = 'arn:aws:iam::123456789012:role/my-task-role-name'
      Resources.*.Properties.TaskRoleArn == %ecs_task_definition_task_role_arn
  }
  
  rule check_ecs_task_definition_execution_role_arn
  {
      let ecs_task_definition_execution_role_arn = 'arn:aws:iam::123456789012:role/my-execution-role-name'
      Resources.*.Properties.ExecutionRoleArn == %ecs_task_definition_execution_role_arn
  }
  ```
+ **區塊層級** – 在區塊內宣告，例如子`when`句，區塊層級變數只能由該特定區塊顯示。區塊以外的任何參考都會導致錯誤。

  在下列範例規則檔案中，變數 `ecs_task_definition_task_role_arn`和 `ecs_task_definition_execution_role_arn` 會在`AWS::ECS::TaskDefinition`類型區塊內的區塊層級初始化。您只能參考`AWS::ECS::TaskDefinition`類型區塊中的 `ecs_task_definition_task_role_arn`和 `ecs_task_definition_execution_role_arn`變數，以取得其個別規則。

  ```
  rule check_ecs_task_definition_task_role_arn
  {
      AWS::ECS::TaskDefinition
      {
          let ecs_task_definition_task_role_arn = 'arn:aws:iam::123456789012:role/my-task-role-name'
          Properties.TaskRoleArn == %ecs_task_definition_task_role_arn
      }
  }
  
  rule check_ecs_task_definition_execution_role_arn
  {
      AWS::ECS::TaskDefinition
      {
          let ecs_task_definition_execution_role_arn = 'arn:aws:iam::123456789012:role/my-execution-role-name'
          Properties.ExecutionRoleArn == %ecs_task_definition_execution_role_arn
      }
  }
  ```

## Guard 規則檔案中的變數範例
<a name="variables-examples"></a>

下列各節提供變數靜態和動態指派的範例。

### 靜態指派
<a name="assigning-static-variables"></a>

以下是 CloudFormation 範本範例。

```
Resources:
  EcsTask:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      TaskRoleArn: 'arn:aws:iam::123456789012:role/my-role-name'
```

根據此範本，您可以撰寫稱為 的規則`check_ecs_task_definition_task_role_arn`，以確保所有`AWS::ECS::TaskDefinition`範本資源的 `TaskRoleArn` 屬性為 `arn:aws:iam::123456789012:role/my-role-name`。

```
rule check_ecs_task_definition_task_role_arn
{
    let ecs_task_definition_task_role_arn = 'arn:aws:iam::123456789012:role/my-role-name'
    Resources.*.Properties.TaskRoleArn == %ecs_task_definition_task_role_arn
}
```

在規則範圍內，您可以初始化名為 的變數`ecs_task_definition_task_role_arn`，並將靜態字串值 指派給該變數`'arn:aws:iam::123456789012:role/my-role-name'`。規則子句會參考 `query|value literal`區段中的 `ecs_task_definition_task_role_arn`變數，`arn:aws:iam::123456789012:role/my-role-name`檢查為 `EcsTask` 資源`TaskRoleArn`屬性指定的值是否為 。

### 動態指派
<a name="example-dynamic-assignment"></a>

以下是 CloudFormation 範本範例。

```
Resources:
  EcsTask:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      TaskRoleArn: 'arn:aws:iam::123456789012:role/my-role-name'
```

根據此範本，您可以初始化檔案`ecs_tasks`範圍內名為 的變數，並將查詢 指派給該變數`Resources.*[ Type == 'AWS::ECS::TaskDefinition'`。Guard 會查詢輸入範本中的所有資源，並將這些資源的相關資訊儲存在 中`ecs_tasks`。您也可以撰寫稱為 的規則`check_ecs_task_definition_task_role_arn`，以確保所有`AWS::ECS::TaskDefinition`範本資源的 `TaskRoleArn` 屬性為 `arn:aws:iam::123456789012:role/my-role-name`

```
let ecs_tasks = Resources.*[
    Type == 'AWS::ECS::TaskDefinition'
]

rule check_ecs_task_definition_task_role_arn
{
    %ecs_tasks.Properties.TaskRoleArn == 'arn:aws:iam::123456789012:role/my-role-name'
}
```

規則子句會參考 `query`區段中的 `ecs_task_definition_task_role_arn`變數，`arn:aws:iam::123456789012:role/my-role-name`以檢查為 `EcsTask` 資源`TaskRoleArn`屬性指定的值是否為 。

### 強制執行 CloudFormation 範本組態
<a name="example-3"></a>

讓我們演練更複雜的生產使用案例範例。在此範例中，我們撰寫 Guard 規則，以確保更嚴格控制 Amazon ECS 任務的定義方式。

以下是 CloudFormation 範本範例。

```
Resources:
  EcsTask:
    Type: 'AWS::ECS::TaskDefinition'
    Properties:
      TaskRoleArn: 
        'Fn::GetAtt': [TaskIamRole, Arn]
      ExecutionRoleArn:
        'Fn::GetAtt': [ExecutionIamRole, Arn]

  TaskIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      PermissionsBoundary: 'arn:aws:iam::123456789012:policy/MyExamplePolicy'

  ExecutionIamRole:
    Type: 'AWS::IAM::Role'
    Properties:
      PermissionsBoundary: 'arn:aws:iam::123456789012:policy/MyExamplePolicy'
```

根據此範本，我們會撰寫下列規則，以確保符合這些要求：
+ 範本中的每個`AWS::ECS::TaskDefinition`資源都連接了任務角色和執行角色。
+ 任務角色和執行角色是 AWS Identity and Access Management (IAM) 角色。
+ 角色在範本中定義。
+ 系統會為每個角色指定 `PermissionsBoundary` 屬性。

```
# Select all Amazon ECS task definition resources from the template
let ecs_tasks = Resources.*[
    Type == 'AWS::ECS::TaskDefinition'
]

# Select a subset of task definitions whose specified value for the TaskRoleArn property is an Fn::Gett-retrievable attribute
let task_role_refs = some %ecs_tasks.Properties.TaskRoleArn.'Fn::GetAtt'[0]

# Select a subset of TaskDefinitions whose specified value for the ExecutionRoleArn property is an Fn::Gett-retrievable attribute
let execution_role_refs = some %ecs_tasks.Properties.ExecutionRoleArn.'Fn::GetAtt'[0]

# Verify requirement #1
rule all_ecs_tasks_must_have_task_end_execution_roles 
    when %ecs_tasks !empty 
{
    %ecs_tasks.Properties {
        TaskRoleArn exists
        ExecutionRoleArn exists
    }
}

# Verify requirements #2 and #3
rule all_roles_are_local_and_type_IAM
    when all_ecs_tasks_must_have_task_end_execution_roles
{
    let task_iam_references = Resources.%task_role_refs
    let execution_iam_reference = Resources.%execution_role_refs

    when %task_iam_references !empty {
        %task_iam_references.Type == 'AWS::IAM::Role'
    }

    when %execution_iam_reference !empty {
        %execution_iam_reference.Type == 'AWS::IAM::Role'
    }
}

# Verify requirement #4
rule check_role_have_permissions_boundary
    when all_ecs_tasks_must_have_task_end_execution_roles
{
    let task_iam_references = Resources.%task_role_refs
    let execution_iam_reference = Resources.%execution_role_refs

    when %task_iam_references !empty {
        %task_iam_references.Properties.PermissionsBoundary exists
    }

    when %execution_iam_reference !empty {
        %execution_iam_reference.Properties.PermissionsBoundary exists
    }
}
```