AWS 上で利用している SSL/TLS 証明書を一括管理するツール aws-cert-utils を作った話

はじめまして、Kaizen Platform SRE の @tkuchiki です。

本記事では AWS 上で利用している SSL/TLS 証明書(以下、証明書)を一括管理するツールを作成したので紹介いたします。

TL;DR

  • aws-cert-utils を作成して AWS 上で利用している証明書を一括管理できるようにした
  • 証明書の一覧表示、証明書を利用している ALB / CLB / CloudFront の一覧表示も可能
  • aws-cert-utilsを利用し証明書を管理することで、更新・確認作業においてミスが発生しにくくなった

背景

今までの問題点

  • CLB / ALB / CloudFront の証明書更新時に aws cli iam でアップロードした証明書を Management Console から一つひとつ切り替えていた
    • 更新対象が多いので作業に時間がかかる
    • 確認作業も大変

そこで、更新、確認作業を cli で完結し、かつ簡単にするために作ったのが aws-cert-utils です。

aws-cert-utils の使い方

インストール

Go 製なので https://github.com/tkuchiki/aws-cert-utils/releases から zip ファイルをダウンロードして解凍すればインストール完了です。

使い方

aws-cert-utils には iamacmalbelbcloudfront という 5つのコマンドと、それぞれがサブコマンドを持っています。 iamacm が証明書自体の管理、albelbcloudfront がそれぞれのリソースを管理するためのコマンドです。

以降では、それぞれの使い方を説明いたします。

IAM

弊社は ACM リリース前からの名残で一部 IAM で証明書を管理していましたが、 このツールで証明書を入れ替える際に管理を ACM に切り替えました。 ACM は、ACM で発行した証明書を利用する場合だけでなく、独自証明書をインポートして使うこともできます。 独自証明書を使っている場合でも ACM で管理したほうが、

  • Management Console から操作(一覧、インポート、更新、削除)できる
    • IAM は API でしか操作(一覧、作成、更新、削除)ができない
  • API または Management Console から
    • その証明書が使われているか確認できる
    • 証明書の期限を確認できる

というメリットがあります。 そのため、現在 IAM を使っている場合でも証明書更新時に ACM での管理に切り替えるのがおすすめです(もちろん、要件を満たせる場合は ACM が発行した証明書に切り替えるのもよいでしょう)。 ということで、./aws-cert-utils iam (upload|update) の使い方は省略します。

一覧

./aws-cert-utils iam list で IAM の証明書を一覧できます。 --path-prefix=/cloudfront/ のように指定することで、CloudFront 用の証明書だけ表示することも可能です。

$ ./aws-cert-utils iam list
+------------------------------+-----------------------+--------------------------------+-------------------------------------------------------------------------------------+
|             NAME             |          ID           |              PATH              |                                         ARN                                         |
+------------------------------+-----------------------+--------------------------------+-------------------------------------------------------------------------------------+
| test-certificate             | XXXXXXXXXXXXXXXXXXXXX | /                              | arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
| test-cloudfront-certificate  | YYYYYYYYYYYYYYYYYYYYY | /cloudfront/                   | arn:aws:iam::xxxxxxxxxxxx:server-certificate/cloudfront/yyyyyyyyyyyyyyyyyyyyyyyyyyy |
+------------------------------+-----------------------+--------------------------------+-------------------------------------------------------------------------------------+

削除

./aws-cert-utils iam delete で IAM の証明書を削除できます。 以下の例だとわかりにくいですが、https://gopkg.in/AlecAivazis/survey.v1 というライブラリを使っており、一覧から対象を選んで削除することができます(AlecAivazis さん、ありがとうございます)。 https://github.com/AlecAivazis/survey#select に GIF アニメがあるのでぜひ動作例を確認してみてください(クールな見た目です)。

$ ./aws-cert-utils iam delete
? Choose the server certificate you want to delete :  test-certificate
Deleted test-certificate

--name に server certificate name を指定して削除することもできます。

$ ./aws-cert-utils iam delete --name=test-certificate
Deleted test-certificate

ACM

インポート

./aws-cert-utils acm import で ACM に証明書をインポートできます。 --cert-path が証明書ファイルパス、--pkey-path が秘密鍵ファイルパス、--chain-path が中間証明書ファイルパスです。

$ ./aws-cert-utils acm import --cert-path cert.pem --pkey-path key.pem --chain-path ca.pem
Imported arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/zzzzzzzz-zzzz-zzzz-zzzz-zzzzzzzzzzzz

ACM は執筆時点で秘密鍵の長さが 1024 bit ~ 2048 bit でなくてはならないため、それ以上の長さの鍵を指定するとエラーがでます。

$ ./aws-cert-utils acm import --cert-path 4096cert.pem --pkey-path 4096key.pem
2017/11/30 17:58:03 Invalid private key length (4096 bit). AWS supports 1024 and 2048 bit RSA private key

本ツール開発時 IAM にも同様の制限がありましたが、何故かアップロード時にはエラーが出ず、証明書をアタッチしようとしたときにエラーが出るという問題が発生したので、 aws-cert-utils iam upload にも同様の鍵長をチェックする処理を実装しています。

一覧

./aws-cert-utils acm list で ACM の証明書を一覧できます。 前述した、使われているかどうかは IN USE? の列を見るとわかります。

$ ./aws-cert-utils acm list
+------------------------+-----------------+-----------------+---------+-------------------------------+-------------------------------------------------------------------------------------+
|        NAME TAG        |   DOMAIN NAME   | ADDITIONAL NAME | IN USE? |           NOT AFTER           |                                   CERTIFICATE ARN                                   |
+------------------------+-----------------+-----------------+---------+-------------------------------+-------------------------------------------------------------------------------------+
|                        | *.example.com   | example.com     | Yes     | 2019-11-14 02:44:43 +0000 UTC | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+------------------------+                 +                 +         +                               +-------------------------------------------------------------------------------------+
| example.com            |                 |                 |         |                               | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy |
+------------------------+-----------------+-----------------+---------+-------------------------------+-------------------------------------------------------------------------------------+

削除

aws-cert-utils acm delete で ACM の証明書を削除できます。 aws-cert-utils iam delete と同様に選択式の削除と、--arn で ARN を指定する削除の2つの方法があります。

ALB

一覧

./aws-cert-utils alb list で ALB を一覧できます。 --cert に IAM/ACM の証明書の ARN を指定することで、特定の証明書を利用している ALB だけ一覧することも可能です。

$ ./aws-cert-utils alb list
+-----------+------+-------------------------------------------------------------------------------------+
|   NAME    | PORT |                              LISTENER SSL CERTIFICATE                               |
+-----------+------+-------------------------------------------------------------------------------------+
| test-alb  |  443 | arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+
| test2-alb |  443 | arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+

証明書一括更新

./aws-cert-utils alb bulk-update で ALB のリスナーで利用する証明書を更新できます。 --source-cert-arn が更新前の証明書(現在利用している証明書)の ARN で、--dest-cert-arn が更新する証明書の ARN です。 --source-cert-arn で指定した証明書から --dest-cert-arn で指定した証明書に切り替わるということになります。

証明書の入れ替えは、気軽に行うのが少し怖い作業だと思います。 そこで、明示的に --no-dry-run を指定しないと実行されないようになっています。

$ ./aws-cert-utils alb bulk-update --source-cert-arn arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --dest-cert-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# Dry run mode

Updated test-alb:443 arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Updated test2-alb:443 arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

--no-dry-run をつけると、以下のように更新できます。

$ ./aws-cert-utils alb bulk-update --source-cert-arn arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --dest-cert-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --no-dry-run
Updated test-alb:443 arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Updated test2-alb:443 arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

$ ./aws-cert-utils alb list
+-----------+------+-------------------------------------------------------------------------------------+
|   NAME    | PORT |                              LISTENER SSL CERTIFICATE                               |
+-----------+------+-------------------------------------------------------------------------------------+
| test-alb  |  443 | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+
| test2-alb |  443 | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+

ALB だけでなく、CLB、CloudFront も --no-dry-run を指定しないと更新されないようになっています。 一つずつ処理したい場合は ./aws-cert-utils alb update を使えば OK です。

CLB

一覧

./aws-cert-utils elb list で CLB を一覧できます。 --cert に IAM か ACM の ARN を指定することで、特定の証明書を利用している CLB だけ一覧することも可能です。

$ ./aws-cert-utils elb list
+-----------+------+-------------------------------------------------------------------------------------+
|   NAME    | PORT |                              LISTENER SSL CERTIFICATE                               |
+-----------+------+-------------------------------------------------------------------------------------+
| test-elb  |  443 | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+
| test2-elb |  443 | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+

証明書一括更新

./aws-cert-utils elb bulk-update で CLB のリスナーで利用する証明書を更新できます。 --source-cert-arn--dest-cert-arn./aws-cert-utils elb bulk-update と同様です。

$ ./aws-cert-utils elb bulk-update --source-cert-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --dest-cert-arn arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# Dry run mode

Updated test-elb:443 arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Updated test2-elb:443 arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

$ ./aws-cert-utils elb bulk-update --source-cert-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --dest-cert-arn arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx --no-dry-run
Updated test-elb:443 arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Updated test2-elb:443 arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

$ ./aws-cert-utils elb list
+-----------+------+-------------------------------------------------------------------------------------+
|   NAME    | PORT |                              LISTENER SSL CERTIFICATE                               |
+-----------+------+-------------------------------------------------------------------------------------+
| test-elb  |  443 | arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+
| test2-elb |  443 | arn:aws:iam::xxxxxxxxxxxx:server-certificate/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
+-----------+------+-------------------------------------------------------------------------------------+

CloudFront

一覧

./aws-cert-utils cloudfront list で CloudFront の Distribution を一覧できます。 --cert に IAM の Certificate ID か ACM の ARN を指定することで、特定の証明書を利用している Distribution だけ一覧することも可能です。 また、--aliases にドメインを指定することで、特定の Aliases を持つ Distribution だけ一覧できます(ただし、検索条件として複数ドメインを指定することはできません)。

$ ./aws-cert-utils cloudfront list
+-----------------+------------------------------+-----------------------------------------------------------------+
| DISTRIBUTION ID |           ALIASES            |                         SSL CERTIFICATE                         |
+-----------------+------------------------------+-----------------------------------------------------------------+
| 11111111111111  | iam.example.com              | XXXXXXXXXXXXXXXXXXXXX | test-cert-name                          |
+-----------------+------------------------------+-----------------------------------------------------------------+
| 22222222222222  | iam2.example.com             | XXXXXXXXXXXXXXXXXXXXX | test-cert-name                          |
+-----------------+------------------------------+-----------------------------------------------------------------+

証明書一括更新

./aws-cert-utils cloudfront bulk-update で Distribution が利用する証明書を更新できます。 現在利用している証明書が IAM の場合は --source-iam-id で Certification ID を、ACM の場合は --source-acm-arn で ACM の ARN を指定します。 変更する証明書が IAM の場合は --dest-iam-id に Certification ID を、ACM の場合は --dest-acm-arn に ACM の ARN を指定します。

$ ./aws-cert-utils cloudfront bulk-update --source-iam-id XXXXXXXXXXXXXXXXXXXXX --dest-acm-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
# Dry run mode

Updated 11111111111111 iam.example.com XXXXXXXXXXXXXXXXXXXXX -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Updated 22222222222222 iam2.example.com XXXXXXXXXXXXXXXXXXXXX -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

$ ./aws-cert-utils cloudfront bulk-update --source-iam-id XXXXXXXXXXXXXXXXXXXXX --dest-acm-arn arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx --no-dry-run
Updated 11111111111111 iam.example.com XXXXXXXXXXXXXXXXXXXXX -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
Updated 22222222222222 iam2.example.com XXXXXXXXXXXXXXXXXXXXX -> arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

$ ./aws-cert-utils cloudfront list
+-----------------+------------------------------+-------------------------------------------------------------------------------------+
| DISTRIBUTION ID |           ALIASES            |                                   SSL CERTIFICATE                                   |
+-----------------+------------------------------+-------------------------------------------------------------------------------------+
| 11111111111111  | iam.example.com              | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------------+------------------------------+-------------------------------------------------------------------------------------+
| 22222222222222  | iam2.example.com             | arn:aws:acm:us-east-1:xxxxxxxxxxxx:certificate/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
+-----------------+------------------------------+-------------------------------------------------------------------------------------+

まとめ

ALB / CLB / CloudFront で利用している証明書を一括で更新する aws-cert-utils の紹介でした。 現在、弊社では ACM から発行した証明書を利用していない関係で本ツールから ACM 証明書のリクエストを送る処理を実装していませんが、実装したい気持ちはあります(Issue or Pull Request お待ちしています)。