こんにちは、 @dz_ こと大平かづみです。
Prologue - はじめに
Ansible でオレオレ証明書を作ってみたので共有します。
[つまづきポイント] pyOpenSSL
が必要
例えば、サーバー上に証明書を作ろうとして openssl_xxx
モジュールを使うと、下記のエラーが発生します。
TASK [task : Generate OpenSSL private key] *************************
fatal: [default]: FAILED! => {"changed": false, "msg": "the python pyOpenSSL module is required"}
下記 issue によると、Ansible の OpenSSL 関連のモジュールは、対象のマシン上に python のライブラリ pyOpenSSL
を必要とするようです。
- Ansible 2.4 - the python pyOpenSSL module is required even if its already installed · Issue #30469 · ansible/ansible · GitHub
- Welcome to pyOpenSSL’s documentation! — pyOpenSSL 17.5.0 documentation
ですが、プロビジョニング対象のマシンに不要なコンポーネントをインストールをしたくありませんね。
そこで、Ansible を実行している環境(localhost)に pyOpenSSL
をインストールし、localhost 上で証明書を作成するように書くことができました。
# Install pyOpenSSL
pip install pyopenssl
ポイント解説
OpenSSL に関する Ansible モジュール
今回は、 openssl_privatekey
, openssl_csr
, openssl_certificate
のモジュールを使いました。これらが、 pyOpenSSL
を必要とします。
- openssl_privatekey - Generate OpenSSL private keys. — Ansible Documentation
- openssl_csr - Generate OpenSSL Certificate Signing Request (CSR) — Ansible Documentation
- openssl_certificate - Generate and/or check OpenSSL certificates — Ansible Documentation
delegate_to
で実行対象を指定する
実行対象を指定するには、 delegate_to
を利用します。今回は、 delegate_to: localhot
と指定することで、Ansible を実行しているマシン上で処理します。
なお、ホストが複数ある場合は、その数分だけ実行されてしまいます。1回だけ処理したい場合は、 run_once
を併用します。 run_once
についてはこちらもご参照ください。
サンプル
検証環境
前回同様、Azure を利用しました。
サンプルコード
こんな感じのコードになりました。
ファイル構成
ansible
├── generate_selfsigned_cert.yml
├── inventory
│ └── all
└── roles
└── selfsigned_cert
├── defaults
│ └── main.yml
├── files
└── tasks
└── main.yml
selfsigned_cert
ロール
---
selfsigned_cert:
cert:
path: /etc/ssl/crt/ssl.crt
privatekey:
path: /etc/ssl/private/ssl.pem
csr:
path: /etc/ssl/csr/ssl.csr
---
- name: Generate OpenSSL private key
openssl_privatekey:
path: "{{ role_path }}/files/{{ selfsigned_cert.privatekey.path | basename }}"
delegate_to: localhost
run_once: yes
- name: Generate OpenSSL CSR
openssl_csr:
path: "{{ role_path }}/files/{{ selfsigned_cert.csr.path | basename }}"
privatekey_path: "{{ role_path }}/files/{{ selfsigned_cert.privatekey.path | basename }}"
common_name: DEMO
delegate_to: localhost
run_once: yes
- name: Generate OpenSSL certificate
openssl_certificate:
path: "{{ role_path }}/files/{{ selfsigned_cert.cert.path | basename }}"
privatekey_path: "{{ role_path }}/files/{{ selfsigned_cert.privatekey.path |basename }}"
csr_path: "{{ role_path }}/files/{{ selfsigned_cert.csr.path | basename }}"
provider: selfsigned
delegate_to: localhost
run_once: yes
- name: Create directories for OpenSSL certificate
become: yes
file:
path: "{{ item }}"
state: directory
owner: root
group: root
mode: 0755
with_items:
- "{{ selfsigned_cert.privatekey.path | dirname }}"
- "{{ selfsigned_cert.cert.path | dirname }}"
- name: Copy these certificate and private key
become: yes
copy:
src: "{{ item.src }}"
dest: "{{ item.dest }}"
owner: root
group: root
mode: 0644
with_items:
- src: "{{ selfsigned_cert.privatekey.path | basename }}"
dest: "{{ selfsigned_cert.privatekey.path }}"
- src: "{{ selfsigned_cert.cert.path | basename }}"
dest: "{{ selfsigned_cert.cert.path }}"
インベントリと playbook
vm-ubuntu
---
- name: All
hosts: all
roles:
- selfsigned_cert
実行結果
ansible-playbook -i inventory/all generate_selfsigned_cert.yml
PLAY [All] **************************************************************************************************************
TASK [Gathering Facts] **************************************************************************************************
ok: [vm-ubuntu]
TASK [selfsigned_cert : Generate OpenSSL private key] *******************************************************************
changed: [vm-ubuntu -> localhost]
TASK [selfsigned_cert : Generate OpenSSL CSR] ***************************************************************************
changed: [vm-ubuntu -> localhost]
TASK [selfsigned_cert : Generate OpenSSL certificate] *******************************************************************
changed: [vm-ubuntu -> localhost]
TASK [selfsigned_cert : Create directories for OpenSSL certificate] *****************************************************
changed: [vm-ubuntu] => (item=/etc/ssl/private)
changed: [vm-ubuntu] => (item=/etc/ssl/crt)
TASK [selfsigned_cert : Copy these certificate and private key] *********************************************************
changed: [vm-ubuntu] => (item={u'dest': u'/etc/ssl/private/ssl.pem', u'src': u'ssl.pem'})
changed: [vm-ubuntu] => (item={u'dest': u'/etc/ssl/crt/ssl.crt', u'src': u'ssl.crt'})
PLAY RECAP **************************************************************************************************************
vm-ubuntu : ok=6 changed=5 unreachable=0 failed=0
作成結果
ちゃんと生成されてるようです~ ╭( ・ㅂ・)و̑ グッ
# Check the certificate
user@vm-ubuntu:~$ openssl x509 -text -noout -in /etc/ssl/crt/ssl.crt
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 94229 (0x17015)
Signature Algorithm: sha256WithRSAEncryption
Issuer:
Validity
Not Before: Feb 27 07:19:04 2018 GMT
Not After : Feb 25 07:19:04 2028 GMT
Subject: CN=DEMO
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (4096 bit)
Modulus:
00:c0:5f ...
# Check the private key
user@vm-ubuntu:~$ openssl rsa -text -noout -in /etc/ssl/private/ssl.pem
Private-Key: (4096 bit)
modulus:
00:c0:5f ...
よし!╭( ・ㅂ・)و̑ グッ
一度 Ansible で作っておけば、あとは簡単ですねー!
Epilogue - おわりに
余談、今までよくわからなかった SSL の自己署名証明書ですが、これを機に苦手意識がすこし減りました!