

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

# 使用 AWS CloudFormation Guard 的 Lambda 主動式控制項
<a name="governance-cloudformation-guard"></a>

[AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html) 是一種開放原始碼的通用型政策即程式碼評估工具。透過比照政策規則驗證基礎設施即程式碼 (IaC) 範本和服務組合，它可被用於實現預防性控管與合規。這些規則還可以依據您的團隊或組織要求進行自訂。對於 Lambda 函數，Guard 規則可透過在建立或更新 Lambda 函數時定義所需的必要屬性設定，控制資源建立和組態更新。

合規管理員會定義部署和更新 Lambda 函數所需的控制項和控管政策清單。平台管理員在 CI/CD 管道中實作控制項，做為程式碼儲存庫的預遞交驗證 Webhook，並為開發人員提供用於在本機工作站驗證範本和程式碼的命令列工具。開發人員使用命令列工具編寫程式碼並驗證範本，然後將程式碼遞交到儲存庫。儲存庫隨後會在將這些程式碼部署到 AWS 環境前透過 CI/CD 管道自動對其進行驗證。

Guard 讓您可以使用特定領域的語言，如下[編寫您的規則](https://docs.aws.amazon.com/cfn-guard/latest/ug/writing-rules.html)並實作您的控制項。

 ![\[Guard rules include resource type, property name, operator, expression value, and optional comment\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/governance-cloudformation-guard.png) 

例如，假設您希望確定開發人員僅選擇最新的執行期。您可以指定兩種不同的政策，一種用來識別已棄用的[執行期](lambda-runtimes.md)，另一種則用來確定即將棄用的執行期。為此，您可能要編寫以下 `etc/rules.guard` 檔案：

```
let lambda_functions = Resources.*[
    Type == "AWS::Lambda::Function"
]

rule lambda_already_deprecated_runtime when %lambda_functions !empty {
    %lambda_functions {
        Properties {
            when Runtime exists {
                Runtime !in ["dotnetcore3.1", "nodejs12.x", "python3.6", "python2.7", "dotnet5.0", "dotnetcore2.1", "ruby2.5", "nodejs10.x", "nodejs8.10", "nodejs4.3", "nodejs6.10", "dotnetcore1.0", "dotnetcore2.0", "nodejs4.3-edge", "nodejs"] <<Lambda function is using a deprecated runtime.>>
            }
        }
    }
}

rule lambda_soon_to_be_deprecated_runtime when %lambda_functions !empty {
    %lambda_functions {
        Properties {
            when Runtime exists {
                Runtime !in ["nodejs16.x", "nodejs14.x", "python3.7", "java8", "dotnet7", "go1.x", "ruby2.7", "provided"] <<Lambda function is using a runtime that is targeted for deprecation.>>
            }
        }
    }
}
```

現在，假設您要編寫定義 Lambda 函數的以下 `iac/lambda.yaml` CloudFormation 範本：

```
  Fn:
    Type: AWS::Lambda::Function
    Properties:
      Runtime: python3.7
      CodeUri: src
      Handler: fn.handler
      Role: !GetAtt FnRole.Arn
      Layers:
        - arn:aws:lambda:us-east-1:111122223333:layer:LambdaInsightsExtension:35
```

在[安裝](https://docs.aws.amazon.com/cfn-guard/latest/ug/setting-up.html) Guard 公用程式後，驗證您的範本：

```
cfn-guard validate --rules etc/rules.guard --data iac/lambda.yaml
```

輸出如下：

```
lambda.yaml Status = FAIL
FAILED rules
rules.guard/lambda_soon_to_be_deprecated_runtime
---
Evaluating data lambda.yaml against rules rules.guard
Number of non-compliant resources 1
Resource = Fn {
  Type      = AWS::Lambda::Function
  Rule = lambda_soon_to_be_deprecated_runtime {
    ALL {
      Check =  Runtime not IN  ["nodejs16.x","nodejs14.x","python3.7","java8","dotnet7","go1.x","ruby2.7","provided"] {
        ComparisonError {
          Message          = Lambda function is using a runtime that is targeted for deprecation.
          Error            = Check was not compliant as property [/Resources/Fn/Properties/Runtime[L:88,C:15]] was not present in [(resolved, Path=[L:0,C:0] Value=["nodejs16.x","nodejs14.x","python3.7","java8","dotnet7","go1.x","ruby2.7","provided"])]
        }
          PropertyPath    = /Resources/Fn/Properties/Runtime[L:88,C:15]
          Operator        = NOT IN
          Value           = "python3.7"
          ComparedWith    = [["nodejs16.x","nodejs14.x","python3.7","java8","dotnet7","go1.x","ruby2.7","provided"]]
          Code:
               86.  Fn:
               87.    Type: AWS::Lambda::Function
               88.    Properties:
               89.      Runtime: python3.7
               90.      CodeUri: src
               91.      Handler: fn.handler

      }
    }
  }
}
```

 Guard 可讓您的開發人員透過本機開發工作站即可了解，他們需要更新範本以便使用組織允許的執行期。這發生在遞交至程式碼儲存庫之前，隨後會使 CI/CD 管道中的檢查失敗。因此，您的開發人員將取得此回饋，以便了解如何開發合乎規範的範本，並且將他們的時間轉移到編寫可創造商業價值的程式碼。此控制可套用到本機的開發人員工作站，在預遞交驗證 Webhook 和/或在部署前的 CI/CD 管道中套用。

## 警告
<a name="governance-cloudformation-guard-considerations"></a>

如果您使用 AWS Serverless Application Model (AWS SAM) 範本定義 Lambda 函數，注意您需要如下更新 Guard 規則以便搜尋 `AWS::Serverless::Function` 資源類型。

```
let lambda_functions = Resources.*[
    Type == "AWS::Serverless::Function"
]
```

Guard 還預期屬性會包含在資源定義當中。同時，AWS SAM 範本允許在單獨的[全域](https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/sam-specification-template-anatomy-globals.html)區段指定屬性。「全域」區段裡定義的屬性不使用您的 Guard 規則進行驗證。

如 Guard 故障診斷[文件](https://docs.aws.amazon.com/cfn-guard/latest/ug/troubleshooting.html)中所述，應注意 Guard 不支援簡寫形式的內部函數 (例如 `!GetAtt` 或 `!Sub`)，而要求使用展開形式：`Fn::GetAtt` 和 `Fn::Sub`。([先前的範例](#guard-iac-yaml)不會評估 Role 屬性，因此為了簡便起見而使用簡寫形式的內部函數。)