Skip to content

Unexpected cross-account behaviour? #27

@orzello

Description

@orzello

Hi there, i'm running into some unexpected behaviour which might suggest a potential bug. For cross-account access, the can_i and who_can queries don't appear to validate the resource policy within the trusting account.

My understanding for cross-account access is that both of these conditions must be met:

  • the resource policy in the trusting account should grant access to the user/role in the trusted account
  • the user/role in the trusted account must have an identity-based policy which grants access to the resource in the trusting account

This is where i've got this from: https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html

I've included some information on the steps below. I may be misunderstanding something though. I'd be interested to get your thoughts and see if you can replicate this :)

Gaad files:

Resource policy files:

1. Setup both accounts

Account 1 (111111111111)

Account 1 is the 'trusted account' and has three users:

arn:aws:iam::111111111111:user/userA
arn:aws:iam::111111111111:user/userB
arn:aws:iam::111111111111:user/userC

arn:aws:iam::111111111111:user/userA has permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowCrossAccountGetObject",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::somenewtestbucket2/*"
        }
    ]
}

arn:aws:iam::111111111111:user/userB has no permissions assigned.

arn:aws:iam::111111111111:user/userC has permissions:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowGetObject",
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::somenewtestbucket2/*"
        }
    ]
}

Account 2 (222222222222)

Account 2 is the 'trusting account' and has an S3 bucket that users in account 1 will try to access.

S3 bucket arn:aws:s3:::somenewtestbucket2 with bucket policy:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowGetObject",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::111111111111:user/userA",
                    "arn:aws:iam::111111111111:user/userB"
                ]
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::somenewtestbucket2/*"
        }
    ]
}

2. Manually verify effective access

From my understanding of IAM, only arn:aws:iam::111111111111:user/userA should have access to the bucket. I manually verified this below:

$ aws --profile account1UserA s3 cp s3://somenewtestbucket2/test.txt ./account1UserADownloaded.txt
download: s3://somenewtestbucket2/test.txt to ./account1UserADownloaded.txt

$ aws --profile account1UserB s3 cp s3://somenewtestbucket2/test.txt ./account1UserBDownloaded.txt
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden

$ aws --profile account1UserC s3 cp s3://somenewtestbucket2/test.txt ./account1UserCDownloaded.txt
fatal error: An error occurred (403) when calling the HeadObject operation: Forbidden

3. run can_i and observe unexpected output

# load account 1 GAAD and Resource Policies files
model.load_gaad("gaad-111111111111.json")
model.load_resource_policies("resource-111111111111.json") 

# load account 2 GAAD and Resource Policies files
model.load_gaad("gaad-222222222222.json")
model.load_resource_policies("resource-222222222222.json")

# Returns True, which is expected
model.can_i("arn:aws:iam::111111111111:user/userA", "s3:GetObject", "arn:aws:s3:::somenewtestbucket2/test.txt", conditions=[], condition_file=None, strict_conditions=True)

# Returns True, which is unexpected
model.can_i("arn:aws:iam::111111111111:user/userB", "s3:GetObject", "arn:aws:s3:::somenewtestbucket2/test.txt", conditions=[], condition_file=None, strict_conditions=True)

# Returns False, which is expected
model.can_i("arn:aws:iam::111111111111:user/userC", "s3:GetObject", "arn:aws:s3:::somenewtestbucket2/test.txt", conditions=[], condition_file=None, strict_conditions=True)

4. run who_can and observe unexpected output

Run who_can query:

who_can_identities = model.who_can("s3:GetObject", "arn:aws:s3:::somenewtestbucket2/test.txt", conditions=[], condition_file=None, strict_conditions=True)

print("who_can results:")
for identity in who_can_identities:
	print(identity)

Prints:

arn:aws:iam::111111111111:user/userA (expected)
arn:aws:iam::111111111111:user/userB (unexpected)

Tried so far:

  • ran using both strict_conditions set to True and False
  • merged the gaad and resource policy files for both accounts (e.g gaad-merged.json andresource-merged.json) and loaded them to the model in one go, e.g model.load_gaad("gaad-merged.json"). This returned the same results as above

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions