1 个不稳定版本
0.7.0 | 2020 年 9 月 18 日 |
---|
#9 in #cloud-formation
115KB
2K SLoC
[预览] AWS CloudFormation Guard
用于验证 AWS CloudFormation 资源是否符合策略的命令行工具。
目录
关于
cfn-guard
是一个用于使用轻量级、类似于防火墙规则语法的语法来检查 CloudFormation 资源属性的工具。
以下是如何使用它的一个示例,给定一个 CloudFormation 模板
> cat ebs_volume_template.json
{
"Resources": {
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 100,
"Encrypted": false,
"AvailabilityZone" : "us-east-1b"
}
},
"NewVolume2" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 99,
"Encrypted": true,
"AvailabilityZone" : "us-east-1b"
}
}
}
}
和规则文件
> cat ebs_volume_rule_set
let encryption_flag = true
let disallowed_azs = [us-east-1a,us-east-1b,us-east-1c]
AWS::EC2::Volume AvailabilityZone NOT_IN %disallowed_azs
AWS::EC2::Volume Encrypted != %encryption_flag
AWS::EC2::Volume Size == 101 |OR| AWS::EC2::Volume Size == 99 |OR| AWS::EC2::Volume Size >= 101
AWS::IAM::Role AssumeRolePolicyDocument.Version == 2012-10-18
AWS::EC2::Volume AvailabilityZone != /us-east-.*/
您可以检查该模板是否符合这些规则
> cfn-guard check -t ebs_volume_template.json -r ebs_volume_rule_set
"[NewVolume2] failed because [AvailabilityZone] is [us-east-1b] and the pattern [us-east-.*] is not permitted"
"[NewVolume2] failed because [Encrypted] is [true] and that value is not permitted"
"[NewVolume2] failed because [us-east-1b] is in [us-east-1a,us-east-1b,us-east-1c] which is not permitted for [AvailabilityZone]"
"[NewVolume] failed because [AvailabilityZone] is [us-east-1b] and the pattern [us-east-.*] is not permitted"
"[NewVolume] failed because [Size] is [100] and the permitted value is [101]"
"[NewVolume] failed because [Size] is [100] and the permitted value is [99]"
"[NewVolume] failed because [Size] is [100] and the permitted value is [>= 101]"
"[NewVolume] failed because [us-east-1b] is in [us-east-1a,us-east-1b,us-east-1c] which is not permitted for [AvailabilityZone]"
Number of failures: 7
我们设计 cfn-guard
以便将其插入到您的构建过程中。
如果 CloudFormation Guard 成功验证 CloudFormation 模板,则不会输出任何内容,并以退出状态 $?
(在 bash 中)退出状态为 0
。如果 CloudFormation Guard 识别到规则违规,则提供违规规则的计数、规则失败的原因以及退出状态为 2
。如果规则集或处理过程中存在运行时错误,它将退出并显示 1
。
如果您希望 CloudFormation Guard 获取规则检查的结果,但仍然得到退出值 0
,请使用 -w
警告标志。
检查与 Rulegen
cfn-guard
有两种模式
检查
check
(如上例所示)检查模板是否与规则集相匹配。
cfn-guard-check
Check CloudFormation templates against rules
USAGE:
cfn-guard check [FLAGS] --rule_set <RULE_SET_FILE> --template <TEMPLATE_FILE>
FLAGS:
-h, --help Prints help information
-s, --strict-checks Fail resources if they're missing the property that a rule checks
-v Sets the level of verbosity - add v's to increase output
-V, --version Prints version information
-w, --warn_only Show results but return an exit code of 0 regardless of rule violations
OPTIONS:
-r, --rule_set <RULE_SET_FILE> Rules to check the template against
-t, --template <TEMPLATE_FILE> CloudFormation Template
Rulegen
rulegen
从 CloudFormation 模板自动生成一组与资源属性匹配的 cfn-guard
规则。这是开始编写规则或从已知的良好模板创建可立即使用的规则集的有用方法。
cfn-guard-rulegen
Autogenerate rules from an existing CloudFormation template
USAGE:
cfn-guard rulegen [FLAGS] <TEMPLATE>
FLAGS:
-h, --help Prints help information
-v Sets the level of verbosity - add v's to increase output
-V, --version Prints version information
ARGS:
<TEMPLATE>
例如
> cfn-guard rulegen Examples/ebs-volume-template.json
AWS::EC2::Volume AvailabilityZone == us-west-2b |OR| AWS::EC2::Volume AvailabilityZone == us-west-2c
AWS::EC2::Volume Encrypted == false
AWS::EC2::Volume Size == 50 |OR| AWS::EC2::Volume Size == 500
考虑到可能产生数百甚至数千条规则,我们建议将输出通过 sort
管道传递并保存到文件中供编辑
cfn-guard rulegen Examples/aws-waf-security-automations.template | sort > ~/waf_rules
编写规则
基本语法
我们将 cfn-guard
规则模式化为防火墙规则。它们易于编写,并且具有声明性语法。
CloudFormation Guard 最基本的规则形式为
<CloudFormation Resource Type> <Property> <Operator> <Value>
可用的运算符包括
==
- 等于!=
- 不等于<
- 小于>
- 大于<=
- 小于等于>=
- 大于等于IN
- 在以下列表中:[x, y, z]
NOT_IN
- 不在以下列表中:[x, y, z]
检查资源属性和属性
规则中的属性可以有两种形式。基本形式旨在使编写简单规则非常直接
AWS::EC2::Volume Encryption == true
这种简单形式假设您正在检查的属性位于资源的Properties
部分
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 101,
"Encrypted": true,
"AvailabilityZone" : "us-west-2b"
}
}
但是,您可能还想要编写一个检查资源属性的规则
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : "100",
"Encrypted" : "true",
},
"DeletionPolicy" : "Snapshot"
}
在这种情况下,假设我们想检查出于部署安全原因的DeletionPolicy
。我们可以编写一个检查位于Properties
之上的属性的规则,通过在属性位置前的符号前加上一个.
来表示您想检查资源根部的值
AWS::EC2::Volume .DeletionPolicy == Snapshot
注释
可以通过#
运算符向规则集添加注释
# This is a comment
规则逻辑
AND和OR
给定规则集中的每个规则都隐式地与每个其他规则进行AND
运算。
您可以使用|OR|
在单行上对规则进行OR
,以提供任意类型的替代可接受值
AWS::EBS::Volume Size == 500 |OR| AWS::EBS::Volume AvailabiltyZone == us-east-1b
WHEN检查
有时,您可能不希望在一个模板中对特定类型的每个资源检查相同的值。您可以使用WHEN-CHECK
语法编写条件检查
<CloudFormation Resource Type> WHEN <Property> <Operator> <Value> CHECK <Property> <Operator> <Value>
例如
AWS::DynamoDB::Table WHEN Tags.* == /.*PROD.*/ CHECK .DeletionPolicy == Retain
第一个部分(WHEN Tags.* == /.*PROD.*/
)是要过滤的条件
第二个部分(CHECK .DeletionPolicy == Retain
)是资源必须通过才能使规则通过的结果
如果条件匹配,则评估结果,并将评估结果添加到整体规则集结果中
请注意,WHEN
检查只能一次操作一个资源类型。它们也可以像常规规则一样使用OR
进行聚合
AWS::DynamoDB::Table when Tags == /.*PROD.*/ check .DeletionPolicy == Retain |OR| AWS::DynamoDB::Table WHEN Tags.* == /.*DEV.*/ CHECK .DeletionPolicy == Delete
要查看条件规则的实际示例,请查看Examples目录中的conditional-ddb-template
文件。
检查嵌套字段
使用显式路径
CloudFormation 资源属性内部的字段可以使用点符号来表示
AWS::IAM::Role AssumeRolePolicyDocument.Statement.0.Principal.Service.0 == lambda.amazonaws.com
请注意,该规则中的列表索引语法与以下Resources
部分的CloudFormation模板相匹配
Resources:
LambdaRoleHelper:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
使用通配符
您还可以将模板项目、列表和映射称为通配符(*
)。通配符是一种预处理器宏,它检查规则文件和模板,将通配符展开成与正在检查的模板中包含的规则长度相同的规则列表。
换句话说,给定以下形式的模板
Resources:
LambdaRoleHelper:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
- Effect: Allow
Principal:
Service:
- ec2.amazonaws.com
以及以下形式的规则
AWS::IAM::Role AssumeRolePolicyDocument.Statement.*.Principal.Service.* == lambda.amazonaws.com
CloudFormation Guard 将遍历模板,并将内部通配符规则转换为
AWS::IAM::Role AssumeRolePolicyDocument.Statement.0.Principal.Service.0 == lambda.amazonaws.com |OR| AWS::IAM::Role AssumeRolePolicyDocument.Statement.1.Principal.Service.0 == ec2.amazonaws.com
通配符语义
请注意,等于(==
)或在列表中(IN
)运算符与不等式(!=
)或在列表外(NOT_IN
)运算符与通配符之间的不同语义意义
AWS::IAM::Role AssumeRolePolicyDocument.Statement.*.Principal.Service.* == lambda.amazonaws.com
意味着 "至少有一个匹配这些通配符的项目应该匹配该值",并且作为一组 OR
规则执行。
AWS::IAM::Role AssumeRolePolicyDocument.Statement.*.Principal.Service.* != lambda.amazonaws.com
意味着 "那些通配符匹配的项目中没有任何一个匹配该值",并且作为一组 AND
规则执行。
要查看规则在运行时的展开情况,请使用 -
标志运行,并在输出中查找 "应用规则"。
正则表达式
您还可以编写与 Rust 正则表达式语法(Rust Regex 语法)匹配的规则,该语法与 Perl 兼容正则表达式(PCRE)语法匹配。
形式为 /<regex pattern>/
因此
AWS::IAM::Role AssumeRolePolicyDocument.Version == /(\d{5})-(\d{2})-(\d{2})/
AWS::EC2::Volume AvailabilityZone != /us-east-.*/
变量语法
赋值
您可以使用 let
语法声明变量
let <VAR NAME> = <list or scalar>
例如
let size = 500
# Regular list
let azs = [us-east-1b, us-east-1b]
# JSON list
let tag_vals = ["tests", 1, ["a", "b"], {"Key":"A","Value":"a"},{"Key":"A","Value":{"Ref":"a"}}]
然后使用 %
在规则中引用这些变量
AWS::EBS::Volume Size == %size
JSON 列表与非 JSON 列表
JSON 列表
任何有效的 JSON 列表字面量都是有效的 JSON 列表。以下列表
let tag_vals = ["tests", 1, ["a", "b"], {"Key":"A","Value":"a"},{"Key":"A","Value":{"Ref":"a"}}]
将展开成以下值的列表
"tests",
1,
["a, b"],
{"Key":"A","Value":"a"},
{"Key":"A","Value":{"Ref":"a"}}
您可以使用 IN
或 NOT_IN
来匹配模板资源的属性。
非 JSON 列表
任何非 JSON 字面量的列表只是逗号分隔的值列表。
混合列表类型
包含 JSON 和非 JSON 值的列表被解释为非 JSON
所以如果
let tag_vals = ["tests", {"Key":"A","Value":"a"},{"Key":"A","Value":{"Ref":"a"}}]
被写成
let tag_vals = [tests, {"Key":"A","Value":"a"},{"Key":"A","Value":{"Ref":"a"}}]
它将评估为以下项的列表
tests,
{"Key":"A",
"Value":"a"},
{"Key":"A",
"Value":{"Ref":"a"}}
这几乎肯定不是您想要的。
如果您在处理 JSON 列表的规则中看到奇怪的行为,请使用 -
运行,您将看到类似以下行
2020-07-01 14:49:18,411 DEBUG [cfn_guard::util] List [tests, {"Key":"A","Value":"a"},{"Key":"A","Value":{"Ref":"a"}}] is not a json list
这将为您提供有关 cfn-guard
如何处理它的更多信息。
(有关详细信息,请参阅 故障排除,了解如何使用不同的日志级别来查看模板和规则集的处理方式。)
环境变量
您还可以使用 Makefile 风格的符号引用 环境变量:%{Name}
因此,您可以重写上面的 IAM 角色规则为
AWS::IAM::Role AssumeRolePolicyDocument.Statement.0.Principal.Service.0 == %{IAM_PRIN}
然后通过设置该变量从命令行调用 cfn-guard
IAM_PRIN=lambda.amazonaws.com cfn-guard -t iam_template -r iam_rule_set
注意:所有环境变量在运行时都可用。它们不需要在 cfn-guard
调用期间明确设置。
环境变量不会被记录,以避免持久化敏感信息。您应该使用它们将敏感值传递到 cfn-guard
而不是 let
形式。
自定义错误消息
在规则语法中有一个可选字段,您可以通过添加 <<
和消息文本到规则末尾来提供自己的自定义消息
AWS::EC2::Volume Encrypted == %encryption_flag << lorem ipsum
此外,重要的是要记住 |OR| 构造是离散规则的连接。因此
AWS::EC2::Volume Size == 201 |OR| AWS::EC2::Volume Size == 199 << lorem ipsum
只会在第二条规则上返回自定义消息,而不是两条。如果您希望两条规则都有自定义消息,您需要将自定义消息添加到 |OR|
的两边
AWS::EC2::Volume Size == 201 << ipsum lorem |OR| AWS::EC2::Volume Size == 199 << lorem ipsum
类似地,当将相同的自定义消息添加到多个规则时,要小心。这可能会掩盖实际的失败。
例如,如果您应用以下 CloudFormation Guard 规则集
let allowed_azs = [us-east-1a,us-east-1b,us-east-1c]
AWS::EC2::Volume AvailabilityZone IN %allowed_azs
AWS::EC2::Volume AvailabilityZone == /.*d/
到 Examples/ebs_volume_template.json。 cfn-guard
会返回
"[NewVolume2] failed because [AvailabilityZone] is [us-west-2c] and the permitted pattern is [.*d]"
"[NewVolume2] failed because [us-west-2c] is not in [us-east-1a,us-east-1b,us-east-1c] for [AvailabilityZone]"
但如果两条规则都有相同的自定义错误消息
AWS::EC2::Volume AvailabilityZone IN %allowed_azs << lorem ipsum
AWS::EC2::Volume AvailabilityZone == /.*d/ << lorem ipsum
结果看起来像是一个错误的重复
"[NewVolume2] failed because [AvailabilityZone] is [us-west-2c] and lorem ipsum"
"[NewVolume2] failed because [AvailabilityZone] is [us-west-2c] and lorem ipsum"
自定义消息在 WHEN 检查 的两边都是语法有效的
AWS::DynamoDB::Table WHEN Tags == /.*PROD.*/ << custom conditional message CHECK .DeletionPolicy != Retain << custom consequent message
但是,condition
的自定义消息仅作为错误消息中包含的原始规则的一部分内联显示
[DDBTable] failed because [.DeletionPolicy] is [Retain] and custom consequent message when AWS::DynamoDB::Table Tags == /.*PROD.*/ << custom conditional message
与 CloudFormation 内置函数一起工作
由于 serde_yaml 解析 YAML 的方式,函数如 !GetAtt
被视为注释并忽略。例如
NewVolume:
Type: AWS::EC2::Volume
Properties:
Size: 512
AvailabilityZone: !GetAtt [EC2Instance, AvailabilityZone]
与规则进行校验
AWS::EC2::Volume AvailabilityZone == !GetAtt [EC2Instance, AvailabilityZone]
导致失败
"[NewVolume] failed because [AvailabilityZone] is [["EC2Instance","AvailabilityZone"]] and the permitted value is [!GetAtt [EC2Instance, AvailabilityZone]]"
这种效果,加上解析器删除值之间的空白,意味着规则必须写成
AWS::EC2::Volume AvailabilityZone == ["EC2Instance","AvailabilityZone"]
其中值被引用,且在 ,
后面没有空格才能匹配。
如果您看到某些应该匹配但实际上没有匹配的内容,失败消息(["EC2Instance","AvailabilityZone"]
)将帮助您确定原因。
关于删除空白的最后部分也适用于 Fn::GetAtt
函数的 JSON 版本
{
"Resources": {
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 100,
"Encrypted": false,
"AvailabilityZone" : { "Fn::GetAtt" : [ "EC2Instance", "AvailabilityZone" ] }
}
},
"NewVolume2" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 99,
"Encrypted": true,
"AvailabilityZone" : "us-east-1b"
}
}
}
它会以类似的消息失败
"[NewVolume] failed because [AvailabilityZone] is [{"Fn::GetAtt":["EC2Instance","AvailabilityZone"]}] and the permitted value is [["EC2Instance","AvailabilityZone"]]"
为了处理两种模板格式中的这两种情况,使用以下类似(无需转义引号和中间空白)的 |OR|
规则
AWS::EC2::Volume AvailabilityZone == ["EC2Instance","AvailabilityZone"] |OR| AWS::EC2::Volume AvailabilityZone == {"Fn::GetAtt":["EC2Instance","AvailabilityZone"]}
如果您对 YAML 或 JSON 的解析方式不确定,请在您要检查的模板上使用 cfn-guard-rulegen
。它输出符合解析器相同属性的形式。
⋊> cfn-guard-rulegen guard-test-ec2-dev.yaml
AWS::EC2::Instance SecurityGroups == ["InstanceSecurityGroup"]
AWS::EC2::Instance KeyName == KeyName
AWS::EC2::Volume AvailabilityZone == ["EC2Instance","AvailabilityZone"]
AWS::EC2::Volume Size == 512
AWS::EC2::Instance ImageId == LatestAmiId
AWS::EC2::SecurityGroup GroupDescription == Enable SSH access via custom port 33322
AWS::EC2::SecurityGroup SecurityGroupIngress == [{"CidrIp":"SSHLocation","FromPort":22,"IpProtocol":"tcp","ToPort":22}]
AWS::EC2::Instance InstanceType == t3.medium
⋊> cfn-guard-rulegen ebs_volume_template_example.json
AWS::EC2::Volume Size == 100 |OR| AWS::EC2::Volume Size == 99
AWS::EC2::Volume Encrypted == true |OR| AWS::EC2::Volume Encrypted == false
AWS::EC2::Volume AvailabilityZone == {"Fn::GetAtt":["EC2Instance","AvailabilityZone"]}
严格检查
--strict-check
标志会导致资源在它不包含规则检查的属性时失败检查。这有助于强制执行可选属性的存在,例如 Encryption == true
。
在组合使用严格检查和通配符之前需要仔细考虑。通配符在运行时创建规则,这些规则映射到所有类型的资源在该通配符位置的所有值。这意味着过于宽泛的通配符会导致过于宽泛的失败。
以下是一个通配符场景的示例
这是一个模板片段
{
"Resources": {
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"AutoEnableIO": true,
"Size" : 101,
"Encrypted": true,
"AvailabilityZone" : "us-west-2b"
}
},
"NewVolume2" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 99,
"Encrypted": true,
"AvailabilityZone" : "us-west-2c"
}
}
}
}
在语义上完全有效(尽管实际价值可疑)使用通配符来确保至少有一个属性的值等于 true
AWS::EC2::Volume * == true
如上节关于通配符的讨论所述,这将在运行时转换为每个属性创建的规则,并通过一个|OR|
进行连接
> cfn-guard -t ~/scratch-template.yaml -r ~/scratch.ruleset -vvv
...
2020-08-07 17:25:59,000 INFO [cfn_guard] Applying rule 'CompoundRule(
CompoundRule {
compound_type: OR,
raw_rule: "AWS::EC2::Volume * == true",
rule_list: [
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "AvailabilityZone",
operation: Require,
value: "true",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "Size",
operation: Require,
value: "true",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "Encrypted",
operation: Require,
value: "true",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "AutoEnableIO",
operation: Require,
value: "true",
rule_vtype: Value,
custom_msg: None,
},
),
],
},
)'
检查将通过。
但是,如果你将通配符规则更改为!=
AWS::EC2::Volume * != false
OR
规则变为AND
规则
2020-08-07 17:33:20,637 INFO [cfn_guard] Applying rule 'CompoundRule(
CompoundRule {
compound_type: AND,
raw_rule: "AWS::EC2::Volume * != false",
rule_list: [
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "AvailabilityZone",
operation: RequireNot,
value: "false",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "AutoEnableIO",
operation: RequireNot,
value: "false",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "Size",
operation: RequireNot,
value: "false",
rule_vtype: Value,
custom_msg: None,
},
),
SimpleRule(
Rule {
resource_type: "AWS::EC2::Volume",
field: "Encrypted",
operation: RequireNot,
value: "false",
rule_vtype: Value,
custom_msg: None,
},
),
],
},
)'
如果你用--strict-checks
运行它,它将失败,因为NewVolume2
不包含AutoEnableIO
属性
> cfn-guard -t ~/scratch-template.yaml -r ~/scratch.ruleset --strict-checks
[NewVolume2] failed because it does not contain the required property of [AutoEnableIO]
Number of failures: 1
诚然,这是一个非常牵强的例子,但了解这种行为很重要。
故障排除
cfn-guard
旨在作为工具链的一部分使用。例如,它不会检查它收到的CloudFormation模板是否是有效的CloudFormation。已经有cfn-lint工具对模板结构进行了深入和彻底的检查,并为用户提供了大量的反馈,以帮助用户编写高质量的模板。
cfn-guard
也不对检查的类型或这些类型可以检查的属性施加限制。当你手工编写规则时,这可能会引起一些困惑,因为你没有得到预期的结果。
要查看规则集是如何处理的,最佳方法是利用不同的日志级别(例如-vvv
)。当启用日志记录时,您可以跟踪整个执行过程,并查看cfn-guard
是如何在内部工作的。
例如,这是一个简单的模板
{
"Resources": {
"NewVolume" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 101,
"Encrypted": false,
"AvailabilityZone" : "us-west-2b"
}
},
"NewVolume2" : {
"Type" : "AWS::EC2::Volume",
"Properties" : {
"Size" : 99,
"Encrypted": false,
"AvailabilityZone" : "us-west-2c"
}
}
}
}
以及一个示例规则集
let encryption_flag = true
AWS::EC2::Volume Encrypted == %encryption_flag
启用-vvv
跟踪日志记录后,您可以看到赋值的解析
2020-06-27 13:18:00,097 DEBUG [cfn_guard::parser] Parsing 'let encryption_flag = true'
2020-06-27 13:18:00,112 DEBUG [cfn_guard::parser] line_type is Assignment
2020-06-27 13:18:00,122 TRACE [cfn_guard::parser] Parsed assignment's captures are: Captures(
{
0: Some(
"let encryption_flag = true",
),
"var_name": Some(
"encryption_flag",
),
"operator": Some(
"=",
),
"var_value": Some(
"true",
),
},
)
2020-06-27 13:18:00,122 TRACE [cfn_guard::parser] Inserting key: [encryption_flag], value: [true] into variables
以及规则
2020-06-27 13:18:00,122 DEBUG [cfn_guard::parser] Parsing 'AWS::EC2::Volume Encrypted == %encryption_flag'
2020-06-27 13:18:00,134 DEBUG [cfn_guard::parser] line_type is Rule
2020-06-27 13:18:00,135 DEBUG [cfn_guard::parser] Line is an 'AND' rule
2020-06-27 13:18:00,135 TRACE [cfn_guard::parser] Entered destructure_rule
2020-06-27 13:18:00,154 TRACE [cfn_guard::parser] Parsed rule's captures are: Captures(
{
0: Some(
"AWS::EC2::Volume Encrypted == %encryption_flag",
),
"resource_type": Some(
"AWS::EC2::Volume",
),
"resource_property": Some(
"Encrypted",
),
"operator": Some(
"==",
),
"rule_value": Some(
"%encryption_flag",
),
},
)
2020-06-27 13:18:00,155 TRACE [cfn_guard::parser] Destructured rules are: [
Rule {
resource_type: "AWS::EC2::Volume",
field: "Encrypted",
operation: Require,
value: "%encryption_flag",
rule_vtype: Variable,
custom_msg: None,
},
]
2020-06-27 13:18:00,155 DEBUG [cfn_guard::parser] Parsed rule is: CompoundRule {
compound_type: AND,
rule_list: [
Rule {
resource_type: "AWS::EC2::Volume",
field: "Encrypted",
operation: Require,
value: "%encryption_flag",
rule_vtype: Variable,
custom_msg: None,
},
],
}
每当你的规则没有按预期表现时,这是一种查看原因的好方法。
故障排除FAQ
问题:我一直在尝试用错误的规则值强制失败,但没有得到任何结果
答案:这几乎总是由于你在规则中尝试检查的属性名称中存在拼写错误。开启--strict-checks
,如果名称不匹配,你会得到一个错误。这是一个查找拼写错误的简单方法。
构建和运行
安装Rust
运行工具
打开你喜欢的任何shell(例如,在Mac/Linux上bash
或在Windows上cmd.exe
)并将cd切换到源文件下载的目录。
使用Cargo
Cargo允许你直接在git目录中运行,但它的速度不如编译后的build-release快。
cargo run -- -t <CloudFormation Template> -r <Rules File>
(注意:中间的--
是必要的,以区分标志是传递给Cargo还是程序)
构建二进制文件
注意:默认情况下,rust会将二进制文件编译为你在构建时运行的平台的二进制文件。如果你需要,你可以在rust中交叉编译。
Mac/Linux
运行
make
将编译的发布二进制文件放入编译它的目录下的bin/
目录中。
Windows
- 运行
cargo build --release
。 - 使用
target\release\cfn-guard.exe
运行二进制文件
日志记录
如果您想查看cfn-guard
在运行时应用的逻辑,您可以使用多个日志级别。
要增加详细程度,只需将详细程度标志(例如,-v、-vv、-vvv)中的 v 字符添加更多即可。
注意:相同的日志级别可以通过目标二进制文件或使用 cargo run
来访问。
测试
如果您修改了源代码并希望运行单元测试,只需执行以下操作:
cargo test
如果您希望使用示例 CloudFormation 模板和规则集,请参阅 Examples
目录。
依赖项
~6.5–9.5MB
~159K SLoC