AWS HTTP API Gateway connected to ALB returns 503 - amazon-web-services

My current solution:
My application consists of two separate services/containers deployed to ECS. These services are inside Virtual Private Cloud (VPC) and to expose the application I created EC2 Application Load Balancer, which works flawlessly, I can access the application through Load Balancer URL easily.
What I'm trying to achieve:
Currently I'm trying to create an API Gateway linked to the load balancer mentioned above, to access the application by API Gateway instead of Load Balancer.
What I did to achieve this
I found an AWS tutorial which basically does what I'm trying to do, so I went step by step with this tutorial
Created Http API Gateway
Created VPC-LINK (connected to all possibles subnets and all possible security groups just in case)
Created single route ANY /{proxy+} to catch basically everything
Created integration to that route (where I selected mentioned above load balancer as a target service).
Everything is step by step, the same as in the tutorial, but unfortunately last step where I should see my webpage I see ERROR: 503 {"message":"Service Unavailable"}
What I did additionally to solve the issue:
Added Api Gateway logs, but I'm not receiving anything interesting there, just raw data like below:
{
"requestId": "PgELwjAyjoEEPgQ=",
"ip": "185.244.96.51",
"requestTime": "24/Mar/2022:18:09:40 +0000",
"httpMethod": "GET",
"routeKey": "ANY /{proxy+}",
"status": "503",
"protocol": "HTTP/1.1",
"responseLength": "33"
}
played with different load balancer listeners (443 or 80).
played with different security groups (tried with same security groups as ALB, or with all possible security groups)
The question is, what I'm missing here?
I guess the problem lies somewhere in the connection between VPC link and load balancer, but to be honest I don't know how to check and verify it. I clicked everything step by step, in many places there was single choice option, so I'm really confused where I could have made a mistake. Here is an illustrative photo of the infrastructure and my guess where the problem could be (but it's still a guess.

The only thing I can think of is, why? Like seriously, APIGW doesn't provide any additional value over the ALB. If you are already using an ALB, the easiest, cheapest, and best thing to do, is point your route53 DNS at the ALB and be done.
In any case VPC-link will never work, APIGW doesn't work with internal VPC, and VPC-link requires the client to be in the same VPC as the service. Since VPC-link is inside the VPC and the HTTP API is outside of course this would cause a problem, and specifically "I can't find that dependency" where 503 is the expected status code.
If some ridiculous reason you still wanted to use APIGW with a public ALB, you can point the APIGW directly at the ALB DNS, and be done. But again, this offers negative value AND costs additional money + performance for an all around negative impact on your users, developers, and your corporate wallet.
If for some reason after all that, here is the AWS Documentation on VPC-Link. In reality the problem with the setup is likely a further configuration issue. You can validate this by checking the ALB flow logs.

One reason to want to do this approach is that the API Gw is being used with say Cognito to provide the access security to the backend API in the VPC rather than say an x-api-key header which is very insecure. In this way API Gw can provide user group level security of all the APIs exported by the backend service. It can also be used to deny access to certain apis through route configuration.

Related

aws application load balancer metrics not showing

I have created an aws application load balancer. I am trying to test something out on it and I have configured the target group and everything. When I try to hit the load balancer I get a bad gateway error (502), which is expected. However these metrics are not showing up in the monitoring section of the load balancer. I submitted around 5 requests.
Furthermore even after registering an ECS service, I still get bad gatewawy. This is what I see on the load balancer/target groups after registering the service
I have also allowed all traffic inbound and outbound from the two security groups (the security group used by the ECS service and the security group used by the load balancer)
However under the registered target when creating the ECS service I specified two availability zones, but it shows only one registered.
figured it out and its kind of silly. My VPN/network was blocking the call going out to the ALB. I'm not sure why, maybe some sort of network policy. But the url looks something like this my-lb-1123366532.us-west-1.elb.amazonaws.com I wasted almost a day trying to figure this out. I'm just putting it out here in case it helps someone.

Reaching GCP Cloud Run instance through VPC with "only internal range" egress

The current setup is as follows:
I have a Cloud Run service, which acts as "back-end", which needs to reach external services but wants to be reached ONLY by the second Cloud Run instance. which acts as a "front-end", which needs to reach auth0 and the "back-end" and be reached by any client with a browser.
I recognize that the setup is not optimal, but I've inherited as is and we cannot migrate to another solution (maybe k8n). I'm trying to make this work with the least amount of impact on the infrastructure and, ideally, without having to touch the services themselves.
What I've tried is to restrict the ingress of the back-end service to INTERNAL and place two serverless VPC connectors (one per service), so that the front-end service would be able to reach the back-end but no one else could.
But I've encountered a huge issue: if I set the egress of the front-end all on the VPC it works, but now the front-end cannot reach auth0 and therefore the users cannot authenticate. If I place the egress as "mixed" (only internal ip ranges go through the VPC) the Google Run URL (*.run.app) is resolved not through the VPC and therefore it returns a big bad 403.
What I tried so far:
Placing a load balancer in front of the back-end service. But the serverless NEG only supports the global http load balancer and I'd need an internal one if I wanted an internal ip to resolve against
Trying to see if the VPC accessor itself MAYBE provided an internal (static) ip, but it doesn't seem so
Someone in another question suggested a "MIG as a proxy" but I haven't managed to figure that out (Can I run Cloud Run applications on a private IP (inside dedicated VPC network)?)
Fooled around with the Gateway API, but it seems that I'd have to provide a openAPI specification for the back-end, and I'm still under the delusion that this might be resolved with a cheaper (in terms of effort) approach.
So, I get that the Cloud Run instance cannot possibly have an internal IP by itself, but is there any kind of GCP product that can act as a proxy? Can someone elaborate on the "MIG as a proxy" approach (Managed Instance Group? Of what, though?), which might be the solution I'm looking for? (Sadly, I do not have the reputation needed to comment on that question or I would have).
Any kind of pointer is, as always, deeply appreciated.
You are designing this wrong. Use Cloud Run's identity-based access control instead of trying to route traffic. Google IAP (Identity Aware Proxy) will block all traffic that is not authorized.
Authenticating service-to-service

Can an API Gateway point to multiple Application Load Balancers?

Having a hard time figuring out a microservices architecture.
Right now I have an ECS Cluster with two services (TodoService, CategoriesService) running in containers. Both of the services have their own Load Balancer. I'm trying to build an API Gateway where /todos would route to the Todo-app-load-balancer and /categories would route to the Categories-app-load-balancer.
First, is this a good approach to microservices? And second, question from the title.
First, is this a good approach to microservices?
Yes, there is nothing wrong with this approach.
Can an API Gateway point to multiple Application Load Balancers?
Yes, you can point each method from the API gateway to an entirely different backend resource.
In case of an Application Load Balancer, there are multiple ways of doing this. Probably the easiest is to have a public Application Load Balancer and to create HTTP integration for it. You have to specify the DNS name for the application load balancer as the endpoint. For more information, see this support page.
Other option would be to use VPC Links, which would integration with private load balancers. While this would be recommended for production, it is a bit more complex to set it up.
Is it a good or bad approach is moreover an architectural decision, But I can suggest using one ALB(Ingress) with different rules can solve your problem, Also in API GATEWAY only allow to add ELB services directly ALB will not but still there is a workaround by adding direct DNS. Here I'm attaching two screenshots for your reference.
Direct integration is not allowed on ALB, but you can use the DNS name manually.

AWS 3-Tier Architecture Issue

Need some serious help here, thanks a lot in advance !
I need to deploy a scalable 3 tier web application on AWS and I am having some doubts/trouble understanding the best practice to design the architecture.
NOTE: As per my understanding, all the backend requests are requested through the browser, after the Frontend server serves html/css/js to the user.
Let me show you what I have come up with till now :
Assuming the above 'note':
Cons (as per my understanding):
All the backend routes will be exposed to the outside world.
Even though backend servers are in private subnet, now that they're being accessed via external load balancer, the endpoints API could be accessed from the users.
How will we route a request from a Load balancer to another Load balancer. Because what I have seen is that you could only route a request to an EC2 instance added in the target group.
To overcome the cons as I think in the above approach, I came up with this architecture instead:
Pros (as per my understanding):
The backend routes are safe (in a way) because we have a way of internally connecting from the frontend to the backend servers(if required).
Cons:
If the request is made from the browser, the endpoints are again exposed.
Solution that I found online:
REAL BIG DOUBT IN THIS LAST ONE
This breaks all the logic of my understanding that : All the requests are made by the browser from the user to the backend because in this the requests to the backend are being routed FROM the frontend servers.
QUESTIONS
What if the backend request (say login) is made by the user from the browser?
How will this work out in such case?
seems like you have done some good work here.
Let me start by making things easy for you:
Users only interact with the Load Balancer: If you want to keep it simple and not break off your frontend asset serving to an external service like CloudFront, which you should if you are starting out, you will be hosting the application only via EC2 instances (application origin, or simply orgin). Your requests would look something like this:
Users <--> ALB <--> EC2
Notice how users never interact with EC2 instances directly, its always via Application Load Balancer (ALB).
If I can oversimply thing, this is how HTTP operates, a request is made to a resource at an IP and the response is sent back from the same resource or IP. So as in your diagram, a request will not be responded back by EC2 but rather be relayed via the ALB.
You don't need NAT gateway: NAT gateway are there to make it possible for resources in provate subnet access the internet. In this case, unless you want your application to access the internet, you don't need NAT gateway. Many large scale applications are actually locked down in part by not keeping this resource at all.
You are still protecting the origin: Given that only the ALB can be accessed over the internet and everything else internal you can structure things here in any way that you want to. you could have few internal microservices that can be used internally without ever being exposed to end users. Note that here request never leaves the VPN.
You can read more about this and build a sample application via the official docs here or access AWS tutorials here.
To me, #3 is the correct solution because it does not expose /api to end users (since you mention "I DO NOT want the users to directly access the /api"). In #1, I don't think you could limit access to /api to only the front-end servers, since security groups work on the whole load balancer, not per-target.
Also, being an Internet-facing load balancer, any requests from the front-end servers to the load balancer in #1 will be referencing the load balancer via public IP addresses. This will cause a 1c/GB charge to go "out of" the VPC and then back in again.
Only #3 correctly refers to back-end resources via private IP addresses. The internal load balancer will be referenced via private IP addresses.

Amazon API Gateway in front of ELB and ECS Cluster

I'm trying to put an Amazon API Gateway in front of an Application Load Balancer, which balances traffic to my ECS Cluster, where all my microservices are deployed. The motivation to use the API Gateway is to use a custom authorizer through a lambda function.
System diagram
In Amazon words (https://aws.amazon.com/api-gateway/faqs/): "Proxy requests to backend operations also need to be publicly accessible on the Internet". This forces me to make the ELB public (internet-facing) instead of internal. Then, I need a way to ensure that only the API Gateway is able to access the ELB outside the VPC.
My first idea was to use a Client Certificate in the API Gatway, but the ELB doesn't seem to support it.
Any ideas would be highly appreciated!
This seems to be a huge missing piece for the API gateway technology, given the way it's pushed. Not being able to call into an internal-facing server in the VPC severely restricts its usefulness as an authentication front-door for internet access.
FWIW, in Azure, API Management supports this out of the box - it can accept requests from the internet and call directly into your virtual network which is otherwise firewalled off.
The only way this seems to be possible under AWS is using Lambdas, which adds a significant layer of complexity, esp. if you need to support various binary protocols.
Looks like this support has now been added. Haven't tested, YMMV:
https://aws.amazon.com/about-aws/whats-new/2017/11/amazon-api-gateway-supports-endpoint-integrations-with-private-vpcs/
We decided to use a header to check to make sure all traffic is coming through API Gateway. We save a secret in our apps environmental variables and tell the API Gateway to inject that when we create the API. Then check for that key in our app.
Here is what we are doing for this:
In our base controller we check for the key (we just have an REST API behind the gateway):
string ApiGatewayPassthroughHeader = context.HttpContext.Request.Headers["ApiGatewayPassthroughHeader"];
if (ApiGatewayPassthroughHeader != Environment.GetEnvironmentVariable("ApiGatewayPassthroughHeader"))
{
throw new error;
}
In our swagger file (we are using swagger.json as the source of our APIs)
"x-amazon-apigateway-integration": {
"type": "http_proxy",
"uri": "https://${stageVariables.url}/path/to/resource",
"httpMethod": "post",
"requestParameters": {
"integration.request.header.ApiGatewayPassthroughHeader": "${ApiGatewayPassthroughHeader}"
}
},
In our docker compose file (we are using docker, but the same could be used in any settings file)
services:
example:
environment:
- ApiGatewayPassthroughHeader=9708cc2d-2d42-example-8526-4586b1bcc74d
At build time we take the secret from our settings file and replace it in the swagger.json file. This way we can rotate the key in our settings file and API gateway will update to use the key the app is looking for.
I know this is an old issue, but I think they may have just recently added support.
"Amazon API Gateway announced the general availability of HTTP APIs, enabling customers to easily build high performance RESTful APIs that offer up to 71% cost savings and 60% latency reduction compared to REST APIs available from API Gateway. As part of this launch, customers will be able to take advantage of several new features including the ability the route requests to private AWS Elastic Load Balancers (ELB), including new support for AWS ALB, and IP-based services registered in AWS CloudMap. "
https://aws.amazon.com/about-aws/whats-new/2020/03/api-gateway-private-integrations-aws-elb-cloudmap-http-apis-release/
It is possible if you use VPC Link and Network Load Balancer.
Please have a look at this post:
https://adrianhesketh.com/2017/12/15/aws-api-gateway-to-ecs-via-vpc-link/
TL;DR
Create internal Network Load Balancer connected to your target group
(instances in a VPC)
In the API Gateway console, create a VPC Link and link it to above NLB
Create API Gateway endpoint, choose "VPC Link integration" and specify your NLB internal URL as an "Endpoint URL"
Hope that helps!
It is now possible to add an authorizer directly to Application Load Balancer (ALB) in front of ECS.
This can be configured directly in the rules of a listener. See this blog post for details:
https://aws.amazon.com/de/blogs/aws/built-in-authentication-in-alb/
Currently there is no way to put API Gateway in front of private ELB, so you're right that it has to be internet facing. The best workaround for your case I can think of would be to put ELB into TCP pass through mode and terminate client certificate on your end hosts behind the ELB.
The ALB should be internal in order to have the requests routed there through private link. Works perfectly fine in my setup without need to put NLB in front of it.
Routes should be as following:
$default
/
GET (or POST or whichever you want to use)
Integration should be attached to all paths $default and GET/POST/ANY etc