Ubuntu Weekly Recipe

第410回あなたの人生を少しだけ豊かにするsudoの使い

皆さんsudo使ってますか? 残念ながらUbuntuは、一般的なデスクトップ用途でさえsudoのお世話になることがたまに存在します。今回はそんなsudoのお話です。

sudoとはなんぞや

sudo「指定したコマンドを別のユーザー権限で実行する」コマンドです。開発が始まったのは1980年と歴史が古く、なおかつ今でも開発が続いているソフトウェアでもあります。その挙動から「substitute user do」の略や、ユーザーを指定しないと管理者権限で実行することから「superuser do」の略とも言われています。さらにsudoコマンドと似た名前のコマンドとしてsuが存在します。こちらは主に別のユーザーに切り替えるためのコマンドで、sudoがsudoコマンドを実行しようとしているユーザーのパスワードを必要とするのに対して、suはsuで切り替える先のユーザーのパスワードが必要です。⁠sudo」より先に「su」が存在していたので、⁠su do」の略だという話もあります[1]⁠。

Ubuntuはシステム管理者である「UID=0」の特権ユーザー(一般的には「root」という名前がついています)のアカウントを「ロック」しています[2]⁠。このため、シングルユーザーモードで起動でもしない限り、rootでログインすることはできません。管理者権限が必要な作業は、一般ユーザーがsudoコマンドを使って実施するのです。

何かパッケージをインストールする場合:
$ sudo apt-get install panzer
[sudo] password for miho: ("miho"ユーザーのパスワードを入力する)

具体的には次のような理由日本語訳でrootアカウントがロックされ、sudoの利用が推奨されています。

  • rootのパスワードを設定しなくてよいので、インストーラーの質問項目を減らせる
  • システム管理者は本人とroot、2つのアカウントのパスワードを覚えておく必要がない
  • 何かシステムに変更を加えるときは明示的にsudoを使わなければならないので、注意を喚起できる
  • /var/log/auth.logにsudoで実行したコマンドが残るので、何かあったときに確認しやすい
  • システムに対する攻撃者は、必ず存在するであろうrootアカウントに対してブルートフォースアタックを行うことが多いので、rootアカウントをロックしておくとその攻撃に対しては安全性が高まる
  • sudoを実行できるユーザーをグループで管理できるので、複数の管理者を追加・削除しやすい
  • あるユーザーには特定のコマンドだけsudoを実行できるようにするなど、細かいポリシー設定が可能

いろいろとお題目を立ててはいますが、⁠外からの攻撃に対しての安全性を高める」というよりは「ユーザーが操作を誤ってシステムを壊してしまう」ことをできるだけ防ぐことが主体のようです。

ちなみにデスクトップ版のUbuntuの場合、何かアプリケーションをインストールしたり、パッケージを更新したり、⁠システム設定」からを設定を変更する程度であればsudoを使う必要はありません。管理者権限が必要な場合は、後ほど出てくるpolkitがパスワード入力ダイアログを表示するため、そこでユーザーのパスワードを入力すればあとは「うまいこと」やってくれます。

sudoの使い方あれこれ

sudoの使い方は「sudo "実行したいコマンド"」を端末に入力する、これだけです。パスワードが問われるので「sudoを使うユーザー」のパスワードを入力してください。なお、セキュリティの観点から入力結果は画面にはまったく表示されません。反応のなさを恐れずにパスワードを入力し、粛々とエンターキーを押せば、最後にはシステムが応えてくれるはずです。

この使い方でほとんどの目的は果たせるはずですが、それでもたまにはすこし違う使い方が必要になることもあります。ここではsudoを使う上で知っておいたほうが便利なことをいくつか紹介しましょう。

リダイレクト先で特権が必要な時

日常的にsudoを使う時に最初に困るのが、パイプやリダイレクトの先で特権が必要な場合でしょう。たとえば何か文字列をechoし結果を、管理者権限でしか書き込めないファイルに追記したい場合、ドキュメントで次のコマンド例を提示されることがしばしばあります。

# echo "foo" > /etc/bar.conf

これをそのままsudoに置き換えても動きません。

$ sudo echo "foo" > /etc/bar.conf
bash: /etc/bar.conf: 許可がありません

エラーメッセージからもわかるとおり、⁠/etc/bar.conf」に書き込もうとしているプロセスはbashです。sudoコマンドによりechoは管理者権限で起動していますが、その親プロセスは一般ユーザーの権限なので、当然書き込めないというわけです。

このようにリダイレクト先で特権が必要な時はteeコマンドを使います。

$ echo "foo" | sudo tee /etc/bar.conf
[sudo] password for miho:
foo

teeコマンドは標準入力を、標準出力と指定したファイルの双方に書き出すコマンドです。このteeコマンドを管理者権限で起動すれば、/etc/bar.confにも書き出せるというわけです。ちなみにteeコマンドにオプションをつけない場合はファイルを上書きします。ファイルに追記したい場合は、⁠-a」オプションをつけてください。

別の手段として、シェルを管理者権限で起動するという方法もあります[3]⁠。

$ sudo sh -c 'echo "foo" > /etc/bar.conf'

この方法は、ドキュメントに例示してあるコマンド列をそのまま使用できることに加えて、/var/log/auth.logにそのコマンド列がそのまま残るというメリットがあります。

teeを使った場合のログ:
sudo: (中略) COMMAND=/usr/bin/tee /etc/bar.conf

shを管理者権限で起動した場合のログ:
sudo: (中略) COMMAND=/bin/sh -c echo "foo" > /etc/bar.conf

しかしながら本来管理者権限は必要ないコマンドまで管理者権限で実行することになります。どちらを使うかは状況にあわせて判断してください。

rootや他のユーザーになりたい

管理者権限が必要な作業はsudoコマンド経由でできますし、前述のようにsudoを使うことでいくつものメリットが存在しますが、どうしてもrootになって作業したい場合が存在するかもしれません[4]⁠。そんなときはsudoの「-s」オプションないしは「-i」オプションを使うと便利です。

$ sudo -s
# pwd
/home/miho
# echo $HOME
/home/miho
# exit
$ sudo -i
# pwd
/root
# echo $HOME
/root

「-s」「-i」の違いは、前者が環境変数SHELLか/etc/passwdで指定したシェルを実行するだけなのに対して、後者はログインシェルとして「~/.login」「~/.profile」も評価するということです。このため「-i」の場合はカレントディレクトリもsudo後のユーザーのホームディレクトリに移動しています。設定されている環境変数も変わっていますので、どちらで実行するかは状況にあわせて変更してください。

なお、上記のオプションに加えて「-u "ユーザーID"」を指定すれば、rootではなく指定したユーザーの権限でシェルが起動します。特定のサービスをインストール時に作成されるユーザーで作業を行いたい場合に便利でしょう。

繰り返しになりますがsudoでシェルを起動した場合、その作業内容は/var/log/auth.logには残らないなど、sudoを使うメリットが損なわれます。⁠Ubuntuではできるだけ避けるべきやり方」だということは心に留めておいてください[5]⁠。

別のユーザーもsudoできるようにする

Ubuntuではインストール時に作成したユーザーのみ、sudoコマンドを実行できるようになっています。もしインストール後に作成したユーザーもsudoを実行できるようにしたい場合、一番簡単な方法はsudoグループに追加することです。

$ sudo adduser "追加したいユーザーID" sudo

またシステム設定の「ユーザーアカウント」からも変更できます。右上の「ロック解除」を選択した上で「アカウントの種類」をクリックすれば、一般ユーザーから管理者への変更が可能です。

特定のユーザーをsudoグループから外したい場合は、次のコマンドを実行します。

$ sudo deluser "追加したいユーザー名" sudo

外したユーザーはsudoを実行できなくなります。sudoグループに誰もいなくなってしまうと、誰もsudoを実行できないのでグループも変更できないという事態になってしまいます。そうするとシングルユーザーモードで起動するかライブセッションを起動して、無理やりルートファイルシステムを書き換えるぐらいしか手がなくなりますので、sudoグループを操作する場合は細心の注意を払ってください。

GUIアプリケーションを管理者権限で起動したい

ファイルブラウザーやテキストエディターといったGUIアプリケーションを管理者権限で起動したいという要望はそれなりにあるようです。しかしながらこれはあまり推奨されていません。GUIアプリケーションは単純にプロセスを起動するだけでなく、他のプロセスと通信したり、ホームディレクトリにキャッシュや設定ファイルを作成・編集したりと裏でいろいろな処理を行っています。これらの処理が管理者権限で行われると、次回一般ユーザー権限で起動した時に、うまく起動できなる可能性があるからです[6]⁠。

過去にはgksuというコマンドが最初からインストールされており、それをsudoのように使う方法が紹介されたこともあります。しかし今ではgksuは初期状態ではインストールされていません。その代わりにUbuntuではpolkitpkexecコマンドを使っています。実際にアップデートマネージャー経由のパッケージの更新やネットワーク設定などで表示されるパスワード入力ダイアログはいずれもこのpolkitによるものです。

pkexecで特定のコマンドを実行したい場合は、XMLベースのアクションファイルを記述する必要があります。残念ながらこのアクションファイルを簡単に記述する方法はまだ存在しません[7]⁠。ただファイルブラウザ(nautilus)とテキストエディター(gedit)に限って言えば、WebUpd8の記事でアクションファイルが公開されていますので、それを使うことにしましょう。以下はgeditの例です。

$ wget https://raw.githubusercontent.com/hotice/webupd8/master/org.gnome.gedit.policy \
    -O /tmp/org.gnome.gedit.policy
$ sudo cp /tmp/org.gnome.gedit.policy /usr/share/polkit-1/actions/

さらにUnity Launcherのファイルアイコンを右クリックした時、pkexec経由で起動するメニューを追加します。

$ cp /usr/share/applications/gedit.desktop ~/.local/share/applications/
$ cat <<END >> ~/.local/share/applications/gedit.desktop

[Desktop Action admin-window]
Name=Open a Admin Window
Exec=pkexec gedit --new-window
END

さらに「~/.local/share/applications/nautilus.desktop」のActions行に追加したadmin-windowアクションを設定してください。

Actions=new-window;new-document;admin-window;

あとはLauncherにgeditアイコンを追加し、アイコンを右クリックすれば「Open a Admin Window」が追加されているはずです。

再度パスワードを問い合わせさせたい

sudoコマンドは一度パスワード認証が成功すると、15分間はsudoコマンドを実行してもパスワードの問い合わせを行いません。この問い合わせを行わない状態を一度無効化し、次は必ずパスワード問い合わせを行うようにしたい場合は、⁠-k」オプションを使用します。

$ sudo -k

他人のシステムでsudoしないために

ローカルでsudoコマンドすることに慣れていると、管理者権限のないシステムにログインしているときに、間違ってsudoコマンドを実行してしまうことがままあります。単純にsudoできないって怒られるだけではあるのですが、/var/log/auth.logにはsudoを実行しようとした形跡が残りますし、場合によってはシステム管理者にアラートが飛ぶかもしれません。

そういう時はホームディレクトリにsudoのラッパーコマンドを用意しておくと、事故を未然に防げます。

$ mkdir ~/bin/
$ cat <<END >> ~/bin/sudo
#! /bin/sh

echo "Don't use sudo in the host"
exit 1
END
$ chmod a+x ~/bin/sudo

Ubuntuでは「~/.profile」「$HOME/bin」「$PATH」に設定してくれますので、これだけでsudoコマンドを実行した時にエラーとなってくれます。本来のsudoを実行する場合は、明示的に「/usr/bin/sudo」とフルパスで呼び出しましょう。

rootアカウントを有効にする

何らかの理由によりrootアカウントを有効にしたい場合は以下のコマンドでパスワードを設定しなおしてください。

$ sudo passwd root

これまで説明したとおり、Ubuntuの場合はrootアカウントでログインする必要は皆無なはずです。どうしても必要な場合のみ、⁠これが汚い大人のやり方というやつか……」と呟きながら設定してください。ちなみに再度rootアカウントを無効化するには、以下のコマンドを実行します。

$ sudo passwd -dl root

「-d」オプションでパスワードを削除した上で、⁠-l」オプションでcrypt()では生成されないパスワード文字列を設定しています。

ユーザーのアカウントを忘れてしまってどのアカウントでもログインできなくなったり、すべてのユーザーをsudoグループから削除してしまったというドジっ子さんは、シングルユーザーモードで起動するのが良いでしょう。

システムを再起動し、電源が入った直後にESCキーかSHIFTキーを押し続けてGRUBの画面を表示します。そのままカーソルキーとエンターキーで「Advanced options for Ubuntu」を選択し、⁠recovery mode⁠⁠」とついた項目を選択します。リカバリーメニューが表示されますので、⁠root」を選択しましょう。

このシングルユーザーモードでは、安全のためにルートファイルシステムを読み込み専用でマウントしています。もしルートファイルシステムの内容を書き換えたい場合は、リマウントする必要があります。

# df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/sda2       113G   25G   83G  24% /
# mount -o remount,rw /dev/sda2 /

「/dev/sda2」の部分は、ルートファイルシステムのパーティションにあわせてください。dfコマンドで「/dev/sda2」とわかったので、ここでは「/dev/sda2」を使っています。

あとはsudoグループの設定を変えた上で、exitします。

# adduser "追加したいユーザーID" sudo
# exit

再びリカバリーメニューにもどりますので、今度は「resume」を選択すると通常起動に戻ります。

sudoの設定変更

sudoの動作やセキュリティポリシーは/etc/sudoersファイルないしは/etc/sudoers.dディレクトリ以下のファイルで設定できます。このファイルは書式を間違えるとsudoができなくなり、結果的に間違いを修正できなくなりますので、慎重に編集を行う必要があります。少なくとも通常のエディターて直接編集するのではなく、保存する前に書式のチェックを行ってくれるvisudoコマンドで編集するのが必須です。

visudoコマンドは/usr/bin/editorをエディターとして使用します。これはUbuntuの場合、update-alternativesで変更できますので、詳しいことは第331回「CUIの標準エディタを変更したい」を参照してください。

設定を変更したい場合、/etc/sudoersを直接変更するのではなく、/etc/sudoers.dディレクトリにファイルを作成するほうが安全です。visudoコマンドはオプションなしだと/etc/sudoersを開いてしまうので、次のように明示的にファイル名を指定しましょう。

$ sudo visudo -f /etc/sudoers.d/timeout

実行権限を管理する

/etc/sudersには以下のようなエントリが存在します。

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

これは「sudoグループ(%はグループ名を指します)に所属するユーザー」「任意のホスト上(最初のALL⁠⁠」で、⁠任意のコマンド(最後のALL⁠⁠」を、⁠任意のユーザーID、グループID(丸括弧の中のALL⁠⁠」で実行できることを意味します。つまり「sudoグループに所属すればなんでもできる」というわけです。

ここで特定のユーザー(maho)にユーザーを追加するadduserコマンドの実行権限だけを与えるようにしてみましょう。これは以下のような設定になります。

maho    ALL=(ALL:ALL) /usr/sbin/adduser

sudoグループに所属する場合、パスワードなしで「sudo apt-get update」を実行できるようにしたい場合は、次のように記述します。

%sudo   ALL=(ALL:ALL) NOPASSWD: /usr/bin/apt-get update

ここで「 update」を省いてしまうと、apt-getコマンドを常にパスワードなしで実行できてしまいます。

その他、sudoersにはかなり複雑なことを記述でいます。実際の例については「/usr/share/doc/sudo/examples/sudoers.gz」を参照してください。

タイムアウト時間を変更する

sudoで設定できるタイムアウト時間は2種類存在します。パスワードの入力待ちのタイムアウト(passwd_timeout)とパスワード入力なしでsudoを実行できる期間(timestamp_timeout)です。いずれも0を設定することで無効化できます。

Defaults        passwd_timeout=0
Defaults        timestamp_timeout=0

パスワードの表示方法を変更する

前述のとおり、sudoを実行するとき入力するパスワードに対するリアクションは何も表示されません。もしログイン時のパスワード入力のようにタイピングに合わせて「*」を表示させたい場合は、pwfeedbackオプションを設定します。

Defaults:maho    pwfeedback

Defaultsの後ろに「:maho」をつけることで、mahoユーザーのみこの設定が反映されます。

sshコマンド経由でsudoを実行できるようにする

sshコマンドの最後にコマンド文字列を渡すと、sshでログインした先でそのコマンドを実行してくれます。このとき、sudoコマンドを渡すと次のようなエラーが表示されます。

$ ssh maho.example.com sudo ls
sudo: no tty present and no askpass program specified

これはsudoの設定で、安全性を高めるためにパスワードのエコーバックを無効化できない状況では、sudoの実行を行わないという設定が入っているためです。もし自動化などのために、sshコマンド越しにsudoを実行したい場合は、sshサーバー側で以下の設定を行いましょう。

Defaults:maho    visiblepw

おすすめ記事

記事・ニュース一覧