AWS API Gateway responds with 403 when first going through Alert Logic WAF - aws-api-gateway

I've seen a lot of questions on this topic, but none had answers that worked for my particular situation.
Context
I have a domain name foo.bar.com mapped in Route 53 to an Application Load Balancer in a VPC
The ALB routes to the WAF in my Alert Logic instance, hosted in the same VPC
I have a "website" in Alert Logic that points to xyz.execute-api.us-east-1.amazonaws.com via HTTPS over port 443
I have an API defined in API Gateway with an Invoke URL the same as above xyz.execute-api.us-east-1.amazonaws.com
My API has a route /hello with an Integration that points to an internal Application Load Balancer in the same VPC and subnets as everything mentioned above
Problem
Doing a GET request to https://xyz.execute-api.us-east-1.amazonaws.com succeeds from Postman while connected to the VPN for the given VPC
Doing a GET request to foo.bar.com failed from Postman - whether or not connected to the VPN - with a status code of 403, a body of { "message": "Forbidden" }, and a x-amzn-ErrorTypeofForbiddenException`
QUESTION: What am I missing?

Related

GCloud Cloud Run - service to service 403 with valid access token and correct invoker role

I get a 403 calling a Cloud Run service from another Cloud Run service.
I can only find this relevant SO question but both the accepted answer checks and the OP's solution are not valid for my use-case.
Use case:
Service A (the called service):
expose public routes to the internet (eg: /public/... )
expose private routes (eg: /internal/...)
expose a 403 custom route /403 with JSON response
I have a subdomain configured using a Load Balancer with two rules:
traffic to this subdomain pointing to internal is redirected to /403
all the other traffic to this subdomain is redirected to my Cloud Run Service
My service is deployed with this config:
Ingress Control is set to internal, with Allow traffic from external HTTP(S) load balancer flagged
A VPC is configured, with Route all traffic through VPC set to true (the same VPC is used by all my services)
Authentication setting is Allow unauthenticated invocations
Service B's service account (the caller) is listed in Service A's permission tab under the Cloud Run Invoker role (same as PubSub's service account)
With this configuration:
Traffic from the internet is served correctly through the subdomain
PubSub can call Service A using the computeMetadata bearer token
Service B gets a 403 using the https://xxx.a.run.app url
Service B obtains a valid computeMetadata token (the JWT is valid, claims are coherent), but 403 with this body is returned:
<html><head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>403 Forbidden</title>
</head>
<body text=#000000 bgcolor=#ffffff>
<h1>Error: Forbidden</h1>
<h2>Access is forbidden.</h2>
<h2></h2>
</body></html>
I am sure this is Google's 403 and not my custom 403 for it's not a JSON response and the request is not logged in Service A's logs.
I tried to allow all unauthenticated traffic and internal urls are served correctly, but I can not expose internal urls.
Does anyone have suggestion on what to check or how to debug this situation?

Questions about istio external authorization

Problem statement:
My goal is to have istio with external authorization service (ideally HTTP, if not possible than GRPC would do as well). There is a requirement to be able to control what exact status code will be returned to client on authorization service. The latter requirement is the most problematic part.
My research
I have read istio documentation on external authorizer
I have made a prototype with HTTP Auth service, but whatever non 200 status
code I return from Auth Service the client always receives 403
Forbidden
In mesh config specification I see the only possibility to set statusOnError but it will be used only in case auth service is unreachable and it can not be dynamically changed.
Also in envoy documentation for GRPC service I see possibility to set custom status
HTTP attributes for a denied response.
{
"status": "{...}",
"headers": [],
"body": "..."
}
Questions:
Is having custom status possible only with GRPC auth service?
Is istio using envoy API-V3 or API-V2?
Any suggestion how to cook istio with external authorizer and custin status codes?
I made the GRPC Auth service prototype and found the answer. It is counter-intuitive but GRPC external auth service is really more flexible than HTTP one. And it really allows to set arbitrary status code

I'm trying to access an AWS API Gateway inside of a VPC, but keep getting timeout errors

I have an AWS API gateway that I created with zappa and an ECR docker image. I assigned the lambda function to a VPC but can no longer access the API.
I created an internet gateway and have the route table routing 0.0.0.0/0 and ::/0 to it.
I have all traffic allowed on all ports on the security group as well.
However, whenever I try to access any endpoints I get a timeout error. If I take the lambda function out of the VPC I am able to access all the endpoints.
You cannot access API gateway from lambda directly, if your lambda inside VPC. In this case you have to use VPC endpoint.
You can use Lambda functions to proxy HTTP requests from API Gateway to an HTTP endpoint within a VPC without Internet access. This allows you to keep your EC2 instances and applications completely isolated from the internet while still exposing them via API Gateway. By using API Gateway to front your existing endpoints, you can configure authentication and authorization rules as well as throttling rules to limit the traffic that your backend receives.
Reference: https://aws.amazon.com/blogs/compute/using-api-gateway-with-vpc-endpoints-via-aws-lambda/#:~:text=Conclusion,exposing%20them%20via%20API%20Gateway

AWS API Gateway HTTP Proxy for HTTPS connections

I cannot for the life of me get the AWS API Gateway HTTP Proxy to work, i.e. redirect http://<my-domain>.com to https://<my-domain>.com. Here is how I set it up:
Using the Test functionality on the ANY method inside the resource works. But if I simply do curl http://<my-domain>.com or run http://<my-domain>.com in Chrome, it fails to connect; https://<my-website>.com works just fine. I'm driving myself crazy trying to figure out what I'm missing here; it seems like it should just redirect http://<my-domain>.com to https://<my-domain>.com, but it doesn't (even on different devices).
So, it turns out that API Gateway's HTTP Proxy allows HTTPS traffic to go to an HTTP endpoint, but not the reverse. In fact, API Gateway won't even establish a connection on port 80; from the FAQ:
Q: Can I create HTTPS endpoints?
Yes, all of the APIs created with Amazon API Gateway expose HTTPS
endpoints only. Amazon API Gateway does not support unencrypted (HTTP)
endpoints.
API Gateway doesn't support unencrypted HTTP traffic. Here are the possible options you can do to secure your website:
If you have access to the server that hosts the website, install an SSL certificate to the webserver.
If the website is hosted on EC2, you can set up a load balancer and let it do the SSL termination.

AWS API Gateway - Test works, deployed API errors. Why?

I'm trying to setup AWS Api Gateway as a reverse proxy for my actual deployed API.
My understanding is that I do this by creating a "Proxy" Resource and then specifying my http endpoint URL - as described here
Create and Test an API with HTTP Proxy Integration through a Proxy Resource
This works fine when I try to use the API through the "Test" function within the Resource Editor. I can make calls to any exposed resources using GET methods and see the successful responses.
However, when I deploy the API Gateway API I can no longer access anything using the "Invoke URL" it gives me - I simply get:
{
"Message": "No HTTP resource was found that matches the request URI 'http://<myuniqueid>.execute-api.eu-west-1.amazonaws.com/api/Sector/100'.",
"MessageDetail": "No type was found that matches the controller named 'Sector'."
}
If I remove the "Use HTTP Proxy integration" checkbox from the "Integration Request" I can get it working, but why doesn't it work as a proxy?
I suspect that this is caused by a known issue with the HTTP proxy integration. When you use an HTTP proxy integration, API Gateway passes all headers through to the integration endpoint, including the HOST header. Many existing http endpoint require the use of a HOST header which matches their DNS name and in such cases, passing through the HOST header of the API Gateway can confuse the endpoint.
UPDATE: We identified a work-around for this issue.
In your integration request, explicitly add a header named "Host" and give it the value of the integration endpoint DNS name. This will replace the Host header forwarded from the incoming client request with the Host header you specify. This should allow your backend endpoint to function correctly.