こんにちは。SREチーム インフラエンジニアの綿引です。
今回は Ansible で SSL証明書更新を自動化したみたというお話です。
SSL証明書の更新って時間がかかりますよね。。後ヒューマンエラーも怖い。。
そこで 自動化
出来たら素敵!と思い vagrant で検証してみました。
興味のある方は是非見て頂ければと思います。
環境・構成
環境・構成は以下となっております。
■ サーバ側設定
・ ホスト名 : ans
・ IP : 172.19.12.101
・ 構成管理ツール : ansible/2.4.2.0
・ (配布用)証明書の保存ディレクトリ : /opt/ansible/ssl/
■ スレーブ側設定
・ ホスト名 : anc
・ IP : 172.19.12.102
・ WEBサーバ : Apache/2.4.6
・ 証明書の保存ディレクトリ : /etc/httpd/conf/ssl.crt/
■ 証明書情報
・ サーバ証明書ファイル名 : test.crt
・ 中間CA証明書ファイル名 : test.cer
・ 秘密鍵ファイル名 : test.key
やりたいこと
やりたいことの流れとしては、以下です。
1. ansible サーバ側に新しい SSL 証明書を配置
2. サーバ側でスクリプトをキック
3. サーバ側の新しい SSL 証明書を、クライアントに配布
4. その後、クライアント側の apache を reload して新しい証明書を適用
では早速やってみたいと思います。
まずAnsibleとは
その前にそもそも Ansible
とは何ぞや、特徴は何だというのを簡単に、、
・構成管理ツール
➡︎ 同じようなプロダクトとしては chef や puppet などですね
・エージェントレス
➡︎ クライアント側にエージェントを入れなくて済むのはありがたい
・シンプル
➡︎ 他の構成管理ツールと比べると記述などがシンプル
個人的にはエージェントレスは嬉しい限りです。
対象サーバの台数が多いとエージェントをインストールするのも面倒ですし、
エージェントのインストールに引きずられて、他のパッケージやソースを入れることもないので。
Ansible のインストール
yum で Absible インストールします。くせもなく非常に簡単でした。
$ yum install epel-release $ yum install ansible $ ansible --version ansible 2.4.2.0 config file = /etc/ansible/ansible.cfg configured module search path = [u'/home/vagrant/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules'] ansible python module location = /usr/lib/python2.7/site-packages/ansible executable location = /usr/bin/ansible python version = 2.7.5 (default, Jun 24 2015, 00:41:19) [GCC 4.8.3 20140911 (Red Hat 4.8.3-9)]
設定ファイルの作成
インストールも完了したので、次は設定を行っていきます。
実行に必要なファイルは(基本的に)以下の2つです。
■ インベントリファイル (hosts ファイル)
・操作したいリモートサーバのホスト名やIPを記述
・インベントリファイルに記載されたリモートサーバに対し操作が実行される
・尚、リモートサーバはグループ化することができ、そのグループに対し操作ができる
■ playbook(モジュール)
・yaml 形式
・リモートサーバに実行させたい処理を記述した定義ファイル
・Ansible の モジュール
を使用し、ファイルコピーやサービス起動など様々な命令が可能
モジュールの数は現在 1,300 ほどあるみたいなので、かなり多くの要望に対応できそうです。
ただ普段使いするのはそこまで多くなさそう。。
今回使用したのは以下のモジュールです。
◆ 使用したモジュール(一部)
No. | モジュール名 | 用途 |
---|---|---|
1 | file | ディレクトリの作成や、対象ファイルの文字列置換 |
2 | copy | ファイルコピー |
3 | service | サービス開始、停止 |
4 | shell | OSコマンドの実施 |
モジュールには他にも yum などがあり、
パッケージインストールも ansible にて可能なので
サーバの自動構築を行う際などに便利そうです。
インベントリファイル作成
まずはインベントリファイルから作成していきます。
適当に /opt 配下に ansible ディレクトリを作り、
その直下に hosts という名前のインベントリファイルを作成します。
$ sudo mkdir /opt/ansible/ $ cd /opt/ansible/ $ sudo vi hosts
先ほどのグループ指定の書き方をします。
“[ ]” 内にグループ名を記載し、参加させたいリモートサーバを羅列します。
[test1] 172.19.12.102
この記載だとtest1
を選べば、第4オクテット 102 (ancサーバ) に対し実行します。
またホスト名で記載することも可能です。
もちろん以下のように複数台を選択することも可能です。
[test2] 172.19.12.103 172.19.12.104
yaml ファイル作成
次はクライアント側の操作を定義する yaml ファイルを作成します。
$ cd /opt/ansible/ $ sudo vi ssl_update.yaml
今回はこのような形で書いてみました。(汚いですが、、)
また変数を使いたかったため、vars_files
というモジュールを使用しております。
vars_files は変数を定義したファイルを外に出すことができるので重宝しました。
- hosts: test1 remote_user: vagrant become: yes vars_files: - /opt/ansible/vars.yml tasks: - name: 1. create backupdir file: path={{ dest_ssl_dir }}/{{ date }} state=directory owner=root group=root mode=0644 - name: 2. backup file shell: cp -p {{ dest_ssl_dir }}/{{ crt_file }} {{ dest_ssl_dir }}/{{ date }}/{{ crt_file }}; cp -p {{ dest_ssl_dir }}/{{ ica_file }} {{ dest_ssl_dir }}/{{ date }}/{{ ica_file }}; cp -p {{ dest_ssl_dir }}/{{ key_nopw_file }} {{ dest_ssl_dir }}/{{ date }}/{{ key_nopw_file }} - name: 3. check file shell: diff -s {{ dest_ssl_dir }}/{{ crt_file }} {{ dest_ssl_dir }}/{{ date }}/{{ crt_file }}; diff -s {{ dest_ssl_dir }}/{{ ica_file }} {{ dest_ssl_dir }}/{{ date }}/{{ ica_file }}; diff -s {{ dest_ssl_dir }}/{{ key_nopw_file }} {{ dest_ssl_dir }}/{{ date }}/{{ key_nopw_file }} - name: 4. update crt_file copy: src={{ new_ssl_dir }}/{{ crt_file }} dest={{ dest_ssl_dir }}/{{ crt_file }} owner=root group=root mode=0644 - name: 5. update ica_file copy: src={{ new_ssl_dir }}/{{ ica_file }} dest={{ dest_ssl_dir }}/{{ ica_file }} owner=root group=root mode=0644 - name: 6. update key_nopw_file copy: src={{ new_ssl_dir }}/{{ key_nopw_file }} dest={{ dest_ssl_dir }}/{{ key_nopw_file }} owner=root group=root mode=0644 - name: 7. httpd configcheck shell: httpd -t - name: 8. httpd reload for CentOS 7 service: name=httpd state=reloaded when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "7") - name: 9.httpd reload for CentOS 56 shell: /etc/init.d/httpd graceful when: (ansible_distribution == "CentOS" and ansible_distribution_major_version == "5") or (ansible_distribution == "CentOS" and ansible_distribution_major_version == "6")
yaml ファイルの内容ですが、各コメントの部分は以下の通りです。
項目 | 内容 |
---|---|
1. create backupdir | 証明書バックアップ用のディレクトリを作成(YYYYMMDD) |
2. backup file | 証明書のバックアップを取得 |
3. check file | 現在のファイルとバックアップに差分がないか確認 (※1) |
4. update crt_file | サーバ証明書ファイルを更新 |
5. update ica_file | 中間CA証明書ファイルを更新 |
6. update key_nopw_file | 秘密鍵ファイルを更新 |
7. httpd configcheck | Apache の configcheck を行う (※2) |
8. httpd reload for CentOS 7 | apache の reload が実行される (※3) |
9. httpd reload for CentOS 56 | apache の reload が実行される (※4) |
※1 ・・・ 差分があった場合はdiff
の返り値が “0” 以外となるためエラーとなる
※2 ・・・ httpd.conf の記述に問題がある場合は返り値が ”0” 以外となるためエラーとなる
※3 ・・・ CentOS 7 systemctl reload htttpd
が実行される
※4 ・・・ CentOS 5 か 6 だった場合に/etc/init.d/httpd graceful
が実行される
最後に /opt/ansible/vars.yml の中身です。
date: "{{ lookup('pipe','date +%Y%m%d') }}" crt_file: test.crt ica_file: test.cer key_nopw_file: test.key new_ssl_dir: /opt/ansible/ssl dest_ssl_dir: /etc/httpd/conf/ssl.crt
実行
ansible を実行するにはansible-playbook
コマンドを実行します。
(使い方例) : $ ansible-playbook -i hostsファイル yamlファイル
$ ansible-playbook -i hosts ssl_update.yaml PLAY [test1] ******************************************************************************************************************************************************************************************************** TASK [Gathering Facts] ********************************************************************************************************************************************************************************************** ok: [anc] TASK [1. create backupdir] ****************************************************************************************************************************************************************************************** changed: [anc] TASK [2. backup file] *********************************************************************************************************************************************************************************************** changed: [anc] TASK [3. check file] ************************************************************************************************************************************************************************************************ changed: [anc] TASK [4. update crt_file] ******************************************************************************************************************************************************************************************* ok: [anc] TASK [5. update ica_file] ******************************************************************************************************************************************************************************************* ok: [anc] TASK [6. update key_nopw_file] ************************************************************************************************************************************************************************************** ok: [anc] TASK [7. httpd configcheck] ***************************************************************************************************************************************************************************************** changed: [anc] TASK [8. httpd reload for CentOS 7] ********************************************************************************************************************************************************************************* changed: [anc] TASK [9.httpd reload for CentOS 56] ********************************************************************************************************************************************************************************* skipping: [anc] PLAY RECAP ********************************************************************************************************************************************************************************************************** anc : ok=9 changed=5 unreachable=0 failed=0
実行後、ブラウザで証明書の更新日を確認したら問題なく更新されておりました。成功です。
hostsファイルのグループ分けやディレクトリ構成、yamlファイルの記載など、
まだまだブラッシュアップが必要ですが一旦使えそうです。
まとめ
今回は Ansible で SSL 証明書をアップデートしました。
自身の環境でそこそこ上手くいったので、サービスに載せられないか検討中です。
皆さまもまだ Ansible 使ったことないんだよねーという方がいらっしゃれば、
参考にして頂けますと幸いです。
ご清覧頂きありがとうございました。
Wedding Parkでは一緒に技術のウエディングパークを創っていくエンジニアを募集しています。
興味のある方はぜひ一度気軽にオフィスに遊びにいらして頂ければと思います。