本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
写作 AWS CloudFormation Guard 规则
在中 AWS CloudFormation Guard,规则就是 policy-as-code规则。您使用 Guard 域专用语言 (DSL) 编写规则,您可以根据这些规则验证 JSON 或 YAML 格式的数据。规则由条款组成。
您可以将使用 Guard DSL 编写的规则保存到使用任何文件扩展名的纯文本文件中。
您可以创建多个规则文件并将其归类为一个规则集。规则集允许您同时根据多个规则文件验证 JSON 或 YAML 格式的数据。
主题
子句
子句是计算结果为 true (PASS) 或 false (FAIL) 的布尔表达式。子句要么使用二元运算符来比较两个值,要么使用对单个值进行运算的一元运算符。
一元子句的示例
以下一元子句评估集合TcpBlockedPorts是否为空。
InputParameters.TcpBlockedPorts not empty
以下一元子句评估该ExecutionRoleArn属性是否为字符串。
Properties.ExecutionRoleArn is_string
二进制子句的示例
以下二进制子句评估该BucketName属性是否包含字符串encrypted,无论大小写如何。
Properties.BucketName != /(?i)encrypted/
以下二进制子句评估该ReadCapacityUnits属性是否小于或等于 5,000。
Properties.ProvisionedThroughput.ReadCapacityUnits <= 5000
编写 Guard 规则子句的语法
<query> <operator> [query|value literal] [custom message]
守卫规则子句的属性
query-
写入以点 (
.) 分隔的表达式,用于遍历分层数据。查询表达式可以包括筛选表达式来定位值的子集。可以将查询分配给变量,这样您就可以编写一次查询,然后在规则集的其他地方引用它们,这样您就可以访问查询结果。有关编写查询和筛选的更多信息,请参阅定义查询和筛选。
必需:是
operator-
一元运算符或二进制运算符,可帮助检查查询的状态。二元运算符的左侧 (LHS) 必须是查询,右侧 (RHS) 必须是查询或值文字。
支持的二元运算符:
==!=(等于)|>(不等于)|>=(大于)|(大于或等于)|<=(小于)|(小于或等于)|IN(在 [x、y、z 格式列表中]<支持的一元运算符:
exists|empty|is_string| |is_list|is_structnot(!)必需:是
query|value literal-
查询或支持的值文字,例如
string或integer(64)。支持的值文字:
-
所有原始类型:
string、、integer(64)、float(64)、bool、charregex -
所有用于表达
integer(64)float(64)、或char范围的专用范围类型,表示为:-
r[<lower_limit>, <upper_limit>],它转换为满足以下表达式k的任何值:lower_limit <= k <= upper_limit -
r[<lower_limit>, <upper_limit>),它会转换为满足以下表达式k的任何值:lower_limit <= k < upper_limit -
r(<lower_limit>, <upper_limit>],它转换为满足以下表达式k的任何值:lower_limit < k <= upper_limit -
r(<lower_limit>, <upper_limit>),这表示任何满足以下表达式k的值:lower_limit < k < upper_limit
-
-
嵌套键值结构数据的关联数组(映射)。例如:
{ "my-map": { "nested-maps": [ { "key": 10, "value": 20 } ] } } -
原始类型或关联数组类型的数组
必需:有条件的;使用二元运算符时为必填项。
-
custom message-
提供有关子句的信息的字符串。该消息显示在
validate和test命令的详细输出中,可用于理解或调试分层数据的规则评估。必需:否
在子句中使用查询
有关编写查询的信息,请参见定义查询和筛选和在 Guard 规则中分配和引用变量。
在子句中使用运算符
以下是示例 CloudFormation 模板,Template-1和Template-2。为了演示支持的运算符的使用,本节中的示例查询和子句参考了这些示例模板。
模板-1
Resources: S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: MyServiceS3Bucket BucketEncryption: ServerSideEncryptionConfiguration: - ServerSideEncryptionByDefault: SSEAlgorithm: 'aws:kms' KMSMasterKeyID: 'arn:aws:kms:us-east-1:123456789:key/056ea50b-1013-3907-8617-c93e474e400' Tags: - Key: stage Value: prod - Key: service Value: myService
模板-2
Resources: NewVolume: Type: AWS::EC2::Volume Properties: Size: 100 VolumeType: io1 Iops: 100 AvailabilityZone: Fn::Select: - 0 - Fn::GetAZs: us-east-1 Tags: - Key: environment Value: test DeletionPolicy: Snapshot
使用一元运算符的子句示例
-
empty— 检查集合是否为空。您还可以使用它来检查查询是否在分层数据中包含值,因为查询会生成集合。你不能用它来检查字符串值查询是否定义了空字符串 ("")。有关更多信息,请参阅 定义查询和筛选。以下子句检查模板是否定义了一个或多个资源。它的计算结果
PASS为,因为中定义了具有逻辑 IDS3Bucket的Template-1资源。Resources !empty以下子句检查是否为
S3Bucket资源定义了一个或多个标签。它的计算结果PASS为,因为在中Template-1为该Tags属性定义S3Bucket了两个标签。Resources.S3Bucket.Properties.Tags !empty -
exists— 检查每次出现的查询是否都有值并且可以用来代替!= null。以下子句检查是否为定义了该
BucketEncryption属性S3Bucket。它的计算结果PASS为,因为BucketEncryption是在S3Bucket中定义的。Template-1Resources.S3Bucket.Properties.BucketEncryption exists
注意
遍历输入数据时,empty和not exists检查true的计算结果是否缺少属性键。例如,如果未在的模板中定义该Properties部分S3Bucket,则该子句的Resources.S3Bucket.Properties.Tag empty计算结果为。trueexists和empty检查不会在错误消息中显示文档内的 JSON 指针路径。这两个子句通常都有检索错误,无法保留这些遍历信息。
-
is_string— 检查每次出现的查询是否为string类型。以下子句检查是否为
S3Bucket资源的BucketName属性指定了字符串值。它的计算结果PASS为,因为在BucketName中Template-1指定了字符串值"MyServiceS3Bucket"。Resources.S3Bucket.Properties.BucketName is_string -
is_list— 检查每次出现的查询是否为list类型。以下子句检查是否为
S3Bucket资源的Tags属性指定了列表。它的计算结果PASS为,因为在中指定了两个键值对。TagsTemplate-1Resources.S3Bucket.Properties.Tags is_list -
is_struct— 检查每次出现的查询是否都是结构化数据。以下子句检查是否为
S3Bucket资源的BucketEncryption属性指定了结构化数据。它的计算结果PASS为,因为BucketEncryption是使用(object)中的ServerSideEncryptionConfigurationTemplate-1属性类型指定的。Resources.S3Bucket.Properties.BucketEncryption is_struct
注意
要检查反向状态,可以将 ( not !) 运算符与is_stringis_list、和运is_struct算符一起使用。
使用二元运算符的子句示例
以下子句检查为中的S3Bucket资源BucketName属性指定的值是否Template-1包含字符串encrypt,无论大小写如何。其计算结果PASS为,因为指定的存储桶名称"MyServiceS3Bucket"不包含字符串encrypt。
Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/
以下子句检查为中的NewVolume资源Size属性指定的值Template-2是否在特定范围内:50 <= Size <= 200。它的计算结果PASS为,因为100是指定的。Size
Resources.NewVolume.Properties.Size IN r[50,200]
以下子句检查中为NewVolume资源VolumeType属性指定的值是否Template-2为io1io2、或gp3。它的计算结果PASS为,因为io1是指定的。NewVolume
Resources.NewVolume.Properties.NewVolume.VolumeType IN [ 'io1','io2','gp3' ]
注意
在子句中使用自定义消息
在以下示例中,的子句Template-2包括自定义消息。
Resources.NewVolume.Properties.Size IN r(50,200) << EC2Volume size must be between 50 and 200, not including 50 and 200 >> Resources.NewVolume.Properties.VolumeType IN [ 'io1','io2','gp3' ] <<Allowed Volume Types are io1, io2, and gp3>>
合并条款
在 Guard 中,写在新行上的每个子句都使用连词(布尔and逻辑)与下一个子句隐式组合。请参阅以下示例。
# clause_A ^ clause_B ^ clause_C clause_A clause_B clause_C
也可以使用 disjunction 将子句与下一个子句合并,方法是在第一个子句的or|OR末尾指定。
<query> <operator> [query|value literal] [custom message] [or|OR]
在 Guard 子句中,首先评估分离词,然后评估连词。保护规则可以定义为计算结果为 () 或 false () 的子句and|AND的分离组合true(a o PASS f or|OR sFAIL)。这类似于连词法线形式
以下示例演示了子句的求值顺序。
# (clause_E v clause_F) ^ clause_G clause_E OR clause_F clause_G # (clause_H v clause_I) ^ (clause_J v clause_K) clause_H OR clause_I clause_J OR clause_K # (clause_L v clause_M v clause_N) ^ clause_O clause_L OR clause_M OR clause_N clause_O
所有基于该示例的子句均Template-1可使用连词进行组合。请参阅以下示例。
Resources.S3Bucket.Properties.BucketName is_string Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/ Resources.S3Bucket.Properties.BucketEncryption exists Resources.S3Bucket.Properties.BucketEncryption is_struct Resources.S3Bucket.Properties.Tags is_list Resources.S3Bucket.Properties.Tags !empty
使用带有守卫规则的方块
块是从一组相关的子句、条件或规则中去除冗长和重复内容的组合。有三种类型的方块:
-
查询区块
-
when方块 -
命名规则块
查询区块
以下是基于该示例的子句Template-1。连词用于合并子句。
Resources.S3Bucket.Properties.BucketName is_string Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/ Resources.S3Bucket.Properties.BucketEncryption exists Resources.S3Bucket.Properties.BucketEncryption is_struct Resources.S3Bucket.Properties.Tags is_list Resources.S3Bucket.Properties.Tags !empty
每个子句中的部分查询表达式都是重复的。您可以使用查询块来提高可组合性,并消除一组具有相同初始查询路径的相关子句的冗长性和重复性。可以编写相同的子句集,如以下示例所示。
Resources.S3Bucket.Properties { BucketName is_string BucketName != /(?i)encrypt/ BucketEncryption exists BucketEncryption is_struct Tags is_list Tags !empty }
在查询块中,块之前的查询为块内的子句设置上下文。
有关使用方块的更多信息,请参阅撰写命名规则块。
when方块
你可以使用方块有条件地评估when方块,其形式如下。
when <condition> { Guard_rule_1 Guard_rule_2 ... }
when关键字表示when区块的起点。 condition是守卫规则。仅当对条件的评估结果为 true (PASS) 时,才会对方块进行评估。
以下是基于的示例when块Template-1。
when Resources.S3Bucket.Properties.BucketName is_string { Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/ }
仅当为指定的值为字符串时,才会对when块中的子句进行求值。BucketName如果在模板的Parameters部分中引用了BucketName为指定的值,如以下示例所示,则不会评估该when块中的子句。
Parameters: S3BucketName: Type: String Resources: S3Bucket: Type: AWS::S3::Bucket Properties: BucketName: Ref: S3BucketName ...
命名规则块
您可以为一组规则(规则集)指定名称,然后在其他规则中引用这些模块化验证块,称为命名规则块。命名规则块采用以下形式。
rule <rule name> [when <condition>] { Guard_rule_1 Guard_rule_2 ... }
rule关键字表示命名规则块的开头。
rule name是一个人类可读的字符串,用于唯一标识命名规则块。这是它封装的 Guard 规则集的标签。在这种用法中,“保护规则” 一词包括子句、查询块、when块和命名规则块。规则名称可用于指代其封装的规则集的评估结果,这使得命名规则块可重复使用。规则名称还提供了有关validate和test命令输出中规则失败的上下文。规则名称与区块的评估状态(PASSFAIL、或SKIP)一起显示在规则文件的评估输出中。请参阅以下示例。
# Sample output of an evaluation where check1, check2, and check3 are rule names. template.json Status = **FAIL** **SKIP rules** check1 **SKIP** **PASS rules** check2 **PASS** **FAILED rules** check3 **FAIL**
您还可以通过在规则名称后指定when关键字和条件来有条件地评估命名规则块。
以下是本主题前面讨论的示例when块。
rule checkBucketNameStringValue when Resources.S3Bucket.Properties.BucketName is_string { Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/ }
使用命名规则块,也可以将前面的内容写成以下内容。
rule checkBucketNameIsString { Resources.S3Bucket.Properties.BucketName is_string } rule checkBucketNameStringValue when checkBucketNameIsString { Resources.S3Bucket.Properties.BucketName != /(?i)encrypt/ }
您可以重复使用命名规则块并将其与其他 Guard 规则分组。以下是几个例子。
rule rule_name_A { Guard_rule_1 OR Guard_rule_2 ... } rule rule_name_B { Guard_rule_3 Guard_rule_4 ... } rule rule_name_C { rule_name_A OR rule_name_B } rule rule_name_D { rule_name_A rule_name_B } rule rule_name_E when rule_name_D { Guard_rule_5 Guard_rule_6 ... }
使用内置函数
AWS CloudFormation Guard 提供了内置函数,您可以在规则中使用这些函数来执行诸如字符串操作、JSON 解析和数据类型转换之类的操作。只有通过对变量的赋值才能支持函数。
关键功能
json_parse(json_string)-
解析模板中的内联 JSON 字符串。解析后,您可以评估生成的对象的属性。
count(collection)-
返回查询解析到的项目数。
regex_replace(base_string, regex_to_extract, regex_replacement)-
使用正则表达式替换部分字符串。
有关可用函数的完整列表,包括字符串操作、集合操作和数据类型转换函数,请参阅 Guard GitHub 存储库中的 Functions 文档