AWS documentation for IAM role principals[1] states the following:
To specify the role ARN in the
Principal
element, use the following format:"Principal": { "AWS": "arn:aws:iam::AWS-account-ID:role/role-name" }
However, when is it ever meaningful for a resource-based policy to use a Principal
element with an IAM role principal, as shown in the snippet? Aren't all IAM actions performed by a role identity actually performed by a role session principal[2] like arn:aws:sts::XXXXXXXXXXXX:assumed-role/MyRole/MyRoleSessionName
?
For instance, the following S3 bucket policy has a Principal
element with an IAM role principal:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:role/MyRole"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
}
}
but it does not grant access to principals who assumed MyRole
(both the role and the bucket are in the same AWS account). To do that rather, the policy needs to use a role session principal with a specific role session name:
"Principal": {
"AWS": "arn:aws:sts::XXXXXXXXXXXX:role:assumed-role/MyRole/MyRoleSessionName"
}
Alternatively, the policy can grant access to all MyRole
role sessions, regardless of session name:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::my-bucket",
"Condition": {
"ArnEquals": {
"aws:PrincipalArn": "arn:aws:iam::XXXXXXXXXXXX:role/MyRole"
}
}
}
}
Here, an IAM role principal is used in the Condition
element. But returning to the question, is it ever applicable to use it in the Principal
element?
Actually, it looks like an IAM role Principal
in a resource-based policy does affect role session principals for that role. I confirmed this recently, and double-checked with AWS support. See below for more information.
In September 2022, when I posted this question, I distinctly remember that the opposite was true (IAM role principal has no effect, as described in the question itself). The same result is confirmed in another, very similar StackOverflow question (API Gateway resource policy: specify IAM role as AWS principal) from 2020, which uses API gateway (instead of S3) as the resource in question.
If IAM policy evaluation logic had been changed between then and now, that would certainly explain this difference. However, it seems highly unlikely that a major change like this would be silently released, unless it was unintentional. Nonetheless, AWS support confirmed that the new (current) behavior is correct.
Thanks to ravron's answer about the NotPrincipal
caveat and the AWS blog post it links to, it's clearer why an IAM role can be targeted via the Principal
element using either a role
ARN or a role-session
ARN:
However, this inverted logic approach proves problematic with IAM roles because the role’s
Principal
value is composed of two Amazon Resource Names (ARNs), therole
ARN and theassumed-role
ARN. Therole
ARN is the identifier for the IAM role itself and theassumed-role
ARN is what identifies the role session in the logs.
In this example, an S3 bucket is used as the resource to which a resource-based policy is attached.
Create a role (EmptyRole
) which has no permissions (identity-based policies), but has a trust policy which allows you to assume it.
Create an S3 bucket (aws-iam-resource-based-policy-test
) with the following bucket policy:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::XXXXXXXXXXXX:role/EmptyRole"
},
"Action": "s3:ListBucket",
"Resource": "arn:aws:s3:::aws-iam-resource-based-policy-test"
}
}
Assume the role EmptyRole
.
$ aws sts assume-role --role-arn arn:aws:iam::XXXXXXXXXXXX:role/EmptyRole --role-session-name TestRoleSession
{
"Credentials": {
"AccessKeyId": "ASIA...",
"SecretAccessKey": "...",
"SessionToken": "...",
"Expiration": "2024-06-18T03:55:09+00:00"
},
"AssumedRoleUser": {
"AssumedRoleId": "AROA...:TestRoleSession",
"Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/EmptyRole/TestRoleSession"
}
}
Use the resulting role session credentials to list the S3 bucket aws-iam-resource-based-policy-test
:
$ aws s3api list-objects --bucket aws-iam-resource-based-policy-test
{
"RequestCharged": null
}
The AWS documentation does not say much about what is expected to happen when an IAM role session principal interacts with a resource-based policy which targets that IAM role in a Principal
element.
One reference occurs in IAM role principals:
When you specify a role principal in a resource-based policy, the effective permissions for the principal are limited by any policy types that limit permissions for the role. This includes session policies and permissions boundaries. For more information about how the effective permissions for a role session are evaluated, see Policy evaluation logic.
Another reference occurs in Resource-based policies and implicit denies in other policy types (same account):
Principal making the request Resource-based policy Identity-based policy Permissions boundary Session Policy Result Reason IAM role session Allows role ARN Implicit deny Implicit deny Implicit deny DENY Permissions boundary and session policy are evaluated as part of the final decision. An implicit deny in either policy results in a DENY decision.
IAM role – Resource-based policies that grant permissions to an IAM role ARN are limited by an implicit deny in a permissions boundary or session policy.
Example role ARN
arn:aws:iam::111122223333:role/examplerole
Both snippets clearly state that permission boundaries and session policies (which limit permissions) can result in a DENY decision, but neither says what happens when these limiting policies are not present or allow the access.
After raising this concern with AWS support, the AWS representative confirmed that AWS may be revising their docs around this:
Our Senior Technical Writer is diligently working to investigate and rectify the documentation issue. Once a suitable solution is identified, it will undergo the necessary internal process to ensure the documentation is updated accordingly.