How can I deny public access to an AWS API gateway? - amazon-web-services

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.

Related

How to allow access to an api resource with api gateway in aws?

I have an api gateway configuration with cognito authorization.
I enabled a general proxy path for all my api calls which end up with v1.
So all api resources under v1 need to be authorized.
But I have a couple of endpoints which I don't need authorization for, since they are webhooks which will be called by 3rd parties.
How can I add a policy to make an exception for these endpoints (resources) so that I can access them without any authorization.
I tried to add a policy as follows:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": "*",
"Action": "execute-api:Invoke",
"Resource": "{myResourceIds}/*/POST/stripe/connect/webhook"
}
]
}
For instance when I call my api with /stripe/connect/webhook I don't want any authorization for that path. How can I acomplish this ?
If you have created separate resource for these calls then you can simply not add any authorization to them. If you have a single ANY resource but want to have authorizer for certain paths and not others you can create a lambda authorizer that checks event path and passes any requests with paths that don't need authorization.

Private S3 static website accessed only by API Gateway

I want to set up a static S3 website that is only accessible via API Gateway, so what I've done is.
S3 side
1. Enabled static website hosting on the S3 bucket.
2. Blocked all public access.
3. Put in a bucket policy that only allows my VPC Endpoint to access it.
{
"Version": "2012-10-17",
"Id": "VPCe",
"Statement": [
{
"Sid": "VPCe",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:*",
"Resource": "arn:aws:s3:::my-bucket.com/*",
"Condition": {
"StringNotEquals": {
"aws:SourceVpce": "vpce-my-vpce"
}
}
}
]
}
API Gateway side
1. Mapped that same VPCE to the API
2. Created a proxy resource
3. In the integration request, I made it HTTP and put my S3 website URL as the endpoint URL, content handling as passththrough.
4. But when I test this through APIGW, I get access denied.
Is there something I'm missing, or am I wrong to expect this to work?
I get a 403, Access Denied on this.
I want to set up a static S3 website that is only accessible via API Gateway,
You can't do this, as its not possible. S3 static websites are only accessible through public URL, thus you need to access it from the internet.
They are not meant to be accessed from VPC using private IP addresses or any VPC endpoints.
If you want to have private static website, you have to host it yourself on private EC2 instance or ECS container.

AWS API Gateway - Issues in setting up cross-account access

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.

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.

Its possible to use AWS Athena using a VPC endpoint?

I would like to know if it is possible to create a VPC endpoint for AWS Athena and restrict to only allow certain users (that MUST BE in my account) to use the VPC endpoint. I currently use this VPC endpoint policy for a S3 endpoint and I would need something similar to use with AWS Athena.
{
"Version": "2008-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": [
"arn:aws:iam::<MY_ACCOUNT_ID>:user/user1",
"arn:aws:iam::<MY_ACCOUNT_ID>:user/user2",
...
]
},
"Action": "*",
"Resource": "*"
}
]
}
The problem I'm trying to solve is to block developers in my company, that are logged in a RDP session inside my company VPN, to offload data to a personal AWS account. So I would need a solution that blocks access to the public internet, so I think a VPC endpoint should be the only option, but I accept new ideas.
Yes you can, check out this doc.
https://docs.aws.amazon.com/athena/latest/ug/interface-vpc-endpoint.html
Also, keep in mind to adopt a encryption at rest and transit when query data via athena, the results always by default is open even if it's saved on a encrypted s3 bucket.