皆さん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コマンドを使って実施するのです。
[2] 具体的には、/etc/shadowにおいてパスワードフィールドにcrypt()関数で暗号化したときに発生し得ない文字である「!」をセットすることで、どんなパスワードもエラーになるため、そのアカウントでログインできなくなります。
何かパッケージをインストールする場合:
$ 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] 。
[6] 同様の現象はCUIアプリケーションでも発生しえます。たとえばnanoやvimをsudoで起動した時に設定が読み込まれない、などです。ちなみに「sudo -e」や「sudoeditor」コマンドを使えば、編集したいファイルを一時的に/tmpに移動し「一般ユーザー権限で」エディターを起動し、編集し終わったら「管理者権限で」反映してくれます。これにより、一般ユーザーの設定を反映したままエディター使用できます。
過去には「gksu 」というコマンドが最初からインストールされており、それをsudoのように使う方法が紹介されたこともあります。しかし今ではgksuは初期状態ではインストールされていません。その代わりにUbuntuでは「polkit 」の「pkexec 」コマンドを使っています。実際にアップデートマネージャー経由のパッケージの更新やネットワーク設定などで表示されるパスワード入力ダイアログはいずれもこの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
コラム:オープンソースカンファレンス2016 Tokyo/Spring
Ubuntu Weekly Topics でも改めて告知する予定ですが、今週末の26日(金) 、27日(土)に、オープンソースカンファレンス2016 Tokyo/Spring が地図上は東京都にある明星大学の日野キャンパスで開催されます。
Ubuntu Japanese Teamも両日参加予定で、いつものようにUbuntu Phoneや(Aquarisのほう ではない)Ubuntu Tablet、Snappyデバイス、XubuntuをインストールしたRaspberry Pi2などの実機を展示します。また、土曜日の15時15分からは『コンテナ型ハイパーバイザー「LXD」入門』と題したセミナー も開催しますので、皆様お誘い合わせの上、お越しください。