-
Notifications
You must be signed in to change notification settings - Fork 21
Description
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: Forbidden3. 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_conditionsset to True and False - merged the gaad and resource policy files for both accounts (e.g
gaad-merged.jsonandresource-merged.json) and loaded them to the model in one go, e.gmodel.load_gaad("gaad-merged.json"). This returned the same results as above