14

I have one S3 bucket in one AWS account (say arn:aws:s3:::my-test-bucket), that needs to be accessed by a IAM group that is defined in another AWS account (say arn:aws:iam::1111222333444:group/mygroup). The following access policy refuses to save, and tells that arn:aws:s3:::my-test-bucket is an invalid principal.

{
    "Statement": [
        {
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:List*",
                "s3:Get*"
            ],
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1111222333444:group/mygroup"
            },
            "Resource": [
                "arn:aws:s3:::my-test-bucket",
                "arn:aws:s3:::my-test-bucket/*"
            ],
            "Sid": "allow-put-for-dedicated-group"
        }
    ],
}

I have tested by replacing the group with one of the users of the other account and this works:

{
    "Statement": [
        {
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:List*",
                "s3:Get*"
            ],
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::1111222333444:user/me"
            },
            "Resource": [
                "arn:aws:s3:::my-test-bucket",
                "arn:aws:s3:::my-test-bucket/*"
            ],
            "Sid": "allow-put-for-dedicated-user"
        }
    ],
}

The group is existing, I do not understand why it says it is an invalid principal. In fact it does not accept any group of my other account.

Does anyone have an explanation (and possibly a solution) to this behaviour?

Thanks in advance, Cheers

Danduk82
  • 769
  • 1
  • 10
  • 29

2 Answers2

14

IAM groups are not valid principals in S3 bucket policies. See this AWS forum post and this SO post for more discussion.

Here's one idea: create an IAM role (for example cross-account-s3) in account #1 (the account with the S3 bucket). That role should have a policy that allows the appropriate S3 bucket access and it should have a trust relationship that says account #2 is trusted for sts:AssumeRole. Then in account #2, delegate permission to assume the cross-account-s3 role to the relevant IAM group. This requires you to trust the IAM admins in the 2nd account to not allow the wrong users to assume the cross-account-s3 role.

jarmod
  • 71,565
  • 16
  • 115
  • 122
  • I noticed, thanks for reply. Indeed this is a sad news. I thought this could be a useful use of groups, defining ACL on resources... I noticed also that there is a feature request on AWS forum about this since 2011... – Danduk82 Jun 09 '15 at 13:56
  • 1
    @Danduk82 Here's one possible idea. Create an IAM role (for example "cross-account-s3") in account #1 (the account with the S3 bucket). That role should have a policy that allows the appropriate S3 bucket access and it should have a trust relationship that says the root user in account #2 has sts:AssumeRole. Then in account #2 give the relevant IAM group a policy that allows users in that group to assume the cross-account-s3 role from account #1. I guess this requires you to trust the IAM admins in the 2nd account to not allow the wrong users to assume the cross-account-s3 role. – jarmod Jun 09 '15 at 15:40
  • mmh, yes. This is a smart way of using policies. It it still a bit frustrating, in the sense that this does not provide the `"who's allowed to use this resource?"` answer by only looking at bucket policies, but at least it makes the use of groups possible. Thanks a lot for your idea. – Danduk82 Jun 11 '15 at 07:35
0

As jarmod said, IAM groups are not valid principles. Also jarmod's solution will work. However it is possible to reference the role that is assumed in the S3 bucket policy. This allows you to deny actions unless they are performed by that role, which then provides the visibility of who has access that you wanted or could be used to further limit the access provided. The role reference is via the Role ID, which can be obtained by the following AWS CLI command: aws iam get-role --role-name ROLE_NAME --profile PROFILE_NAME, where ROLE_NAME is the name of the role created with sts:AssumeRole and PROFILE_NAME is the AWS profile setup to access the role.

Something like the following could then be used for the S3 bucket policy:

{
    "Statement": [
        {
            "Action": [
                "s3:ListBucket",
                "s3:PutObject",
                "s3:List*",
                "s3:Get*"
            ],
            "Effect": "Deny",
            "Principal": "*"
            "Resource": [
                "arn:aws:s3:::my-test-bucket",
                "arn:aws:s3:::my-test-bucket/*"
            ],
            "Sid": "deny-put-for-anyone-but-dedicated-role",
            "Condition": {
                "StringNotLike": {
                    "aws:userId": [
                        "ROLE_ID:*"
                    ]
                }
            }
        }
    ],
}

More details about this can be found in this blog post, which includes using userId to limit access to a user.

WhiteKnight
  • 4,938
  • 5
  • 37
  • 41