AWS API Gateway - Issues in setting up cross-account access - amazon-web-services

I am trying to use an existing API gateway which is present in accountA. I am having some EC2 instances which are having some scripts to invoke the API gateway present. These instances may/may not reside in the same AWS account as the one where my API gateway is present (Let's call the other account as accountB).
For the authentication part currently, there's only AWS_IAM authentication implemented at the API gateway level. The EC2 instances (in both the accounts) are having IAM roles attached which are having IAM permissions to invoke the API.
The permission for the same looks as:
{
"Sid": "InvokeAPI",
"Effect": "Allow",
"Action": "execute-api:Invoke",
"Resource": "*"
}
When I try to invoke the API from the instances which are in accountA, it is working as expected. However, when I try to invoke the API from my instances in accountB, the gateway returns a 403 error with the following message:
User: arn:aws:sts::accountB:assumed-role/invoke_api_iam_role/i-xxxxxxxxx is not authorized to access this resource
I tried to look at API gateway resource policies and tried to whitelist the accountB's EC2 IAM role in accountA API Gateway's resource policy and still, I'm getting the same error.
Current resource policy implemented at the API gateway kinda looks like this:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::accountB:role/invoke_api_iam_role"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:accountA:myAPIID/*"
}
]
}
For signing the requests to the API gateway through the awsv4 signature, I use aws-requests-auth
Please help to resolve this issue.

So as it turns out, everything above is correct and you need to deploy the API to a particular stage for applying the resource policy against it.

Related

How can I deny public access to an AWS API gateway?

Similar to this question, I would like to deny public access to an AWS API Gateway and only allow access when the API is invoked via a specific user account. I have applied the following resource policy to the gateway:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"NotPrincipal": {
"AWS": [
"arn:aws:iam::123456789012:root",
"arn:aws:iam::123456789012:user/apitestuser"
]
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:123456789012:abcd123456/*"
}
]
}
But when I run
curl -X GET https://abcd123456.execute-api.us-east-1.amazonaws.com/dev/products
I still receive a success response with data:
[{"id":1,"name":"Product 1"},{"id":2,"name":"Product 2"}]
I am expecting to receive a 4XX response instead.
How can I change the policy to deny public access to the gateway? Or, is it not possible to deny public access without using a VPC? Ideally I wish to avoid using a VPC as using a NAT gateway in multiple regions will be costly. I also want to avoid building in any authentication mechanism as authentication and authorization take place in other API gateways which proxy to this gateway.
Based on the comments.
The issue was that the stage was not re-deployed after adding/changing the policy.
So the solution was to re-deploy the stage for the policy to take effect.

Lambda http trigger

I created a lambda function in AWS.
I want to trigger it by a API Gateway/http call.
after creating the http trigger i can see the following:
but when I try to use a GET/POST calls to this address I receive "internal server error".
I checked the logs and I see the following:
The IAM role configured on the integration or API Gateway doesn't have permissions to call the integration. Check the permissions and try again.
What should I do? which permission I need?
Quoting from the docs here
When an API is integrated with an AWS service (for example, AWS
Lambda) in the back end, API Gateway must also have permissions to
access integrated AWS resources (for example, invoking a Lambda
function) on behalf of the API caller. To grant these permissions,
create an IAM role of the AWS service for API Gateway type. When you
create this role in the IAM Management console, this resulting role
contains the following IAM trust policy that declares API Gateway as a
trusted entity permitted to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "apigateway.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}

Control role permission in AWS

I'm new to AWS. I'm developing an application using Spring boot. I use AWS cognito for the sign in and sign up. I created a group called ROLE_ADMIN in cognito and connect with IAM role which was also created by me as ROLE_ADMIN_IAM.
I'm using AWS Api gateway (HTTP Apis, but similarly REST Apis) to communicate with Apis. Then integrated the Cognito jwt authorizer in Api gateway.
Everything working perfectly. The problem I'm facing now is, when a user sign in, I need to prevent few Apis based on his role which is in cognito groups. So I tried to attach policies to IAM role (ROLE_ADMIN_IAM already created), but it doesn't work.
This is what I attached to ROLE_ADMIN_IAM
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"apigateway:GET"
],
"Resource": [
"arn:aws:apigateway:ap-south-1::/apis/09bccr0"
]
}
]
}
I tried restrict every resources also. But doesn't work
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "*",
"Resource": "*"
}
]
}
I'm afraid whether the way I tried is wrong or correct? I've been working for days. But couldn't find any solution. Please anyone give me a solution. Thanks in advance.
Update 1.
Since this doesn't work, I created a Identity pool and attached user pool Id and client id with it. It automatically creates two Roles for authentication user and unauthentication user. Then I went to Api gateway and changed the authorizer to IAM. The documentation itself says when we use IAM as an authorizer we need to use Signature 4 version. (I switched to IAM form cognito jwt, because I don't find any documentation or article say I can go with cognito jwt when we use Identity pool to define roles).
In the react application, I use amplify. When I configure Identity pool, it provides temporary Accesskey and SecretKey after a successful login. I tried to use it with postman -> Authorization -> AWS Signature, it always gives {"message":"Forbidden"}
When you create a group in a Cognito user pool you need to attach proper IAM role to that group. IAM policy that allows actual API calls should look like that:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"execute-api:Invoke"
],
"Resource": [
"arn:aws:execute-api:us-east-1:*:a123456789/test/POST/mydemoresource/*"
]
}
]
}
You just need to replace demo string with your API Gateway ARN, method and endpoint. Pay attention to the "execute-api:Invoke" action.
Permission "apigateway:GET" does not allow you to call an API but to get service information about API. "apigateway:*" permissions allow you to make management AWS API call not actual API call.
For more information please check these articles:
Management calls
Execution calls

Lambda and API Gateway on the same VPC resulting in User: anonymous is not authorized to perform: execute-api:Invoke on resource

I'm trying to learn about resource policies and permissions in general in AWS.
The idea that started as something easy, an API Gateway denying access to everything but other resources in the same VPC ended as a nightmare.
What I want: My API allowing traffic/calls only to resources on the same VPC.
So I created 2 subnets and an open Security Group (all traffic inbound and outbound just for testing purposes)
I created an API Gateway with integrating to a Lambda function and another lambda function and deploy them to that VPC.
The API Gateway has one resource /hi and allows just GET.
When you hit that path it proxies to Lambda which returns a simple message: Hi.
The other lambda (which is on the same VPC) makes a call to the API and returns an error or the response.
Until now, everything works well. The lambda function hits API Gateway which poxies to lambda and return Hi.
But, as I said, I want to play with permissions. So I decided to lock down the calls to API Gateway to the VPC where both reside.
So I added this resource policy to API Gateway:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:account-id:api-id/*/*/*",
"Condition": {
"StringNotEquals": {
"aws:sourceVpc": "vpc-id"
}
}
},
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:account-id:api-id/*/*/*"
}
]
}
Then I went to the lambda (not the one that is part of the service, if not the one that invokes API Gateway) and add the Managed Policy
AWSLambdaVPCAccessExecutionRole
Also an inline policy allowing execute-api:Invoke on the resource arn:aws:execute-api:us-east-1:account-id:api-id///*
When I run again the lambda function (which was working previously with both, my API Gateway and dummy apis like https://jsonplaceholder.typicode.com/) I receive the following error:
INFO json {
Message: 'User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:account-id:api-id/dev/GET/hi with an explicit deny'
}
If I removed the resource policy in API Gateway, it works again... As soon as I add it, it retrieves the same error.
Does anyone know why this happens?
I'm turning crazy. I will appreciate help.
Edition: Trying an IAM role and resource policy
I also tried to use a role.
For this, in the API I set the following resource policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::account-id:role/my-role-for-API-Gateway"
},
"Action": "execute-api:Invoke",
"Resource": "arn:aws:execute-api:us-east-1:account-id:api-id/*/*/*"
}
]
}
Then, I attached that role to my lambda function (the one that should be able to invoke the API).
Important: That lambda is not part of the service. It is a separate Lambda that should be able to call API Gateway which will proxy the request to the lambda that it is part of the service.
I attached the following policies to that role.
AWSLambdaVPCAccessExecutionRole (because I also tried within the same VPC)
AmazonAPIGatewayInvokeFullAccess (open permission just to be sure I was not missing anything)
Inline policy allowing the invocation of the API by resource ARN: arn:aws:execute-api:us-east-1:account-id:api-id///*
I even tried giving AdministratorAccess to that role just to exhaust possibilities.
I test through API Gateway console, and I receive the proper console.
When I test through Lambda console, I receive the following error:
INFO json {
Message: 'User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:us-east-1:account-id:api-id/dev/GET/hi'
}
So the question for this block would be: how a lambda could invoke an API Gateway which is restricting access to a specific role which the lambda has?
Part of the issue is that aws:SourceVpc condition can be only used for private API. From docs:
aws:SourceVpc - This key can be used only for private APIs.
Since you are using regional API, your StringNotEquals will not work, and you are getting explicit deny.
If you want to use aws:SourceVpc, you have to modify your api to be private API. But if its only learning experience for resource-based policies, the simplest way to learn them would be with bucket policies.

Provide AWS account ids access to API Gateway

I want to give some AWS account ids access to call the api gateway that is in my account. What is the best way to do this?
I think there is a way to add resource policy that gives that AWS account access. Is that a good way to do that? I am talking about a production kind of service?
Also, does all the resouces of AWS account will get access to API gateway?
For each API Gateway endpoint we can change the Authorization option from None to AWS_IAM:
Then we can configure access to the API from the Resource Policy section of the API Gateway. From the Resource Policy page, click on the "AWS Account Whitelist" button to get a policy template, excerpted below:
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::{{otherAWSAccountID}}:root",
"arn:aws:iam::{{otherAWSAccountID}}:user/{{otherAWSUserName}}",
"arn:aws:iam::{{otherAWSAccountID}}:role/{{otherAWSRoleName}}"
]
},
"Action": "execute-api:Invoke",
"Resource": [
"execute-api:/{{stageNameOrWildcard*}}/{{httpVerbOrWildcard*}}/{{resourcePathOrWildcard*}}"
]
}
As an alternative (or in addition) to IAM authorization, we can control usage with API Keys, which enables the ability to rate limit (throttle) API calls and to set quotas.
More info:
https://aws.amazon.com/blogs/compute/control-access-to-your-apis-using-amazon-api-gateway-resource-policies/
https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html