0

何度も要求されるパスワード入力を省略する(sudoersファイルについて②)

特定のソフトウェアを使っていると内部的に sudo を実行しており、毎回パスワードの入力を要求されて面倒!ということがあると思います。例えばVagrantのsynced_folder機能をnfsで使っていると vagrant up の度にパスワードを入力しなければなりませんが、正直面倒ですね。
というわけでパスワード入力を省略したいです。でもなんでもかんでもパスワード無しで sudo できてしまうのは怖いので、特定のコマンドだけパスワード無しでも sudo できるようにする方法の解説です。

***ご自身の責任の元に信頼できる相手だけに sudo 権限を渡すようにしてください。***

■ sudo しているコマンドを把握する

まずはパスワード入力を求められた際に、ソフトウェアの内部で実行しているコマンドが何なのか知らなければいけません。

それを知るにはシステムログを見るのが手っ取り早いです。環境によりけりですが、
Linuxは /var/log/secure 、Macはデフォルトで /var/log/system.log に書きだすようです。
ご自身の環境についてはsyslogとかrsyslogの設定ファイルに記載があります。

sudo が実行されると全てのログが出てくるので tail しときます。

tail -f /var/log/system.log | grep sudo

この状態でそのパスワード入力を要求してくるソフトウェアを実行し、実際にパスワードを入力したりすると、ここにもりもりとログが出てきます。
例えば vagrant up するとこんなログが得られます。(分かりやすいように若干加工しています)

% tail -f /var/log/system.log | grep sudo | cut -d';' -f 4
 COMMAND=/usr/bin/sed -E -e /^# VAGRANT-BEGIN:( 501)? ad65f9aa-b0f6-4c6a-820b-f8e51d79ab3e/,/^# VAGRANT-END:( 501)? ad65f9aa-b0f6-4c6a-820b-f8e51d79ab3e/ d -ibak /etc/exports
 COMMAND=/bin/zsh -c echo '# VAGRANT-BEGIN: 501 ad65f9aa-b0f6-4c6a-820b-f8e51d79ab3e' >> /etc/exports
 COMMAND=/bin/zsh -c echo '"/Users/hachim.jp/src/qiita" 192.168.33.11 -alldirs -mapall=501:20' >> /etc/exports
 COMMAND=/bin/zsh -c echo '# VAGRANT-END: 501 ad65f9aa-b0f6-4c6a-820b-f8e51d79ab3e' >> /etc/exports
 COMMAND=/sbin/nfsd restart

というわけでこれらのコマンドを sudo できれば vagrant up 時のパスワード入力をスキップできることになります。

■ 特定コマンドをパスワードなしで sudo できるようにする

先ほどのコマンドをパスワード無しでroot権限で実行できるようにする設定は例えばこんな感じで書けます。

/etc/sudoers
hachim.jp mbp.local=(root) NOPASSWD: /bin/zsh -c echo '*' >> /etc/exports
hachim.jp mbp.local=(root) NOPASSWD: /sbin/nfsd restart
hachim.jp mbp.local=(root) NOPASSWD: /usr/bin/sed -E -e /*/\,/*/ d -ibak /etc/exports

詳しくはsudoers(5)を読んでもらうとして、軽く意味だけ説明すると

「hachim.jpユーザはmbp.localマシンでrootとしてパスワード無しでこれらのコマンドを実行できる」という意味になります。

コマンドの中に含まれる * はワイルドカードです。
3行目でやっているようにコマンド中に , が出てくる場合はバックスラッシュでエスケープする必要があります。

ところでmbp.localというのは僕のMACのマシン名なのでローカルマシンでのみ実行できることになります
(localhostとか127.0.0.1と入力してもローカルマシンという意味にはならないので注意)
ちなみにマシンの名前は uname -n で確認できます。

$ uname -n
mbp.local

どのマシンでも、どのユーザとしても実行できるようにするにはALLを指定します。手軽な反面権限が強いのでご利用は計画的に。

hachim.jp ALL=(ALL) NOPASSWD: /sbin/nfsd restart

■ Cmnd_Aliasを使って共通化

ただこれだとこれらの3つの設定が互いに関係しあったものだということが分かりませんし、権限を変えようと思うと3箇所も変えないといけなくて面倒なので、こういう時はCmnd_Aliasという機能を使います。

/etc/sudoers
Cmnd_Alias VAGRANT_EXPORTS_ADD = /bin/zsh -c echo '*' >> /etc/exports
Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/\,/*/ d -ibak /etc/exports
hachim.jp mba=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE

■ /etc/sudoersを編集する場合は必ず visudo を使う

ところで/etc/sudoersを直接編集しては 絶対にいけません
/etc/sudoersは変更したら、ファイルが正しかろうが文法に間違いがあろうが、即座にその効果が適用されます。

つまり、ファイルを壊したらあなたは sudo できなくなります。

sudo できないということは/etc/sudoers を編集することもできないので、
何かしらの方法で直接rootになるか、ストレージを外部マシンにマウントしてそっちで編集するとかでないと復旧できなくなります。

visudo は/etc/sudoersを編集する専用のコマンドで、
編集完了時に保存する前に構文をチェックして問題がある場合はロールバックしたりしてくれます。
名前を見るとViじゃないとダメな雰囲気がありますが、EDITOR環境変数を指定しているとそのエディタが使われます。

■ スクリプトから編集する場合は visudo -c -f

手動で編集する場合は visudo を使うとして、スクリプトなどから自動的に編集する場合は visudo -c -f を使うといいと思います。

-c はcheck-onlyオプションで変更を適用せずに構文のチェックだけを行い、 -f は外部ファイルをチェックするオプションです。

例えば既存のものに新しい設定を追記するスクリプトはこんな感じで書いておくと安心感があります。

# 一時ファイルを作成
tmp=`mktemp -t vagrant_sudors`
# /etc/sudoersの内容を取ってくる
cat /etc/sudoers > $tmp
# 追記したい内容
cat >> $tmp <> /etc/exports
Cmnd_Alias VAGRANT_NFSD = /sbin/nfsd restart
Cmnd_Alias VAGRANT_EXPORTS_REMOVE = /usr/bin/sed -E -e /*/\\,/*/ d -ibak /etc/exports
%staff `hostname`=(root) NOPASSWD: VAGRANT_EXPORTS_ADD, VAGRANT_NFSD, VAGRANT_EXPORTS_REMOVE
EOF
# 構文をチェック
visudo -c -f $tmp
if [ $? -eq 0 ]; then
    echo 'Vagrant用のコマンドをsudoersに追加'
    cat $tmp > /etc/sudoers
else
    echo '構文エラー。中止'
fi

rm -f $tmp

以上です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です