ちゃんと普通に考えたら当たり前なんですけど、普段SELinuxが無効な環境で作業していると、軽くはまるので備忘で残しておきます。
Apacheを設定する次のような素朴なタスクを定義しているとしましょう。
roles/web/tasks/main.yml
---
- yum: name=httpd state=installed
- service: name=httpd state=running enabled=yes
実行するとApacheがインストールされて、起動します。
$ ansible-playbook -i hosts.ini vagrant.yml
PLAY [web] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [yum name=httpd state=installed] ****************************************
changed: [192.168.33.12]
TASK: [service name=httpd state=running enabled=yes] **************************
changed: [192.168.33.12]
PLAY RECAP ********************************************************************
192.168.33.12 : ok=3 changed=2 unreachable=0 failed=0
この後、設定ファイルを追加したくなったとします。
roles/web/tasks/main.yml
---
- yum: name=httpd state=installed
- template: dest=/etc/httpd/conf.d/ltsv.conf src=etc/httpd/conf.d/ltsv.conf.j2 owner=root group=root mode=0644
notify: restart httpd
- service: name=httpd state=running enabled=yes
これは失敗してしまいます。
$ ansible-playbook -i hosts.ini vagrant.yml
PLAY [web] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [yum name=httpd state=installed] ****************************************
ok: [192.168.33.12]
TASK: [template dest=/etc/httpd/conf.d/ltsv.conf src=etc/httpd/conf.d/ltsv.conf.j2] ***
changed: [192.168.33.12]
TASK: [service name=httpd state=running enabled=yes] **************************
ok: [192.168.33.12]
NOTIFIED: [restart httpd] *****************************************************
failed: [192.168.33.12] => {"failed": true, "item": ""}
msg: httpd: Syntax error on line 221 of /etc/httpd/conf/httpd.conf: Could not open configuration file /etc/httpd/conf.d/ltsv.conf: Permission denied
PLAY RECAP ********************************************************************
to retry, use: --limit @/var/tmp/ansible/vagrant.retry
192.168.33.12 : ok=4 changed=1 unreachable=0 failed=1
「Permission denied」って言われて意味が分からなくなりますが、ls -Z
としてみると分かります。
$ vagrant ssh -- ls -Z /etc/httpd/conf.d
-rw-r--r--. root root system_u:object_r:httpd_config_t:s0 README
-rw-r--r--. root root unconfined_u:object_r:user_home_t:s0 ltsv.conf
-rw-r--r--. root root system_u:object_r:httpd_config_t:s0 welcome.conf
セキュリティコンテクストがよろしくないですね。というわけで、ファイルを変更したり追加した時にはrestorecon
コマンドを呼び出すようにします。
roles/web/tasks/main.yml
---
- yum: name=httpd state=installed
- template: dest=/etc/httpd/conf.d/ltsv.conf src=etc/httpd/conf.d/ltsv.conf.j2 owner=root group=root mode=0644
notify:
- restorecon /etc/httpd/conf.d
- restart httpd
- service: name=httpd state=running enabled=yes
roles/web/handlers/main.yml
---
- name: restorecon /etc/httpd/conf.d
command: /sbin/restorecon -R /etc/httpd/conf.d
- name: restart httpd
service: name=httpd state=restarted
hanlers/main.yml
の中身は書いた順番に実行されます、つまり、restart httpd
より 先に restorecon
を書かなくてはいけません。restorecon
を後から付け足す時なんか忘れがちなので注意。
これでうまくいきます。
$ ansible-playbook -i hosts.ini vagrant.yml
PLAY [web] ********************************************************************
GATHERING FACTS ***************************************************************
ok: [192.168.33.12]
TASK: [yum name=httpd state=installed] ****************************************
ok: [192.168.33.12]
TASK: [template dest=/etc/httpd/conf.d/ltsv.conf src=etc/httpd/conf.d/ltsv.conf.j2 owner=root group=root mode=0644] ***
changed: [192.168.33.12]
TASK: [service name=httpd state=running enabled=yes] **************************
ok: [192.168.33.12]
NOTIFIED: [restorecon /etc/httpd/conf.d] **************************************
changed: [192.168.33.12]
NOTIFIED: [restart httpd] *****************************************************
changed: [192.168.33.12]
PLAY RECAP ********************************************************************
192.168.33.12 : ok=6 changed=3 unreachable=0 failed=0
Ansibleのfileモジュールにはselevel
、serole
、setype
、seuser
というSELinux用のオプションがありますが、(普通)/etc/httpd
全体としてセキュリティコンテクストの設定がされているので、それ以下であればわざわざ設定しなくても大丈夫です。
$ vagrant ssh -- grep /etc/httpd /etc/selinux/targeted/contexts/files/file_contexts
/etc/httpd(/.*)? system_u:object_r:httpd_config_t:s0
/etc/httpd/alias(/.*)? system_u:object_r:cert_t:s0
/etc/httpd/logs system_u:object_r:httpd_log_t:s0
/etc/httpd/modules system_u:object_r:httpd_modules_t:s0
/etc/httpd/conf/keytab -- system_u:object_r:httpd_keytab_t:s0