てくなべ

ネットワーク、自動化などの技術的なことを書いていきます。Ansible、StackStorm等

Ansible の ios_command の出力結果でパスワードが ******** でマスクされる

■ はじめに

Ansible には Cisco IOSshow コマンドを実行できる ios_command モジュールが用意されています。 このモジュールは設計上、コマンド実行結果にパスワードで指定した文字列が含まれる場合、パスワードに関係ない箇所でも******** でマスクするという動作をします。(例外あり、後述。)

この記事では動作の確認と対応案をご紹介します。

  • 動作確認バージョン
    • Ansible 2.5.0
    • Ansible 2.4.3


■ 現象

詳細は以下の issue に記載されています。(設計上の動作のため closed )

github.com

例えば、cisco99 というパスワードを指定していいて、かつ、パスワードに関係ない箇所にも cisco99 という文字列が含まれているコンフィグ想定して、どのような時にどのようにマスクされるかを見ていきます。

  • 想定事前コンフィグ抜粋
interface Loopback0
 description hogehogecisco99hogehoge

以下のように、 ios_config モジュール内の providerpassword オプションでパスワードを指定すると、コマンド実行結果にそのパスワードと文字列が ******** でマスクされます。

Playbook

- hosts: ios
  gather_facts: no
  connection: local

  tasks:
    - name: show
      ios_command:
        commands:
          - show run
        provider:
          username: cisco
          password: cisco99        # パスワード
      register: result

    - name: debug
      debug:
        msg: "{{ result.stdout_lines[0] }}"

出力結果例(抜粋)

パスワードと同じ文字列である cisco99 がマスクされます。

interface Loopback0
 description hogehoge********hogehoge

このように、パスワードが平文でコンフィグに書かれている場合にマスクすることを意図した設計のようですが、パスワードが同じ文字列が、description などパスワードと関係ない箇所に現れる場合でもマスクします。


■ 対応案

パスワードと同じ文字列をコンフィグに含めない

パスワード認証を利用する場合は、まずはこれが原則かと思います。

鍵を利用する

冒頭で紹介した issue のコメントでも提案されている方法です。鍵利用した認証に変更することで、そもそもPlaybookや変数でパスワードをしなくなるので上記のような現象は起こらなくなります。

ansible_ssh_pass 変数を利用する

ios_config モジュール内の providerpassword オプションでパスワードを指定するのではなく、どこかしらで ansible_ssh_pass で変数で指定するとマスクされません。

Playbook

- hosts: ios
  gather_facts: no
  connection: local

  # 今回は見通しが良いようにPlaybook内に変数定義
  vars:
    ansible_user: cisco
    ansible_ssh_pass: cisco99        # パスワード

  tasks:
    - name: show
      ios_command:
        commands:
          - show run
      register: result

    - name: debug
      debug:
        msg: "{{ result.stdout_lines[0] }}"

出力結果例(抜粋)

パスワードと同じ文字列である cisco99 がマスクされず、そのまま出力されます。

interface Loopback0
 description hogehogecisco99hogehoge

Ansible 2.5 の場合

Ansible 2.5 では network_cli という新しいコネクションタイプの利用が推奨されています。netowrk_cli では、そもそもモジュール内の privider オプションで指定した認証情報は利用せず、ansible_useransible_ssh_pass などの変数を利用します。

Playbook

- hosts: ios
  gather_facts: no
  connection: network_cli

  # 今回は見通しが良いようにPlaybook内に変数定義
  vars:
    ansible_user: cisco
    ansible_ssh_pass: cisco99    # パスワード
    ansible_network_os: ios      # network_cli 固有の変数

  tasks:
    - name: show
      ios_command:
        commands:
          - show run
      register: result

    - name: debug
      debug:
        msg: "{{ result.stdout_lines[0] }}"

出力結果例(抜粋)

パスワードと同じ文字列である cisco99 がマスクされず、そのまま出力されます。

interface Loopback0
 description hogehogecisco99hogehoge


■ まとめ

セキュリティを考慮した設計上の動作ではありますが、状況によっては副作用的な動きとなります。上記であげた対応案が参考になれば幸いです。

なお、本件は 2018/03/24 に参加させていただいた Ansible Workshop #3 2018 Spring で小耳に挟んだ話でした。気になったでので確認してみました。