はじめに

AWSユーザーの間で、Amazon RDSのSSL証明書の有効期限が近づいてきた件が最近話題になっています。

自分の業務でもRDSを使用していたため、この件について検討する必要がありました。
ただ、証明書について改めて勉強しなおしたり、そもそも更新する必要があるのかなど、考えることが結構多いように感じました。

おそらく同じような状況にある方が多いと思うので、この記事では主に以下を記載します。

  • そもそも今回の事象は何なのか
  • 更新作業の影響はどれほどなのか
  • Terraformを使用した証明書の更新手順はどうなるのか

逆に以下のようなことは記載しません。

  • 証明書についての基礎知識(SSL証明書とは?CAとは?)
  • RDS、Aurora Serverless v2 についての基礎知識

今回の事象の概要説明

RDSのSSL証明書の有効期限が近づいている方には、RDSのコンソール画面に以下のような表示が出てくるはずです。

詳細については、以下の公式ドキュメントに記載されています。
https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html

公式ドキュメントの内容を踏まえて、今回の事象をざっくり説明するとこんな感じです。

  • 対象となるのは、RDSと RDSに接続してくるアプリケーションの間で使用されるSSL証明書
  • 現在デフォルトに設定されているrds-ca-2019という証明書は、2024年に期限切れになる
  • rds-ca-2019は自動ローテーションもサポートされていないため、証明書の切り替え作業が必要
  • 他の証明書にはrds-ca-rsa2048-g1rds-ca-rsa4096-g1rds-ca-ecc384-g1の3種類があるが、rds-ca-2019からの更新であればrds-ca-rsa2048-g1がオススメ

rds-ca-rsa2048-g1が推奨されている理由ですが、アルゴリズムが同じだからだと推測されます。
暗号化アルゴリズムが変わってしまうと、アプリケーションの処理でトラブルが起こる可能性があるためだと思います。(あくまでも個人的な推測です)

なお、rds-ca-rsa2048-g1rds-ca-rsa4096-g1rds-ca-ecc384-g1はいずれも自動ローテーションがサポートされています。
rds-ca-2019は有効期限が近いですし、自動ローテーションもサポートされてないので今後使う理由はあまりないと思います。

更新作業時の影響

作業範囲の確認

ここまで読んだところで、更新作業にどれだけ稼働を取られるのか途方に暮れる方もいるかと思いますが、実はRDSの使い方によって影響範囲が変わってきます。

まず前提として、RDS ProxyかAurora Serverlessのどちらかを使用している場合には、アプリケーション側での更新作業は不要です。

Amazon RDS Proxy および Aurora Serverless は AWS Certificate Manager (ACM) の証明書を使用します。RDS Proxy を使用している場合は、SSL/TLS 証明書を更新するときに、RDS Proxy 接続を使用するアプリケーションを更新する必要はありません。
(中略)
Aurora Serverless である場合は、SSL/TLS 証明書を更新する必要はありません。

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/UsingWithRDS.SSL-certificate-rotation.html

「じゃあ何もしなくていいのか!やったぜ!」と思った方、一回落ち着いてRDSのコンソール画面をちゃんと見てみましょう。

何もしないで放置していると、メンテナンスウィンドウを使って自動的(≒強制的)に更新されると書かれています。
つまり、アプリケーション側での更新作業が不要であっても、RDSそのものの証明書の切り替えは必要であるということです。

RDSの再起動

RDSの設定変更となると、気になるのは再起動やセッションの切断が発生するのかどうかです。
メンテナンスウィンドウを設定していればあまり気にせずともいいのですが、一度確認しておきましょう。

この点について調査していると、関連しそうな記載が公式ドキュメントにありました。

和訳:
AWS CLI を使用している場合は、 describe-certificatesコマンドを使用して、アカウントで利用可能な CA を確認できます。ValidTillこのコマンドは、出力に各 CA の有効期限も表示します。description-db-engine-versionsコマンドを使用すると、特定の DB エンジンおよび DB エンジン バージョンで利用可能な CA を見つけることができます。
(中略)
DB エンジンのバージョンが再起動なしで証明書のローテーションをサポートしているかどうかも SupportsCertificateRotationWithoutRestart に出力されます。

https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.SSL.html

describe-db-engine-versionsのリファレンスを確認してみると、確かに証明書のローテーション時の再起動有無についてのパラメーターであることが確認できます。

SupportsCertificateRotationWithoutRestart -> (boolean)
A value that indicates whether the engine version supports rotating the server certificate without rebooting the DB instance.

https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html

ただしここで注意したいのは、SupportsCertificateRotationWithoutRestart証明書のローテーション時の再起動有無であって、証明書の付け替え時の再起動有無ではないと解釈できる点です。

今回実施したいのはローテーションではなく証明書の付け替え作業なので、SupportsCertificateRotationWithoutRestartとは別だと思われます。

では、証明書の付け替え作業での再起動の要否の確認ですが、これはコンソール上で確認できるようです。

RDSの左のメニューの中から[証明書の更新]をクリックします。
すると以下のような画面が表示されますが、この中の[Restart Required]が再起動要否を示しているようです。

これは推測ですが、おそらく DBエンジンの違いやAuroraかどうかによって再起動要否は変わってくるようです。
なお、後述してる条件(PostgreSQL 15.2、Aurora Serverless v2)では再起動は走っていませんでした。

Terraformでの更新作業

では、実際に証明書の更新をしてみようと思います。
今回は、以前Terraformで構築したAurora Serverless v2を更新していきます。
諸々の前提条件はざっくりとこんな感じです。

  • DBエンジンはPostgres
  • バージョンは15.2
  • 検証なのでシングルAZ構成

まずはTerraformのコードを編集してみます。

今回対象になっているSSL証明書とは、aws_rds_cluster_instanceリソースの中のca_cert_identifierという引数が対応しています。
https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance

以前構築した際にはca_cert_identifierを明示的に定義していなかったので、とりあえず追記してみます。

resource "aws_rds_cluster" "example" {
  cluster_identifier     = "example"
  engine                 = "aurora-postgresql"
  engine_mode            = "provisioned"
  engine_version         = "15.2"
  database_name          = "example"
    :
  (中略)
    :
}

resource "aws_rds_cluster_instance" "example" {
  identifier         = "example"
  cluster_identifier = aws_rds_cluster.example.id
  instance_class     = "db.serverless"
  engine             = aws_rds_cluster.example.engine
  engine_version     = aws_rds_cluster.example.engine_version
    :
  (中略)
    :
  ca_cert_identifier = "rds-ca-rsa2048-g1"
}

これでterraform applyを実行しましたが、なぜか証明書は更新されませんでした。。。

ここで一旦、挙動を確認するためにコンソール画面で作業をしてみます。
まずは対象のDBインスタンスの変更画面に移動し、[認証機関]をrds-ca-2019からrds-ca-rsa2048-g1に変更します。

案内文が出ますが、これはアプリケーション側で証明書を更新してくださいという内容です。なので今回は無視してOKです。

和訳:
CA 証明書のローテーションをスケジュールする前に、新しい CA 証明書を使用するように、データベースに接続するクライアント・アプリケーションを更新してください。これを行わないと、アプリケーションとデータベース間の接続が中断されます。

変更を確定させようとすると、最後に[変更のスケジュール]を聞かれます。
今回はすぐに反映させたいので[すぐに適用]にします。

すると今度は、ちゃんと証明書が更新されました。

ここですでにお気づきの方もいるかもしれませんが、Terraformで変更ができなかったのは[変更のスケジュール]が原因です。

今回のコードでは、apply_immediatelyという引数を明示的に設定していませんでしたが、apply_immediatelyはデフォルトでfalseになっています。
これは「データベースの変更を次のメンテナンス・ウィンドウ中に適用する」という設定を意味します。

apply_immediately – (Optional) Specifies whether any database modifications are applied immediately, or during the next maintenance window. Default isfalse.

https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/rds_cluster_instance#apply_immediately

つまり、最初にterraform applyを実行したときは「メンテナンスウィンドウを待って証明書の切り替えを実施する」という設定になってしまっていたことがわかります。

この引数をtrueに設定すると変更が即時反映される設定になるので、apply_immediately = trueを追加してリトライしてみます。

resource "aws_rds_cluster" "example" {
  cluster_identifier     = "example"
  engine                 = "aurora-postgresql"
  engine_mode            = "provisioned"
  engine_version         = "15.2"
  database_name          = "example"
    :
  (中略)
    :
}

resource "aws_rds_cluster_instance" "example" {
  apply_immediately  = true
  identifier         = "example"
  cluster_identifier = aws_rds_cluster.example.id
  instance_class     = "db.serverless"
  engine             = aws_rds_cluster.example.engine
  engine_version     = aws_rds_cluster.example.engine_version
    :
  (中略)
    :
  ca_cert_identifier = "rds-ca-rsa2048-g1"
}

こうすることで、証明書の更新がちゃんとできることが確認できました!

まとめ

今回はRDSの証明書更新の概要と作業影響について整理した上で、Terraformを使った更新作業の紹介をしました。

今回は検証環境での実施でしたが、実際に更新をする際はサービスへの影響を十分に考える必要があります。
事前の検証やスケジュール調整などをしっかり行なった上で、証明書の更新を実施してください。

その際に、今回の記事が何かの助けになれば幸いです。