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ユーザーを作成する方法 を参考にしてください。

お気軽にご相談ください

お見積りへ お問い合わせへ
▲