- 公開日
- 最終更新日
【やってみた】EC2上のAnsibleからTLS証明書を自動配布(ACM)
この記事を共有する
目次
パーソル&サーバーワークスの髙井です。
AWS を中心としたクラウドインフラの設計・構築・運用を担当しています。
はじめに
Ansible は、サーバーの構成や設定を自動化する構成管理ツールです。
前回は、 TLS 証明書を Linux サーバーと Windows サーバーへ配布しました。
本ブログでは同じ証明書を、 AWS Certificate Manager(以下、ACM)へインポートし、Application Load Balancer(以下、ALB)で HTTPS 公開する ところまでを扱います。
ポイントは、 Ansible の接続先が「サーバー」ではない という点です。
ACM は AWS の API であり、どこかのサーバーへ SSH や WinRM でログインするわけではありません。
本ブログは Playbook の書き方を1行ずつ解説するものではありません。
インベントリや Playbook の中身には深入りせず、 コマンドを実行した結果、証明書が ACM へ入り ALB が HTTPS を終端するようになる という Ansible の実用性に焦点を当てます。
設定ファイルの具体的な記述よりも、動かした結果の実行画面を中心に見ていきます。
Ansible の基本的な用語については、 入門編 で解説しています。あわせてご確認ください。
想定読者
- Ansible の基本用語を理解していて、localhost 実行で AWS の API を扱うと何が起きるのかを知りたい方
ALB で HTTPS 公開する
今回の題材を一言でいうと、 「ブラウザーから HTTPS でテストページを開けるようにする」 ことです。
通信の経路は下記のようになります。
ブラウザー ──HTTPS(443)──▶ ALB(ACM 証明書で終端)──HTTP(80)──▶ Linux Node(テストページ)
ここで ACM と ALB が担うのは、 インターネットからの入口(ブラウザー ↔ ALB 間)の暗号化 です。
インターネットを通る経路を HTTPS にすることが目的で、今回の構成では ALB がその入口で TLS を終端します。
| 登場人物 | 役割 |
|---|---|
| Control Node | Ansible を実行し、証明書を生成して ACM へインポートする |
| ACM | 証明書を保管する。ALB から参照される |
| ALB | ACM の証明書で HTTPS を終端する |
| Linux Node | ALB の背後でテストページを返す |
本ブログで Ansible が担当するのは 「証明書を生成し、ACM へインポートする」ところまでです。
ALB や各サーバーの用意は CloudFormation 側で行い、本ブログでは深く触れません。
Ansible は「どこで」動くのか
前回、Ansible は Linux へ SSH、Windows へ WinRM で接続して構成しました。
一方で今回は、 接続先のサーバーがありません。
証明書を ACM へインポートするのは AWS の API を呼ぶ操作であり、どこかにログインして作業するわけではないからです。
このような場合、Ansible は 自分自身(localhost)で処理 します。
Playbook には、リモート接続をせず Ansible を動かしているサーバー(Control Node)の上でそのまま処理する、という指定が書かれています。
同じ Ansible でも、リモートのサーバーを構成するだけでなく、ローカルで AWS の API を叩く用途にも使える という例です。
ここで、リモートのサーバーへ配布する場合との違いがもう1つあります。
サーバーへ配布するときは、接続先・接続方式・接続ユーザーを Inventory(接続対象を定義するファイル)に登録しておく必要がありました。
一方 API を相手にする場合は接続先のサーバーがないため、 Inventory への登録は不要で、Playbook だけで処理が完結します。
localhost で実行する指定だけで、Inventory を用意しなくてもその場で実行できます。

インポートの前に証明書を検査する
Playbook は、ACM へインポートする前に 証明書が壊れていないか を検査します。
この検査は Play の冒頭(pre_tasks)で行い、1つでも失敗したらインポートを中止します。
| 検査 | 目的 |
|---|---|
| ファイルの存在 | 証明書・秘密鍵・CA 証明書がそろっているか |
| 有効期間 | すぐに期限切れになる証明書をインポートしないか |
| CA 署名の検証 | 証明書が CA で正しく検証できるか |
| 証明書と秘密鍵の一致 | 証明書と秘密鍵の組み合わせが正しいか |
壊れた証明書を ACM へ入れると、それを参照する ALB の HTTPS が壊れます。 入れる前に検査して落とすほうが安全です。
「本処理の前に前提を点検する」用途で pre_tasks を使うと、安全側に倒した Playbook になります。
秘密鍵の内容を扱う Task には no_log: true を付け、実行ログに鍵の中身が出ないようにします。

ACM へインポートする
インポートは、Playbook の中から AWS CLI の aws acm import-certificate を実行して行います。
証明書・秘密鍵・CA チェーンの3ファイルを渡します。
実行されるコマンドは、要点だけ示すと下記のような形です。
aws acm import-certificate \
--certificate fileb://<サーバー証明書> \
--private-key fileb://<サーバー秘密鍵> \
--certificate-chain fileb://<CA 証明書> \
--region <リージョン>
秘密鍵を渡すため、この処理は実行ログに中身が出ないよう設定しています。
| 渡すもの | 内容 |
|---|---|
| --certificate | サーバー証明書 |
| --private-key | サーバー秘密鍵 |
| --certificate-chain | 証明書チェーン(CA 証明書) |

冪等性が効かないケースもある
前回、「Ansible は冪等性があり、同じ内容なら変更しない」ことを配布で確認しました。
ところが ACM のインポートは、 同じ証明書でも実行するたびに新しいバージョンが作られる ため、そのままでは冪等になりません。
これを避けるため、設計上の工夫を入れています。
一度インポートして得られた証明書の識別子(ARN)を設定に記録しておき、2回目以降はその ARN を指定して 再インポート(更新) にします。
こうすると、何度実行しても証明書が増殖せず、同じ証明書が更新される動きになります。
モジュールや API によっては冪等性が自動では保証されないことがあり、その場合は設計で冪等に寄せる という考え方は、実際に Playbook を書くうえで重要なポイントです。
ALB で HTTPS 公開する
Ansible が ACM へインポートすると、証明書の ARN(識別子)が返ってきます。
この ARN を ALB の HTTPS リスナーに指定すると、ALB はその証明書を使って HTTPS を終端します。
Ansible で ACM へインポート → 証明書 ARN を取得 → ALB の HTTPS リスナーへ指定
ここで順番が重要になります。
ALB の HTTPS リスナーは実在する証明書の ARN を必要とするため、先に ACM へインポートしておく必要があります。
証明書がまだ無い状態で ALB を作ろうとすると、参照先が無く失敗します。
この順番だけ押さえておけば迷いません。
公開できたら、ブラウザーで ALB のアドレスを HTTPS で開いて確認します。

補足:証明書の警告について
検証環境では自己署名の証明書を使うため、ブラウザーで警告が出ます。これは想定どおりの挙動です。
確認したいのは「Ansible から ACM への経路が機能し、ALB がその証明書で HTTPS を終端できること」なので、警告を承認して進み、テストページが表示されれば成功です。
鍵マークが有効な状態まで見たい場合は、独自ドメインと公的 CA の証明書が必要になります。
まとめ
本ブログの要点は下記のとおりです。
- 証明書を置く先はサーバーではなく ACM で、HTTPS を終端するのは ALB です
- 接続先のサーバーがないため、Ansible は localhost で AWS CLI を実行して ACM へインポートします
- インポート前に証明書を検査し、壊れた証明書で HTTPS を壊さないようにします
- ACM のインポートは冪等ではないため、ARN を指定した再インポートで証明書の増殖を防ぎます
- ALB の HTTPS リスナーは実在する証明書 ARN を必要とするため、先に ACM へインポートしてから ALB を立てます
リモートのサーバーを SSH / WinRM で構成する使い方と、localhost で AWS の API を扱う使い方、そして API の都合で冪等性を設計で補う考え方など、実務で役立つ観点が詰まった題材でした。
最後までお読みいただきありがとうございました。
参照ドキュメント
- Local playbooks (connection: local)
- ansible.builtin.command module
- Importing certificates into AWS Certificate Manager
- HTTPS listeners for your Application Load Balancer
この記事は私が書きました
髙井 大暉
記事一覧頑張ってインフラエンジニアやってます。