sudoersとはsudoに関する設定の定義ファイルです。suコマンドでユーザ切り替えを実施せずsudoコマンドを使用する環境を構築すれば、危険な操作のみ確認を求めたり、初級エンジニアに一部権限のみを譲渡したりする事ができます。
余談ですが、suはsuper userの略でもswitch userの略でもありません。suはsubstitute userの略だそうです。
$ man su SU(1) User Commands SU(1) NAME su - run a shell with substitute user and group IDs SYNOPSIS su [OPTION]... [-] [USER [ARG]...] DESCRIPTION Change the effective user id and group id to that of USER.
sudoers
sudoers 基本設定
sudoに関する設定は/etc/sudoersに記録されます。この設定ファイルは直接編集する事は非推奨とされており、設定ファイルを編集する時はvisudoというコマンドを使用する事が推奨されています。
# visudo
sudoersは<User>, <Host>, <Runas>, <Cmnd>を以下の書式を用いて指定します。
<User> <Host> = (<Runas>) <Cmnd>
/etc/sudoersの設定例を紹介します。以下の設定は、rootユーザはsudoで全てのコマンドが実行できるようになり、sysadmグループはreboot以外のコマンドがsudoで実行できるようになります。(“%”をつけるとグループを指定する意味になります。また、!は否定を意味しコマンドを実行を禁止する意味になります。)
root ALL=(ALL) ALL %sysadm ALL=(ALL) ALL, !/sbin/reboot
動作確認を行ないます。sysadmグループにユーザに切り替え、tailなどの一般的なコマンドは使用できるものの/sbin/rebootは実行できない事を確認します。 (なお、実はこの設定ではrebootコマンドは実行できてしまいます。/sbin/rebootのようなフルパス指定は拒否していますが、rebootのような短縮指定は拒否されていない事に注意して下さい。)
[root@localhost ~]# su - sysadm [sysadm@localhost ~]$ sudo tail -f /var/log/secure 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 sysadm: May 27 15:40:26 localhost sshd[8764]: Accepted password for root from 192.168.48.1 port 52899 ssh2 May 27 15:40:26 localhost sshd[8764]: pam_unix(sshd:session): session opened for user root by (uid=0) <omitted> [sysadm@localhost ~]$ [sysadm@localhost ~]$ [sysadm@localhost ~]$ sudo /sbin/reboot Sorry, user sysadm is not allowed to execute '/sbin/reboot' as root on localhost.localdomain. [sysadm@localhost ~]$
sudoers Aliasの定義
<User> <Cmnd>に対してAliasを定義する事もできます。設定例は以下の通りです。
[root@localhost ~]# visudo User_Alias SYSADM = %sysadm, millert, mikef, dowdy User_Alias DBA = %mysql, bostley, jwfox, crawl Runas_Alias DB = root, mysql Host_Alias TRUST = 192.168.48.0/24 Cmnd_Alias SHUTDOWN = *halt, *shutdown, *poweroff, \ *reboot, /sbin/fastboot, /sbin/init root ALL=(ALL) ALL SYSADM ALL=(ALL) ALL, !SHUTDOWN DBA TRUST=(DB) /usr/bin/mysql, /etc/init.d/mysqld
sudoers ログ設定
sudoによって操作されたコマンドをログ出力する事もできます。ログ出力をする事によって、誰がいつどんな操作をしたかを記録に残す事ができ、トラブル時の状況把握が容易になります。
デフォルトでは、authprivのfacilityに出力されます。CentOS 6では/var/log/secureに出力されるようです。もし、/etc/sudores, /etc/rsyslog.confを以下のように編集します。
[root@localhost ~]# visudo Defaults syslog=local3 [root@localhost ~]# vi /etc/rsyslog.conf # sudo log local3.* /var/log/sudo.log [root@localhost ~]# /etc/init.d/syslog restart Shutting down system logger: [ OK ] Starting system logger: [ OK ] [root@localhost ~]#
sudoの実行結果がログ出力されている事を確認します。
[root@localhost ~]# tail -f /var/log/sudo.log May 27 21:12:44 localhost sudo: sysadm : command not allowed ; TTY=pts/2 ; PWD=/home/sysadm ; USER=root ; COMMAND=/etc/init.d/httpd restart May 27 21:13:52 localhost sudo: sysadm : command not allowed ; TTY=pts/2 ; PWD=/home/sysadm ; USER=root ; COMMAND=/sbin/reboot
sudoers パスワードキャッシュ
sudoコマンド時のパスワードは、毎回聞かれえるわけではありません。デフォルトでパスワードは5分間キャッシュされます。もし、毎回パスワードを聞くようにして、より慎重な作業を行いたい場合はキャッシュ時間を短くする事をお勧めします。
設定例は以下の通りです。timestamp_timeoutにキャッシュ時間を分単位で定義します。なお、0を指定した場合はキャッシュしない事を意味します。
[root@localhost ~]# visudo Defaults timestamp_timeout = 0
sudoers パスワードなし
以下のようにNOPASSWDと指定すると、sudo実行時にパスワードが聞かれなくなります。sudoを含むスクリプトを定期実行したい場合などにお勧めの手法です。また、nagios, muninなどの監視ツールはパスワードなしを前提としているソフトウェアになっております。
[root@localhost ~]# visudo root ALL=(ALL) ALL SYSADM ALL=(ALL) NOPASSWD: ALL, !SHUTDOWN DBA TRUST=(DB) /usr/bin/mysql, /etc/init.d/mysqld
/etc/sudoers.d/
/etc/sudoers.dに個別設定を記載する事もできます。例えば、/etc/sudoers.d/fooを以下のように編集すると、ユーザfooは全てのコマンドをパスワードなしでsudo実行できるようになります。
# User rules for foo foo ALL = NOPASSWD: ALL
若干紛らわしい仕様なので、補足説明を行ないます。/etc/sudoersの”#includedir /etc/sudoers.d”はコメントではなく設定です。”#includedir /etc/sudoers.d”をうっかり削除してしまうと、/etc/sudoers.d/以下の設定が効かなくなってしまうので注意が必要です。
## Allows members of the users group to shutdown this system # %users localhost=/sbin/shutdown -h now ## Read drop-in files from /etc/sudoers.d (the # here does not mean a comment) #includedir /etc/sudoers.d cloud-user ALL=(ALL) NOPASSWD: ALL ec2-user ALL=(ALL) NOPASSWD: ALL
設定例
特定の処理のみパスワードなしにする
危険のない定型業務やバッチ処理は、パスワードなしでsudo実行したいと思う事はよくあります。以下の設定例は、特定のコマンドのみをパスワードなしでsudo実行できるようにし、それ以外はパスワードを求めるようにしております。
特定のコマンドとは、ビルドインのコマンドでも、自作スクリプトでもどちらでも差し支えございません。以下の設定例は、yumコマンドと自作スクリプト/tmp/test.shのみパスワードなしにしております。
なお、PASSWD, NOPASSWDの順で記述してください。7, 8行目の順番を入れ替えると想定通りの動作をしてくれません。
[root@localhost ~]# visudo Cmnd_Alias NOPASS_CMD = /usr/bin/yum, \ /usr/local/scripts/test.sh root ALL=(ALL) ALL junior_admin ALL=(ALL) PASSWD: ALL junior_admin ALL=(ALL) NOPASSWD: NOPASS_CMD
自作スクリプトがパスワードなしで実行できる事を確認するため、適当なスクリプト/tmp/test.shを作成します。
[semi_admin@localhost ~]$ cat << EOF > /tmp/test.sh #!/bin/sh echo "ktkr" EOF [semi_admin@localhost ~]$ chmod 755 /tmp/test.sh
動作確認は以下の通りです。yum, /tmp/test.shはパスワードなしで実行できますが、”/etc/init.d/httpd restart”はパスワードの入力を求められている事が分かります。
[semi_admin@localhost ~]$ sudo yum search zsh Loaded plugins: etckeeper, fastestmirror, refresh-packagekit, security Loading mirror speeds from cached hostfile * base: ftp.tsukuba.wide.ad.jp * epel: ftp.riken.jp * extras: ftp.tsukuba.wide.ad.jp * rpmforge: ftp.riken.jp * updates: ftp.tsukuba.wide.ad.jp =========================================================================== N/S Matched: zsh =========================================================================== autojump-zsh.noarch : Autojump for zsh gromacs-zsh.noarch : GROMACS zsh support python-twisted-core-zsh.x86_64 : Tab completion for Zsh and Twisted Core zsh-html.x86_64 : Zsh shell manual in html format zsh-lovers.noarch : A collection of tips, tricks and examples for the Z shell zsh.x86_64 : A powerful interactive shell Name and summary matches only, use "search all" for everything. [semi_admin@localhost ~]$ [semi_admin@localhost ~]$ [semi_admin@localhost ~]$ sudo /tmp/test.sh ktkr [semi_admin@localhost ~]$ [semi_admin@localhost ~]$ [semi_admin@localhost ~]$ sudo /etc/init.d/httpd restart [sudo] password for semi_admin: Stopping httpd: [ OK ] Starting httpd: [ OK ] [semi_admin@localhost ~]$
sudoers 抜け道
sudoには抜け道が多くセキュリティ対策として過信するのは禁物であると思います。どちらかと言うと、sudoはオペミス防止の観点での設定するようにしましょう。
以下、sudoの抜け道の例をあげます。
フルパスではない指定
短縮コマンド(フルパスではない指定)を禁止する事は非常に難しいです。例えば、以下のような/etc/sudoersの設定例について考えます。
root ALL=(ALL) ALL %sysadm ALL=(ALL) ALL, !/sbin/reboot
この設定は、/sbin/rebootは禁止していますが、rebootは禁止されていません。もしもrebootを完全に禁止したいならば、上記のようなブラックリスト形式ではなく、許可するコマンドをホワイトリスト形式で指定しなければなりません。
[sysadm@localhost ~]$ sudo /sbin/reboot Sorry, user sysadm is not allowed to execute '/sbin/reboot' as root on localhost.localdomain. [sysadm@localhost ~]$ [sysadm@localhost ~]$ [sysadm@localhost ~]$ sudo reboot Broadcast message from root (pts/0) (Sun May 27 21:20:26 2012): The system is going down for reboot NOW! [sysadm@localhost ~]$
なお、ホワイトリスト形式の指定は運用負担が大きいので、お勧めはできません。もし、一般ユーザからのセキュリティ対策を行ないたいならば、別のソリューションを検討すべきかと思います。sudoersには、オペミス防止以上の役割を期待してはいけない気がします。
bash 実行
bashの実行権限をsudoで許可してしまうと、実はどんな操作でもできてしまいます。例えば以下のようなスクリプトを定義してsudoで実行すると簡単にrebootできてしまいます。(-sオプションはシェルを実行するの意味です)
[sysadm@localhost ~]$ echo "/sbin/reboot" > ~/test.sh [sysadm@localhost ~]$ sudo -s ~/test.sh Broadcast message from root (pts/0) (Sun May 27 22:49:33 2012): The system is going down for reboot NOW! [sysadm@localhost ~]$
Tips
sudo: sorry, you must have a tty to run sudo
ssh越しでsudoを実行すると、”sudo: sorry, you must have a tty to run sudo”とのエラーメッセージが出力される事があります。
[foo@localhost ~]$ ssh 192.168.0.1 "sudo su - /etc/init.d/httpd restart" sudo: sorry, you must have a tty to run sudo [foo@localhost ~]$
これはsudoersのデフォルト設定が、ターミナルモニタ(例 teraterm, putty)での接続を必要としているためです。sudoersは事故防止の観点で、ターミナルなしのような自動実行のsudoは許可しておりません。
この現象を回避するには、ssh接続する際に-tオプションを付与します。-tは、ターミナルモニタをエミュレートする事を意味します。動作確認例は以下の通りです。
[foo@localhost ~]$ ssh -t 192.168.0.1 "sudo su - root /etc/init.d/rsyslog restart" Shutting down system logger: [ OK ] Starting system logger: [ OK ] Connection to 192.168.0.1 closed. [foo@localhost ~]$
/etc/sudoersのrequirettyを変更する事でも対応可能です。requirettyの前に打ち消しを意味する”!”を追加する事によって、ターミナルモニタ接続を要求しないようになります。
diff --git a/sudoers b/sudoers index 414fc5f..c9f9ccc 100644 --- a/sudoers +++ b/sudoers @@ -53,7 +53,7 @@ # Disable "ssh hostname sudo <cmd>", because it will show the password in clear. # You have to run "ssh -t hostname sudo <cmd>". # -Defaults requiretty +Defaults !requiretty # # Refuse to run if unable to disable echo on the tty. This setting should also be
/etc/sudoersのパーミッション 440 vs 600 vs 775
この記事を始めて書いたのは2012年01月の事です。そして、今日(2012年10月)、2年ぶり更新をかけるのですが、CentOS 6.X系では/etc/sudoersのパーミッションは440でなくても動作します。最も緩い設定は775です。
OSディストリビューション次第ですが、CentOS 6.X系で/etc/sudoersのパーミッションが緩すぎる場合は、以下のようなエラーメッセージが出力されます。
[foo@localhost ~]$ sudo su - sudo: /etc/sudoers is world writable
world writableが許容されないので、最も緩い設定は775になります。
/etc/sudoers 設定自動化
sudoersの設定自動化について考察します。chefを用いた場合の最小限のレシピは以下の通りです。
template "/etc/sudoers" do source 'sudoers.erb' mode '0440' owner 'root' end
恐らく初見の方は、「こんなレシピで動くの?」 「パーミッション足りないのでは?」と感じると思います。でも、実際に実行して見ると動きます。
オーケストレーションツール登場以前は、以下のようなスクリプトを組んでいた方も多いと思いますが、
#!/bin/sh chmod 600 /etc/sudoers cat << EOF > /etc/sudoers ## Sudoers allows particular users to run various commands as ## the root user, without needing the root password. <omitted> EOF chmod 440 /etc/sudoers
chefを使う場合は「chmodでパーミッションを緩めてまたパーミッションを厳しくして」の操作を省略する事ができます。