Edge API Gateway Custom Domain with SAM: certificate in us-east-1 when using another region
Tags: aws, serverless, apigateway, awssam
Published: 2023-12-28 16:16:37

## Purpose?

I want to deploy an [edge-optimized](https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-endpoint-types.html#api-gateway-api-endpoint-types-edge-optimized) API Gateway with a custom domain name.

## The tool to build it?

My infrastructure background led me to CloudFormation when I started on AWS. Where some developers can start with SST, ServerlessFramework, or CDK.
In the serverless world, I use SAM (Serverless Application Model).

## Problem?
To deploy an Edge API Gateway, it's [mandatory to generate a certificate in us-east-1](https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-custom-domains.html#edge-optimized-custom-domain-names).
The problem with CloudFormation is that resources in one stack are deployed in a single region. We are not able to set another region for a specific resource.
**_Example:_** Create a Certificate with ACM (AWS Certificat Manager) in us-east-1.

## How to solve it?
From this statement, we have multiple options to choose from:

1. To create a dedicated stack for the certificate in us-east-1, and use the certificate in our main stack, for me in eu-west-1.
2. To create a unique stack (in eu-west-1) and use CloudFormation custom resources to handle certificate creation in us-east-1.

To learn more about CloudFormation custom resources, you can check out [this workshop](https://mng.workshop.aws/cloudformation/customresource.html).

## Why the first option?

I chose the first option for simplicity and maintainability. Custom resources expand CloudFormation but I love to keep things simple. That means not creating too many resources via custom resources.

I will use custom resources in my solution to "GET" some values (not creating anything).

## Stack
Prerequisites:
- Having your Route53 zone in the same AWS Account.

**Architecture**
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfa45xba7agnflttn0zj.png)

Let's go and Build !!!

**1/ As you can see in the diagram above, the first step is to create the "certificate.yaml" file.**

To create an ACM certificate on AWS with DNS as  DomainValidationOptions, we need to provide the DomainName and the HostedZoneId. CloudFormation does not get the HostedZoneId dynamically.

I made a custom resource for a dynamic approach, not hardcoded. AWS should provide the support of DomainName only.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1h15wzjh7yvppaqqcuxa.png)

To get the ARN of this certificate from the other stack I store it in a ParameterStore.
```
 CertificateARN:
    Type: "AWS::SSM::Parameter"
    Properties:
      Name: !Ref ACMCertificate
      Type: "String"
      Value: !Ref Certificate
```

**2/ Deploy the main stack with the template named "template.yaml".**
Now we need to deploy the main stack, our EDGE API Gateway. We need to get the certificate we created in Step 1 and the HostedZoneId for our domain. To do this we will create a second custom resource.
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/llr6abctoiflfkk1uz26.png)

The stack described in this article is available on my [GitHub](https://github.com/wbattou/edge-api-gateway-custom-domain) if you want to test or reuse it.