「sudo su」を理解する

Linux で root ユーザに切り替えて作業を始める時に打つ $ sudo su - というコマンド。コレが何を意味しているのか、改めて理解しようとしてみる。

まず、root ユーザは、全ての特権を持つ「神」ユーザ。自分で Linux OS を新規インストールしたりしない限り、普段は「root ユーザのパスワード」を知ることはないだろう。

su コマンドは本来「ユーザをスイッチする」コマンドで、ユーザ名を指定せず $ su と実行すると、root ユーザに切り替える動作になる。この時、切り替える対象のユーザ = root ユーザのパスワードを問われる。そのユーザのパスワードを知っているなら、そのユーザに切り替えて作業することもできていいよね、という考え方だ。

特権が必要で、root ユーザとして作業をしたいが、$ su と実行した時に root ユーザのパスワードを問われて、それは知らないわー、となると、root ユーザとして作業できない。

そこで登場するのが sudo コマンド。コレは指定のコマンドだけ他のユーザで実行できるコマンドだ。$ sudo -u USERNAME whoami と指定すれば、USERNAME ユーザの権限で whoami コマンドを実行できる。-u オプションを指定しないと root ユーザでそのコマンドを実行する動きになる。このコマンドを実行する時パスワードを問われるが、そのパスワードはコマンドを実行するユーザのパスワードなので、切り替え対象のユーザ (= root) のパスワードは知らなくて良い。

ということは、$ sudo su というコマンドは、$ sudo su root と書いているのと同じ。「su コマンドで root ユーザに切り替える」という動作を、root ユーザのパスワードなしに実行するため、sudo を手前に付けている、というワケだ。

su - という最後のハイフンは何かというと、ハイフンを付ければ切り替え先のユーザのホームディレクトリに移動する、というだけ。付けなくてもユーザ切り替え自体の動きには変わりない。

Docker を使って root ユーザを扱ってみる

それではココで、Docker を使って、CentOS の root ユーザを扱ってみよう。

# CentOS 7 系のコンテナを立ち上げる
$ docker run -it centos:7

# すぐに root ユーザでログインする。この状態ではまだ root ユーザのパスワードが設定されていない
[root@ce1d848eb274 /]# cat /etc/shadow
root:locked::0:99999:7:::
bin:*:17834:0:99999:7:::
daemon:*:17834:0:99999:7:::
adm:*:17834:0:99999:7:::
lp:*:17834:0:99999:7:::
sync:*:17834:0:99999:7:::
shutdown:*:17834:0:99999:7:::
halt:*:17834:0:99999:7:::
mail:*:17834:0:99999:7:::
operator:*:17834:0:99999:7:::
games:*:17834:0:99999:7:::
ftp:*:17834:0:99999:7:::
nobody:*:17834:0:99999:7:::
systemd-network:!!:17870::::::
dbus:!!:17870::::::

# root ユーザのパスワードを任意に設定する
# パスワードは8文字以上で、大文字小文字・数字などを組み合わせないと「BAD PASSWORD」と警告が出る
[root@ce1d848eb274 /]# passwd root
Changing password for user root.
New password:  # ← 任意にパスワードを入力する
Retype new password:  # ← 任意にパスワードを入力する
passwd: all authentication tokens updated successfully.

# デフォルトでは sudo コマンドがインストールされていないと思われるのでインストールする
[root@ce1d848eb274 /]# yum install sudo -y

# 何かユーザを新たに作ってみる
[root@ce1d848eb274 /]# useradd neo

# 作成したユーザに切り替える
[root@ce1d848eb274 /]# su neo

# 作成したユーザのセッションになった。ココで su root を実行すると root ユーザに切り替えられる
[neo@ce1d848eb274 /]$ su
Password:  # ← ココで root ユーザのパスワードを入力する

# root ユーザに切り替えられた
[root@ce1d848eb274 /]# 

コレが su 単独の動きだ。続いて、sudo がどのように動くか見てみよう。

# 作成したユーザに切り替える
[root@ce1d848eb274 /]# su neo

# sudo を使って root ユーザに切り替えようとしてみる
[neo@ce1d848eb274 /]$ sudo su

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 neo: 
# 作成したユーザのパスワードを問われるが、未設定なので Control + C で抜ける

# root ユーザに戻る
[neo@ce1d848eb274 /]$ exit
exit

# root ユーザで、作成したユーザのパスワードを新規設定する
[root@ce1d848eb274 /]# passwd neo
Changing password for user neo.
New password:  # ← 入力
Retype new password:  # ← 入力
passwd: all authentication tokens updated successfully.

# 作成したユーザに切り替え、再度 sudo su を試す
[root@ce1d848eb274 /]# su neo
[neo@ce1d848eb274 /]$ sudo su

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 neo:  # ← 作成したユーザのパスワードを入力する
neo is not in the sudoers file.  This incident will be reported.

sudo 時に作成したユーザのパスワードを入力しても、コレだけでは sudo が実行できない。「作成したユーザが sudo 実行して良いコマンド」を指定していないからだ。

# root ユーザに戻る
[neo@ce1d848eb274 /]$ exit
exit

# /etc/sudoers を編集するため visudo を実行する
[root@ce1d848eb274 /]# visudo

visudo コマンドは、/etc/sudoers ファイルを vi で編集するための専用コマンド。

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

このような行があると思うので、コレを参考に、作成したユーザが全てのコマンドを sudo 実行できるよう設定してみる。

## Allow root to run any commands anywhere
root    ALL=(ALL)       ALL

# 以下を追加する
neo    ALL=(ALL)    ALL

編集が終わったら :wq で保存して終了する。

# 作成したユーザに切り替える
[root@ce1d848eb274 /]# su neo

# sudo を使って root ユーザに切り替えてみる
[neo@ce1d848eb274 /]$ sudo su
[sudo] password for neo:  # ← 作成したユーザのパスワードを入力する

3 root ユーザに切り替えられた
[root@ce1d848eb274 /]# 

sudo 時にパスワードの入力を求められないようにするには、$ visudo した時に

neo    ALL=(ALL)    ALL

ではなく、

neo    ALL=(ALL)    NOPASSWD:    ALL

と書けば良い。なお、スペースの数は特に決まりがないので、1つ以上で適当に入れれば良い。

以上

こんな感じ。少し sudosu への理解が深められたと思う。