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! :-)