

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

# 使用 實作 Lambda 的預防性控制 AWS Config
<a name="governance-config"></a>

儘早在開發過程中確保無伺服器應用程式的合規性至關重要。在本主題中，我們將說明如何使用 [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html) 實作預防性控制項。這可讓您在開發過程的早期實作合規檢查，並且使您可以在 CI/CD 管道中實作相同的控制項。這也會標準化 規則集中受管儲存庫中的控制項，讓您可以在 AWS 帳戶中一致地套用控制項。

例如，假設您的合規管理員定義了一項要求，以確保所有 Lambda 函數都包含 AWS X-Ray 追蹤。使用 AWS Config的主動模式，您可以在部署之前對 Lambda 函數資源執行合規檢查，藉由提供更快速的基礎設施意見回饋作為程式碼範本，降低部署設定不當的 Lambda 函數並節省開發人員時間的風險。以下是使用 進行預防性控制的流程視覺化 AWS Config：

 ![\[CloudFormation requests must pass AWS Config rules before provisioning.\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/governance-config-1.png) 

考慮所有 Lambda 函數都必須啟用追蹤功能的要求。為了回應，平台團隊會識別在所有帳戶中主動執行特定 AWS Config 規則的需求。此規則會將任何未設定 X-Ray 追蹤組態的 Lambda 函數標記為不合規資源。團隊開發規則，將其封裝在[一致性套件](https://docs.aws.amazon.com/config/latest/developerguide/conformance-packs.html)中，並將一致性套件部署到所有 AWS 帳戶，以確保組織中的所有帳戶統一套用這些控制項。您可以採用 AWS CloudFormation Guard 2.x.x 語法編寫該規則，它將採用以下形式：

```
rule name when condition { assertion }
```

以下是檢查以確保 Lambda 函數已啟用追蹤功能的範例 Guard 規則：

```
rule lambda_tracing_check {
  when configuration.tracingConfig exists {
      configuration.tracingConfig.mode == "Active"
  }
}
```

 平台團隊透過強制每個 AWS CloudFormation 部署叫用預先建立/更新[掛](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks-structure.html)鉤，採取進一步的動作。他們會全權負責開發此勾點和設定管道、強化合規規則的集中控制，並確保在所有部署中一致地套用這些規則。若要開發、封裝和註冊掛鉤，請參閱 CloudFormation 命令列界面 (CFN-CLI) 文件中的[開發 AWS CloudFormation 掛鉤](https://docs.aws.amazon.com/cloudformation-cli/latest/hooks-userguide/hooks-develop.html)。您可以使用 [CloudFormation CLI](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/initiating-hooks-project-python.html) 來建立勾點專案：

```
cfn init
```

此命令會要求您提供有關勾點專案的一些基本資訊，並在其中建立包含下列檔案的專案：

```
README.md
<hook-name>.json
rpdk.log
src/handler.py
template.yml
hook-role.yaml
```

做為勾點開發人員，您需要在 `<hook-name>.json` 組態檔案中新增所需的目標資源類型。在下列組態中，勾點被設為在使用 CloudFormation 建立任何 Lambda 函數之前執行。您也可以為 `preUpdate` 和 `preDelete` 動作新增類似的處理常式。

```
    "handlers": {
        "preCreate": {
            "targetNames": [
                "AWS::Lambda::Function"
            ],
            "permissions": []
        }
    }
```

您也需要確保 CloudFormation 勾點具有呼叫 AWS Config APIs的適當許可。您可以透過更新名為 `hook-role.yaml` 的角色定義檔案來執行該動作。角色定義檔案預設具有下列信任政策，以允許 CloudFormation 擔任相關角色。

```
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - hooks.cloudformation.amazonaws.com
                - resources.cloudformation.amazonaws.com
```

若要允許此勾點呼叫組態 API，您必須將下列許可新增至政策陳述式。然後，您可以使用 `cfn submit` 命令提交勾點專案，CloudFormation 會在其中為您建立具有所需許可的角色。

```
      Policies:
        - PolicyName: HookTypePolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - "config:Describe*"
                  - "config:Get*"
                  - "config:List*"
                  - "config:SelectResourceConfig"
                Resource: "*
```

接下來，您需要在 `src/handler.py` 檔案中編寫 Lambda 函數。在此檔案中，您將在啟動該專案時發現已建立的名為 `preCreate`、`preUpdate` 和 `preDelete` 的方法。您旨在撰寫一個常用、可重複使用的函數，使用 在 AWS Config 主動模式下呼叫 `StartResourceEvaluation` API 適用於 Python (Boto3) 的 AWS SDK。此 API 呼叫會將資源屬性做為輸入，並且比照規則定義評估資源。

```
def validate_lambda_tracing_config(resource_type, function_properties: MutableMapping[str, Any]) -> ProgressEvent:
  LOG.info("Fetching proactive data")
  config_client = boto3.client('config')
  resource_specs = {
      'ResourceId': 'MyFunction',
      'ResourceType': resource_type,
      'ResourceConfiguration': json.dumps(function_properties),
      'ResourceConfigurationSchemaType': 'CFN_RESOURCE_SCHEMA'
  }
  LOG.info("Resource Specifications:", resource_specs)
  eval_response = config_client.start_resource_evaluation(EvaluationMode='PROACTIVE', ResourceDetails=resource_specs, EvaluationTimeout=60)
  ResourceEvaluationId = eval_response.ResourceEvaluationId
  compliance_response = config_client.get_compliance_details_by_resource(ResourceEvaluationId=ResourceEvaluationId)
  LOG.info("Compliance Verification:", compliance_response.EvaluationResults[0].ComplianceType)
  if "NON_COMPLIANT" == compliance_response.EvaluationResults[0].ComplianceType:
      return ProgressEvent(status=OperationStatus.FAILED, message="Lambda function found with no tracing enabled : FAILED", errorCode=HandlerErrorCode.NonCompliant)
  else:
      return ProgressEvent(status=OperationStatus.SUCCESS, message="Lambda function found with tracing enabled : PASS.")
```

現在，您可以從處理常式為預先建立的勾點呼叫常用的函數。以下是處理常式的範例：

```
@hook.handler(HookInvocationPoint.CREATE_PRE_PROVISION)
def pre_create_handler(
        session: Optional[SessionProxy],
        request: HookHandlerRequest,
        callback_context: MutableMapping[str, Any],
        type_configuration: TypeConfigurationModel
) -> ProgressEvent:
    LOG.info("Starting execution of the hook")
    target_name = request.hookContext.targetName
    LOG.info("Target Name:", target_name)
    if "AWS::Lambda::Function" == target_name:
        return validate_lambda_tracing_config(target_name,
            request.hookContext.targetModel.get("resourceProperties")
        )
    else:
        raise exceptions.InvalidRequest(f"Unknown target type: {target_name}")
```

在此步驟之後，您可以註冊勾點並將其設定為接聽所有 AWS Lambda 函數建立事件。

 開發人員會使用 Lambda 為無伺服器微服務準備基礎設施即程式碼 (IaC) 範本。此準備工作包括遵守內部標準，然後進行本機測試並將範本遞交至儲存庫。以下是範例 IaC 範本：

```
  MyLambdaFunction:
  Type: 'AWS::Lambda::Function'
  Properties:
    Handler: index.handler
    Role: !GetAtt LambdaExecutionRole.Arn
    FunctionName: MyLambdaFunction
    Code:
      ZipFile: |
        import json

        def handler(event, context):
            return {
                'statusCode': 200,
                'body': json.dumps('Hello World!')
            }
    Runtime: python3.14
    TracingConfig:
        Mode: PassThrough
    MemorySize: 256
    Timeout: 10
```

做為 CI/CD 程序的一部分，當部署 CloudFormation 範本時，CloudFormation 服務會在佈建 `AWS::Lambda::Function` 資源類型前直接調用預先建立/更新勾點。勾點利用以主動模式執行的 AWS Config 規則來驗證 Lambda 函數組態是否包含必要的追蹤組態。來自勾點的回應將決定下一個步驟。如果合規，勾點將發出成功訊號，CloudFormation 會繼續佈建資源。若不合規，CloudFormation 堆疊部署將會失敗，管道立即停止，而系統會記錄詳細資訊以供後續審核。合規通知將傳送至相關的利害關係人。

您可以在 CloudFormation 主控台中找到勾點成功/失敗的資訊：

 ![\[Hook success/fail information in the CloudFormation console\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/governance-config-2.png) 

如果已經為 CloudFormation 勾點啟用日誌，您可以擷取勾點評估結果。以下是狀態為失敗的勾點範例日誌，表示 Lambda 函數未啟用 X-Ray：

 ![\[Sample log for a hook with a failed status\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/governance-config-3.png) 

如果開發人員選擇將 IaC 變更為將 `TracingConfig Mode` 值更新為 `Active` 並重新部署，勾點將成功執行且堆疊將繼續建立 Lambda 資源。

 ![\[CloudFormation console shows successful resource deployment\]](http://docs.aws.amazon.com/zh_tw/lambda/latest/dg/images/governance-config-4.png) 

透過這種方式，您可以在 AWS 帳戶中開發和部署無伺服器資源時， AWS Config 以主動模式使用 實作預防性控制。透過將 AWS Config 規則整合到 CI/CD 管道，您可以識別並有針對性地封鎖不合規的資源部署，例如缺少主動追蹤組態的 Lambda 函數。這可確保只有符合最新控管政策的資源才會部署到您的 AWS 環境中。