我尝试使用 IAM 策略将所有 AWS 资源的访问限制为公共 IP 或 VPC。文档表明这应该可行,并且对于 IP 案例来说似乎效果很好。但一旦我添加了 VPC 的条件,它就崩溃了。
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
"NotIpAddressIfExists": {
"aws:SourceIp": "a.b.c.d/32"
},
"StringNotEqualsIfExists": {
"aws:sourceVpc": "vpc-1234wxyz"
}
}
}
}
在“拒绝”声明中,如果满足任何条件,请求将被拒绝。
对于来自 VPC 外部的请求,“aws:SourceIp”存在且“aws:sourceVpc”不存在,因此它仅评估您的“aws:SourceIp”条件。
对于来自 VPC 内部的请求,“aws:SourceIp”存在并且“aws:sourceVpc”存在,因此它会评估两者。由于您位于 VPC 内部,因此条件允许访问,但由于您的源 IP 是 AWS 实例的 IP,因此条件拒绝访问。
基本上,问题在于您依赖于“IfExists”,并假设只有一个或另一个存在,但在您的 VPC 内部两者都存在。对此有一个特殊情况,仅当请求通过Endpoint(例如到S3)时:
注意
如果请求来自使用 Amazon VPC 终端节点的主机, 那么 aws:SourceIp 密钥不可用。你应该使用 VPC 特定密钥。有关更多信息,请参阅 VPC 终端节点 - Amazon VPC 用户指南中的控制终端节点的使用。
仅在这种特殊情况下,亚马逊才会删除“aws:SourceIp”,这将使您的“IsExists”起作用。
如果有人偶然发现这一点,我使用以下 ECR 存储库策略仅启用一些外部 IP 地址并能够从 VPC 内部拉取。 (请注意,您需要创建 S3、ECR-api、ECR-dkr VPC 端点)
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "FullAccess",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::12382478912338:root"
},
"Action": "ecr:*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"102.xx.yy.zz/32",
"21.xx.yy.zz/32"
]
},
"Bool": {
"aws:ViaAWSService": "false"
},
"StringNotEquals": {
"aws:SourceVpc": "vpc-123857123oi4j147"
}
}
}
]
}