I'm trying to create a multi-region serverless application on AWS. I've followed the instructions given here. I'm using Serverless framework, which uses Cloudformation scripts for creating all the resources on AWS.
I want to create a custom domain for API gateway as a Regional Endpoint. When it creates a Regional endpoint, it generates a target domain. I would like to know how can I get the value of the target domain in my Cloudformation script?
When I create an Edge optimized Endpoint, I get the value of the CloudFront deployment by using the DistributionDomainName
attribute. But I don't see any attribute for the target domain name when a Regional Endpoint is created. I tried using the DistributionDomainName
attribute for a Regional endpoint, but it throws an error which says that there is no DistributionDomainName
.
Below is a part of my script -
# Creates a custom domain for the ApiGateway
customDomain:
Type: 'AWS::ApiGateway::DomainName'
Properties:
DomainName: ${self:custom.domain}
EndpointConfiguration:
Types:
- REGIONAL
RegionalCertificateArn: ${self:custom.certificateArn}
# Insert a DNS record in route53 hosted zone to redirect from the custom domain to CF distribution
dnsRecord:
Type: AWS::Route53::RecordSet
Properties:
Region: ${self:provider.region}
SetIdentifier: ${self:provider.region}
HostedZoneId: ${self:custom.hostedZoneId}
Name: ${self:custom.domain}
Type: CNAME
TTL: 60
ResourceRecords:
- "Fn::GetAtt": [customDomain, DistributionDomainName]
Please help. Thanks!
UPDATE
Cloudformation now returns the regional domain name through RegionalDomainName
property. It could be used as Fn:GetAtt : [customDomain, RegionalDomainName]
.
This is not possible at the moment.
As you mentioned, the only exposed parameter is DistributionDomainName and this works only for edge-optimized endpoints.
As a workaround (until it will be implemented in CloudFormation) you could use a CustomResource backed up by your own Lambda function to return the regionalDomainName attribute.
Here's a sample CloudFormation YAML code that does this:
Resources:
# The workaround Lambda that returns the regionalDomainName property
RegionalDomainLambda:
Type: AWS::Lambda::Function
Properties:
Runtime: python2.7
Handler: index.handler
Role:
'Fn::GetAtt': [YOUR_ROLE_GOES_HERE, Arn] # make sure you include apigateway:GET
Timeout: 50
Code:
ZipFile: |
import cfnresponse
import json
import boto3
client = boto3.client('apigateway')
def handler(event, context):
response_data = {}
try:
domainName = event['ResourceProperties']['DomainName']
regional_domain_name = client.get_domain_name(domainName=domainName)['regionalDomainName']
response_data['value'] = regional_domain_name
cfnresponse.send(event, context, cfnresponse.SUCCESS,response_data, "RegionalDomainNameString")
except Exception as e:
response_data['exception'] = e
cfnresponse.send(event, context, cfnresponse.FAILED, response_data, "RegionalDomainNameString")
# The resource that serves as a placeholder
RegionalDomain:
Type: Custom::CustomResource
Properties:
ServiceToken:
'Fn::GetAtt': [RegionalDomainLambda, Arn]
DomainName: {Ref: YOUR_API_GATEWAY_DOMAIN_NAME_GOES_HERE}
# And here's how to use it
SomeOtherResource:
SomeOtherProperty: {'Fn::GetAtt': [RegionalDomain, value]}