てくなべ (tekunabe)

ansible / network automation / 学習メモ

ネットワーク機器のコンフィグの固有情報を「匿名化」するツール netconan

はじめに

ネットワーク機器のコンフィグファイルをどこかに提示する際、パスワードや IP アドレス、SNMP コミュニティ名などの固有情報をマスクしたり、変更したりする機会はないでしょうか。 netconan はそれを自動で変換してくれるツールです。

github.com

インストール

pip ですぐにインストールできます。

pip install netconan

使い方

オプションで、コンフィグファイル名や、匿名化の詳細を指定します。

  • -i オプションで対象のコンフィグファイル(またはディレクトリ)
  • -o オプションで出力先のファイル名(またはディレクトリ)
  • IPアドレスを匿名化する場合は、-a または --anonymize-ips オプションを指定します
  • -w オプションで「この単語があったら匿名化して」という指定もできます

詳細は、README を参照してください。

以下、ヘルプを転記します。

$ netconan --help
usage: netconan [-h] [-a] [-c CONFIG] [-d DUMP_IP_MAP] -i INPUT
                [-l {DEBUG,INFO,WARNING,ERROR,CRITICAL}] [-n AS_NUMBERS] -o
                OUTPUT [-p] [-r RESERVED_WORDS] [-s SALT] [-u]
                [-w SENSITIVE_WORDS] [--preserve-prefixes PRESERVE_PREFIXES]

Args that can start with '--' can also be set in a config file (specified via
-c). If an arg is specified in more than one place, then command line values
override config file values which override defaults. Config file syntax
allows: key=value, flag=true, stuff=[a,b,c] (for more details, see here
https://goo.gl/R74nmi).

optional arguments:
  -h, --help            show this help message and exit
  -a, --anonymize-ips   Anonymize IP addresses
  -c CONFIG, --config CONFIG
                        Netconan configuration file with defaults for these
                        CLI parameters
  -d DUMP_IP_MAP, --dump-ip-map DUMP_IP_MAP
                        Dump IP address anonymization map to specified file
  -i INPUT, --input INPUT
                        Input file or directory containing files to anonymize
  -l {DEBUG,INFO,WARNING,ERROR,CRITICAL}, --log-level {DEBUG,INFO,WARNING,ERROR,CRITICAL}
                        Determines what level of logs to display
  -n AS_NUMBERS, --as-numbers AS_NUMBERS
                        List of comma separated AS numbers to anonymize
  -o OUTPUT, --output OUTPUT
                        Output file or directory where anonymized files are
                        placed
  -p, --anonymize-passwords
                        Anonymize password and snmp community lines
  -r RESERVED_WORDS, --reserved-words RESERVED_WORDS
                        List of comma separated words that should not be
                        anonymized
  -s SALT, --salt SALT  Salt for IP and sensitive keyword anonymization
  -u, --undo            Undo reversible anonymization (must specify salt)
  -w SENSITIVE_WORDS, --sensitive-words SENSITIVE_WORDS
                        List of comma separated keywords to anonymize
  --preserve-prefixes PRESERVE_PREFIXES
                        List of comma separated IPv4 prefixes to preserve

対応ベンダー

残念ながら一覧になっているドキュメントが見当たりませんでした。 例示されているのは Cisco です。試せてもいませんが、過去の issue などを見ると他に、Juniper、Arista について言及するものはありました。

まとめ

ネットワークコンフィグファイルを「匿名化」するツール netconan をご紹介しました。 この手の作業は意外と手間で、漏れも発生しがちなので、本ツールの活用を検討してみてはいかがでしょうか。

DevLOVE X、やらかした(いい意味で)

■ DevLOVE X とは

f:id:akira6592:20190629211239j:plain

2019/06/22 - 23 に、DevLOVE X を開催しました。 devlove.doorkeeper.jp devlove.wixsite.com

DevLOVE X は、DevLOVEという開発(Develop)を愛する人たちのコミュニティの10周年を記念したイベントです。ことの始まりは2008年6月21日。つまり実際は丸11年だったりもします。

2days、60を超えるセッション、5トラックという規模感です。

資料まとめ

まとめありがとうございます。

DevLOVE Xのスライドまとめ #devlovex - 名前考えるの苦手

devlovex を含むはてブ

はてブありがとうございます。

本文 「devlovex」 を検索 - はてなブックマーク

toggeter

まとめありがとうございます。

devlovexに関連する86件のまとめ - Togetter


■ スタッフをやってきました

このイベントのスタッフとして数ヶ月間関わってきました。当日はルームDという部屋の司会を2日間担当しました。twitterの反応を見ながら1日目と2日目のやり方を少し変えたりしました。

続々と揃う登壇者の面々、集まる参加者。そして当日の熱気。 もちろんここまででも充実感に満たされたのですが、その後もぞわぞわした感触に見舞われました。


■ 続々と集まる参加、登壇報告ブログ

その感触は、イベント後に続々とアップされる参加報告によるものでした。やらかしたぞ、これは、と。登壇者によるすばらしいセッションの数々と、参加者によるアウトプットという行動に感謝です。ブログ書くのは初めてという方もいらっしゃって、そんな機会を作れたことをとてもうれしく思います。

ここでは感謝の意味を込めて、私が見つけられた範囲で、参加や登壇、スタッフ報告のブログをまとめます。

ykmc09.hateblo.jp shinyorke.hatenablog.com poohsunny.hatenablog.com iwakiri.hatenablog.com takaking22.com note.mu hub.attractor.co.jp daiksy.hatenablog.jp blog.samuraikatamaris.red note.mu run-around.hatenablog.com keinumata.hatenablog.com www.tsuyok.work note.mu medium.com www.yohhatu.com sun0range.com makow.hatenablog.com shinkufencer.hateblo.jp shinkufencer.hateblo.jp tenten0213.hatenablog.com sun0range.com shacho.beproud.jp arclamp.hatenablog.com hmatsu47.hatenablog.com hmatsu47.hatenablog.com kobase16.hatenablog.com note.mu note.mu note.mu sadayoshi-tada.hatenablog.com note.mu note.mu medium.com note.mu note.mu note.mu

■ さいごに

登壇者みなさま、スポンサー各社さま、会場提供&当日スタッフしていただいたナビタイムジャパンさま、そしてご参加いただいたみなさま、ありがとうございました!

スタッフのみなさんもおつかれさまでした!!

[Ansible] ネットワークプラットフォームのバージョンとサポートの関係

はじめに

Ansible は、Ansible 2.8 現在 50以上のネットワークプラットフォームに対応しています。

プラットフォームごとに、どのバージョンでテスト、サポートされているかの情報が、探すのにやや手間取ってしまうので、こちらにリンクまとめておきます。

Ansible Network Team でメンテナンスされているネットワークモジュール

docs.ansible.com

Ansible のバージョンとネットワークプラットフォームのバージョンのマトリックス

access.redhat.com

その他 参考

www.redhat.com

[Ansible] 小ネタ: Playbook は JSON で書ける

はじめに

※あくまで小ネタの話なので実運用で利用するのはおすすめしません。

YAML は JSON のほぼスーパーセットなのであれば、JSON で Playbook を書けるのでは?と思ったことがあったので試してみました。

Playbook

$ cat test.yml 
[
  {
    "gather_facts": false, 
    "connection": "local", 
    "tasks": [
      {
        "debug": {
          "msg": "hello!"
        }
      }
    ], 
    "hosts": "localhost"
  }
]
  • (参考) 上記 Playbook を通常通り YAML で書いた場合
- hosts: localhost
  gather_facts: false
  connection: local
  
  tasks:
    - debug:
        msg: "hello!"

YAML から JSON への変換を試すには、このようなサービスを利用するとお手軽です。

実行

$ ansible-playbook -i localhost, test.yml 

PLAY [localhost] ******************************************************************************

TASK [debug] **********************************************************************************
ok: [localhost] => {
    "msg": "hello!"
}

PLAY RECAP ************************************************************************************
localhost                  : ok=1    changed=0    unreachable=0    failed=0   

できました。(Ansible 2.7)

Playbook のリストやディクショナリの関係がよく分からなくなったりした場合、JSONで書いたり眺めたりすると良い練習になるかも知れません。

補足

Ansible では YAML 1.1 を扱いますが、YAML 1.2 の仕様には

The primary objective of this revision is to bring YAML into compliance with JSON as an official subset.

という記載があります。

[Ansible] エラー「paramiko is not installed: No module named 'paramiko'」の原因と対策

■ エラーの原因と対策

Ansible コントールノードに paramiko (PythonSSHクライアント実装ライブラリ)がインストールされていない環境で、Ansible を実行すると、以下のようなエラーが表示されて異常終了してしまいます。

fatal: [iosao1]: FAILED! => {"msg": "paramiko is not installed: No module named 'paramiko'"}

対策としては、paramiko をインストールします。

pip install paramiko


■ 補足

Ansible 2.8 以降でネットワークモジュール利用時に注意

Ansible 2.7 台までは、 paramiko も一緒にインストールされる構成でしたが、Ansible 2.8 から一緒にインストールされない構成になりました。

2.8 からのドキュメントにも関連の記述が追記されました。

In order to use the paramiko connection plugin or modules that require paramiko, install the required module

paramiko was included in Ansible’s requirements.txt prior to 2.8.

これでも、例えばサーバーに対して ssh コネクションプラグインで接続する場合は問題ありません。paramiko を利用しないためです。 一方で、ネットワークモジュールとセットで利用する network_cli コネクションプラグインで接続する場合は、内部で paramiko を利用するため paramiko がないと前述のようなエラーになってしまいます。

例えば以下のような Playbook です。

- hosts: iosal
  gather_facts: no
  connection: network_cli

  tasks:
    - name: show version
      ios_command:
        commands:
          - show version

2.7 からのアップデートの場合は paramiko が残る

Ansible 2.7 までのバージョンから 2.8 にアップデートすると、paramiko は残ります。 そのため、「Ansible 2.8 の環境なのに、paramiko がないエラーが出る環境と出ない環境がある」という現象が起こりえます。

  • Ansible 2.7.10 から pip install -U ansible して 2.8.0 にアップデートした場合
$ pip list
Package      Version
------------ -------
ansible      2.8.0  
asn1crypto   0.24.0 
bcrypt       3.1.6  
cffi         1.12.3 
cryptography 2.6.1  
Jinja2       2.10.1 
MarkupSafe   1.1.1  
paramiko     2.4.2    <--
pip          10.0.1 
pyasn1       0.4.5  
pycparser    2.19   
PyNaCl       1.3.0  
PyYAML       5.1    
setuptools   39.0.1 
six          1.12.0 
  • Ansible 2.8 を新規インストールした場合の pip list
$ pip list
Package      Version
------------ -------
ansible      2.8.0  
asn1crypto   0.24.0 
cffi         1.12.3 
cryptography 2.6.1  
Jinja2       2.10.1 
MarkupSafe   1.1.1  
pip          10.0.1 
pycparser    2.19   
PyYAML       5.1    
setuptools   39.0.1 
six          1.12.0 

ncclient インストールで一緒に paramiko もインストールされる

Junos モジュールなどではnetconf コネクションプラグインで接続します。そのため、NETCONF 接続 Python ライブラリである ncclient を別途インストールします。 この際、paramiko も一緒にインストールされる構成になっています。

[Ansible] Ansible 2.8 リリース、便利機能や注意点まとめ

f:id:akira6592:20190517162018p:plain:w400

■ はじめに

2019/05/16 に Ansible 2.8.0 がリリースされました。多数のモジュールの追加や、機能追加、バグ修正機能削除機能の非推奨化、仕様変更が含まれています。

大きめなトピックとしては以下のものがあります。

この記事では、CHANGELOGPorting Guide を中心に、気になった点と関連URLをまとめます。 特性が分かるように、主観ですが「便利」「地味に便利」「ちょっと注意」というタグのようなものをつけています。

また、★ 印があるものは、2019/05/31 開催予定の Ansible Night in Osaka 2019.05でもご紹介する予定です。リモート参加枠もありますので、よろしければご参加ください。

[2019/06/01追記] 当日の発表資料です。

www.slideshare.net

特に CHANGELOG は、それでだけ見てもどういったことが分かりにくいものもありますので、関連URLも参考にしていただくと良いかと思います。Ansible 2.8 へのアップデート判断の材料になれば幸いです。

■ 変更

全体

権限昇格

ansible-galaxy

制御 / jinja2 / 変数

インベントリ

環境

ファイル

システム

Windows

ネットワーク


■ 新規プラグイン

コネクションプラグイン

インベントリプラグイン

Lookup


■ 新規モジュール

Cloud

Files

Monitoring

Net Tools

Network

Notification

Source Control

System


■ まとめ

Ansible 2.8.0 、CHANGELOGPorting Guide を中心に、気になった点と関連URLをまとめました。

基本的には便利になりますが、非推奨として残しておいたものの削除や、paramiko の非同梱化など、ちょっとした注意点もありました。

[Ansible] restconf_get モジュールで Cisco IOS XE のインターフェース情報を取得してみる

■ はじめに

Ansible 2.8 では、RESTCONF でネットワーク機器の情報を取得したり、設定を変更したりできる RESTCONF モジュールが導入されます。(本記事執筆時現在 RC段階)

この記事では restconf_get モジュールを利用して、IOS-XE へ RESTCONF でアクセスしてインターフェース情報の取得を試してみます。(後述しますが、そのままではうまくいかなかったので、暫定対処として一部コードの修正をして試しました → Ansible 2.8.2 でバグ解消済み)


■ 環境

  • Cisco IOS-XE (16.8)
    • Cisco DevNet SandBox
      • NETCONF-YANG and RESTCONF Always-On
      • netconf-yangrestconf コマンド有効
  • Ansible 2.8.0rc1
    • 本記事執筆時現在 RC段階のため、pip install ansible==2.8.0rc1 でインストール

■ 準備

Playook 実行に必要なファイルや Playbook を作成していきます。

インベントリファイル

ホスト情報を示すインベントリファイルを作成します。

  • inventory
[ios]
iosao1 ansible_host=ios-xe-mgmt.cisco.com

変数定義ファイル

インベントリファイルで定義したグループ ios が利用する変数を定義するファイルを作成します。

  • group_vars/ios.yml
ansible_connection: httpapi
ansible_httpapi_port: 9443
ansible_network_os: restconf
ansible_user: root
ansible_password: p@ss9999
ansible_httpapi_use_ssl: yes
ansible_httpapi_validate_certs: no

変数の説明

変数が多数登場しますのでそれぞれ説明します。

  • ansible_connection
  • ansible_httpapi_port
    • 利用するポートを指定します。SSH 接続では ansible_portansible_ssh_port 変数でポート番号を指定しますが、ansible_httpapi_port であることにご注意ください。
    • デフォルトは、変数 ansible_httpapi_use_ssl の値によって変わります。yes の場合は 443no の場合は 80 です。
    • ここでは、環境の都合により 9443 を指定しています。
  • ansible_network_os
    • ネットワークOSを指定します。
    • ios_configjunos_config モジュールなどのベンダー個別モジュールを利用する場合はこの変数は iosjunos といった値を指定しますが、RESTCONF モジュールを利用する場合は、このように restconf を利用します。こうすることで、restconf という httpapi プラグインが利用されます。
    • もし、例えば ios を指定した場合は unable to load API plugin for network_os ios というエラーが表示されます。
  • ansible_user
    • ユーザー名を指定します。
  • ansible_password
    • パスワードを指定します。ここではダミーの値を記載しています。必要に応じて ansible-vault で暗号化します。
  • ansible_httpapi_use_ssl
  • ansible_httpapi_validate_certs
    • SSL/TLS 接続する場合に証明書をかどうかを指定します。デフォルトは yes です。
    • ここでは、環境の都合により no を指定しています。

Playbook

処理内容を記載する Playbook を作成します。

  • restconf.yml
- hosts: ios
  gather_facts: no

  tasks:
    - name: restconf test
      restconf_get:
        path: /data/ietf-interfaces:interfaces
      register: result

    - name: debug result
      debug:
        msg: "{{ result }}"

path は Cisco DevNet Learning Labs の「Exploring IOS XE YANG Data Models with RESTCONF」や、こちらのサンプルに出てきたものを利用します。

restconf モジュールでは、root_path としてデフォルトで /restconf が定義されているため、実際には、/restconf 以降を path に指定します。


■ 実行(失敗)

それでは、Playbook を実行します。が、エラーになってしまいます。

$ ansible-playbook -i inventory restconf.yml

(...略...)
fatal: [iosao1]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "code": 406, "msg": "HTTP Error 406: Not Acceptable"}
(...略...)

HTTP Error 406: Not Acceptable とのことなので、HTTP の Acceppt フィールドまわりを調査しました。

原因調査と暫定対処

Ansible ではなく Postman で同様の GET を試すと以下の結果になりました。

  • Accept: application/yang-data+json では正常に json で情報が取得できた
  • Accept: では 406: Not Acceptable になった
  • Accept フィールド自体を指定しない場合は、XML で情報が取得できた

また、lib/ansible/module_utils/network/restconf/restconf.py を見ると、以下のようになっていました。

    accept = None
    if output == 'xml':
        accept = 'application/yang.data+xml'

    connection = Connection(module._socket_path)
    return connection.send_request(None, path=path, method='GET', accept=accept)

どうやら、Accept フィールドが空になってしまっていたようです。

暫定対処として、

    accept = None

の箇所を

    accept = 'application/yang-data+json'

に修正しました。


■ 再実行(成功)

暫定対処したところで、再度同じ Playbook を実行します。

$ ansible-playbook -i inventory restconf.yml 

PLAY [ios] ***********************************************************************************************************************

TASK [restconf test] *************************************************************************************************************
 [WARNING]: Platform darwin on host iosao1 is using the discovered Python interpreter at /usr/bin/python, but future installation
of another Python interpreter could change this. See
https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information.

ok: [iosao1]

TASK [debug result] **************************************************************************************************************
ok: [iosao1] => {
    "msg": {
        "ansible_facts": {
            "discovered_interpreter_python": "/usr/bin/python"
        }, 
        "changed": false, 
        "failed": false, 
        "response": {
            "ietf-interfaces:interfaces": {
                "interface": [
                    {
                        "description": "DON'T TOUCH ME", 
                        "enabled": true, 
                        "ietf-ip:ipv4": {
                            "address": [
                                {
                                    "ip": "10.10.20.48", 
                                    "netmask": "255.255.255.0"
                                }
                            ]
                        }, 
                        "ietf-ip:ipv6": {}, 
                        "name": "GigabitEthernet1", 
                        "type": "iana-if-type:ethernetCsmacd"
                    }, 
                    {
                        "enabled": true, 
                        "ietf-ip:ipv4": {}, 
                        "ietf-ip:ipv6": {}, 
                        "name": "GigabitEthernet2", 
                        "type": "iana-if-type:ethernetCsmacd"
                    }, 
                    {
                        "enabled": false, 
                        "ietf-ip:ipv4": {}, 
                        "ietf-ip:ipv6": {}, 
                        "name": "GigabitEthernet3", 
                        "type": "iana-if-type:ethernetCsmacd"
                    }
                ]
            }
        }, 
        "warnings": [
            "Platform darwin on host iosao1 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change this. See https://docs.ansible.com/ansible/2.8/reference_appendices/interpreter_discovery.html for more information."
        ]
    }
}

PLAY RECAP ***********************************************************************************************************************
iosao1                     : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

こんどは正常にインターフェース情報を取得できました。

※ちらっと表示されている Python interpreter についての WARNING の詳細は こちらをご参照ください。


■ まとめ

Ansible 2.8 で導入される restconf_get モジュールで、Cisco IOS-XE のインターフェース情報を取得してみました。 (一部コード修正が必要だった点は、他の対応方法があるのかなどの点は現時点では不明です。)

RESTCONF が有効であれば、他のベンダーの機器にも使える雰囲気がします。ベンダーごとにモジュールを使い分けなくて良い点は便利そうだと感じました。

また、Cisco IOS-XE では、RESTCONF が使えるようになってきているようなので、今後 RESTCONF は自動化の手段の選択肢になり得るのではないかと思います。

[2019/05/27 追記] 少しに気なる issue を見つけました。

restconf httpapi plugin Media Type · Issue #56680 · ansible/ansible · GitHub

[2019/09/06 追記] Ansible 2.8.2 で修正されていることを確認しました。 ansible/CHANGELOG-v2.8.rst at stable-2.8 · ansible/ansible · GitHub

Fix media type of RESTCONF requests.

[2019/09/09 追記] 設定変更編を投稿しました。

tekunabe.hatenablog.jp