Application Load Balancer Authoriation Header not passed through - amazon-web-services

I currently have an API on API Gateway (REST) that has a single proxy endpoint hooked up to an HTTP proxy integration. I have a cognito authorizer that authorizes incoming JWTs issued by Cognito and then if valid it forwards the request along to our ECS instance via an Application Load Balancer.
The project that is running in that instance requires the Authorization header to be there for authorization purposes. The problem is that header is not forwarded to the container. After much debugging, we determined that the header was going missing when the ALB isforwarding the request to the container (previously this question was asking about API Gateway because I assumed that's where things were going wrong). Other custom headers can go through but not "Authorization".
Does anyone have any experience persisting the Authorization header using ALB? I'm very new to ALB so still learning how to build these projects.

If you're passing a header Authorization, it will be remapped with X-Amzn-Remapped-Authorization by Amazon API Gateway REST APIs.
For more information, see this guide.

We actually had two rules on the alb. One redirecting the api call from port 80 to port 443, then a forward rule to the container. We discovered that the header went missing at the redirect rule, so we eliminated that and added listener on port 80 that forwarded the call to the ecs task.

Related

Can I get an example of how to connect a lambda function to a domain name?

I've been wasting about 12 hours going in circles in what seems like this:
I am trying to just make a simple static landing page in lambda and hook the root of a domain to it.
The landing page works, but api gateway didn't because AWS doesn't seem to set permissions properly by default ("internal server error" with API gateway and lambda on AWS) but now the gateway link works.
So the next steps were the following:
add a custom domain name in the api gateway
add the api mapping in the custom domain name
in route 53, create a wildcard certificate with *.domain.com and domain.com
create an A record that points to the api gateway with domain.com
create a CNAME record that points to the A record
and I get an error 403 with absolutely nothing in the log. I log both 'default' and '$default' stages in the api gateway.
I read https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-403-error-lambda-authorizer/ which is all about looking at what's in the logs...
and I find the doc is both everywhere and nowhere because it's built as chunks of 'do this' and 'do that' without ever painting a whole picture of how each piece is connected to the other, or any graph with the hierarchy of services, etc. Reminds me of code that works only when you follow the example documented and breaks otherwise.
I'm sure I'm doing something wrong, but given the lack of logs and lack of cohesive documentation, I have no idea about the problem.
Not to mention that http doesn't even connect, just https.
Can anyone outline the steps needed to achieve this? essentially: [http|https]://(www).domain.com -> one lambda function
You cannot use API Gateway for an HTTP request; it only supports HTTPS.
From the Amazon API Gateway FAQs (emphasis mine):
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. By default, Amazon API Gateway assigns an internal domain to the API that automatically uses the Amazon API Gateway certificate. When configuring your APIs to run under a custom domain name, you can provide your own certificate for the domain.
You can use CloudFront to automatically redirect HTTP to HTTPS. How do I set up API Gateway with my own CloudFront distribution? provides a pretty simple walkthrough of connecting an API Gateway to CloudFront (you can skip the API Gateway portion and use the one you created). The important thing you'll need to do that is not in that document is to select Redirect HTTP to HTTPS.
If you truly need HTTP traffic you're probably going to need to go with an ALB.

AWS Load Balancers and Strict Transport Security Header

I am supposed to send a response from my web service with an STS header, but the service itself sits behind an AWS ALB which terminates SSL and sends the traffic on via http. This seems to be a common scenario and likely not limited to AWS, i.e. many LB's have the capability to terminate SSL as this is a very useful feature!
I have read through some messages from people who have already had this issue and have not seen any answers that seem anything other than a workaround - it seems to me to be a catch 22 situation, the LB doesn't send it as it isn't within its remit (according to one response from AWS support) and the target web server can't add it coz that header can only be added to https responses which the web server is not processing!
So my question is, is the sts header really that important if my web service can only respond on an https endpoint (no http enpdoint, not even a redirect)? Or is it still vulnerable to things like mitm attacks etc?
thanks in advance

Allow request from API Gateway to private ALB

I have a public API gateway set up, I want to forward the requests from API Gateway to a private ALB in the VPC. On AWS Console, for API Gateway VPC link setup I could only select an NLB in the VPC.
Is there a reason why we can only route to NLB and not to ALB?
Is there a way I can route to private ALB from the API Gateway?
Currently AWS only supports connecting to NLB for VPC link integrations. They have a feature request in place to enable support for ALB as well. For now, you can do -
Public API --> VPC Link --> NLB --> ALB
In the target groups of the NLB, add the private IPs of the ALB. This way you can reap benefits of the NLB (TCP layer) and ALB (HTTPS).
Using static IP addresses for Application Load Balancers
The selected answer is outdated. It is possible to have API Gateway integrate, thorugh http, with an internal facing ALB by using VPC Link and private resource integration.
For step by step details, see my answer on another question: https://stackoverflow.com/a/67413951/2948212
edit: I see I was confusing this post with another one... I believe my answer still adds value though, so I am leaving it (I thought this specified REST API Gateways and not HTTP API Gateways, but it does not).
Answer
While #diegosasw's answer is valid and useful, it is for AWS HTTP API Gateways, not AWS REST API Gateways.
With that being said, they are correct in saying it is possible! Please see the following AWS documentation regarding how to accomplish this: https://aws.amazon.com/premiumsupport/knowledge-center/api-gateway-application-load-balancers/
Please note one particular downside of AWS's documented approach: it requires a public ALB. Of course this is not ideal, though one can still harden their ALB so that it only accepts traffic originating from the REST API Gateway. If this is not acceptable for the existing use case, then #Suraj Bhatia's answer above must be followed (for REST API integrations, at least). If HTTP Gateways are acceptable, then #diegosasw's answer is the better approach to take due to it being simpler to manage and still allowing for a private ALB 🙂
For prosperity, AWS's documentation states the following:
Note: The following procedure assumes two things:
You have access to a public Application Load Balancer and its DNS
name. You have an API Gateway REST API resource with an HTTP method.
In the API Gateway console, choose the API you want to integrate with the Application Load Balancer.
In the Resources pane, for Methods, choose the HTTP method that your API uses.
Choose Integration Request.
In the Integration Request pane, for Integration Type, choose HTTP.
Note: To pass the entire API request and its parameters to the backend
Application Load Balancer, create one of the following instead: An
HTTP proxy integration
-or- An HTTP custom integration
For more information, see Set up HTTP integrations in API Gateway.
In the Endpoint URL field, enter either the Application Load Balancer's default DNS name or custom DNS name. Then, add the
configured protocol of its listener. For example, an Application Load
Balancer that's configured with an HTTPS listener on port 8080
requires the following endpoint URL format: https://domain-name:8080/
Important: Make sure that you create an HTTP listener or HTTPS
listener for the Application Load Balancer using the port and listener
rules of your choice. For more information, see Listeners for your
Application Load Balancers. For an Application Load Balancer
configured with an HTTPS listener, the associated certificate must be
issued by an API Gateway-supported certificate authority. If you have
to use a certificate that's self-signed or issued by a private
certificate authority, then set insecureSkipVerification to true in
the integration's tlsConfig.
Choose Save.
Deploy the API.

AWS service to proxy (NOT REDIRECT) HTTP to HTTPS?

Is there any aws product that allows to proxy HTTP to HTTPs without having to spin up a EC2 instance and setup nginx or whatever?
Tried API Gateway but seems to only allow HTTPS
Tried putting cloudfront in front of API gateway but all it does is redirect the request.
Not sure if there is any way to do what I need? For legacy reasons (which cannot change so don't bother suggesting that) I need a way to expose an HTTP endpoint and internally proxy it to my host through HTTPS.
I was hoping there's a service I could use to avoid having to manage and maintain another instance.
Cheers!
You can't Proxy HTTP to HTTPS, that wont work. You must redirect. You mention without having to setup nginx or whatever. Nginx would simply redirect your HTTP request to HTTPS. Same as Cloudfront would do. You can use Cloudfront to redirect HTTP to HTTPS without using API gateway.
Reading your question again, your application only listens on 443? If that is the case use Cloudfront or stick a docker container(nginx) on the EC2 host where your application runs.

How to safely secure micro-services in AWS VPC with ALB and OAuth server?

tldr: See bold generic questions below.
I have built the infrastructure outlined below(in attachment) in AWS. OAuth specifies an auth server which issues tokens(Authorizes) and then authenticates tokens on each request and allows a proxy to the internal ALB.
It's based on a micro-services architecture and uses oauth to issue tokens and authenticate them from the client apps. The client apps could be apps inside the VPC or apps external to the VPC. As you can see I want all requests to go through OAuth server before they get to the internal ALB. Now the different types of apps should use different types of grants to get an access tokens. Those access tokens will contain a scope which relates to the routes(API endpoints) of the internal ALB.
Now I have a few questions which I hope are as succinct as possible:
AWS VPC ALB Questions
What is the most secure way of insuring that only the oauth apps communicate with the internal ALB and not other apps in the public subnet? So we can be sure that all requests to the internal ALB are authenticated? Do I have to somehow attach a new oauth only subnet to the input of internal ALB but how do I restrict the internal ALBs input?
To the same end, how do I ensure apps in the same subnet do not communicate with each other? Basically, how do I ensure that no internal apps communicate with each other and must be passed all the way to the external load balancer and therefore to oauth from the private subnet.
Route 53 SLL termination ALB
Does SSL termination on certain port stop traffic directed from different domains. If I make a call to ALB port 433 from internal ALB with SSL termination do I have to call from the host(route53 something.com) specified by the certificate or can I use the DNS hostname of the ALB(something.elb.amozonaws.com) resolved by AWS ok?
Scopes and OAuth
How to compare each request's url and it's token with oauth scopes? I want to relate oauth scopes to api endpoints. So each request goes to a route endpoint with an access_token which contains scopes. This scope will have to be compared with the request url on each request to make sure it’s allowed. Does oauth come with this functionality? I would guess not. However whats the point of scopes if this is not the case? Seems like scope is just an array I need to do some processing on after authentication rather than it being special in oauth. I’m probably missing something :-).
This post is too long already so I can’t for obvious reasons get into all the details but if you would like more detail I would of course give them. Even a help in the right direction would be useful at this point.
Thanks in advance.