S3 Bucket策略和IAM角色冲突

5

我正在尝试使用S3存储桶策略提供对存储桶的通用访问,同时还允许使用角色策略对特定角色进行访问。该角色由Lambda函数用于处理存储桶中的对象。但是,它在第一个障碍处停止了——即使在角色策略中允许,在存储桶策略中也没有明确拒绝"incoming/"前缀的GET操作。

角色策略:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowBucketPut",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::bucket-name/*"
        },
        {
            "Sid": "AllowIncomingGetDelete",
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:DeleteObject"
            ],
            "Resource": "arn:aws:s3:::bucket-name",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "incoming/*"
                }
            }
        }
    ]
}

注意:我也试过删除条件并将资源更改为“arn:aws:s3:::bucket-name/incoming*”,这似乎只是改变了策略模拟器的行为。另一个注意点:在带有“incoming / *”前缀的存储桶中使用GET确实可以在模拟器中工作,但在实践中却不行。
由于我不确定哪些声明可能相关,因此我没有删除下面存储桶策略中的任何声明。已省略IP地址。
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPublicList",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::bucket-name",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "public*"
                }
            }
        },
        {
            "Sid": "AllowPublicGet",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucket-name/public*"
        },
        {
            "Sid": "AllowPrivateList",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::bucket-name",
            "Condition": {
                "StringLike": {
                    "s3:prefix": "private*"
                },
                "IpAddress": {
                    "aws:SourceIp": [
                        "..."
                    ]
                }
            }
        },
        {
            "Sid": "AllowPrivateGet",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucket-name/private*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "..."
                    ]
                }
            }
        },
        {
            "Sid": "AllowIncomingPut",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::bucket-name/incoming*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "..."
                    ]
                }
            }
        }
    ]
}

对于篇幅过长的文本,我感到抱歉。

我不明白为什么我的角色无法获取以"incoming/"为前缀的对象。

当执行以下操作时,Lambda函数会收到403访问被拒绝的错误:

S3.download_file(bucket, key, localfile)
2个回答

6
根据文档(http://docs.aws.amazon.com/AmazonS3/latest/dev/amazon-s3-policy-keys.html),s3:prefix 条件仅适用于 s3:ListBucket API,强制调用者在 ListBucket 操作中指定前缀。它似乎不适用于 GetObject API 调用。
因此,您对带有条件 s3:prefix == ...Allow 在 GET(Object)请求中不会匹配任何请求(因为这些请求不包含策略键“s3:prefix”!),因此您实际上未在角色策略中允许这些请求。由于您似乎也没有在存储桶策略中允许该请求,并且没有任何拒绝语句,因此您的 Lambda 代码被隐式拒绝
您应该使用一个 Resource,正如您在策略模拟器上尝试过的一样:"Resource": "arn:aws:s3:::bucket-name/incoming/*"
此外 -- 你可能有理由像你这样明确指定策略,但这似乎有点不寻常 --,通常针对 S3 相关策略的 "Resource" 元素,当您想要描述前缀时,将是类似于 ...incoming/* 而不仅仅是 ...incoming*。这可以防止一些意外的结果。例如,假设您有一个名为 incoming/ 的 "文件夹",然后您创建了一个名为 incoming-top-secret/ 的文件夹。按照您编写策略的方式,您将授予对这两个前缀的访问权限!但是 - 如果不真正了解您的环境的确切细节,很难确定您真正需要什么。只是想确保您(和任何其他阅读此内容的人)知道这个微妙(但重要)的细节!
根据您提供的描述,这就是我所能想到的全部。如果您尝试了这些更改,仍然无法正常工作,请相应地更新您的问题,并提供您尝试过的新策略。祝好运!

非常感谢您的澄清。如帖子中所述,我按照您描述的方式指定资源时也遇到了相同的问题。我已经找出了问题所在...有点明白了。等我回到工作岗位后会进行更新。 - unclemeat

0

你能尝试将以下语句添加到存储桶策略中吗?

    {
        "Sid": "AllowIncomingGet",
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": "arn:aws:s3:::bucket-name/incoming/*",
        "Condition": {
            "IpAddress": {
                "aws:SourceIp": [
                    "..."
                ]
            }
        }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接