Source Allies Logo

Sharing Our Passion for Technology

& Continuous Learning

<   Back to Blog

Node Reference - HTTPS

Teammates sitting together and looking at code

Prerequisites

This article builds on the prior article: Node Reference - HTTPS/DNS{:target="_blank"}.

HTTPS and DNS

In this post we are going to add a friendly DNS address that can be used to invoke our service so that clients do not have to use the auto-generated AWS load balancer name. We will also need to generate a signed SSL certificate so that the traffic to this endpoint can be served over HTTPS.

AWS has the ability to manage DNS records via Route 53{:target="_blank"}. Route 53 can automatically resolve DNS requests to our Application Load Balancer. It also has the ability to check the health of our application endpoint and route requests based on geographic proximity. All of this functionality can be managed through our Cloudformation template.

To start, add these parameters{:target="_blank"} to your cloudformation.template.yml:

BaseDomain:
  Type: String
  Description: Domain name to place this application under as a subdomain
Subdomain:
  Type: String
  Description: Subdomain to deploy this app to

Now we can add a Route 53 Record Set{:target="_blank"} resource to your Resources section:

DNSRecord:
  Type: AWS::Route53::RecordSet
  Properties:
    HostedZoneName: !Sub '${BaseDomain}.'
    Name: !Sub '${Subdomain}.${BaseDomain}'
    Type: A
    AliasTarget:
      HostedZoneId: !GetAtt 'LoadBalancer.CanonicalHostedZoneID'
      DNSName: !GetAtt 'LoadBalancer.DNSName'

Also, change these occurrences (shown below) of port 80 to 443 and of HTTP to HTTPS:

  LBListener:
    Type: AWS::ElasticLoadBalancingV2::Listener
      ...
      Port: 443
      Protocol: HTTPS

Finally, in your parameters/dev.params.json and parameters/prod.params.json add the BaseDomain and Subdomain parameters. Your parameter files should now look something like this:

{
  "Parameters": {
    "VpcId": "vpc-65axx202",
    "SubnetIds": "subnet-7d6xxxb,subnet-d8xxxxx",
    "Subdomain": "products",
    "BaseDomain": "example.com",
    "Image": "RELEASE_IMAGE_URL"
  }
}

Certificate generation

Before we can push our changes, a certificate must be specified for HTTPS load balancer listeners.

AWS is able to generate and publicly sign SSL certificates via the Certificate Manager{:target="_blank"}. As with our Route53 resource, we can also configure our new certificate entirely via Cloudformation. You can add your certificate resource to your cloudformation.template.yml as shown below:

Certificate:
  Type: AWS::CertificateManager::Certificate
  Properties:
    DomainName: !Sub '${Subdomain}.${BaseDomain}'
    DomainValidationOptions:
      - DomainName: !Sub '${Subdomain}.${BaseDomain}'
        ValidationDomain: !Ref BaseDomain

AWS Certificate Manager can use two methods to verify that you own the domain name you are attempting to generate a certificate for:

It can send a validation email to one of the Validation Addresses{:target="_blank"} on either the domain or a superdomain of the domain. Cloudformation will wait to complete the deployment until the confirmation link is clicked in the email. This is the mechanism we are using above.

(AWS can also use a CNAME record to validate the certificate, although this mechanism is not yet available via Cloudformation{:target="_blank"}.)

Lastly, we need to tell our AWS::ElasticLoadBalancingV2::Listener{:target="_blank"} to serve this certificate by adding the following Certificates property to your Listener:

LBListener:
  Type: AWS::ElasticLoadBalancingV2::Listener
  DependsOn:
    - LoadBalancer
    - TargetGroup
  Properties:
    DefaultActions:
      - Type: forward
        TargetGroupArn: !Ref TargetGroup
    LoadBalancerArn: !Ref LoadBalancer
    Port: 443
    Protocol: HTTPS
    Certificates:
      - CertificateArn: !Ref Certificate

Finally, commit and push your changes to cloudformation.template.yml.

After deploying the template, making a request to your configured domain name (i.e. https://theproducts.sourceallies.com{:target="_blank"}) will resolve and you'll see your new SSL certificate in use.

That is all there is to it. We now have a custom subdomain for our service and a publicly valid certificate. The certificate is automatically created as part of the deployment and will be automatically renewed for us prior to the expiry date. See the changes we made here{:target="_blank}.

Table of Contents

If you have questions or feedback on this series, contact the authors at nodereference@sourceallies.com.