

这是 AWS CDK v2 开发者指南。旧版 CDK v1 于 2022 年 6 月 1 日进入维护阶段，并于 2023 年 6 月 1 日终止支持。

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

# 在合成时进行 AWS CDK 策略验证
<a name="policy-validation-synthesis"></a>

## 在合成时进行策略验证
<a name="policy-validation"></a>

如果您或您的组织使用任何策略验证工具（例如 [AWS CloudFormation Guard](https://docs.aws.amazon.com/cfn-guard/latest/ug/what-is-guard.html) 或 [OPA](https://www.openpolicyagent.org/)）在 AWS CloudFormation 模板上定义约束，则可以在合成时将其与 AWS CDK 集成。使用适当的策略验证插件，您可以让 AWS CDK 应用程序在合成后立即根据您的策略对生成的 AWS CloudFormation 模板进行检查。如果有任何违规行为，合成将失败，控制台将打印一份报告。

AWS CDK 在合成时执行的验证可在部署生命周期的某一时刻验证控制功能，但它们不能影响合成之外发生的操作。示例包含了直接在控制台中或通过服务 API 执行的操作。它们无法阻止合成后对 AWS CloudFormation 模板的改变。应独立设置一些其他机制来更权威地验证相同的规则集，例如 [AWS CloudFormation 钩子](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html)或 [AWS Config](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html)。尽管如此，AWS CDK 在开发过程中评估规则集的功能仍然很有用，因为这有助于提高检测速度和开发人员的工作效率。

AWS CDK 策略验证的目标是尽量减少开发过程中所需的设置量，并使其尽可能简单。

**注意**  
此功能被视为实验性质，插件 API 和验证报告的格式将来都有可能发生变化。

## 对于应用程序开发人员
<a name="for-application-developers"></a>

要在应用程序中使用一个或多个验证插件，请使用 `Stage` 的 `policyValidationBeta1` 属性：

```
import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';
const app = new App({
  policyValidationBeta1: [
    new CfnGuardValidator()
  ],
});
// only apply to a particular stage
const prodStage = new Stage(app, 'ProdStage', {
  policyValidationBeta1: [...],
});
```

合成后，将立即调用以这种方式注册的所有插件，来验证在您定义的范围内生成的所有模板。特别是，如果在 `App` 对象中注册模板，则所有模板都将接受验证。

**警告**  
除了修改云程序集之外，插件可以执行 AWS CDK 应用程序可以执行的任何操作。插件可以从文件系统中读取数据、访问网络等。作为插件的使用者，您有责任验证其使用是否安全。

### AWS CloudFormation Guard 插件
<a name="cfnguard-plugin"></a>

采用 [https://github.com/cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard) 插件，您可以使用 [AWS CloudFormation Guard](https://github.com/aws-cloudformation/cloudformation-guard) 来执行策略验证。`CfnGuardValidator` 插件中内置了一组精选的 [AWS Control Tower 主动控制功能](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html)。可在[项目文档](https://github.com/cdklabs/cdk-validator-cfnguard/blob/main/README.md)中找到当前规则集。如[在合成时进行策略验证](#policy-validation)中所述，我们建议组织使用 [AWS CloudFormation 钩子](https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/hooks.html)来设置更权威的验证方法。

对于 [AWS Control Tower](https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html) 客户，可以在整个组织中部署这些相同的主动控制功能。当您在 AWS Control Tower 环境中启用 AWS Control Tower 主动控制功能时，这些控制功能可以停止部署通过 AWS CloudFormation 部署的不合规资源。有关托管的主动控制功能及其工作原理的更多信息，请参阅 [AWS Control Tower 文档](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html)。

最好将这些 AWS CDK 捆绑的控制功能和托管的 AWS Control Tower 主动控制功能一起使用。在这种情况下，您可以使用相同的主动控制功能来配置此验证插件，这些控制功能在 AWS Control Tower 云环境中处于活动状态。然后，您可以通过在本地运行 `cdk synth` 来快速确信您的 AWS CDK 应用程序将通过 AWS Control Tower 控制。

### 验证报告
<a name="validation-report"></a>

合成 AWS CDK 应用程序时，将调用验证器插件并打印结果。下面显示了一个示例报告。

```
Validation Report (CfnGuardValidator)
-------------------------------------
(Summary)
╔═══════════╤════════════════════════╗
║ Status    │ failure                ║
╟───────────┼────────────────────────╢
║ Plugin    │ CfnGuardValidator      ║
╚═══════════╧════════════════════════╝
(Violations)
Ensure S3 Buckets are encrypted with a KMS CMK (1 occurrences)
Severity: medium
  Occurrences:

    - Construct Path: MyStack/MyCustomL3Construct/Bucket
    - Stack Template Path: ./cdk.out/MyStack.template.json
    - Creation Stack:
        └──  MyStack (MyStack)
             │ Library: aws-cdk-lib.Stack
             │ Library Version: 2.50.0
             │ Location: Object.<anonymous> (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:25:20)
             └──  MyCustomL3Construct (MyStack/MyCustomL3Construct)
                  │ Library: N/A - (Local Construct)
                  │ Library Version: N/A
                  │ Location: new MyStack (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:15:20)
                  └──  Bucket (MyStack/MyCustomL3Construct/Bucket)
                       │ Library: aws-cdk-lib/aws-s3.Bucket
                       │ Library Version: 2.50.0
                       │ Location: new MyCustomL3Construct (/home/johndoe/tmp/cdk-tmp-app/src/main.ts:9:20)
    - Resource Name: amzn-s3-demo-bucket
    - Locations:
      > BucketEncryption/ServerSideEncryptionConfiguration/0/ServerSideEncryptionByDefault/SSEAlgorithm
  Recommendation: Missing value for key `SSEAlgorithm` - must specify `aws:kms`
  How to fix:
    > Add to construct properties for `cdk-app/MyStack/Bucket`
      `encryption: BucketEncryption.KMS`

Validation failed. See above reports for details
```

默认情况下，将以人类可读的格式打印报告。如果您想要 JSON 格式的报告，请通过 CLI 使用 `@aws-cdk/core:validationReportJson` 进行启用，或将其直接传递给应用程序：

```
const app = new App({
  context: { '@aws-cdk/core:validationReportJson': true },
});
```

或者，您可以使用项目目录中的 `cdk.json` 或 `cdk.context.json` 文件来设置此上下文键值对（请参阅[上下文值和 AWS CDK](context.md)）。

如果您选择 JSON 格式，则 AWS CDK 会将策略验证报告打印到云程序集目录中名为 `policy-validation-report.json` 的文件中。对于默认的人类可读格式，报告将打印为标准输出。

## 对于插件作者
<a name="plugin-authors"></a>

### 插件
<a name="plugins"></a>

AWS CDK 核心框架负责注册和调用插件，然后显示格式化的验证报告。该插件的职责是充当 AWS CDK 框架和策略验证工具之间的转换层。可以用 AWS CDK 支持的任何语言创建插件。如果您正在创建可能使用多种语言的插件，则建议使用 `TypeScript` 来创建该插件，这样您就可以使用 JSII 以每种 AWS CDK 语言发布该插件。

### 创建插件
<a name="creating-plugins"></a>

AWS CDK 核心模块和策略工具之间的通信协议由 `IPolicyValidationPluginBeta1` 接口进行定义。要创建新插件，必须编写一个可以实现此接口的类。您需要实现两件事：插件名称（通过覆盖 `name` 属性）和 `validate()` 方法。

框架将调用 `validate()`，同时传递一个 `IValidationContextBeta1` 对象。待验证模板的位置由 `templatePaths` 给出。该插件应返回一个 `ValidationPluginReportBeta1` 实例。此对象表示用户在合成结束时将收到的报告。

```
validate(context: IPolicyValidationContextBeta1): PolicyValidationReportBeta1 {
  // First read the templates using context.templatePaths...
  // ...then perform the validation, and then compose and return the report.
  // Using hard-coded values here for better clarity:
  return {
    success: false,
    violations: [{
      ruleName: 'CKV_AWS_117',
      description: 'Ensure that AWS Lambda function is configured inside a VPC',
      fix: 'https://docs.bridgecrew.io/docs/ensure-that-aws-lambda-function-is-configured-inside-a-vpc-1',
      violatingResources: [{
        resourceName: 'MyFunction3BAA72D1',
        templatePath: '/home/johndoe/myapp/cdk.out/MyService.template.json',
        locations: 'Properties/VpcConfig',
      }],
    }],
  };
}
```

请注意，不允许插件修改云程序集中的任何内容。任何这样的尝试都将导致合成失败。

如果您的插件依赖于外部工具，请记住，某些开发人员可能尚未在他们的工作站中安装该工具。为了尽量减少摩擦，我们强烈建议您随插件包提供一些安装脚本，以实现整个过程的自动化。更好的做法是，在安装软件包时运行该脚本。例如，使用 `npm`，您可以将其添加到 `package.json` 文件中的 `postinstall` [脚本](https://docs.npmjs.com/cli/v9/using-npm/scripts)中。

### 处理豁免
<a name="handling-exemptions"></a>

如果您的组织有处理豁免的机制，则可以将其作为验证器插件的一部分来实现。

以下示例场景说明了可能的豁免机制：
+ 组织有一条规则，即*除非*在某些情况下，否则不允许使用公有 Amazon S3 存储桶。
+ 开发人员正在创建属于以上其中一种情况的 Amazon S3 存储桶，并请求豁免（例如创建工单）。
+ 安全工具知道如何从注册了豁免的内部系统中进行读取

在这种情况下，开发人员将在内部系统中请求异常，然后需要以某种方式“注册”该异常。在警卫插件示例的基础上，您可以创建一个处理豁免的插件，方法是筛选出在内部票务系统中具有匹配豁免的违规行为。

请参阅现有插件获取实现示例。
+  [@cdklabs/cdk-validator-cfnguard](https://github.com/cdklabs/cdk-validator-cfnguard) 