自定义策略检查助力自动化推理民主化
新的IAM Access Analyzer功能使用自动化推理,确保用IAM策略语言编写的访问策略不会授予意外访问权限。
通过Amit Goel, Jeremiah Dunham
2023年12月8日
阅读时间:7分钟
为了控制对某机构云中资源的访问,客户可以编写身份与访问管理(IAM)策略。IAM策略语言富有表现力,允许创建细粒度策略,控制谁可以对哪些资源执行哪些操作。这种控制可用于强制执行最小权限原则,仅授予执行任务所需的权限。但如何验证IAM策略是否符合安全要求?在2023年re:Invent大会上,宣布推出IAM Access Analyzer自定义策略检查,帮助用户根据安全标准对策略进行基准测试。自定义策略检查将策略语句转换为数学公式的任务抽象化,使客户无需具备形式逻辑专业知识即可享受自动化推理的好处。
自定义策略检查在开发流程中的作用
IAM Access Analyzer API CheckNoNewAccess 确保在更新策略时不会无意中添加权限。通过 CheckAccessNotGranted API,可以指定开发人员不应在其IAM策略中授予的关键权限。
自定义策略构建在一个名为Zelkova的内部服务上,该服务使用自动化推理来分析IAM策略。此前,使用Zelkova构建了预防性和探测性托管控制,例如某服务S3 Block Public Access以及IAM Access Analyzer的公共和跨账户发现。现在,随着自定义策略检查的发布,可以设置安全标准,并阻止不符合该标准的策略被部署。
Zelkova的工作原理
Zelkova通过将策略转换为精确的数学表达式来建模IAM策略语言的语义。然后使用称为可满足性模理论(SMT)求解器的自动化引擎来检查策略的属性。可满足性(SAT)求解器检查是否可以给布尔变量分配真值或假值以满足一组约束;SMT是SAT的推广,包括字符串、整数、实数或函数。使用SMT分析策略的好处在于它的全面性。与针对给定请求或一小部分请求模拟或评估策略的工具不同,Zelkova可以针对所有可能的请求检查策略的属性。
考虑以下某服务S3存储桶策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
}
]
}
Zelkova将此策略转换为以下公式:
(Action = "s3:PutObject") ∧ (Resource = "arn:aws:s3:::DOC-EXAMPLE-BUCKET")
在此公式中,"∧"是数学符号,表示“与”。Action和Resource是代表任何可能请求中的值的变量。仅当请求被策略允许时,该公式才为真。这种精确的数学表示非常有用,因为它允许全面回答有关策略的问题。例如,可以询问策略是否允许公共访问,得到的答案是肯定的。
对于上述简单策略,可以通过手动审查判断是否允许公共访问:策略语句中的 "Principal": "*" 意味着任何人(公众)都被允许访问。但手动审查容易出错且不可扩展。或者,可以编写简单的语法检查来查找 "Principal": "*" 等模式。然而,这些语法检查可能会遗漏策略的细微差别以及策略不同部分之间的相互作用。考虑对上述策略进行如下修改,添加一个带有 "NotPrincipal": "123456789012" 的Deny语句;该策略仍然具有 "Principal": "*" 模式,但不再允许公共访问:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": ["s3:PutObject"],
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
},
{
"Effect": "Deny",
"NotPrincipal": "123456789012",
"Action": "*",
"Resource": "*"
}
]
}
利用Zelkova中策略语义的数学表示,可以精确地回答有关访问权限的问题。
使用Zelkova回答问题
以一个相对简单的问题为例。通过IAM策略,可以授予对要共享的资源的跨账户访问权限。对于敏感资源,希望检查是否不可能进行跨账户访问。假设要检查上述策略是否允许账户123456789012以外的任何人访问S3存储桶。正如将策略转换为数学公式一样,可以将要询问的问题(或要检查的属性)转换为数学公式。要检查所有允许的访问是否都来自自己的账户,可以将属性转换为以下公式:
(Principal = 123456789012)
为了证明该属性对策略成立,现在可以尝试证明只有 (Principal = 123456789012) 的请求才被策略允许。数学中常用的一种技巧是反转问题。不是试图证明属性成立,而是通过找到不满足该属性的请求来证明它不成立——换句话说,满足 (Principal ≠ 123456789012) 的请求。为了找到这样的反例,寻找对变量Principal、Action和Resource的赋值,使得以下公式成立:
(Action = "s3:PutObject") ∧ (Resource = "arn:aws:s3:::DOC-EXAMPLE-BUCKET") ∧ (Principal ≠ 123456789012)
Zelkova将策略和属性转换为上述数学公式,并使用SMT求解器高效搜索反例。对于上述公式,SMT求解器可以生成一个反例,表明此类访问确实被策略允许(例如,Principal = 111122223333)。对于之前修改的带有Deny语句的策略,SMT求解器也可以证明结果公式无解,并且策略不允许来自账户123456789012外部的任何访问:
(Action = "s3:PutObject") ∧ (Resource = "arn:aws:s3:::DOC-EXAMPLE-BUCKET") ∧ (Principal = 123456789012) ∧ (Principal ≠ 123456789012)
策略中带有 "NotPrincipal": "123456789012" 的Deny语句被转换为约束 (Principal = 123456789012)。通过检查上述公式,可以看到它无法被满足:来自策略和属性的Principal约束是矛盾的。SMT求解器可以通过彻底排除解来证明这一点以及更复杂的公式。
自定义策略检查
为了让Zelkova的使用民主化,需要在更易访问的接口背后抽象数学公式的构建。为此,推出了IAM Access Analyzer自定义策略检查,包含两个预定义检查:CheckNoNewAccess 和 CheckAccessNotGranted。
通过 CheckNoNewAccess,可以确认在更新策略时不会意外添加权限。开发人员通常从更宽松的策略开始,并随着时间的推移将其完善到最小权限。现在,通过 CheckNoNewAccess,可以比较策略的两个版本,以确认新版本不会比旧版本更宽松。假设开发人员更新了本文中的第一个示例策略,以禁止跨账户访问,但同时添加了一个新操作:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "123456789012",
"Action": [
"s3:PutObject",
"s3:DeleteBucket"
],
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET"
}
]
}
CheckNoNewAccess 将两个版本的策略转换为公式Pold和Pnew。然后搜索公式 (Pnew ∧ ¬Pold) 的解,这些解代表新策略允许但旧策略不允许的请求("¬" 是数学符号,表示“非”)。由于新策略允许主体123456789012执行旧策略不允许的操作,检查失败,安全工程师可以审查此策略更改是否可接受。
通过 CheckAccessNotGranted,安全工程师可以通过指定要针对策略更新检查的关键权限来更具规范性。假设要确保开发人员不授予删除重要存储桶的权限。在前面的示例中,CheckNoNewAccess 仅因为权限是通过更新添加的才检测到这一点。通过 CheckAccessNotGranted,安全工程师可以指定 s3:DeleteBucket 作为关键权限。然后将关键权限转换为公式 (Action = "s3:DeleteBucket"),并搜索策略允许的具有该操作的请求。由于前面的策略允许此操作,检查失败,从而阻止该权限被部署。
通过能够将关键权限指定为 CheckAccessNotGranted API的参数,现在可以根据自己的标准检查策略——而不仅仅是针对现成的、广泛适用的检查。
调试失败
通过民主化策略检查,无需昂贵且耗时的手动审查,自定义策略检查帮助开发人员更快地行动。当策略通过检查时,开发人员可以放心地进行更新。如果策略未通过检查,IAM Access Analyzer会提供附加信息,以便开发人员进行调试和修复。
假设开发人员编写了以下基于身份的策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ec2:DescribeInstance*",
"ec2:StartInstances",
"ec2:StopInstances"
],
"Resource": "arn:aws:ec2:*:*:instance/*"
},
{
"Effect": "Allow",
"Action": [
"s3:GetObject*",
"s3:PutObject",
"s3:DeleteBucket"
],
"Resource": "arn:aws:s3:::DOC-EXAMPLE-BUCKET/*"
}
]
}
再假设安全工程师指定了关键权限,包括 s3:DeleteBucket。如上所述,CheckAccessNotGranted 在此策略上失败。
对于任何给定的策略,有时很难理解检查失败的原因。为了让开发人员更清楚,IAM Access Analyzer使用Zelkova解决额外的问题,将故障精确定位到策略中的特定语句。对于上述策略,检查失败并显示描述“新访问位于索引为1的语句中”。此描述表明第二个语句包含关键权限。
自动化推理民主化的关键是使其使用简单且易于指定属性。通过额外的自定义检查,将继续支持客户在最小权限之路上前进。FINISHED