てくなべ (tekunabe)

ansible / network automation / 学習メモ

[Ansible] ACI モジュールの認証情報を環境変数で指定してPlaybookをすっきりさせる

これは、Ansible Advent Calendar 2020 (Qiita版)の19日目の記事です。

はじめに

Ansible には Cisco ACI の操作にも対応していて、モジュールが多数あります。

内部的には APICAPI を利用しますが、httpapi コネクションプラグインには対応していません。 そのため、基本的には各タスクごとに接続先や認証情報を指定する必要があり、Playbook が冗長になりがちになります。

YAML のアンカー、エイリアス、マージを利用すれば冗長さはある程度抑えられますが、YAML に慣れてないと初見で読み解けなかったり、マージ自体はタスクごとに指定が必要という点は残ります。

一方で、cisco.aci collection の version 1.1.0で、環境変数によって接続先や認証情報を指定できるようになりました。 この機能により、各タスクごとに接続先や認証情報を指定する必要がなくなりました。

この記事では、簡単なサンプルでご紹介します、

  • 動作確認環境
    • Ansible 2.10.3 / 2.9.15
    • cisco.aci collection 1.1.0
      • 2020/12/19 現在の最新は 2.0.0 です
      • Ansible 2.9 系でも利用可能
    • DevNet Sandox ACI Version 4.1(1k)


環境変数名とモジュールオプション名の対応

接続先や認証情報を指定する環境変数は、モジュールの各オプションに対応する形で用意されています。対応は以下のとおりです。

項目 環境変数 モジュールのオプション 備考
ホスト名 ACI_HOST host
ポート ACI_PORT port
ユーザー名 ACI_USERNAME, ANSIBLE_NET_USERNAME username
パスワード ACI_PASSWORD, ANSIBLE_NET_PASSWORD password
証明書名 ACI_CERTIFICATE_NAME certificate_name 署名ベース認証でのみ利用
秘密鍵のファイル名 ACI_PRIVATE_KEY private_key 署名ベース認証でのみ利用 
証明書検証の有無 ACI_VALIDATE_CERTS validate_certs
SSL/TLSの利用 ACI_USE_SSL use_ssl
プロキシ利用の有無 ACI_USE_PROXY use_proxy
タイムアウト ACI_TIMEOUT timeout

各モジュールの説明ページ(例: aci_tenant モジュール)にも説明があります。

優先度はモジュールのオプションのほうが高く、モジュールのオプションが指定されていなければ環境変数を参照する仕様です。

(補足) 2種類の認証方式

aci_* モジュールは、パスワードベース、署名ベースの2種類の認証方式があります。

パスワードベース認証方式は環境面の手間が少ない反面、DDoS 攻撃と誤認されやすいデメリットがあります。

一方、署名ベース認証方式は証明書や鍵を用意して APIC に登録するといった準備が必要ですが、DDoS 攻撃と誤認されにくいメリットがあります。

この記事でご紹介するサンプルは、準備が簡単なパスワードベース認証方式を利用した Playbook です。必要に応じて読み替えてください。


サンプル Playbook

テナント test_tenant01 と、 Application Profile test_ap01EPG test_epg01 を作成する Playbook です。

環境変数で一括指定

環境変数を指定するenvironment キーワードは、Play レベルで指定します。Task レベルでも指定できますが、ここではなるべく冗長さを排除するために、 Play レベルで指定します。

また、各パラーメーターの実際の値は、別途変数定義ファイルで定義済みのものとします。

---
- hosts: apic
  gather_facts: no
  connection: local

  environment:  # 環境変数による接続先や認証情報の指定
    ACI_HOST: "{{ ansible_host }}"
    ACI_USERNAME: "{{ username }}"
    ACI_PASSWORD: "{{ password }}"
    ACI_VALIDATE_CERTS: false

  tasks:
    - name: create tenant
      cisco.aci.aci_tenant:
        tenant: test_tenant01
        state: present

    - name: create ap
      cisco.aci.aci_ap:
        tenant: test_tenant01
        ap: test_ap01
        state: present

    - name: create epg
      cisco.aci.aci_epg:
        tenant: test_tenant01
        ap: test_ap01
        epg: test_epg01
        state: present

(比較用)タスクごとに指定した場合

比較のために、普通にタスクごとに接続先や認証情報を指定した場合の Playbook も掲載します。

このように、基本的には各タスクに hostusername などの接続先や認証情報の指定が必要です。

---
- hosts: apic
  gather_facts: no
  connection: local

  tasks:
    - name: create tenant
      cisco.aci.aci_tenant:
        host: "{{ ansible_host }}"  # タスクごとに指定する場合
        username: "{{ username }}"  # タスクごとに指定する場合
        password: "{{ password }}"  # タスクごとに指定する場合
        validate_certs: no          # タスクごとに指定する場合
        tenant: test_tenant01
        state: present

    - name: create ap
      cisco.aci.aci_ap:
        host: "{{ ansible_host }}"  # タスクごとに指定する場合
        username: "{{ username }}"  # タスクごとに指定する場合
        password: "{{ password }}"  # タスクごとに指定する場合
        validate_certs: no          # タスクごとに指定する場合
        tenant: test_tenant01
        ap: test_ap01
        state: present

    - name: create epg
      cisco.aci.aci_epg:
        host: "{{ ansible_host }}"  # タスクごとに指定する場合
        username: "{{ username }}"  # タスクごとに指定する場合
        password: "{{ password }}"  # タスクごとに指定する場合
        validate_certs: no          # タスクごとに指定する場合
        tenant: test_tenant01
        ap: test_ap01
        epg: test_epg01
        state: present

この場合、少し Playbook が長くなってしまいます。


実行結果

Play 単位の環境変数で接続先や認証情報を指定した Playbook を実行します。

$ ansible-playbook -i inventory.ini aci_test.yml         
PLAY [apic] ******************************************************************************************************

TASK [create tenant] *********************************************************************************************
changed: [apic01]

TASK [create ap] *************************************************************************************************
changed: [apic01]

TASK [create epg] ************************************************************************************************
changed: [apic01]

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

$

無事に接続、認証も成功し、処理が正常に完了しました。

f:id:akira6592:20201205183254p:plain
作成されたもの


まとめ

Play 単位の環境変数で、接続先や認証情報を指定することで、各タスクがスッキリする Playbook をご紹介しました。

タスクごとに接続先や認証情報を指定することを避けたい場合は、この方法を検討してみてはいかがでしょうか。