VTRyo Blog

一歩ずつ前に進むブログ

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

f:id:vtryo:20180714235526p:plain こんなエラーが吐かれたあと、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環境)] (http://qiita.com/nyoro_712/items/8c80e32aa49f7a2d2eaf)

  • .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をいじる必要がある」とかも知らなかった。