Amazon Web Services|Blog|How To|SSL

AWS Certificate Manager

AWS Certificate Manager

Today we are going to take a look at another one of my favorite services.  AWS Certificate Manager. In this exploration we are going to be interacting with JSON which Powershell makes more difficult then it ought to.  So please keep in mind that if you are using the AWS CLI on bash or cygwin or similar your mileage will vary (especially where it comes to parsing and generating JSON).  Our goal is to be able to walk all the way through the certificate issuance process, including validation.

This process includes some changes to DNS so if you are using Route 53 please refer back to our previous article in this series on Scalable Solutions – Amazon Route 53 Basics.

Before we dive in lets talk about why AWS Certificate Manager.  The primary reason for ACM is that it allows us to no longer worry about certificate expiration, which is a huge benefit.  Now, this is a huge benefit which actually causes a significant downside at the same time. The biggest drawback to ACM is that we can only deploy these certs to AWS controlled resources which are exclusively managed by AWS, such as Elastic Load Balancers, Cloudfront Distributions, and API Gateways.  Since they control the infrastructure they can seamlessly issue and replace certificates as needed, thus no expiration headaches.

Requesting a Certificate

Now like any certificate infrastructure you will need to request a certificate.  Remember that when you are issuing certs you must account for all domain names that will be used when accessing the site or you will receive browser errors.

$ aws acm request-certificate –domain-name [ domain-name ] –validation-method [ EMAIL | DNS ] –subject-alternative-names [ domain-name1 domain-name2 ] –domain-validation-options DomainName=[ url ],ValidationDomain=[ domain ]

Here we are bringing up a new server named monkey.itfromallangles.com which will require a certificate to serve HTTPS traffic.  We don’t have any alternative names, also we have specified some domain-validation-options, these are only necessary for EMAIL based validation methods.

PS&gt; aws acm request-certificate –domain-name monkey.itfromallangles.com –validation-method DNS –domain-validation-options DomainName=monkey.itfromallangles.com,ValidationDomain=itfromallangles.com<br />

{<br />

&quot;CertificateArn&quot;: &quot;arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659&quot;<br />

}

Now pay attention to the certificate arn, this will be needed later.

Describing a Certificate

Now lets take a look at the certificate we created earlier.  Notice that the ValidationStatus is PENDING_VALIDATION and the element below that which indicates the ResourceRecord which the validation engine will be checking for.  You can manually create this in your DNS zone.

PS&gt; aws acm describe-certificate –certificate-arn arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659<br />

{<br />

&quot;Certificate&quot;: {<br />

&quot;CertificateArn&quot;: &quot;arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659&quot;,<br />

&quot;Status&quot;: &quot;PENDING_VALIDATION&quot;,<br />

&quot;SubjectAlternativeNames&quot;: [<br />

&quot;monkey.itfromallangles.com&quot;<br />

],<br />

&quot;DomainName&quot;: &quot;monkey.itfromallangles.com&quot;,<br />

&quot;InUseBy&quot;: [],<br />

&quot;KeyUsages&quot;: [],<br />

&quot;DomainValidationOptions&quot;: [<br />

{<br />

&quot;ValidationStatus&quot;: &quot;PENDING_VALIDATION&quot;,<br />

&quot;ResourceRecord&quot;: {<br />

&quot;Type&quot;: &quot;CNAME&quot;,<br />

&quot;Name&quot;: &quot;_b10e7b9a64be4d8215455f6d73369fd4.monkey.itfromallangles.com.&quot;,<br />

&quot;Value&quot;: &quot;_faabe6071c86f5d4357ea668e9b0105b.acm-validations.aws.&quot;<br />

},<br />

&quot;ValidationMethod&quot;: &quot;DNS&quot;,<br />

&quot;DomainName&quot;: &quot;monkey.itfromallangles.com&quot;<br />

}<br />

],<br />

&quot;KeyAlgorithm&quot;: &quot;RSA-2048&quot;,<br />

&quot;SignatureAlgorithm&quot;: &quot;SHA256WITHRSA&quot;,<br />

&quot;Type&quot;: &quot;AMAZON_ISSUED&quot;,<br />

&quot;ExtendedKeyUsages&quot;: [],<br />

&quot;CreatedAt&quot;: 1530283403.0,<br />

&quot;Subject&quot;: &quot;CN=monkey.itfromallangles.com&quot;<br />

}<br />

}

Retrieve Validation Record Details from ACM

Here we are going to retrieve the record details for easier creation of the record.

PS&gt; $record = (aws acm describe-certificate –certificate-arn arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659 | ConvertFrom-Json).Certificate.DomainValidationOptions.ResourceRecord

Lets take a look at what we have.

PS&gt; $record.name<br />

_b10e7b9a64be4d8215455f6d73369fd4.monkey.itfromallangles.com.<br />

PS&gt; $record.value<br />

_faabe6071c86f5d4357ea668e9b0105b.acm-validations.aws.<br />

PS&gt; $record.type<br />

CNAME

We will use these in the next section.

Build Change Set for Validation Record

Here we are going to create a temporary file in your TEMP directory that will create the record you need to see.

PS&gt; @{<br />

Changes = @(<br />

@{<br />

Action = ‘UPSERT'<br />

ResourceRecordSet = @{<br />

Name = $record.Name<br />

Type = $record.Type<br />

TTL = 300<br />

ResourceRecords = @(<br />

@{<br />

Value = $record.Value<br />

}<br />

)<br />

}<br />

})<br />

} | ConvertTo-Json -Depth 5 -Compress | Out-File $env:TEMP\route53change.json -Encoding ASCII

This is really where Powershell does the opposite of shining, the hoops you have to jump through to make this JSON usable is ridiculous.

Create Change Resource Record Sets Request in Route 53

The command below takes the file that we have created and applies it against the hosted zone which matches itfromallangles.com

PS&gt; aws route53 change-resource-record-sets –hosted-zone-id ((aws route53 list-hosted-zones | ConvertFrom-Json).&quot;HostedZones&quot; | where { $_.Name -eq &quot;itfromallangles.com.&quot; }).Id –change-batch file://$env:TEMP\route53change.json<br />

{<br />

&quot;ChangeInfo&quot;: {<br />

&quot;Status&quot;: &quot;PENDING&quot;,<br />

&quot;SubmittedAt&quot;: &quot;2018-06-29T17:08:12.448Z&quot;,<br />

&quot;Id&quot;: &quot;/change/C1QOL63X6O24IZ&quot;<br />

}<br />

}

We will need the change id to check the status of the zone update.  As we can see above it is PENDING.

Check Change Status

This allows us to check the status of a given changeset.

PS&gt; aws route53 get-change –id C1QOL63X6O24IZ<br />

{<br />

&quot;ChangeInfo&quot;: {<br />

&quot;Status&quot;: &quot;INSYNC&quot;,<br />

&quot;SubmittedAt&quot;: &quot;2018-06-29T17:08:12.448Z&quot;,<br />

&quot;Id&quot;: &quot;/change/C1QOL63X6O24IZ&quot;<br />

}<br />

}

We are looking for it to say INSYNC.

Check Certificate Status

Now that we have DNS updated we can check the certificate’s validation status.

PS&gt; (aws acm describe-certificate –certificate-arn arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659 | ConvertFrom-Json).Certificate.DomainValidationOptions.ValidationStatus<br />

PENDING_VALIDATION

Not yet, lets give it some more time.

PS&gt; (aws acm describe-certificate –certificate-arn arn:aws:acm:us-east-1:112233445566:certificate/612c35e2-f8b5-49ac-8f20-246e851c0659 | ConvertFrom-Json).Certificate.DomainValidationOptions.ValidationStatus<br />

SUCCESS

SUCCESS that is what we were waiting for, this certificate can now be associated with our resources.

News & Insights