

这是 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)或Config AWS 。](https://docs.aws.amazon.com/config/latest/developerguide/WhatIsConfig.html)尽管如此， AWS CDK 在开发过程中评估规则集的能力仍然很有用，因为它可以提高检测速度和开发人员的工作效率。

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

**注意**  
之前的`Beta1`接口（例如`IPolicyValidationPluginBeta1``PolicyValidationPluginReportBeta1`、和 on 的`policyValidationBeta1`属性`Stage`）已升级为稳定的无后缀等效接口（例如，）。`IPolicyValidationPlugin` `PolicyValidationPluginReport`这些`Beta1`接口已被弃用，但可以继续使用。现在，推荐的注册验证插件的方法是通过`Validations`类而不是`policyValidationBeta1`属性。

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

### 添加验证插件
<a name="adding-validation-plugins"></a>

要在应用程序中使用一个或多个验证插件，请使用以下`Validations`类：

```
import { Validations } from 'aws-cdk-lib';
import { CfnGuardValidator } from '@cdklabs/cdk-validator-cfnguard';

const app = new App();

// Add a validation plugin to the entire app
Validations.of(app).addPlugins(new CfnGuardValidator());

// Or add to a particular stage
const prodStage = new Stage(app, 'ProdStage');
Validations.of(prodStage).addPlugins(new CfnGuardValidator());
```

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

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

### 添加警告和错误
<a name="adding-warnings-and-errors"></a>

该`Validations`类还提供了向构造中添加自定义警告和错误的方法：

```
import { Validations } from 'aws-cdk-lib';

const bucket = new s3.Bucket(this, 'MyBucket');

// Add a warning
Validations.of(bucket).addWarning('MyWarningId', 'This bucket does not have versioning enabled');

// Add an error (will cause synthesis to fail)
Validations.of(bucket).addError('MyErrorId', 'This bucket must have encryption enabled');
```

### 确认警告
<a name="acknowledging-warnings"></a>

如果要取消特定警告，请使用以下`acknowledge`方法：

```
import { Validations } from 'aws-cdk-lib';

Validations.of(myConstruct).acknowledge({ id: 'MyWarningId', reason: 'This is acceptable for our use case' });
```

该`acknowledge`方法接受带有 a `id` 和 a 的`Acknowledgment`对象`reason`。`id`使用分`::`隔符将验证源前缀与规则名称分开（例如，`annotation::MyWarning`或`cdknag::AwsSolutions-S1`）。如果您提供的裸身份不带`::`，则会自动添加`annotation::`前缀。

### AWS CloudFormation 警卫插件
<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 控制塔环境中启用 Cont AWS rol Tower 主动控制时，这些控件可以停止部署通过 AWS CloudFormation部署的不合规资源。有关托管的主动控制功能及其工作原理的更多信息，请参阅 [AWS Control Tower 文档](https://docs.aws.amazon.com/controltower/latest/userguide/proactive-controls.html)。

这些 AWS CDK 捆绑控件和托管 Cont AWS rol Tower 主动控件最好一起使用。在这种情况下，您可以使用与 Contro AWS l Tower 云环境中相同的主动控件来配置此验证插件。然后，您可以通过在`cdk synth`本地运行来快速确信您的 AWS CDK 应用程序将通过 Cont AWS rol 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 CD](context.md) K）。

如果您选择 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 核心模块和您的策略工具之间的通信协议由`IPolicyValidationPlugin`接口定义。要创建新插件，必须编写一个可以实现此接口的类。您需要实现两件事：插件名称（通过覆盖 `name` 属性）和 `validate()` 方法。

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

```
validate(context: IPolicyValidationContext): PolicyValidationPluginReport {
  // 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) 