Ansible

AnsibleのCopyモジュールでsudoers.d配下にファイル追加をしたらroot権限がお亡くなりになった

More than 1 year has passed since last update.

こんなエラーが吐かれたあと、sudo権限がお亡くなりになった。

TASK [users : copy sudoers] *****************************************************************************************************************************************************************changed: [ipaddress] => (item={u'dest': u'.', u'src': u'roles/users/files/usersfile'})

fatal: [ipaddress]: FAILED! => {"failed": true, "msg": "Failed to get information on remote file (/etc/sudoers.d/.): Shared connection to ipaddress closed.\r\n"}
to retry, use: --limit @xxx.retry

ansibleの公式を見るとわかるが、sodoers関連の管理はlineinfileモジュールを使うのが定石のよう。

# Validate the sudoers file before saving

- lineinfile:
path: /etc/sudoers
state: present
regexp: '^%ADMIN ALL='
line: '%ADMIN ALL=(ALL) NOPASSWD: ALL'
validate: 'visudo -cf %s'


http://docs.ansible.com/ansible/lineinfile_module.html



で、原因は?

諸説あり。今後、正確に特定したい。

今回確認したところをメモ。


追記 2017/5/16

改行コードが原因だった。

MacとWindowsとでは改行コードが異なる。

windowsの改行コードはCRLFだ。


備忘録:改行コード「LF」と「CR」と「CRLF」の違い



解決策


  • Windowsで使用していたAtomの設定を変える

「OSデフォルトの文字コードを使用する」設定になっていた。

なので、Atomユーザは以下の記事を参考にして改行コード設定をLFに変換しておく。


Atomエディタ上からファイルを新規作成する際のデフォルトの改行コードを設定する(Windows環境)



  • .gitconfigで改行コードの設定をする

MacからPushしたコードの改行コードはLFなのに、windowsでPullしたコードはCRLFになってしまったりするので、設定を追記しておく。


windows環境の git で改行コードの自動変換に注意



  • 試しに新規作成したファイルの改行コードを確認

以下のコマンドで改行コードを確認できる。

$がついていれば改行コードLF。

$ cat -e <filename>

また、Atomユーザは右下のステータスで簡単に改行コードを確認・変更ができる。


sudoers.d配下のファイルアクセス権が変わった?

検証環境のサーバで試しにアクセス権を640に変更して、そのユーザがsudoになることができないか試したが、sudoが使用できたので違うっぽい。


ソースコードをvisudo -cfしたらsyntax errorだった

いやもうこれだろって感じ。ただ、ファイルの内容は既存のファイルからコピーしたものだった。


bash on Windowsから実行したことによる文字コード

上記のsyntax errorが出ていた理由はこれではないか。

サーバに設定されていた文字コードはASCII (LF)

失敗した際の文字コードはASCII (CRLF)だった。

実行環境(Windows、Mac、Linuxなど)によって差分がある説。


対応策


  • Copyモジュールでsudoers.d/にファイルを置くのではなく/etc/sudoersに直接記述させる

  • syntaxチェックをするコマンドを叩かせる

  • 万が一root権限が死んでもvisudo出来る方法を確立させる


Copyモジュールでsudoers.d/にファイルを置くのではなく/etc/sudoersに直接記述させる

冒頭の通り、lineinfileモジュールとregexpを使って記述するように変える。


syntaxチェックをするコマンドを叩かせる

まるまる引用で申し訳ないが、commandモジュールを使って万が一に備える方法って感じ。

Ansible的にはcommand、Shellモジュールを使うのは冪等性が保てないので、やるとしても最終手段という認識。

そして今回はその最終手段を使うべきとき。

tasks:

- name: Copy sudoers file for safety
command: cp -f /etc/sudoers /etc/sudoers.tmp

- name: Create sudoers file backup
command: cp -f /etc/sudoers /etc/sudoers.bak

- name: Create admins group
group: name=admins system=yes state=present

- name: make sure we can sudo as admin group
lineinfile: dest=/etc/sudoers.tmp state=present regexp='^%admin' line='%admin ALL=(ALL) ALL'

- name: also make sure ssh-agent works via sudo
lineinfile: dest=/etc/sudoers.tmp state=present regexp='^Defaults env_keep\+\=SSH_AUTH_SOCK' line='Defaults env_keep+=SSH_AUTH_SOCK'

- name: Final sudoers file check
shell: visudo -q -c -f /etc/sudoers.tmp && cp -f /etc/sudoers.tmp /etc/sudoers


sudoers safety and sanity checking in playbook



万が一root権限が死んでもvisudo出来る方法を確立させる

root権限がない時点でお手上げ。と思いきや、探せばあるもので。

pkexec visudoコマンドでなんとスーパーユーザでvisudoを実行できるらしい。

ただ、このpkexecは予めインストールしてないと打てない・・・。今回の件のように、お亡くなりになってからでは遅いので注意。

今回はスナップショットで復元することになった・・・。これがあればサーバを止めなくてもよかったなあ。


/etc/sudoersがsyntax errorでsudo使えなくなった時の対処法



おわりに

sudo関連は怖い。と、同時に、万が一に備えてrootになる方法を把握しておかなければならないなと思った。

「amazonLinuxはデフォルトでrootユーザになれないので、cfgをいじる必要がある」とかも知らなかった。