Thomas Cheng
Thomas Cheng

Reputation: 715

AWS CloudFormation - Add New Certificate to an existing listener

What I have is one platform stack, and possibly multiple web application stacks (each represent one web application). The platform stack deploys an ECS platform that allows hosting multiple web applications, but doesn't actually have any web applications. It's just a platform. Then, each web application stack represents a web application.

One of the HTTPS listeners I have in my platform stack template is this. Basically I have an HTTPS listener on port 443, and will carry one default certificate (by requirement you will need at least one certificate to create https listener):

"BsAlbListenerHttps": {
  "Type": "AWS::ElasticLoadBalancingV2::Listener",
  "Properties": {
    "Certificates": [{
      "CertificateArn": {
        "Ref": "BsCertificate1"
      }
    }],
    ...
    "Port": "443",
    "Protocol": "HTTPS"
  }
},
...

Now, let's say if I want to create a new web application (eg. www.example.com), I deploy the web application stack, specify some parameters, and obviously, I'll have to make a bunch of new resources. But at the same time, I will have to modify the current "BsAlbListenerHttps".

I'm able to import the current listener (using Imports and Exports) into my web application stack. But what I want to do is also add a new certificate for www.example.com to the listener.

I've tried looking around but failed to find any answer.

Does anyone know how to do this? Your help is appreciated. Thank you!

Upvotes: 5

Views: 3828

Answers (1)

Rodrigo Murillo
Rodrigo Murillo

Reputation: 13648

What I do in similar cases, is to use only one certificate for the entire region, and add domains to it as I add apps/listeners that are on different domains. I also do this per environment, so I have a staging cert and a production cert in 2 different templates. But for each you would define a standalone cert stack, called for example, certificate-production.json, but use the stack name as 'certificate' so that regardless of the environment, the stack reference is consistent:

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "SSL certificates for production V2",

  "Resources" : {
    "Certificate" : {
      "Type": "AWS::CertificateManager::Certificate",
      "Properties": {
        "DomainName": "*.example.com",
        "SubjectAlternativeNames" : [ "*.example2.com","*.someotherdomain.com" ]
      }
    }
  },

  "Outputs": {
    "CertificateId" : {
        "Value" : {"Ref":"Certificate"},
        "Description" : "Certificate ID",
        "Export" : {  "Name" : {"Fn::Sub": "${AWS::StackName}-CertificateId" }} 
    }
  }  
}

As you can see by using the SubjectAlternativeNames property, this certificate will serve 3 wild card domains. This way I can update the domains as I add services, and rerun the stack. The dependent listeners are not changed in anyway - they always refer to the single app certificate in the region.

One caveat: When you update a cert in CloudFormation, it will email all host administrtors on the given domain ([email protected] etc.). Each domain will get a confirmation email, and each email has to be confirmed again. If all the domains are not confirmed in this way, then the stack will fail to create/update.

Using this technique, I can manage SSL for all my apps without any trouble, while making it easy to add new ssl endpoints for new domains.

I create the certificate stack right after the main VPC stack, so all later stacks can refer to the certificate id defined here via an export.

Upvotes: 1

Related Questions