AWS API Gateway should prevent use of TLS v1 - amazon-web-services

Refering to AWS Cloudfront Documentation, AWS API Gateway supports TLS v1.0, v1.1, v1.2.
But I want to limit the encryption protocols to TLS v1.1 and v1.2 for my Gateway API. Where do I configure this?
I do not see any cloudfront distribution for my API. Gateway resource page does not have an option to specify the security protocol.
My API is running in production for last 2 years using a custom domain.
Any idea how do I limit my API to TLS V1.1 and V1.2 protocols only in API Gateway?

I have just been working on this extensively and through a great deal of trial & error, I can document what I believe is the current optimal solution to this. The answer from suman j was the best solution back in Oct 2017 however it does have a limitation and also AWS has evolved since then.
So what is the limitation?
If you are using Lambda with the API Gateway and delete the Custom Domain Name, then manually creating a CloudFront distribution and associating a Lambda Function requires a specific Lambda version number. That is, it does not support aliases. This is problematic with CI/CD where the version numbers can continually change. However, the API Gateway Custom Domain Name Base Path Mappings do support aliases so it can be better to continue using these.
So how has AWS evolved?
As of November 2017, API Gateway supports creating Regional Endpoints in Custom Domain Names. These endpoints do not create a CloudFront distribution, thus optimising the strategy of placing your own CloudFront distribution in front of them that prevents the use of TLS v1.0.
So how do I set it all up?
The steps I used to do this (via the console) are as follows. Note that you may need to change some settings to support your particular application. For the purposes of this documentation let’s say your api is named api.example.com.
In API Gateway, edit your Custom Domain Name, add a Regional Configuration, select your certificate and click on Save. Note: for regional APIs, you need to use an ACM certificate from the same region as the API. More info here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-regional-api-custom-domain-migrate.html
Copy the Target Domain Name of the newly created Regional Endpoint. (Eg d-abcdefg123.execute-api.us-east-1.amazonaws.com)
In Route 53 or your DNS Provider, change the mapping of your API from the Edge Optimized CloudFront target domain name to the newly created Regional Endpoint target domain name (ie d-abcdefg123.execute-api.us-east-1.amazonaws.com).
Once the DNS change has propagated, edit the Custom Domain name and delete the Edge Optimized Endpoint by clicking on the x icon. This should then enable you to then create a new CloudFront distribution with the same CNAME of your API without AWS blocking you.
In API Gateway, create a new Custom Domain Name with Domain Name = regional-api.example.com, Endpoint Configuration = Regional and select the ACM Certificate. Click on Save and then Edit and add the Base Path Mapping as per your current API and click on Save. Copy the Target Domain Name of the newly created Regional Endpoint. (Eg d-xyzabcd456.execute-api.us-east-1.amazonaws.com)
In Route 53 or your DNS Provider, create a new CNAME record mapping regional-api.example.com to the newly created Regional Endpoint target domain name. (Ie d-xyzabcd456.execute-api.us-east-1.amazonaws.com)
In CloudFront create a new Distribution with the following settings:

ORIGIN SETTINGS:
Origin Domain Name = regional-api.example.com
After entering the above the following hidden fields should then be displayed:
Origin SSL Protocols = TLSv1.2 & TLSv1.1
Origin Protocol Policy = HTTPS Only
DEFAULT CACHE BEHAVIOUR SETTINGS:
(these values are what I needed for the app that calls the API to work properly)
Viewer Protocol Policy = Redirect HTTP to HTTPS
Allowed HTTP Methods = GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
Cached HTTP Methods = OPTIONS
Cache Based on Selected Request Headers = Whitelist
Whitelist Headers = Authorization
Object Caching = Customize
Minimum TTL = 0
Maximum TTL = 0
Default TTL = 0
Forward Cookies = All
Query String Forwarding and Caching = Forward all, cache based on all
Smooth Streaming = No
Restrict Viewer Access (Use Signed URLs or Signed Cookies) = No
Compress Objects Automatically = No 
Lambda Function Associations = None

DISTRIBUTION SETTINGS:
Price Class = Use All Edge Locations
AWS WAF Web ACL = None
Alternate Domain Names (CNAMEs) = test-api.example.com
SSL Certificate = Custom SSL Certificate (example.com)
Custom SSL Client Support = Only Clients that Support Server Name Indication (SNI)
Security Policy = TLSv1.1_2016 (recommended)
Supported HTTP Versions = HTTP/2, HTTP/1.1, HTTP/1.0
While waiting for the CloudFront Distribution creation to complete (average 40 mins), in Route 53 or your DNS Provider create a new CNAME record mapping test-api.example.com to the newly created CloudFront Domain Name (eg d123abcdefg.cloudfront.net)
Once the Distribution creation has completed fully test your application against test-api.example.com
If the testing is all good then update the Alternate Domain Names (CNAMEs) of your new CloudFront to be = api.example.com. (note - this will not make it ‘live’, the DNS change below is required for this)
Once the distribution update is complete (average 40 mins) then in Route 53 or your DNS Provider, update the CNAME record mapping of api.example.com to the newly created CloudFront Domain Name (ie d123abcdefg.cloudfront.net)
If all is working well you can now delete the Route 53 / DNS CNA test-api.example.com record plus delete the api.example.com API Gateway Custom Domain Name.
For bonus points, if using Route 53 it is recommended to use A and AAAA record aliases instead of CNAME’s for the Route 53 steps above (which I have done). This reduces cost slightly, hides the underlying CloudFront distribution somewhat and also enables IPv6 support.
I hope this helps! :-)

In order for Gateway API with additional cloud front distribution to work, we need to
From AWS Console, under API Gateway go to Custom Domain Name and delete the mapped entry.
Create a new cloudfront distribution with
Cloudfront settings
Origin Domain Name as your Gate API endpoint https://abcdfefg.execute-api.us-east-1.amazonaws.com
Viewer Protocol Policy as HTTPS Only
Origin SSL Protocols as TLSv1.2, TLSv1.1 (Uncheck TLSv1)
Add a CNAME entry under Alternate Domain Name to refer to custom domain name
and few other defaults
After the above changes are completed, accessing the custom domain name on https will enforce the TLS security settings as defined in Cloudfront distribution.

AWS has announced that this is now configurable for edge-optimised API Gateway implementations:
https://aws.amazon.com/about-aws/whats-new/2019/06/amazon-api-gateway-adds-configurable-transport-layer-security-version-custom-domains/
https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-custom-domain-tls-version.html

For anyone seeing this, you can now set a minimum TLS version of 1.2 for your custom domain in API Gateway: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-custom-domain-tls-version.html

You may create API gateway distribution in your CloudFront distribution list. If your API gateway origin has HTTPS, you can specify what type of TLS protocols to be use between cloudfront and API gateway. Between viewer/client and cloudfront, you can specify the TLS protocols and suites in General section > Security Policy of CloudFront configuration. This configuration only visible if you use custom SSL with SNI. You may choose between:
TLSv1
TLSv1_2016
TLSv1.1_2016
TLSv1.2_2018

As of now, You can enforce minimum TLS version by specifying a security policy for your custom domain. Supported security policies are TLS1.0 and TLS 1.2
Minimum version of TLS version API Gateway security policy support is TLSv1.0
Recommended security policy through Custom Domain Name is TLSv1.2
For greater control over TLS version, Create a CloudFront distribution in your account and use Regional API Gateway endpoint as origin.
Minimum TLS version 1.3 is only possible through Custom CloudFront distribution.
Refer : https://cloudnamaste.com/minimum-tls-version-for-api-gateway/

Related

How can I use aws to secure a domain with https for a non aws origin?

I did a search in the aws docs and couldn't find anything that could help me to setup a cloudfront distribution for a non aws origin server to secure my domain with https. I'm using route 53 to manage my dns for the domain, I'd like to setup https for the domain but it is not hosted with aws. How can I use aws to create a secure domain with https?
Update: I've created the cloudfront distribution and set the alternative cnames to the domain (example.com and www.example.com). In Route 53 I updated the A record for the domain - example.com - to be an alias and pointed it to the cloudfront distribution, but when I try to access the site I get page not working error. The domain does now have he secure padlock, but I can't access the site. Here is the error that I get when I access the site:
The simplest way is to use a CloudFront distribution in front of your non AWS endpoint. This endpoint would be configured as a custom origin endpoint.
You would need to generate or upload a certificate to ACM to attach to the resource. This must be done before you can use the distribution on your own domain, if you don't have it when you create the distribution you will need to edit it later.
The AWS documentation includes documentation for Creating a Distribution. If you follow this and reference your endpoint as the custom origin you will be able to create the host.
You will need to ensure you configure the Origins Origin Protocol Policy option to be HTTP Only if your host does not have a HTTPS certificate.
Be aware that as the CloudFront distribution communicates with your endpoint over the internet, any traffic between CloudFront and your endpoint will still not be encrypted.

Custom Domain for API Gateway not able to set 404

I am trying to setup a custom domain endpoint for API gateway published endpoint but not able to set.
I've followed all steps
Custom domain DNS is managed by AWS (aws cannot own this as its a .ai URL)
Created ACM Certificate for subdomain. (subdomain.host.ai)
Add Custom API in API Gateway with Mapping to particular Stage
Add A record for custom domain to point to "d-abcde12345.execute-api.us-west-2.amazonaws.com"
What might be going wrong.
When you are pointing to a DNS hostname, rather than an IP, you need a CNAME record. More importantly, when you assign a custom domain to your API Gateway, it will create a CloudFront distribution for you and gives you a CloudFront endpoint: E123CNFSOMETHING.cloudfront.net. You need to create a CNAME record in your registrar dashboard to point to this address, not the API Endpoint:
FROM TO TTL
subdomain E123CNFSOMETHING.cloudfront.net. 300

Disable http redirection to https

I'm developing little service using lambda functions which returns "Fact of the day" in your CLI using curl.
First, I developed business logic, deployed and created lambda using Serverless.
Second, I bought domain using aws route 53, Provisioned certificate and routed domain using `Custom Domain Name on API gateway.
At the moment if you would visit https://domain.io service works as intented but if you would try call curl domain.io it outputs:
<html>
<head><title>301 Moved Permanently</title></head>
<body bgcolor="white">
<center><h1>301 Moved Permanently</h1></center>
<hr><center>CloudFront</center>
</body>
</html>
My goal is to get service running without SSL (or redirect), by calling curl domain.io.
Is it possible to avoid redirection? Or can you create API custom domain name without certificate?
Currently I call curl -F domain.io it will follow redirect, but it's not solution I'm looking for.
Thank you!
Remove the custom domain configuration from API Gateway.
Wait a few minutes for API Gateway to release the custom domain in the AWS Edge Network (there isn't a way to determine when this is complete, but you'll get an error on one of the subsequent steps until it is. 20 minutes should be sufficient).
Create a CloudFront distribution, using the generic ...execute-api...amazonaws.com domain name assigned to your API stage.
For Origin Protocol Policy, select HTTPS Only.
Set the Origin Path to your stage prefix (e.g. /prod or /v1) -- whatever you set up as the stage prefix.
Set the Viewer Protocol Policy to HTTP and HTTPS.
Set the Minimum TTL and Default TTL to 0.
Set the Alternate Domain Name for the distribution to your custom domain.
If you want SSL to optionally work on your custom domain, associate an ACM certificate with the CloudFront distribution.
Change your DNS entry to point to the *.cloudfront.net hostname assigned to your distribution.
Wait for the CloudFront distribution state to change from In Progress to Deployed.
Test.
This seems like a lot of effort to enable HTTP against API Gateway, but it is necessary, because API Gateway was specifically designed not to support HTTP -- it only works with HTTPS, because that's a best-practice for APIs, generally.
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.
https://aws.amazon.com/api-gateway/faqs/
CloudFront is commonly known as a CDN, but it is in fact something of a Swiss Army knife of custom HTTP request manipulation, and this is a case of that.
Once you verify your behavior, you can optionally increase the Default TTL in CloudFront, which will cause it to cache responses for up to that value in seconds, reducing your costs by sending fewer actual requests to API Gateway and replaying cached responses to the callers.
This setup differs from what you have, now, because you are in control of the CloudFront distribution, instead of API Gateway... so you can customize it in ways that API Gateway doesn't allow when it is in control.

how to make AWS api gateway accept http instead of https

I have a Lambda function proxied by API Gateway. However, API Gateway only expose https and not http. I searched everywhere but looks like API Gateway is not possible to accept http.
So my question is how to translate http client calls to https and send to api gateway? I am asking because my client can only make http calls and they won't change.
You can put a Cloudfront distribution in front of API Gateway with to following setup:
Origin Protocol Policy: HTTPS Only
Viewer Protocol Policy: HTTP and HTTPS
Forward Headers: None
Object Caching: Use Origin Cache Headers
CloudFront is a quick solution as it's much easier to set up compared to instantiating an Elastic Beanstalk.
I have spent couple of hours trying to get this right, so just to share some good write-ups and one more gentle reminder:
This Smartcam project utilize Amazon API Gateway and CloudFront, it describes the setup procedure in details.
The official example given in Amazon's doc demonstrates how to create GET and POST method with query string parameters (e.g. /search?keyword=mars&...), JSON payload and plus path parameters. Must read!
Personal 2 cents:
if you are using query string parameters, make sure to edit behavior and then choose forward all, cache all under Query String Forwarding and Caching.
Alternatively, read this doc for another two possible configurations.
If you already set the Origin Path to your stage variable (by default: /prod), then when you invoke your CloudFront domain, skip the /prod, simply: xxxx.cloudfront.net/resource1/resource2?param1=...&param2=...
I recently had a 4 hour long phone call with an AWS representative about a similar problem we had in production stage. My situation was similar, there was nothing we could change in APIGateway to fix it (the rep tried all kinds of tricks, but nothing seemed working). So our conclusion was to spin up an EC2 instance as a proxy server for APIGateway and forward all the traffic. There was some additional work such as transferring the domain name, but overall it worked just fine. In your case, as you only need to redirect HTTP traffic, a simple ElasticBeanstalk proxy app might be enough (EB uses HTTP by default and is behind a Nginx proxy server).
You may create a CloudFront distribution just for the HTTP to HTTPS redirection.
I advise you to first obtain a SSL certificate for your domain, in ACM (Certificate Manager), the region must be us-east-1.
In CloudFront, click Create Distribution then select Web to create a web distribution.
Here are all the settings you may use, with some extra explanation. Please note that I use v0 as API Gateway stage for this example.
# ORIGIN SETTINGS
# ---
# Origin Domain Name - Paste the domain name of your API Gateway > Stages > v0 but without the path at the end
Origin Domain Name: https://<getway-id>.execute-api.eu-central-1.amazonaws.com
# Origin Path - The name of your API Gateway stage
Origin Path: /v0
# Origin ID - The ID for this origin
# By default it will be defined as `Custom-<getway-id>.execute-api.eu-central-1.amazonaws.com/v0`
# I replace `Custom` by `v0` just to quickly recognise it in the list later on.
Origin ID: v0-<getway-id>.execute-api.eu-central-1.amazonaws.com/v0
# Minimum Origin SSL Protocol - Choose the minimum SSL protocol for CloudFront to use when it establishes an HTTPS connection to your origin.
Minimum Origin SSL Protocol: TLSv1.2
# Origin Protocol Policy - HTTPS since that is all that API Gateway supports. So with HTTPS CloudFront to connects to your origin only over HTTPS.
Origin Protocol Policy: HTTPS
# DEFAULT CACHE BEHAVIOR SETTINGS
# ---
# Viewer Protocol Policy - CloudFront allowed protocol to access your web content
Viewer Protocol Policy: Redirect HTTP to HTTPS
# Allowed HTTP Methods - HTTP methods you want to allow for this cache behavior
# Select at least GET, HEAD, OPTIONS
Allowed HTTP Methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
# Compress Objects Automatically - No since we are not serving files via CloudFront, we are just returning redirects
Compress Objects Automatically: No
# DISTRIBUTION SETTINGS
# ---
# Price Class
# There is no extra charge for using extra locations, so you may leave it on `Use All Edge Locations`. The total request count is aggregated across all locations for the free tier.
Price Class: Use All Edge Locations
# Alternate Domain Names (CNAMEs) - The domain names of your websites
Alternate Domain Names (CNAMEs): www.example.com
# SSL Certificate - The `Custom SSL Certificate` MUST be a certificate obtained in us-east-1
# So, you may go to ACM (certificate manager) and request a certificate there
# https://console.aws.amazon.com/acm/home?region=us-east-1
SSL Certificate: Custom SSL Certificate > www.example.com
# Custom SSL Client Support - Leave to default value
Custom SSL Client Support: Clients that Support Server Name Indication (SNI)
# Security Policy - Leave to default value
Security Policy: TLSv1.2_2018
Once your CloudFront distribution deployed, go to Route 53 and select your Domain Name in your Hosted Zones.
Create a Record Set > A or select the existing A record. Then in the Record edition console:
Set Alias to Yes. Then set the Alias Target so it points to your CloudFront distribution (instead of your API Gateway if that's what you previously defined). It will appear in a dropdown, and be like www.example.com (<cloudfront-id>.cloudfront.net)
You could also use an Application Load Balancer in front of the Lambda to accomplish this:
https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html

How to CNAME to Amazon API Gateway Endpoint

I'm trying to set a CNAME on Cloudflare to point to an Amazon API Gateway endpoint. The CNAME is for use when referring to one of my subdomains. The gateway in turn points to the IP of a server on DigitalOcean. I am very new to Amazon web services and would appreciate if someone could give me an overview of the correct configuration for the DNS, Amazon Gateway and Cloudfront (which I think is needed to expose the gateway to DNS servers external to Amazon). Any help would be much appreciated.
UPDATE
I've been going at this for a while now and not making much progress. Does anyone have an idea if this is a viable approach or how else it might be done?
UPDATE2
I thought I needed to add the CNAME record to cloudFlare and just ended up in a redirect loop, observed by:
curl -L -i -v https://sub.mydomain.com/
NOTE: It seems this method doesn't work anymore as AWS now only accepts certificates from certain authorities. I haven't tested it myself, but the answer by Gunar looks promising.
There are several reasons why it doens't work to simply point Cloudflare at your API Gateway domain and call it a day:
API Gateway uses shared hosting so it uses the domain name to figure out what API to send requests to. It has no way of knowing that api.yourdomain.com belongs to your API.
API Gateway requires that you use https, but the certificate that it uses is only valid for the default domain.
There is a solution, however. Here are the steps that I followed when I recently set this up:
Generate an origin certificate from the crypto tab of the Cloudflare dashboard.
Import the certificate to AWS Certificate manager in the us-east-1 region, even if your API is located in a different region. If you are prompted for the certificate chain you can copy it from here.
Add your custom domain in the API Gateway console and select the certificate you just added. Check the AWS support article for more information on how to do this.
It usually takes about 45 minutes for the custom domain to finish initializing. Once it's done it will give you a new Cloudfront URL. Go ahead and make sure your API still works through this new URL.
Go to the Cloudflare DNS tab and setup a CNAME record pointing to Cloudfront URL you just created.
Switch to the crypto tab and set your SSL mode to "Full (Strict)". If you skip this step you'll get a redirect loop.
That's it. Enjoy your new highly available API served from your custom domain!
Set up Amazon's API Gateway Custom Domain with CloudFlare
In your AWS management console go to the API Gateway service and select Custom Domain Names from the left menu.
Click the Create button.
Log into CloudFlare, select your domain and open the Crypto tab
Go to SSL and set your SSL mode to "Full (Strict)" to avoid a redirect loop.
Go to Origin Certificates and click Create Certificate
Let CloudFlare generate a private key and a CSR and choose RSA as the private key type
Make sure that the hostname for your custom API domain is covered. (e.g. api.mydomain.com. You can specifically configure this custom domain or use a wildcard such as *.mydomain.com as is configured by default.
Pick PEM as the key format which is selected by default.
In AWS switch to region US-EAST-1 and goto the Certificate Manager.
Click Import a Certificate.
Copy the certificate body from your CloudFlare certificate to Certificate body to the configuration of the custom domain in the AWS Management Console.
Copy the Private key to the certificate private key field in the console
In the certificate chain copy the Cloudflare Origin CA - RSA Root which can be found here.
Enter your custom domain name in the AWS console and a name for your certificate
Now the custom domain name will be created in AWS CloudFront. It can take up to an hour before the domain becomes active.
The next thing you need to do is set up the mappings of the custom domain in the AWS Console.
The final step is to create a new CNAME Record in CloudFlare to link your domain to the CloudFront url. When you open the settings page of your custom domain in the AWS console copy the Distribution domain name. This is the domain you need to use when creating the new CNAME Record.
Source
I couldn't get any of the other answers to work. So I ended up having AWS generate the certificate instead of using a Cloudflare Origin one. That's because AWS wouldn't accept my Cloudflare certificate, even when the chain was provided. I couldn't see Cloudflare in Mozilla's Certificate Authority list (which is what AWS relies on, according to the docs) so I guess that makes sense.
Here's the outline of my solution:
Create AWS Route53 Zone
Create AWS ACM Certificate (must be in us-east-1) with validation method DNS
Create Cloudflare DNS Record with the output of (2)
Create AWS API Gateway Domain Name
Create Cloudflare DNS CNAME Record pointing '#' (root domain) to the Cloudfront domain name from step (4)
Create AWS API Gateway Base Path Mapping
This should be roughly it. May this help someone. Feel free to ask questions.
Both existing answers to this question are correct, but if the issue still persists even after following these directions perfectly, try going into the API Gateway settings, navigate to "Custom Domain Name" and configure the Base Path Mappings.
This was the missing step that solved all my problems.