ユニファ開発者ブログ

ユニファ株式会社プロダクトデベロップメント本部メンバーによるブログです。

sudoの設定ファイルsudoersについて

おはこんばんにちは!
ユニファのサービスインフラ担当のすずきです!

私の出身は京都なんですが、最近新宿で関西人の集まる酒場なるところを発見し潜入してみました!
するとそこには、関西人もしらないB級グルメとか大阪の地ビールとか、サン◯リアのサングリアとか色んな商品があったので、 気になる方はぜひ探してみてくださいw

どこかの回しもんみたいなことはこれくらいにして本題へ

いつもAWSとかのことばっかりやってるので今回はsudoの設定ファイル sudoers を取り上げてみようと思います。

sudoについて

人によってはとりあえず sudo つけて実行すれば管理者権限で実行できるんでしょ?みたいに思われるかもしれませんが、それは sudoers にてそのユーザは sudo 利用時にこのユーザの権限で、このコマンドは実行しても良いですよと許可をもらっているだけなんです。

Amazon Linux では ec2-user の所属するグループが、すべてのコマンドをすべてのユーザの権限として実行していいですよという権利をもらっているだけなのです。

Amazon Linuxのsudoers

Amazon Linux /etc/sudoers から権限設定している所抜き出してみます。

root ALL=(ALL)   ALL
%wheel  ALL=(ALL)   ALL

これは だれが[%をつけるとグループ] どこから[ホスト名とか]=(だれになって[カンマでグループも指定できる]) 実行できるコマンド を表しています。

root の場合で言うと、 ユーザrootは どこからでも=(すべてのユーザ、グループとして)  すべてのコマンドを実行できる になります。

%wheel はグループ名を表しているので、wheel グループに所属するユーザはすべてのユーザとしてすべてのコマンドを実行できるようになります。

また、sudoersのサブ?設定ファイルを /etc/sudoers.d/ 以下に配置できます。 その中に 90-cloud-init-users だったり cloud-init といったファイルが存在しているはずなので確認すると ec2-user が存在します。

ec2-user ALL=(ALL) NOPASSWD:ALL

新しく出てきた NOPASSWD はパスワードの確認が不要というものです。
NOPASSWD がない場合は、sudoを実行したユーザのパスワードが求められるのですが、新しく作成されたユーザなどパスワードがないユーザなどでは NOPASSWD を付けてやらないと実行できません。

ユーザ作って試してみる

適当なユーザを作ってみて結果をみてみます、ついでに %wheel ALL=(ALL) ALL の項目も試してみます。

$ sudo adduser test01
$ id test01
uid=1002(test01) gid=1002(test01) groups=1002(test01)

グループの状況を見ると gid=1002(test01) groups=1002(test01) なのでwheelグループに所属していないことがわかります。 このままでsudo実行するとパスワードが求められます。しかし、パスワードがないのとそもそもwheelに所属していないので何もできません。

$ sudo su - test01
(test01)$ tail -n /var/log/messages
tail: /var/log/messages: invalid number of lines
(test01)$ sudo tail /var/log/messages

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test01:

つづいて、wheelに所属させてみます。

$ sudo usermod -G wheel test01
$ id test01
uid=1002(test01) gid=1002(test01) groups=1002(test01),10(wheel)
$ sudo su - test01
(test01)$ sudo tail -n1 /var/log/messages

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test01:
^Csudo: 1 incorrect password attempt

やはり今回もパスワードが求められます。見た目上はかわらないですけど…

実行できるようにするには、sudoersのwheelの設定に NOPASSWD を入れてやる必用があります。 /etc/suders の修正には visudo というコマンドを利用します。

$ visudo

- %wheel  ALL=(ALL)      ALL
+ %wheel  ALL=(ALL)      NOPASSWD: ALL

問題なければ、viと同様の操作で保存してやればいいです。 もし構文をミスっていた場合は以下のように怒られるので、e を押して修正してください、q を押したが最後2度と sudo が実行できなくなるのでご注意ください。

>>> /etc/sudoers: syntax error near line 99 <<<
What now?
Options are:
  (e)dit sudoers file again
  e(x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)

What now? 

これは、/etc/suders.d/ 以下に放り込んだ際も同様です…
放り込む場合は事前に visudo -cf ファイル名 で構文チェックするのが良いかと思います。

話は戻って NOPASSWDwheel に追加したので確認します。

[ec2-user@localhost ~]$ sudo su - test01
Last login: Wed May 16 06:57:30 UTC 2018 on pts/0
[test01@localhost ~]$ sudo tail -n1 /var/log/messages
May 16 07:10:23 localhost su: (to test01) vagrant on pts/0

パスワードが聞かれること無く、コマンドが実行できています。 ちなみに、今 wheel から抜くと同じようにパスワードが聞かれます。 sudo gpasswd -d test01 wheel 試したければこのようにしてグループから追い出してください。

実行できるコマンドを制御する

先程の test01 いまだとなんでもできちゃうので、ログを見るために taillessgrep だけ実行できるようにしてみます。 またまた visudo の出番です。

$ visudo

- %wheel  ALL=(ALL)      NOPASSWD: ALL
+ %wheel  ALL=(ALL)       NOPASSWD: /usr/bin/tail, /usr/bin/less, /usr/bin/grep

suders を書き換えてコマンドをsudoを実行してみました、許可されたもの以外はパスワードが求められて失敗するのが見れると思います。

$ sudo su - test01
(test01)$ sudo tail -n1 /var/log/messages
May 16 07:31:05 localhost su: (to test01) vagrant on pts/0
(test01)$ sudo cat -n1 /var/log/messages

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test01:
(test01)$ sudo less /var/log/messages
(test01)$ sudo grep '07:31:05' /var/log/messages
May 16 07:31:05 localhost su: (to test01) vagrant on pts/0
(test01)$ sudo service nginx start

We trust you have received the usual lecture from the local System
Administrator. It usually boils down to these three things:

    #1) Respect the privacy of others.
    #2) Think before you type.
    #3) With great power comes great responsibility.

[sudo] password for test01:

失敗例の最後のnginxの再起動のようなコマンドもそのまま記入してやれば実行可能だったりします。

$ visudo

- %wheel  ALL=(ALL)       NOPASSWD: /usr/bin/tail, /usr/bin/less, /usr/bin/grep
+ %wheel  ALL=(ALL)       NOPASSWD: /usr/bin/tail, /usr/bin/less, /usr/bin/grep, /usr/sbin/service nginx start

ただ、 /usr/sbin/service nginx と書いて stop/start 両方許可みたいな書き方はできないみたいです。

良い書き方などあればコメント等いただけたら幸いです。

おまけ

やっちまう

>>> /etc/sudoers: syntax error near line 99 <<<
What now?
Options are:
  (e)dit sudoers file again
  e(x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)

What now? Q

やっちまった場合

$ sudo  tail /var/log/messages
>>> /etc/sudoers: syntax error near line 99 <<<
sudo: parse error in /etc/sudoers near line 99
sudo: no valid sudoers sources found, quitting
sudo: unable to initialize policy plugin
$

二度とsudoれなくなる…sudoしたいよぉ…

復旧したい場合のお話。

  1. rootユーザで作業してたらそのままvisudoする

  2. 別のマシンにボリュームマウントして修正(クラウドじゃないと面倒かな、物理でもできなくはないですが) やっちまたサーバを停止→ボリュームを外す→別の生きてるサーバにマウント→別のサーバからマウントしたボリューム内のsudoersファイル修正→ボリューム戻して起動

  3. 未検証: pkexec を使うplicykitってパッケージに入ってるらしいですどうするかは謎

やっちまった場合の事を書いて今回のブログは終了です。 AWS以外の事書いたわーと思ったけど、Amazon Linux取り上げとるヤーンみたいな自分へのツッコミをしつつ、 読んでいただけた方で何かあればご意見ご感想いただけたらと思います。

最後まで読んでいただきありがとうございました。

すずき