てくなべ (tekunabe)

ansible / network / automation / 学習の記録

[Ansible] httpd.conf を編集後にファイルの検証処理を挟む方法

はじめに

Ansible の lineinfilereplace などのファイルを編集するモジュールには validate オプションを備えているものがあります。

validate オプションには編集後のファイルの妥当性を検証するコマンドを指定します。 これにより、編集に問題がなければ処理を継続、問題があれば処理を停止、のようにワンクッション挟めるため安全性を高められます。

公式ドキュメントの lineinfile モジュールの Example には、/etc/sudoers 編集後に実行する validate オプションの例があります。

この記事では、 Apache httpd の設定ファイルである、httpd.conf を validete する Playbook の例をご紹介します。


サンプル Playbook の作成

以下のような簡単な Playbook を利用します。

- hosts: web
  gather_facts: no
  become: yes

  tasks:
    - name: configure Listen Port
      lineinfile:
        path: /etc/httpd/conf/httpd.conf
        regexp: '^Listen 80$'
        line: 'Listen 8080'
        validate: httpd -tf %s    # point
      notify:
        - restart httpd

  handlers:
    - name: restart httpd
      service:
        name: httpd
        state: restarted
        enabled: yes

処理は以下のとおりです。

  • lineinfile モジュールによりhttpd.conf^Listen 80$Listen 8080 に置換
    • 変更なしなら、終了
    • 変更ありなら、次へ
  • httpd -tf コマンドにて validate する
    • 問題ありなら、エラーで終了
    • 問題なしなら、次へ

validate: httpd -tf %s について補足

validate オプションには httpd -tf %s を指定しています。

httpd コマンドの -t オプションによって、httpd.conf に問題がないか検証できます。-f オプションを併用することで検証対象のファイルを明示指定できます。

%s は Ansible 側の仕様によるものです。lineinfile などのモジュールでは、編集対象のファイルを直接編集せず、編集用に一時ファイルを作成します。その一時ファイルのパスが %s に格納されます。

そのため、httpd -t のみの指定の場合、Ansible が編集した一時ファイルを検証の対象にしないでご注意ください。


Playbook の実行

validete が OK なパターンと NG なパターンそれぞれ試します。

OK パターン

$ ansible-playbook -i inventory.ini web.yml

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

TASK [configure Listen Port] ****************************************************************************************
changed: [localhost]

RUNNING HANDLER [restart httpd] *************************************************************************************
changed: [localhost]

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

validete に問題がなかったので、処理が継続されました。

NG パターン

Playbook で指定した置換後文字列の

        line: 'Listen 8080'

        line: 'Listen XXX'

にして試します。 httpd.conf の Listen は待受ポート番号を指定する項目のため、文字列が指定されると httpd -tf %s の validate によって Syntax Check になります。

$ ansible-playbook -i  inventory.ini web.yml
PLAY [localhost] ****************************************************************************************************

TASK [configure Listen Port] ****************************************************************************************
fatal: [localhost]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "failed to validate: rc:1 error:AH00526: Syntax error on line 43 of /tmp/tmpbcDcMD:\nPort must be specified\n"}

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

failed to validate: rc:1 error:AH00526: Syntax error on line 43 of /tmp/tmpbcDcMD:\nPort must be specified\n" というエラーメッセージとともに validate が NG となり、処理がエラーで停止されました。

手動で validate した場合は、以下の実行イメージです。

$ httpd -tf <対象httpd.conf>
AH00526: Syntax error on line 43 of <対象httpd.conf>:
Port must be specified


さいごに

もし validate オプションを指定しなかった場合、httpd.conf に問題があっても、ハンドラー restart httpd が呼ばれてしまい、再起動を試みたところで失敗し、httpd が停止したままになってしまいます。

validate オプションを有効に使うことで、このような自体を未然に防げます。

参考