- Newest
- Most votes
- Most comments
Thanks alot Francisco for the support
After hours of work and multiple testing attempts, we managed to make it work by following the steps below :
-
Create a IAM Authenticated Regional API Gateway.
-
Create a custom domain name for that API Gateway, let's say api.customdomain.eu.
-
Don't create a record on DNS/Route53 for that API Gateway Custom domain name as you will need it for the CloudFront Distribution.
-
Create a CloudFront Distribution with an alternate Domain Name, the same as the custom domain name associated with the API Gateway.
-
Add the API Gateway as an Origin to the CloudFront Distribution.
-
Disable caching on CloudFront or create a new Cache Policy that forwards Authorization headers to the Origin "as shown in the attached img".
-
Create a CNAME/Alias Record that maps the custom domain name "api.customdomain.eu" to the CloudFront Distribution domain name.
-
Start testing using a Python script that signs "sigv4" your requests to the CloudFront Distribution or use Postman with AWS Signature Authorization enabled. The host used should be the custom domain name "api.customdomain.eu".
I tried the suggested solution, but in this case we recieved 403 HTTP Error with the following message :
The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.
I suggest trying this, for instance, using python to build a custom signed/authenticated CloudFront request.
Source of information: https://github.com/aws-samples/sigv4a-signing-examples/blob/main/python/sigv4a_sign.py
from sigv4a_sign import SigV4ASign
import requests
service = 'execute-api'
region = 'eu-west-1'
method = 'POST'
url = 'https://REDACTED.execute-api.eu-west-1.amazonaws.com/test/REDACTED'
data = 'REDACTED'
aws_request_config = {
'method': 'POST',
'url': url,
'data': data
}
headers = SigV4ASign().get_headers(service, region, aws_request_config)
headers['host'] = 'REDACTED.cloudfront.net'
url = 'https://REDACTED.cloudfront.net/test/REDACTED'
r = requests.post(url, data=data, headers=headers)
print(f'status_code: {r.status_code}')
print(f'response: {r.text}')
The basic points I want to highlight are:
- Make sure you sign the request using the API Gateway URL
- Make sure you build the request using the HTTP Host header of your CloudFront distribution
Update: For the second point, to restrict API Gateway request processing to CloudFront I suggest using custom Lambda Authorizers as explained here: https://docs.aws.amazon.com/apigateway/latest/developerguide/apigateway-use-lambda-authorizer.html For instance, you can include a custom HTTP Header/Value pair from CloudFront distribution and implement the logic in Lambda as authorization layer.
I hope that helps.
Relevant content
- asked 8 months ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 17 days ago
- AWS OFFICIALUpdated 2 years ago
- AWS OFFICIALUpdated 2 years ago
This is because the HTTP Host header used for CloudFront and API Gateway are different. In that case, in the python code snippet I provided you can see the "trick" of signing the request with the API Gateway URL (this is what API Gateway is expecting) and then change the host header to point to CloudFront one. Another option is using custom domain name with same value in both API Gateway and CloudFront.