Managing your PKI using AWS Certificate Manager

Deep
7 min readDec 8, 2020

PKI (Public Key Infrastructure)

PKI is a framework that is used to encrypt the public keys and include their affiliated crypto-mechanisms. Now a days, many organizations rely on PKI to manage security through encryption. Mostly the encryption used through PKI is asymmetric encryption, which involves two keys public and private key, where anyone can use the public key to encrypt the data and whoever owns the private key can decrypt the encrypted data. We are using PKI to verify devices, websites, services etc…

Common examples of PKI today are SSL Certificates on websites. SSL Certificates ensures that the visitors are actually accessing the intended website and not the malicious website. We can use PKI for public websites and also for our internal website/internal services. In this blog, we will focus on how we manage our PKI for internal websites/services like AWS Load balancers, S3 endpoints, API Gateways etc…

Traditional way of managing internal PKI is bit complex, since we have to create our own Root certificate, Intermediate certificate and issue certificates for all our services. Rotating and managing each and every certificate is a tedious process. AWS Certificate Manager provides support to manage our own PKI on Cloud, where all the manual work will be taken care by AWS itself. Let’s see the workflow of the PKI below.

Workflow

PKI with AWS ELB

In this blog, we are going to create our own Root CA, Intermediate CA and provision SSL Certificates for our (internal) DNS record which is pointing to the ELB DNS and we will see how AWS automatically renews our certificate. Below are the AWS Services we used,

  1. ELB — Application Load Balancer.
  2. EC2 installed with Nginx/Apache.
  3. AWS Certificate Manger.
  4. Route 53 — Private domain.

Let’s go in detail on how we configure everything.

Create Root CA and Intermediate CA Certificates

On ACM, go to private CA and create CA.

Fill in your details, only Common Name(CN) field is mandatory.

Add required tags if needed.

This is the place where you authorize ACM to use this CA Certificate to create private certificates for our application/services.

Finally review everything and create the Root certificate. Now you will be automatically redirected to configure few parameters for our Root CA. I chose the validity as 10 years and SHA256withRSA algorithm.

And review the parameters and create the CA. This is going to be our Root CA certificate. And you can now see the same in ACM portal.

Next, we are going to create Intermediate CA using our Root CA. This time we are using Subordinate CA.

Follow the same process as we used to create our Root CA Certificate. Once you provisioned the intermediate CA, set the certificate parameters. We are going to point our Root CA Certificate as Parent private CA and I set the validity as 5 years. If you want more Intermediate CA’s you can achieve it using path length variable.

Review and create Intermediate certificate as well.

Now provision your private certificates using our newly created CA certificate. Go to ACM — Certificate Manger — Request a private Certificate.

Provision your certificates in few clicks!

Now we need to choose our CA, whatever the CA we select will be used to provision our certificate. Here, I am selecting the subordinate CA (i.e. intermediate CA). Since we used our Root CA to provision Intermediate CA, by selecting Intermediate CA we create the following chain of trust with Root CA — Intermediate CA — Private Certificates.

Enter your domain name.

shoppingapp.com is the internal domain I created in Route 53.

Optionally add tags if you want. Then review and provision the certificate.

That’s it! We have provisioned our private certificate using our own Root CA and Intermediate CA.

For this example, I provisioned an EC2 instance and installed Nginx. No configuration is touched in Nginx. On Route 53, I have created a local zone named shoppingapp.com.

On to the Load Balancer now

Create your internal application load balancer now.

When you navigate to next page, AWS automatically populate our ACM certificate here. Just select the correct certificate and proceed. There is only one certificate for me, nothing much to do here.

Next configure security group allow port 80 and 443 from everywhere and outbound to all.

Register your target nodes, I just have one node to register, then review and provision your ALB.

Let’s look at the ALB Listeners now.

Our Load balancer listens on both http and https port (80 and 443 respectively) and forwards both traffic to target group. In target group we have a single EC2 instance with Nginx installed and Nginx listening on port 80. Health check is also configured on port 80.

User access — http://app.shoppingapp.com — Route 53 resolves to ALB DNS — ALB listens on port 80 and sends traffic to TG (app-shoppingapp-tg) — EC2 where Nginx is running. And the same flow happens to https request also.

We need to force http requests also to redirect to https. View/edit rules the http listener, delete the forward to target group and add redirect to https and update.

Now everything is configured, let’s verify it. Curl request clearly says the what we configured on http listener rule.

~$ curl app.shoppingapp.com
<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
</body>
</html>

Now the modified workflow is,

User access → http://app.shoppingapp.com → Route 53 resolves to ALB DNS → ALB listens on port 80 and forwards traffic to https on port 443 with 301 http code → ALB listens on port 443 also and sends traffic to TG (app-shoppingapp-tg) → EC2 where Nginx is running. And the same flow happens to https request also.

SSL termination happens in the ALB and all the backend connection (from ALB to EC2) will use http port.

Accessing in a web browser redirects me to the https url as well. Let’s look at the certificate now.

My website app.shoppingapp.com is signed by Shoppingapp-Subordinate CA (which is our Intermediate CA) which is signed by Shoppingapp-Root (Root CA). This is how our chain of trust looks like. I already added my Root cert to the browser trusted store, so I don’t get any warning here. Just add the Root Certificate trusted store on your organization, all your certificates created from the Root CA will be automatically trusted.

Closing Notes

This is pretty easy way to move your PKI to AWS completely. AWS automatically renews your certificates and there is ideally very less maintenance required from your end. You can use certificates for all your internal services, websites. There are several ways you leverage the use of ACM, in case you have multiple AWS accounts configured in AWS Organizations, create a Root CA on Root AWS account and share it across to all accounts, so that the sub accounts holders can create their Intermediate certificate out of the shared Root CA and provision the private certificates for their services. In the upcoming part 2, we will see how we share ACM Root CA and use it in other AWS account and how to secure Root/Intermediate CA Certificates using AWS IAM policies.

--

--