Reputation: 81
I am trying to setup an API Gateway endpoint with a resource policy, which allows access to a specific IAM role in my account. The IAM role is cross-account, setup with a trust policy which allows AssumeRole to a specific IAM user principal from another account.
In the API Gateway resource policy, when I set AWS principal to the role ARN: arn:aws:iam::********:role/myRole
, I get the following 403 error when invoking the API:
User: arn:aws:sts::********:assumed-role/myRole/mySession is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-west-2:********:********/test/POST/echo
But, if I change the AWS principal to be the temporary STS user ARN: arn:aws:sts::********:assumed-role/myRole/mySession
, then I can invoke the API successfully.
Here's the resource policy that doesn't work:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::********:role/myRole"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:********:********/*"
}
]
}
Here's the resource policy that works:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:sts::********:assumed-role/myRole/mySession"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:********:********/*"
}
]
}
Can IAM roles be used as AWS principals for API Gateway resource policy?
Upvotes: 8
Views: 4535
Reputation: 10264
Actually, it looks like it is possible to grant access to an IAM role session principal by specifying the underlying role ARN in the Principal
element of a REST API resource policy in API Gateway.
As stated in the original question, this was previously not possible. The same was confirmed in September 2022 in another, very similar question: AWS IAM role principal vs role session principal.
If I had to guess, IAM policy evaluation logic had been changed since then; that would explain the difference in behavior.
Create a role (EmptyRole
) which has no permissions (identity-based policies), but has a trust policy which allows it to be assumed.
Create a Rest API in API Gateway.
Set a resource policy on the API which grants access to the EmptyRole
role ARN:
{
"Version": "2012-10-17",
"Statement": {
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::${ACCOUNT_ID}:role/EmptyRole"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:${ACCOUNT_ID}:${API_ID}/*"
}
}
Add a new method under the /
resource:
Method details
AWS_IAM
](https://docs.aws.amazon.com/Method request settings
Deploy the API to a stage (dev
).
Make an AWS4 signed request against the dev
stage API Gateway URL. For example:
import aws4 from "aws4";
const API_ID = "...";
const STAGE_NAME = "dev";
async function main() {
const options = aws4.sign({
headers: {},
path: `/${STAGE_NAME}`,
method: "GET",
host: `${API_ID}.execute-api.${process.env.AWS_REGION}.amazonaws.com`,
service: "execute-api",
region: process.env.AWS_REGION,
});
const url = new URL(`https://${options.host}`);
url.pathname = options.path;
const response = await fetch(url, {
method: options.method,
headers: options.headers,
});
console.log(`${response.status} ${response.statusText}`);
console.log(await response.text());
}
await main();
See https://stackoverflow.com/a/73696226/1727828. It contains more details around using an IAM role ARN in the Principal
element of a resource-based policy, and contains relevant references to AWS documentation.
Upvotes: 1
Reputation: 4581
You can achieve this by specifying the role in the condition element of the policy (see an explanation below):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-west-2:********:********/*",
"Condition": {
"ArnEquals": {
"aws:PrincipalArn": "arn:aws:iam::********:role/myRole"
}
}
}
]
}
Here's the fragment of the docs with an explanation (link):
you can specify the role principal as the principal in a resource-based policy or create a broad-permission policy that uses the aws:PrincipalArn condition key. When you use this key, the role session principal is granted the permissions based on the ARN of role that was assumed, and not the ARN of the resulting session. Because AWS does not convert condition key ARNs to IDs, permissions granted to the role ARN persist if you delete the role and then create a new role with the same name. Identity-based policy types, such as permissions boundaries or session policies, do not limit permissions granted using the aws:PrincipalArn condition key with a wildcard(*) in the Principal element, unless the identity-based policies contain an explicit deny.
See also APIGW resource policy condition keys
So there are two consequences that needs to be taken seriously for sensitive solutions (as stated in the doc):
Principal
element of the resource policy is used, the policy needs to be updated after role replacement to keep an access.Upvotes: 1
Reputation: 97
Based on the documentation https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-control-access-policy-language-overview.html,
Principal – The account or user who is allowed access to the actions and resources in the statement. In a resource policy, the principal is the IAM user or account who is the recipient of this permission.
Looks like roles cannot be added as a principal.
P.S: Spent two days trying to restrict access using roles, but couldn't get it to work.
Upvotes: 1