てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible][ACI] Vault で暗号化した秘密鍵を署名ベースの認証方式で利用する

【目次】

はじめに

Ansible の ACI モジュールが APIC に対してリクエストする認証方式には、パスワードベース(Password-based authentication)と、署名ベース(Signature-based authentication using certificates)があります。

署名ベース認証方式の仕組みと準備と Playbook の書き方については、以前の記事でとりあげました。 tekunabe.hatenablog.jp

今回の記事では、署名ベース認証方式を利用時に、Ansible Vault で暗号化した秘密鍵を利用する方法を、Ansible Engine と Ansible Tower それぞれのをご紹介します。

公式ドキュメントによると、Ansible 2.8 から暗号化された秘密鍵ファイルを利用できるようなったようです。

Ansible Tower では Tower らしく、Vault のパスワードを認証情報(Credential)に登録します。

  • 前提条件
    • APIC: Cisco DevNet Sandbox (APIC 4.1)
    • Ansible 2.8.2
    • Ansible Tower 3.5.2
    • 署名ベース認証の対象ユーザー: admin
      • 手順の検証容易性のために admin を利用していますが、運用環境では他のユーザーを利用を推奨


秘密鍵の暗号化(Ansible Engine / Ansible Tower 共通)

Ansible Engine、Ansible Tower 共通の準備として、まず秘密鍵を Ansible Vault で暗号化します。 admin.key が秘密鍵です。入力するパスワードは復号時に利用するので覚えておきます。

$ ansible-vault encrypt admin.key 
New Vault password:             (暗号化パスワードを入力)
Confirm New Vault password:     (暗号化パスワードを再度入力)
Encryption successful

秘密鍵が暗号化されました。中身を確認します。

$ cat admin.key 
$ANSIBLE_VAULT;1.1;AES256
34663837626431373834623430303234633730343262353336333331363562303365626435393231
6362663361323336656430313065646530626339643831320a303063343363353030363238393835
...(略)...

無事に暗号化されているのを確認できました。


■ Ansible Engine の場合

Ansible Engine で、暗号化された秘密鍵を利用する方法を紹介します。以下の 2つの方法があります。

  1. private_key オプションで file lookup plugin を利用して暗号化された秘密鍵データを取得
  2. 暗号化データを変数に割りてて、private_key オプションで変数を指定

ここでは、1 の file lookup plugin を利用します。2 の変数を利用する方法は 公式ドキュメントの「Using Ansible Vault to encrypt the private key」を参照してください。

Playbook

特定の EPG の方法を取得する簡単な Playbook で試します。

---
- hosts: apic
  gather_facts: no

  tasks:
    - name: 
      aci_epg:
        host: "{{ ansible_host }}"
        username: admin           # 証明書保有ユーザー名
        certificate_name: admin   # 証明書名
        private_key:  "{{ lookup('file', 'admin.key') }}"  # 秘密鍵
        validate_certs: no
        tenant: tenant1
        ap: ap1
        epg: epg1
        state: query
      register: result

なお、private_key オプションには本来、private_key: "admin.key" のように秘密鍵のパスも指定できますが、暗号化された秘密鍵ファイルのパスは指定できないのでご注意ください。秘密鍵ファイルとして認識されれず、Provided private key file '********' does not appear to be a private key. Please correct." というエラーになってしまいます。

実行

ansible-playbook コマンドに --ask-vault-pass をつけて、実行時に都度、暗号化パスワードを入力するようにします。

$ ansible-playbook -i inventory.ini query_epg.yml --ask-vault-pass
Vault password:     (暗号化パスワードを入力)

PLAY [query] ***********************************************************************

TASK [aci_epg] *********************************************************************
ok: [apic01]

PLAY RECAP *************************************************************************
apic01                     : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

無事に、暗号化された秘密鍵ファイルを利用して APIC に接続し、Playbook を実行できました。

他にもいろいろ方法はありますが、詳細は公式ドキュメントをご参照ください。

Ansible Vault — Ansible Documentation

Ansible Engine 側の場合はここまでです。


■ Ansible Tower の場合

次に、Ansible Tower で、暗号化された秘密鍵を利用する方法を紹介します。

Tower らしく、Vault というタイプの認証情報(Credential)に Vault のパスワードを登録します。 暗号化された秘密鍵のデータを利用する方法は 2つあります。

  1. private_key オプションで file lookup plugin を利用して暗号化された秘密鍵データを取得(Ansible Engineと同じ)
  2. インベントリ変数に暗号化データを設定して、private_key オプションで変数を指定

まず、認証情報(Credential)の登録手順を説明し、上記 2つの方法をそれぞれ説明します。

準備: 認証情報(Credential)の登録

まず、準備として Vault のパスワードを認証情報に登録します。

認証情報の名前を指定し、タイプとして Vault を指定します。VAULT パスワードには、ansible-vault コマンドで秘密鍵ファイルを暗号化した時に指定したパスワードを入力します。復号時に自動的に利用されます。

f:id:akira6592:20191105235033p:plain
タイプ Vault の認証情報の登録

認証情報の登録は以上です。

続いて、暗号化された秘密鍵のデータを利用する方法は 2つの方法を説明します。

1. file lookup plugin を利用する方法

1 つめは、Ansible Engine のときと同様に file lookup plugin を利用する方法です。 Playbook も同じです。

Playbook

---
- hosts: apic
  gather_facts: no

  tasks:
    - name: 
      aci_epg:
        host: "{{ ansible_host }}"
        username: admin           # 証明書保有ユーザー名
        certificate_name: admin   # 証明書名
        private_key:  "{{ lookup('file', 'admin.key') }}"  # 秘密鍵
        validate_certs: no
        tenant: tenant1
        ap: ap1
        epg: epg1
        state: query
      register: result

この Playbook を利用する ジョブテンプレートを作成しておきます。認証情報には先ほど作成した Vault のものを指定します。

f:id:akira6592:20191105235745p:plain:w400
認証情報の選択

f:id:akira6592:20191105235930p:plain
認証情報の選択

認証情報の登録、選択は以上です。

実行

ジョブテンプレートを実行します。ジョブ実行時には、認証情報に登録した Vault パスワードが自動で利用されるため、 入力は求められません。

f:id:akira6592:20191106000039p:plain
ジョブテンプレートの実行

無事に、暗号化された秘密鍵ファイルを利用して APIC に接続し、Playbook を実行できました。

これが、file lookup plugin を利用する方法でした。

2. インベントリ変数に暗号化データを設定して利用する方法

2 つめは、インベントリ変数に暗号化データを設定して利用する方法です。 暗号化された秘密鍵を、ファイルとして管理したくない場合に便利です。

インベントリの設定

APIC のホスト変数に暗号化された秘密鍵のデータそのものを指定します。 指定の方法が Ansible Engine の場合と異なるなるので注意が必要です。

private_key: !vault |
    $ANSIBLE_VAULT;1.1;AES256
    34663837626431373834623430303234633730343262353336333331363562303365626435393231
    6362663361323336656430313065646530626339643831320a303063343363353030363238393835
    39613164626531376334393062343164613639653265616639623037373035386462313934313931
    6533626665356566350a313665633163356130663035343736356165376231623133616266306538
...(略)...

ではなく、以下のような形式で指定する必要があります。 変数名に直接暗号化データを指定するのではなく、__ansible_vault というキーを挟んで、一行ごとに空行を挟んで指定します。

private_key:
  __ansible_vault: >-
      $ANSIBLE_VAULT;1.1;AES256
      
      34663837626431373834623430303234633730343262353336333331363562303365626435393231

      6362663361323336656430313065646530626339643831320a303063343363353030363238393835
      
      39613164626531376334393062343164613639653265616639623037373035386462313934313931
      
      6533626665356566350a313665633163356130663035343736356165376231623133616266306538
...(略)...

f:id:akira6592:20191106000214p:plain
少し特殊な暗号化データの指定

Playbook

private_key オプションには、変数名のみ指定します。

---
- hosts: apic
  gather_facts: no

  tasks:
    - name: 
      aci_epg:
        host: "{{ ansible_host }}"
        username: admin           # 証明書保有ユーザー名
        certificate_name: admin   # 証明書名
        private_key:  "{{ private_key }}"  # 秘密鍵(データそのもの格納された変数)
        validate_certs: no
        tenant: tenant1
        ap: ap1
        epg: epg1
        state: query
      register: result

この Playbook を利用する ジョブテンプレートを作成しておきます。

実行

ジョブテンプレートを実行します。先ほどと同じく、ジョブ実行時には、認証情報に登録した Vault パスワードが自動で利用されます。

f:id:akira6592:20191106000421p:plain
ジョブテンプレートの実行

無事に、暗号化された秘密鍵ファイルを利用して APIC に接続し、Playbook を実行できました。

これが、インベントリで暗号化データを変数に割り当てて利用する方法でした。


まとめ

Ansible Engine、Ansible Tower それぞれで、APIC に接続する秘密鍵を VAULT で暗号して利用する方法をご紹介しました。

  • file lookup plugin で暗号化された秘密鍵のファイルを指定して、暗号化パスワードを与えると、秘密鍵を利用できる
  • Ansible Tower では、Vault というタイプの認証情報に Vault パスワードを登録することで、ジョブ実行時に都度パスワードを入力する手間が省ける
  • 暗号化データを変数に設定して利用することで、秘密鍵をファイルとして管理する必要をなくせる
  • Tower の インベントリ変数に VAULT で暗号化したデータを指定する場合はちょっとしたコツがある