こんなエラーが吐かれたあと、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'
で、原因は?
諸説あり。今後、正確に特定したい。 今回確認したところをメモ。
追記 2017/5/16
改行コードが原因だった。 MacとWindowsとでは改行コードが異なる。 windowsの改行コードはCRLFだ。
解決策
- Windowsで使用していたAtomの設定を変える
「OSデフォルトの文字コードを使用する」設定になっていた。 なので、Atomユーザは以下の記事を参考にして改行コード設定をLFに変換しておく。
[Atomエディタ上からファイルを新規作成する際のデフォルトの改行コードを設定する(Windows環境)] (http://qiita.com/nyoro_712/items/8c80e32aa49f7a2d2eaf)
- .gitconfigで改行コードの設定をする
MacからPushしたコードの改行コードはLFなのに、windowsでPullしたコードはCRLFになってしまったりするので、設定を追記しておく。
- 試しに新規作成したファイルの改行コードを確認
以下のコマンドで改行コードを確認できる。 $がついていれば改行コード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
万が一root権限が死んでもvisudo出来る方法を確立させる
root権限がない時点でお手上げ。と思いきや、探せばあるもので。
pkexec visudo
コマンドでなんとスーパーユーザでvisudoを実行できるらしい。
ただ、このpkexec
は予めインストールしてないと打てない・・・。今回の件のように、お亡くなりになってからでは遅いので注意。
今回はスナップショットで復元することになった・・・。これがあればサーバを止めなくてもよかったなあ。
おわりに
sudo関連は怖い。と、同時に、万が一に備えてrootになる方法を把握しておかなければならないなと思った。 「amazonLinuxはデフォルトでrootユーザになれないので、cfgをいじる必要がある」とかも知らなかった。