某机构Web服务(AWS)的Identity and Access Management(IAM)策略为客户提供了对某中心Web服务云中资源访问的精细控制。这种控制通过仅授予执行特定任务所需的权限,帮助客户执行最小权限原则。然而,在实践中,编写强制执行最小权限的IAM策略要求客户理解其应用程序运行所需的权限,这在应用程序规模增长时会变得具有挑战性。
为了帮助客户理解哪些权限是不必要的,在2023年的re:Invent大会上推出了IAM Access Analyzer未使用访问发现功能。IAM Access Analyzer会分析客户的AWS账户,识别未使用的访问,并创建一个集中仪表板来报告其发现。这些发现会突出显示未使用的角色以及IAM用户的未使用访问密钥和密码。对于活跃的IAM角色和用户,这些发现提供了对未使用服务和操作的可见性。
为了将此服务更进一步,于2024年6月推出了在Access Analyzer中细化未使用权限的建议功能。此功能建议对客户原始IAM策略进行细化,在保留策略结构的同时移除未使用的权限。这些建议不仅简化了移除未使用权限的过程,还有助于客户为精细权限实施最小权限原则。
本文讨论了Access Analyzer策略建议如何基于未使用权限来建议策略细化,从而完成了从监控过度宽松的策略到细化它们的闭环。
策略建议实践
让我们通过一个例子来看看策略建议是如何工作的。假设您有一个IAM角色名为MyRole,并附加了以下IAM策略:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"lambda:AddPermission",
"lambda:GetFunctionConfiguration",
"lambda:UpdateFunctionConfiguration",
"lambda:UpdateFunctionCode",
"lambda:CreateFunction",
"lambda:DeleteFunction",
"lambda:ListVersionsByFunction",
"lambda:GetFunction",
"lambda:Invoke*"
],
"Resource": "arn:aws:lambda:us-east-1:123456789012:function:my-lambda"
},
{
"Effect" : "Allow",
"Action" : [
"s3:Get*",
"s3:List*"
],
"Resource" : "*"
}
]
}
上述策略有两个策略语句:
- 第一个语句允许对AWS Lambda(一项提供函数执行即服务的AWS产品)中的某个函数执行操作。允许的操作通过列出单个操作以及通配符字符串
lambda:Invoke*来指定,该通配符允许所有以Invoke开头的AWS Lambda操作,例如lambda:InvokeFunction。 - 第二个语句允许对任何某中心简单存储服务(S3)存储桶执行操作。操作由两个通配符字符串指定,表明该语句允许以
Get或List开头的某中心S3操作。
为未使用发现启用Access Analyzer将提供一个发现列表,每个发现详细说明了特定角色的操作级别未使用权限。例如,对于附加了上述策略的角色,如果Access Analyzer发现任何被允许但未使用的AWS Lambda或某中心S3操作,它将把它们显示为未使用的权限。
未使用的权限定义了被IAM策略允许但未被该角色使用的操作列表。这些操作特定于一个命名空间(一组聚集在一起并与其他命名空间隔离以提高安全性的资源)。以下是一个Json格式的示例,显示了为附加了上述策略的MyRole找到的未使用权限:
[
{
"serviceNamespace": "lambda",
"actions": [
"UpdateFunctionCode",
"GetFunction",
"ListVersionsByFunction",
"UpdateFunctionConfiguration",
"CreateFunction",
"DeleteFunction",
"GetFunctionConfiguration",
"AddPermission"
]
},
{
"serviceNamespace": "s3",
"actions": [
"GetBucketLocation",
"GetBucketWebsite",
"GetBucketPolicyStatus",
"GetAccelerateConfiguration",
"GetBucketPolicy",
"GetBucketRequestPayment",
"GetReplicationConfiguration",
"GetBucketLogging",
"GetBucketObjectLockConfiguration",
"GetBucketNotification",
"GetLifecycleConfiguration",
"GetAnalyticsConfiguration",
"GetBucketCORS",
"GetInventoryConfiguration",
"GetBucketPublicAccessBlock",
"GetEncryptionConfiguration",
"GetBucketAcl",
"GetBucketVersioning",
"GetBucketOwnershipControls",
"GetBucketTagging",
"GetIntelligentTieringConfiguration",
"GetMetricsConfiguration"
]
}
]
此示例显示了在AWS Lambda和某中心S3中未被使用但被我们之前指定的策略允许的操作。
如何细化原始策略以移除未使用的权限并实现最小权限?一种选择是手动分析。可以想象以下过程:
- 找到允许未使用权限的语句;
- 通过引用未使用权限,从这些语句中移除单个操作。
然而,在处理大型策略和长列表的未使用权限时,此过程容易出错。此外,当策略中存在通配符字符串时,从中移除未使用的权限需要仔细调查哪些操作应替换这些通配符字符串。
策略建议功能自动为客户完成这种细化!
下面的策略是Access Analyzer在从上述策略中移除未使用操作后建议的策略(该图还显示了原始策略和修订后策略之间的差异):
{
"Version": "2012-10-17",
"Statement" : [
{
"Effect" : "Allow",
"Action" : [
- "lambda:AddPermission",
- "lambda:GetFunctionConfiguration",
- "lambda:UpdateFunctionConfiguration",
- "lambda:UpdateFunctionCode",
- "lambda:CreateFunction",
- "lambda:DeleteFunction",
- "lambda:ListVersionsByFunction",
- "lambda:GetFunction",
"lambda:Invoke*"
],
"Resource" : "arn:aws:lambda:us-east-1:123456789012:function:my-lambda"
},
{
"Effect" : "Allow",
"Action" : [
- "s3:Get*",
+ "s3:GetAccess*",
+ "s3:GetAccountPublicAccessBlock",
+ "s3:GetDataAccess",
+ "s3:GetJobTagging",
+ "s3:GetMulti*",
+ "s3:GetObject*",
+ "s3:GetStorage*",
"s3:List*"
],
"Resource" : "*"
}
]
}
让我们看看每个策略语句发生了什么变化。
对于第一个语句,策略建议移除了所有单独列出的操作(例如,lambda:AddPermission),因为它们出现在未使用的权限中。由于没有未使用的权限以lambda:Invoke开头,建议保留lambda:Invoke*不变。
对于第二个语句,让我们重点关注原始策略中出现的通配符s3:Get*。有许多操作可以以s3:Get开头,但只有一部分显示在未使用的权限中。因此,不能简单地将s3:Get*从策略中移除。相反,建议的策略将s3:Get*替换为七个以s3:Get开头但未被报告为未使用的操作。
其中一些操作(例如,s3:GetJobTagging)是单个操作,而另一些包含通配符(例如,s3:GetAccess*和s3:GetObject*)。手动替换修订后策略中的s3:Get*的一种方法是列出所有以s3:Get开头但未使用的操作。然而,这将导致策略冗长,因为以s3:Get开头的操作有50多个。
相反,策略建议会找出使用通配符来合并多个操作的方法,输出诸如s3:GetAccess*或s3:GetMulti*之类的操作。得益于这些通配符,建议的策略简洁明了,但仍然允许所有以s3:Get开头且未被报告为未使用的操作。
我们如何决定在新生成的通配符操作中放置通配符的位置?在下一节中,我们将深入探讨策略建议如何通过通配符泛化操作,以仅允许那些未出现在未使用权限中的操作。
操作泛化原理深入探讨
策略建议遵循“最不一般泛化”的数学原理——即找到建议策略限制性最小(即允许范围最窄)的修改,同时仍允许原始策略允许的所有操作。这种基于定理的方法保证了修改后的策略仍然允许原始策略授予的所有且仅限那些未被报告为未使用的权限。
为了实现针对未使用权限的最不一般泛化,我们构建了一种称为字典树的数据结构。这是一种树形结构,其中每个节点都扩展了一个对应于树中路径的令牌序列。在我们的案例中,节点表示操作之间共享的前缀,并为未使用权限报告中出现的操作设置了特殊标记。通过遍历字典树,我们找到了不包含未使用操作的最短前缀字符串。
下图展示了一个简化的字典树,描述了可以替换原始策略中S3 Get*通配符的操作(为清晰起见,省略了一些操作):
(描述:一个字典树,描述了可以替换IAM策略中Get*通配符的操作。包含未使用操作的节点用橙色表示;其余节点用绿色表示。)
在高层次上,字典树表示以s3:Get开头的一些可能操作共享的前缀。其根节点表示前缀Get;根节点的子节点将其前缀附加到Get上。例如,名为Multi的节点表示所有以GetMulti开头的操作。
如果一个节点没有对应的未使用操作以其前缀开头,我们说它是安全的(在图中用绿色表示);否则,它是不安全的(用橙色表示)。例如,节点s3:GetBucket是不安全的,因为操作s3:GetBucketPolicy未被使用。同样,节点ss是安全的,因为没有未使用权限以GetAccess开头。
我们希望最终的策略只包含对应于安全节点的通配符操作,并且我们希望包含足够的安全节点以允许所有已使用的操作。我们通过选择对应于最短安全前缀的节点来实现这一点——即那些本身安全但其父节点不安全的节点。因此,建议的策略将s3:Get*替换为不包含未使用权限的最短前缀,例如s3:GetAccess*、s3:GetMulti*和s3:GetJobTagging。
这些最短的安全前缀共同构成了一个新的策略,虽然语法上与原始策略相似,但却是移除未使用操作后得到的最不一般泛化。换句话说,我们没有移除比必要更多的操作。
您可以在Access Analyzer中找到如何开始将策略建议与未使用访问结合使用。要了解更多关于支持策略建议的理论基础,请务必查阅相关科学论文。FINISHED