sudoersの設定方法

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でパーミッションを緩めてまたパーミッションを厳しくして」の操作を省略する事ができます。

 

タイトルとURLをコピーしました