2026年5月21日
2026年5月21日
sudoersで特定のコマンドだけ許可する方法|visudoでの書き方と抜け道の防ぎ方
sudoers を使うと、「このユーザーには nginx の再読み込みだけ」「このグループにはログの閲覧だけ」のように、root 権限で実行できるコマンドを絞り込めます。この記事では、Ubuntu 24.04(sudo 1.9.15)で動作を確認した書き方を中心に、引数の制限や、許可したつもりが全権限を渡してしまう落とし穴まで説明します(2026年10月時点)。
どんなときに使うか
- 開発者やデプロイ用ユーザーに、Web サーバーの再起動・設定テストだけを許可したい
- 運用担当者にログの閲覧だけを許可し、設定変更はさせたくない
- 自動化スクリプト(CI やバックアップ)に、必要な1コマンドだけをパスワードなしで実行させたい
全権限(ALL)を渡す代わりに、必要なコマンドだけを列挙するのが基本の考え方です。
編集は visudo で行う
/etc/sudoers をエディターで直接編集すると、書き間違えたときに sudo 自体が使えなくなり、root に戻れなくなることがあります。編集には構文チェック付きの visudo を使います。
# /etc/sudoers.d/ に独立したファイルを作る(推奨)
sudo visudo -f /etc/sudoers.d/web-ops
本体の /etc/sudoers を直接触るより、/etc/sudoers.d/ に用途ごとのファイルを置く方法が管理しやすくなります。Ubuntu・Debian・RHEL 系の標準の /etc/sudoers には、このディレクトリを読み込む @includedir /etc/sudoers.d(古い書式では #includedir)が入っています。
注意点が2つあります。
- ファイル名に
.を含めない:web-ops.confのように.を含む名前や~で終わる名前は読み込まれません(sudoers のマニュアルに記載)。実際にbob.confというファイルで全権限を書いても、sudo -l -U bobでは「実行を許可されていない」と表示されました。 - パーミッションは 0440:
visudo -fで作れば適切な権限になります。別の場所で書いたファイルを置く場合は、先に構文を確認してからコピーします。
sudo visudo -cf /tmp/web-ops # 構文だけ確認(parsed OK と出れば可)
sudo install -m 0440 /tmp/web-ops /etc/sudoers.d/web-ops
sudo visudo -c # 全体をもう一度確認
基本の書き方
書式は次のとおりです。
ユーザー ホスト=(実行ユーザー) タグ: コマンド, コマンド, ...
| 部分 | 例 | 意味 |
|---|---|---|
| ユーザー | deploy / %webadmin |
% を付けるとグループ |
| ホスト | ALL |
通常は ALL でよい |
| 実行ユーザー | (root) |
どのユーザーとして実行できるか。(ALL) にすると任意のユーザーになれる |
| タグ | NOPASSWD: |
パスワード入力を省略(省くと本人のパスワードを求める) |
| コマンド | /usr/bin/systemctl reload nginx |
/ から始まるフルパスで書く |
コマンドは / から始まるフルパスで書きます。パスは command -v systemctl などで確認できます(Ubuntu 24.04 では systemctl は /usr/bin/systemctl、nginx は /usr/sbin/nginx)。
例1: 1人のユーザーに Web サーバーの操作だけを許可する
# /etc/sudoers.d/web-ops
Cmnd_Alias WEB_RELOAD = /usr/sbin/nginx -t, /usr/bin/systemctl reload nginx, /usr/bin/systemctl restart nginx
Cmnd_Alias WEB_LOGS = /usr/bin/journalctl -u nginx --no-pager
deploy ALL=(root) NOPASSWD: WEB_RELOAD, WEB_LOGS
Cmnd_Alias でコマンドのまとまりに名前を付けておくと、複数のユーザーやグループに同じ権限を渡すときに読みやすくなります。
例2: グループ単位で許可する
%webadmin ALL=(root) WEB_RELOAD
webadmin グループのメンバー全員が、自分のパスワードを入力したうえで WEB_RELOAD のコマンドを実行できます。メンバーの追加は sudo usermod -aG webadmin ユーザー名 です。
引数まで制限する
ここが最も間違えやすい点です。sudoers では、コマンドを引数なしで書くと、どんな引数でも付けて実行できる扱いになります。
| 書き方 | 実行できるもの |
|---|---|
/usr/bin/systemctl |
systemctl を任意の引数で(stop・disable・edit なども可能) |
/usr/bin/systemctl reload nginx |
systemctl reload nginx だけ |
/usr/bin/ls "" |
引数なしの ls だけ |
つまり deploy ALL=(root) NOPASSWD: /usr/bin/systemctl と書くと、どのサービスでも停止できてしまいます。必要な引数まで書きましょう。
正規表現で引数を絞る(sudo 1.9.10 以降)
sudo 1.9.10 以降では、^ で始まり $ で終わる正規表現を引数に使えます。Ubuntu 24.04 の sudo 1.9.15 で visudo の構文チェックを通ることを確認しました。
deploy ALL=(root) NOPASSWD: /usr/bin/systemctl ^(reload|restart) (nginx|php8\.3-fpm)$
sudo --version でバージョンを確認し、1.9.10 より古い環境では、許可する組み合わせを1つずつ列挙してください。
ワイルドカード * は使わない
/usr/bin/cat /var/log/nginx/* のような書き方は、* が空白も含む任意の文字列に一致するため、/var/log/nginx/access.log /etc/shadow のように別のファイルを追加で指定されるおそれがあります。ログを読ませたい場合は、ログを読めるグループ(Ubuntu では adm)に加える方法も検討してください。
許可するとシェルに抜けられるコマンド
次のようなコマンドは、それ自体の機能でシェルや任意のコマンドを起動できるため、許可すると実質的に root 権限を渡すことになります。
- エディター(
vi・vim・nanoなど)、ページャー(less・more) find(-exec)、awk、tar、rsync、gitなど外部コマンドを呼べるものbash・sh・pythonなどのインタープリター- 一般ユーザーが書き換えられる場所にあるスクリプト
ファイルの編集だけを許可したい場合は、エディターではなく sudoedit を使います。ユーザーは一時ファイルを自分の権限で編集し、保存時に sudo が元のファイルへ書き戻します。
deploy ALL=(root) sudoedit /etc/nginx/sites-available/example.conf
# deploy ユーザー側の操作
sudoedit /etc/nginx/sites-available/example.conf
設定を確認する
設定後は、意図どおりに絞り込めているかを確認します。
# 管理者側: 対象ユーザーに許可されているコマンドの一覧
sudo -l -U deploy
# 対象ユーザー側: 自分に許可されているコマンドの一覧
sudo -l
Ubuntu 24.04 のコンテナで例1の設定を入れ、deploy ユーザーで試した結果は次のとおりです(-n はパスワードを聞かずに失敗させるオプション)。
| 実行したコマンド | 結果 |
|---|---|
sudo -n /usr/sbin/nginx -t |
実行できた |
sudo -n /usr/bin/systemctl stop nginx |
拒否(sudo: a password is required) |
sudo -n cat /etc/shadow |
拒否 |
許可されていないコマンドを実行すると、パスワードを入力しても「許可されていない」旨のメッセージが出て、実行されません。
よくある落とし穴
- 後に書いた行が優先される: 同じユーザーに複数の行が一致した場合、最後に一致した行が使われます(より具体的な行が優先されるわけではありません)。
- sudo グループに入っていると意味がない: Ubuntu では
sudoグループ、RHEL 系ではwheelグループのメンバーは標準で全コマンドを実行できます。権限を絞りたいユーザーは、これらのグループから外します(sudo gpasswd -d ユーザー名 sudo)。 (ALL)の付けすぎ:(ALL)にすると、root 以外の任意のユーザーとしても実行できます。root としてだけ実行させるなら(root)と書きます。NOPASSWDは必要な行だけに: 自動化スクリプト用など、パスワードを入力できない場面に限って使います。
まとめ
- 編集は
visudo -f /etc/sudoers.d/ファイル名で行い、ファイル名に.を含めない - コマンドはフルパスで、引数まで書く(引数を省くと任意の引数を許可したことになる)
- エディター・ページャー・インタープリターなど、シェルに抜けられるコマンドは許可しない。編集は
sudoeditで - 設定後は
sudo -l -U ユーザー名で一覧を確認し、許可していない操作が拒否されることも試す
su コマンドそのものを使えるユーザーを絞る方法は Linuxのsuコマンドを使えるユーザーを制限する方法、sudo を使う作業用ユーザーの作り方は VPSでsudoユーザーを作成する方法 を参考にしてください。