如何将S3存储桶策略写入* *仅允许特定的IAM角色和Cloudfront Origin Access Identity?

时间:2017-09-10 14:05:12

标签: amazon-s3 amazon-cloudfront amazon-iam

我的总体目标: 我尝试了几个方面并阅读了相关的AWS文档,但我无法确定如何编写S3存储桶策略以仅允许访问特定的IAM角色和Cloudfront Origin Access Identity(OAI),并拒绝其他所有人。

到目前为止我尝试过的事情: 1.我找到了这个博客,其中展示了如何限制对特定IAM角色的s3存储桶访问:https://aws.amazon.com/blogs/security/how-to-restrict-amazon-s3-bucket-access-to-a-specific-iam-role/ 2.基于上面的博客,我写了以下的桶策略。此策略仅允许MY_IAM_ROLE允许对名为“myBucket”的存储桶执行所有操作:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::myBucket",
                "arn:aws:s3:::myBucket/*"
            ],
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "MY_IAM_ROLE_USER_ID:*"
                    ]
                }
            }
        }
    ]
}
  1. 我无法找到一个aws范围的密钥 - http://docs.aws.amazon.com/AmazonS3/latest/dev/amazon-s3-policy-keys.html - 用于OAI,我可以将其插入“aws:userId”数组以及MY_IAM_ROLE_USER_ID。我尝试插入OAI的CanonicalUserId,但它没有用。
  2. 我的问题: 如何在一个政策声明中合并(1)aws:IAM角色/用户的用户ID和(2)OAI ID?

5 个答案:

答案 0 :(得分:1)

总而言之,您需要一个限制访问S3存储桶和内容的存储桶策略,但允许访问您希望指定的Cloudfront Origin Access Identity以及您的IAM角色。我有几种方法可以做到这一点,一个使用NotPrincipal元素,另一个使用Principal元素。这取决于有多少人使用您的IAM角色,或者您是否计划扩展对角色的访问权限。您可以通过使用NotPrincipal元素和显式拒绝在存储桶策略中指定权限来阻止Amazon Identify和Access Management(IAM)实体访问您的Amazon S3存储桶。但是,NotPrincipal不支持通配符。

在此策略示例中,您必须列出每个用户的角色会话名称以及将承担角色的每个实例ID:

"Effect": "Deny",
"NotPrincipal": {
"AWS": [
    "arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/cross-account-audit-app",
    "arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/instanceID",
    "arn:aws:iam::444455556666:role/cross-account-read-only-role",
    "arn:aws:iam::444455556666:root"
    ]
}

要涵盖所有这些用户和实例,您需要在语句中使用通配符来表示假定的角色:

"arn:aws:sts::444455556666:assumed-role/cross-account-read-only-role/*"

但是,NotPrincipal元素不支持通配符。如果您只使用角色或一个实例,这将起作用,但在扩展时,您需要添加ARN为用户/实例承担角色。

在此示例中,使用NotPrincipal作为每个语句块中的目标实体,而不是"Principal": "*",其中包括每个允许块的条件。在"aws:userid": ["ROLE-ID:*"]中使用通配符来包括调用进程传递的所有名称(例如应用程序,服务或实例ID),以便在进行调用以获取临时凭证时使用。 有关详细信息,请参阅所有请求中可用的信息。包含root帐户以防止锁定:

"Condition": {
    "StringLike": {
        "aws:userid": [
            "AROAID2GEXAMPLEROLEID:*",
            "444455556666"
        ]
    }
}

Deny块中的StringNotLike:

"Condition": {
    "StringNotLike": {
        "aws:userid": [
            "AROAID2GEXAMPLEROLEID:*",
            "444455556666"
        ]
    }
}

以下是完整的政策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": "arn:aws:s3:::myExampleBucket",
            "Condition": {
                "StringLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }
        },
        {
            "Sid": "",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::myExampleBucket/*",
            "Condition": {
                "StringLike": {
                    "aws:userid": [
                        "AROAID2GEXAMPLEROLEID:*",
                        "444455556666"
                    ]
                }
            }
        },
        {
            "Sid": "",
            "Effect": "Deny",
            "Principal": "*",
                "Action": "s3:*",
                "Resource": [
                    "arn:aws:s3:::myExampleBucket/*",
                    "arn:aws:s3:::myExampleBucket"
                ],
                "Condition": {
                    "StringNotLike": {
                        "aws:userid": [
                            "AROAID2GEXAMPLEROLEID:*",
                            "444455556666"
                        ]
                    }
                }
            }
        ]
}
  

注意:

     

获取有关IAM角色的信息 以下get-role命令获取有关名为Test-Role:

的角色的信息
aws iam get-role --role-name Test-Role

输出:

{
    "Role": {
        "AssumeRolePolicyDocument": "<URL-encoded-JSON>",
        "RoleId": "AIDIODR4TAW7CSEXAMPLE",
        "CreateDate": "2013-04-18T05:01:58Z",
        "RoleName": "Test-Role",
        "Path": "/",
        "Arn": "arn:aws:iam::123456789012:role/Test-Role"
    }
}
  

重要提示   
基本上,当您使用 CloundFront API 创建 Origin Access Identity 时,您将获得UserID和S3规范ID,您必须记下它以使用此功能在条件字符串中。

     

http://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html#private-content-creating-oai-api

     

如果您目前没有CloudFront的Origin Access Identity的ID,请创建一个新ID,您可以按照建议保存ID元素和S3 Canonical ID。

答案 1 :(得分:1)

我遇到了同样的问题,我只需要限制对Cloudbuck(OAI),MediaConvert(Role)和某些用户(IAM)的访问。

NotPrincipal指令适用于Cloudfront和单个用户,但是正如@MuhammadHannad所说,问题在于,对于一​​个角色,您必须列出与之关联的每个会话名称,并且无法通过将通配符与字符串,因为该元素不支持。

使用"Condition": {"StringNotLike": {"aws:userid" [...]}}也不起作用,因为正如您在评论中所说,Cloudfront Origin Access Identity没有相应的aws:userid

我想我终于找到了解决方案,我们可以使用StringNotLike而不是使用"Condition": {"ArnNotLike": {"aws:PrincipalArn": [...]}},它的行为显然与NotPrincipal相同,但是可以使用通配符在资源名称中。

{
    "Sid": "1",
    "Effect": "Deny",
    "Principal": "*",
    "Condition": {
        "ArnNotLike": {
            "aws:PrincipalArn": [
                "arn:aws:iam::111122223333:user/S3-USER",
                "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity AAAABBBBCCCC1",
                "arn:aws:iam::111122223333:role/MediaConvertRole",
                "arn:aws:sts::111122223333:assumed-role/MediaConvertRole/*",
                "arn:aws:iam::111122223333:root"
            ]
        }
    },
    "Action": "s3:*",
    "Resource": [
        "arn:aws:s3:::myBucket",
        "arn:aws:s3:::myBucket/*"
    ]
}

答案 2 :(得分:0)

这似乎有点远,但找到Origin Access Identity的ID(不是规范用户ID ...找到以E开头并且大约12个字符的ID )并将其添加到政策中:

"StringNotLike": {
   "aws:userId": [
      "MY_IAM_ROLE_USER_ID:*",
      "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EXXEXAMPLEXX"
   ]
 }

请注意单词&#34; CloudFront Origin Access Identity&#34;包括空格,是这个引用字符串的一部分。完全按照所示插入,仅更改12个字符ID。

可能阻止此策略拒绝访问OAI。 如果有办法将OAI的用户包含在条件键中,这似乎是唯一可行的解​​决方案。

另外,您需要第二个策略声明,即允许对OAI进行必要访问的正常声明。

答案 3 :(得分:0)

我的老答案会支持某些人,但可能不是你的。所以,我正在发布另一个答案,它将更准确地满足您的需求。以下角色策略将允许访问IAM角色和OAI,并将拒绝其他所有人:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "1",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EXXXXXXXXX"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        },
        {
            "Sid": "2",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": [
                    "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity EXXXXXXXXX",
                    "arn:aws:iam::AWS-account-ID:role/role-name"
                ]
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::bucketname/*"
        }
    ]
}

答案 4 :(得分:0)

您的问题可以通过将Principal: "*"语句中的Deny替换为引用CloudFront OAI的相应NotPrincipal,并为CloudFront OAI添加适当的Allow语句来解决:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "NotPrincipal": {
        "CanonicalUser": "..."
      },
      "Action": "s3:*",
      "Resource": [
        "arn:aws:s3:::myBucket",
        "arn:aws:s3:::myBucket/*"
      ],
      "Condition": {
        "StringNotLike": {
          "aws:userId": [
            "MY_IAM_ROLE_USER_ID:*"
          ]
        }
      }
    },
    {
      "Effect": "Allow",
      "Principal": {
        "CanonicalUser": "..."
      },
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::myBucket/*"
    }
  ]
}

这样,您的IAM角色会被Deny条件排除在aws:userId条件之外,而您的CloudFront OAI会被NotPrincipal条件排除在外。所有其他主体仍将被拒绝访问,CloudFront OAI将仅具有您在存储桶策略中直接授予它的权限。

回想起来似乎很简单,这个解决方案肯定不是很明显,这个答案应归功于AWS Support,他最近为我回答了同样的问题。