■ 現象: 特権ユーザーにもかかわらずエラーに
特定条件下で、Ansible の ios_config
モジュール使用時に、特権ユーザーを利用しているにもかかわらず、operation requires privilege escalation
というエラーが表示され、Playbook の処理が中断されてしまう不具合があります。
通常であれば、operation requires privilege escalation
というエラーは、コンフィグ投入などの特権が必要な操作を、特権でない状態で実行しようとしたときに表示されるエラーです。この不具合では、特権ユーザーであってもこのエラーが表示されてしまいます。
この不具合は数ヶ月見守っていたのですが、ここ最近で修正の動きがあったため、記事にまとめました。
■ 発生条件
私が試したり、調べたりした範囲では、以下のような発生条件となりました。
コマンド実行結果の取得に時間がかかり、コマンド実行結果に `>` が含まれる
検証環境は Ansible 2.7.0 です。
どうやら、処理に時間がかかるとプロンプト以外に >
が含まれている場合、それをユーザー(非特権)EXEC モードのプロンプトの一部として解釈してしまい「権限がないのでこのコマンドは実行できない」という判断になってしまうようです。
- (参考)プロンプトの例
iso1> # ユーザーEXECモードの例 ios1> enable ios1# # 特権EXECモードの例
プロンプト以外に >
が含まれる可能性があるのは、インターフェースの description や、SNMP コミュニティ名、ACL名などです。
対象バージョンの範囲は、こちらのコメントの
The root cause of the issue is in the fix made in PR #39063 (from 2.5.2 onwards) to handle the ios device on which \r\n characters are not prefixed before prompt
を含めて考えると以下のようになると思います。 (2.7.0以外未検証)
- 2.5 系: 2.5.2 以降
- 2.6 系: 2.6.0 以降
- 2.7 系: 2.7.0 (現状本バージョンのみ)
■ 対策見込み
修正分が Ansible 2.7.1 としてリリースされる予定です。
このリリースでは、 network_cli
コネクションプラグインのパラメーターとして、 persistent_buffer_read_timeout
が追加される予定です。このパラメーターで、プロンプトを解釈するタイミングを調整して対策することになります。デフォルトは 0.1 秒です。
network_cli
コネクションプラグインのパラーメーター一覧
なお現状、2.7.1はリリースされていませんが、
pip install git+https://github.com/ansible/ansible.git@stable-2.7
でインストールできるバージョン「ansible 2.7.0.post0」で確認したところ、エラーは出なくなりました。
場合に読もると思いますが、persistent_buffer_read_timeout
は調整不要でした。
[2018/10/26 追記] Ansible 2.7.1 がリリースされました。 https://github.com/ansible/ansible/blob/stable-2.7/changelogs/CHANGELOG-v2.7.rst#v2-7-1
Fix prompt mismatch issue for ios (https://github.com/ansible/ansible/issues/47004)
■(参考)検証内容詳細
私が検証した方法を記載します。
コンフィグテンプレートの準備
現象を再現するための仕込みのコンフィグとして、以下を準備します。
- snmp.j2
{% for i in range(200) %} snmp-server community com{{ i }} RO h>oge {% endfor %}
コマンドの最後のオプション(ACL名)であるh>oge
に >
を含めているのがポイントです。
この Jinja2 テンプレートは、以下のようなコマンドを生成します。
snmp-server community com0 RO h>oge snmp-server community com1 RO h>oge snmp-server community com2 RO h>oge ...(略)... snmp-server community com198 RO h>oge snmp-server community com199 RO h>oge
Playbook の準備
- set_snmp.yml
- hosts: iosprg gather_facts: no tasks: - name: set snmp ios_config: src: snmp.j2 vars: ansible_command_timeout: 300 # 投入に時間がかかるためデフォルト 10 秒より伸ばす
コンフィグの仕込み
準備したコンフィグテンプレートをいったん流し込みます。
$ ansible-playbook -i inventory.ini insert.yml
これで準備が整いました。
再現試行
対象機器が、
- コマンド実行結果の取得に時間がかかり、コマンド実行結果に
>
が含まれる
という状態になったところで、もう一度同じ Playbook を実行します。通常であれば、変更なしで正常終了するはずです。
$ ansible-playbook -i inventory.ini set_snmp.yml PLAY [iosprg] ******************************************************************************************************************* TASK [set snmp] *************************************************************************************************************** An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible.module_utils.connection.ConnectionError: operation requires privilege escalation fatal: [iosprg1]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n File \"/home/vagrant/.ansible/tmp/ansible-local-6780JjM2oM/ansible-tmp-1540298326.36-234692567510359/AnsiballZ_ios_config.py\", line 113, in <module>\n _ansiballz_main()\n File \"/home/vagrant/.ansible/tmp/ansible-local-6780JjM2oM/ansible-tmp-1540298326.36-234692567510359/AnsiballZ_ios_config.py\", line 105, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File \"/home/vagrant/.ansible/tmp/ansible-local-6780JjM2oM/ansible-tmp-1540298326.36-234692567510359/AnsiballZ_ios_config.py\", line 48, in invoke_module\n imp.load_module('__main__', mod, module, MOD_DESC)\n File \"/tmp/ansible_ios_config_payload_4kli5Q/__main__.py\",line 536, in <module>\n File \"/tmp/ansible_ios_config_payload_4kli5Q/__main__.py\", line 467, in main\n File \"/tmp/ansible_ios_config_payload_4kli5Q/__main__.py\", line 328, in edit_config_or_macro\n File \"/tmp/ansible_ios_config_payload_4kli5Q/ansible_ios_config_payload.zip/ansible/module_utils/connection.py\", line 173, in __rpc__\nansible.module_utils.connection.ConnectionError: operation requires privilege escalation\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1} to retry, use: --limit @/vagrant/demo/insert.retry PLAY RECAP ********************************************************************************************************************** iosprg1 : ok=0 changed=0 unreachable=0 failed=1
operation requires privilege escalation
というエラーが発生しました。
ios_config
モジュールは、指定されたコンフィグ投入前の事前コンフィグを取得処理があるため、その際に >
が引っかかってしまったのではないかと思います。
なお、ACL名のところを変えていくつかのパターンで試したところ、以下のような結果になりました。
- エラー発生
h>oge
hoge>
- 正常
hoge
■ 関連 issue / PR
issue github.com
devel ブランチへのマージ github.com
stable-2.7 ブランチへのマージ github.com