<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Conor Maher</title>
    <description>The latest articles on DEV Community by Conor Maher (@conzy).</description>
    <link>https://dev.to/conzy</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F277490%2F1a7335b9-84f3-4cc3-b44d-2627f2575859.jpeg</url>
      <title>DEV Community: Conor Maher</title>
      <link>https://dev.to/conzy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/conzy"/>
    <language>en</language>
    <item>
      <title>How to update your terraformed RDS / Aurora certificates</title>
      <dc:creator>Conor Maher</dc:creator>
      <pubDate>Wed, 15 Jan 2020 00:42:22 +0000</pubDate>
      <link>https://dev.to/conzy/how-to-update-your-terraformed-rds-aurora-certificates-3dnl</link>
      <guid>https://dev.to/conzy/how-to-update-your-terraformed-rds-aurora-certificates-3dnl</guid>
      <description>&lt;p&gt;This post was prompted by Jeff Barr's recent &lt;a href="https://aws.amazon.com/blogs/aws/urgent-important-rotate-your-amazon-rds-aurora-and-documentdb-certificates" rel="noopener noreferrer"&gt;Urgent &amp;amp; Important blog post&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you use RDS or Aurora you have probably received an email with this subject recently:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important Reminder: Update Your Amazon RDS SSL/TLS Certificates by February 5, 2020&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you operate many AWS accounts or have put this change on the back burner your inbox might look like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1e3g5alim676ge8ery2t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1e3g5alim676ge8ery2t.png" alt="Lots of emails"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I was a bit concerned when I first saw this communication in October. A &lt;em&gt;lot&lt;/em&gt; more people are now concerned as the deadline is looming and the AWS social media / email campaign has ramped up. You even have to dismiss a modal upon logging in to AWS RDS Console at the minute to acknowledge these changes!&lt;/p&gt;

&lt;h2&gt;
  
  
  Does this affect you?
&lt;/h2&gt;

&lt;p&gt;The first thing you have to do is figure out if this issue affects you. If you don't make SSL connections to your database this issue probably doesn't affect you.&lt;/p&gt;

&lt;p&gt;If you use &lt;a href="https://aws.amazon.com/premiumsupport/knowledge-center/users-connect-rds-iam/" rel="noopener noreferrer"&gt;IAM Database Authentication&lt;/a&gt; this definitely affects you!&lt;/p&gt;

&lt;p&gt;The first thing to do is to update your application to support the new certificate.&lt;/p&gt;

&lt;h2&gt;
  
  
  Update your Application
&lt;/h2&gt;

&lt;p&gt;Note: &lt;em&gt;If you do not have some kind of sandbox / staging environment it is worth spinning up an RDS / Aurora cluster with your existing terraform code so you can test all this safely&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;There are 100s of possible languages / clients you may be using to interact with RDS, so this part is up to you. I will give a lowest common denominator example in Bash towards the end of this post. But you need to update the certificate you use to connect to RDS.&lt;/p&gt;

&lt;p&gt;AWS have updated their combined ca bundle to include both the old and new certificate to avoid a chicken and egg scenario. i.e the &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;rds-ca-2015-root.pem&lt;/code&gt; will only work with RDS instances configured to use the old 2015 certificate&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;rds-ca-2019-root.pem&lt;/code&gt; will only work with RDS instances configured to use the new 2019 certificate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By using the &lt;code&gt;rds-combined-ca-bundle.pem&lt;/code&gt; certificate in our application we can update the underlying RDS certificate without issue. Those certificates are available in S3. Links as well as additional documentation are available in the &lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html" rel="noopener noreferrer"&gt;official AWS Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Terraform Changes
&lt;/h2&gt;

&lt;p&gt;Typically when I get a notification like this from AWS my initial thought is "I hope I can achieve this with Terraform" I have found when you start using Infrastructure as Code you want every single change to be orchestrated by that tool. Out of bounds changes feel dirty and you want everything to be driven by version controlled code. &lt;/p&gt;

&lt;p&gt;Both the &lt;code&gt;aws_db_instance&lt;/code&gt; and &lt;code&gt;aws_rds_cluster_instance&lt;/code&gt; resources support the &lt;code&gt;ca_cert_identifier&lt;/code&gt; argument. You can update each resource to have the &lt;code&gt;ca_cert_identifier&lt;/code&gt; argument. You probably want to expose this as a variable so that other consumers of this module have a choice. You may still be responsible for this code in 5 years when the 2024 cert is rolled out!&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_db_instance"&lt;/span&gt; &lt;span class="s2"&gt;"db"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;# truncated for brevity&lt;/span&gt;
  &lt;span class="nx"&gt;tags&lt;/span&gt;                    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.tags}"&lt;/span&gt;
  &lt;span class="nx"&gt;apply_immediately&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.apply_immediately}"&lt;/span&gt;
  &lt;span class="nx"&gt;ca_cert_identifier&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.ca_cert_identifier}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let's update our variable to &lt;code&gt;rds-ca-2019&lt;/code&gt; so that our &lt;code&gt;aws_rds_cluster_instance&lt;/code&gt; resource is configured to use the new certificate.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"ca_cert_identifier"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"rds-ca-2019"&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Allows you to modify the underlying RDS certificate"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We can now run a &lt;code&gt;terraform plan&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;At the point you may get an error like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;Error&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;your_module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_db_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"ca_cert_identifier"&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;field&lt;/span&gt; &lt;span class="nx"&gt;cannot&lt;/span&gt; &lt;span class="nx"&gt;be&lt;/span&gt; &lt;span class="nx"&gt;set&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Thats because you write best practices terraform and have pinned your provider version! &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 1.52"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.aws_region}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Your current provider does not have support for updating the &lt;code&gt;ca_cert_identifier&lt;/code&gt;. We pin terraform providers for the same reason we pin software libraries. To avoid breaking changes and other surprises from upstream. Typically you can head to the GitHub repo for the AWS provider and find out A) If what you are trying to do is supported. B) What provider version it was introduced in.&lt;/p&gt;

&lt;p&gt;In this case (and most cases) the provider maintainers are on top of things and support for updating the certificate was introduced in &lt;code&gt;v2.37.0&lt;/code&gt; of the provider. We can simply bump our minimum provider version&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"aws"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~&amp;gt; 2.37"&lt;/span&gt;
  &lt;span class="nx"&gt;region&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${var.aws_region}"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Lets do another plan. &lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;your_module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_db_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;
    &lt;span class="nx"&gt;ca_cert_identifier&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="s2"&gt;"rds-ca-2015"&lt;/span&gt; &lt;span class="err"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"rds-ca-2019"&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now we get the expected plan. &lt;/p&gt;

&lt;p&gt;However this change would not be applied immediately. Many changes to RDS resources are applied at the next maintenance window. Depending on the workload this may be the desired approach. We can run &lt;code&gt;terraform apply&lt;/code&gt;&lt;br&gt;
and make the change. &lt;/p&gt;

&lt;p&gt;You may notice that if you do another &lt;code&gt;plan&lt;/code&gt; it looks like our change did nothing. That's because the certificate won't be changed until a reboot during the maintenance window. To verify our work we can use the aws cli&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws rds describe-db-instances --db-instance-id your-db-identifier | jq '.DBInstances[].PendingModifiedValues'


{
  "CACertificateIdentifier": "rds-ca-2019"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Here we can see this instance has pending modifications.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applying immediately
&lt;/h3&gt;

&lt;p&gt;In this particular case I want to make the change immediately so I can make a connection from my client and ensure the certificate chain works as expected&lt;/p&gt;

&lt;p&gt;I recommend exposing an &lt;code&gt;apply_immediately&lt;/code&gt; variable on modules that create RDS resources.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"apply_immediately"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Should modifications be applied immediately? Otherwise they are applied at next maintenance window"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;It has a sensible default of &lt;code&gt;false&lt;/code&gt;, but we still have the flexibility to apply changes immediately. In a production environment maybe somebody else on your team has to approve a Pull Request to make this change and your PR body would explain your rationale for the change. After the change is made you would set &lt;code&gt;apply_immediately&lt;/code&gt; back to &lt;code&gt;false&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;After setting our &lt;code&gt;apply_immediately&lt;/code&gt; variable to &lt;code&gt;true&lt;/code&gt; our plan looks like this:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;

&lt;span class="err"&gt;~&lt;/span&gt; &lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;your_module&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;aws_db_instance&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;db&lt;/span&gt;
    &lt;span class="nx"&gt;apply_immediately&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;    &lt;span class="s2"&gt;"false"&lt;/span&gt; &lt;span class="err"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt;
    &lt;span class="nx"&gt;ca_cert_identifier&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;   &lt;span class="s2"&gt;"rds-ca-2015"&lt;/span&gt; &lt;span class="err"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"rds-ca-2019"&lt;/span&gt;

&lt;span class="nx"&gt;Plan&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;add&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;change&lt;/span&gt;&lt;span class="err"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nx"&gt;to&lt;/span&gt; &lt;span class="nx"&gt;destroy&lt;/span&gt;&lt;span class="err"&gt;.&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;For me this apply took 90 seconds. The RDS instance rebooted and now has the new certificate.&lt;/p&gt;

&lt;p&gt;Bash example of connecting to an RDS instance with SSL and IAM authentication. The following code should work before and after your certificate upgrade&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;

wget https://s3.amazonaws.com/rds-downloads/rds-combined-ca-bundle.pem
&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;aws rds generate-db-auth-token &lt;span class="nt"&gt;--hostname&lt;/span&gt; the_host &lt;span class="nt"&gt;--port&lt;/span&gt; 3306 &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1 &lt;span class="nt"&gt;--username&lt;/span&gt; db_user&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
mysql &lt;span class="nt"&gt;-h&lt;/span&gt; the_host &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3306 &lt;span class="nt"&gt;--ssl-ca&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;rds-combined-ca-bundle.pem &lt;span class="nt"&gt;--enable-cleartext-plugin&lt;/span&gt; &lt;span class="nt"&gt;-u&lt;/span&gt; db_user &lt;span class="nt"&gt;--password&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="s2"&gt;"


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;I hope this helps anyone that has terraformed RDS workloads.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>terraform</category>
      <category>rds</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
