11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Linux の一般ユーザが sudo を使える仕組みをハンズオンで学ぶ

Last updated at Posted at 2023-12-09

本記事は フューチャー Advent Calendar 2023 10日目の記事です。

前日の9日目は、@domori さんの「ISUCON入門」でした。パフォーマンスチューニング力を競う「ISUCON」の魅力発信に加えて、今後も ISUCON 対策で実践した内容を投稿されるとのことなので、どんなチューニングネタがあるのか楽しみになる記事でした!私もチャンスがあれば、ISUCON のような「技術スキルを競い合うイベント」に参加したいなと思いました。

はじめに

普段の開発は Mac オンリーにしたいのですが、現在は訳あって Windows で開発しています。Windows での開発事情に疎いため絶賛キャッチアップ中なのですが、WSL2(Windows Subsystem for Linux 2)を使えば「ほぼ Linux 環境」として環境構築とコーディングが進められることに(今更ながら)気付き、「もろもろの設定」に WSL2 を加えて、プロダクト開発を進めています。

WSL2 で Ubuntu や CentOS の環境構築を進める中で、何度か「Permission denied」にぶつかり、「ああ、sudo を忘れていたな」を繰り返す中で「そういえば、sudoって、どういう権限制御になっているんだっけ?」の疑問が浮かびましたので、Linux の知識整理を兼ねて sudo の実行制御を本記事にまとめました。

TL;DR

Q. Linux の一般ユーザが sudo を使える理由は?
A. /etc/sudores に記載されているからです。

もう少しだけ踏み込むと

  • /etc/sudores 、及び、/etc/sudoers.d 配下のファイルに、sudo の実行制御が記載されています
  • 特定のユーザ、または、特定のグループに所属する全ユーザの sudo 実行権限は、上記ファイルを確認すれば分かります

Linux 前提知識

sudo の解説に入る前に、前提知識として必要なところを説明します。

  • ユーザ情報
  • グループ情報

ユーザ情報の確認

まずは、Linux の「ユーザ」についてです。
各ユーザの ID と所属グループは、以下のコマンドにより確認できます。

# コマンド
$ id                # 現在ログイン中のユーザの情報
$ id <user_name>    # <user_name>で指定したユーザの情報

実行例

$ id
uid=1000(main-user) gid=1000(main-user) groups=1000(main-user),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),116(netdev)
$ id sub-user
uid=1002(sub-user) gid=1002(sub-user) groups=1002(sub-user)

また、ユーザの一覧は /etc/passwd に記載されています。
(※以下、本記事に記載されたファイルパスについて、一部の Linux ディストリビューションではパスが異なる場合があります)

$ sudo cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
main-user:x:1000:1000:,,,:/home/main-user:/bin/bash
sub-user:x:1002:1002:,,,:/home/sub-user:/bin/bash

各項目は「:」ごとに分かれて、それぞれは以下を意味しています。

ユーザ名:旧パスワード欄(現在は「x」で統一):ユーザID:グループID:コメント:ホームディレクトリ:デフォルトシェル

所属グループの確認

続いて「グループ」の確認方法です。
ユーザは必ず1つ以上のグループに所属します。

# コマンド
$ groups                # 現在ログイン中のユーザが所属するグループ一覧
$ groups <user_name>    # <user_name>で指定したユーザが所属するグループ一覧

実行例

$ groups
main-user adm dialout cdrom floppy sudo audio dip video plugdev netdev
$ groups sub-user
sub-user : sub-user

グループの一覧は、/etc/group に記載されています。

$ cat /etc/group
root:x:0:
...
sudo:x:27:main-user
main-user:x:1000:
sub-user:x:1002:

それぞれの項目は、以下内容が対応しています。

グループ名:旧パスワード欄(現在は「x」で統一):グループID:グループ所属ユーザ

各ユーザを最低でも1つのグループに所属させるため、多くの Linux ディストリビューションでは「一般ユーザの追加時に、ユーザと同名のグループを作成して、そのグループにユーザ所属させる」という形を取ります。このため、グループ一覧にユーザ名と同名のグループが見つかります。(もちろん、全てのユーザを同じグループに追加する例外ケースもあります。)また、ユーザ名とグループ名が同名の場合は、「グループ所属ユーザ」の記入をスキップできます。(ex. main-userユーザはmain-userグループに所属していますが、/etc/group に記載されたmain-userグループの「グループ所属ユーザ」には、main-userユーザが記載されていない)

以上で、前提知識の説明は終了です。

新規ユーザを作成して、sudo を使えるようにする

それでは、ハンズオンに入ります。

本ハンズオンでは、Linux に新規ユーザを作成し、そのユーザが sudo を使えるようになるまでのプロセスを辿ります。これにより「Linux ユーザが sudo を実行できる仕組み」を見ていきます。
各種コマンド操作のため「sudo が実行できるユーザ」で、以下の操作を進めてください。

新規ユーザを作成する

まず、新しいユーザ(今回は、beginner)を追加します。

$ sudo adduser beginner
Adding user `beginner' ...
Adding new group `beginner' (1003) ...
Adding new user `beginner' (1003) with group `beginner' ...
Creating home directory `/home/beginner' ...
Copying files from `/etc/skel' ...
New password:
Retype new password:
passwd: password updated successfully
Changing the user information for beginner
Enter the new value, or press ENTER for the default
        Full Name []:
        Room Number []:
        Work Phone []:
        Home Phone []:
        Other []:
Is the information correct? [Y/n] Y

追加後、ユーザ情報とグループ情報を確認します。

$ id beginner
uid=1003(beginner) gid=1003(beginner) groups=1003(beginner)

$ sudo cat /etc/passwd | grep beginner
beginner:x:1003:1003::/home/beginner:/bin/sh
$ groups beginner
beginner : beginner

$ cat /etc/group | grep beginner
beginner:x:1003:

beginner は、ユーザ名と同じ名前のグループに所属していますね。
この状況で beginner にスイッチして、sudo を実行してみます。

$ su beginner       #beginnerにスイッチ
Password:

$ cat /etc/passwd
cat: /etc/passwd: Permission denied

$ sudo cat /etc/passwd     #sudoでファイルの中身を見ようとするが、見れない。
[sudo] password for beginner:
beginner is not in the sudoers file.  This incident will be reported.

$ exit         #beginnerからログアウト
exit

アカウント作成後に、追加で何も設定していないため sudo は実行できません。
エラーメッセージの「sudoers file」がキーポイントです。

sudo を使えるようにする

先ほど追加したユーザ beginnersudo を実行できるように設定します。
sudo の実行制御は /etc/sudores に記載されていますので、まずは設定ファイルの中身を確認します。

$ sudo cat /etc/sudoers
~

# User privilege specification
root    ALL=(ALL:ALL) ALL

~

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

~

読み方

sudores
どのユーザへの設定か 接続ホストはどこか = (どのユーザとして:どのグループとして) どのような操作を許可するのか

sudores の読み方を踏まえると、
現在の設定では「rootユーザ」と「sudoグループへの所属ユーザ」に権限が与えられていることが分かります。

sudores
# rootユーザは、どのホストからの接続でも、すべての操作ができる
root    ALL=(ALL:ALL) ALL

# sudoグループの所属ユーザは、どのホストからの接続でも、すべての操作ができる
%sudo   ALL=(ALL:ALL) ALL

今やりたいことは「beginnersudo を使えるようにする」ことです。
sudoers には「sudoグループの所属ユーザは、すべての操作ができる」と設定されているので、

  • beginnersudoグループ に所属させる
  • sudo コマンドを実行する

を試してみます。

beginnersudoグループ に所属させる

まずは、sudo グループの状況を確認します。

$ cat /etc/group | grep sudo
sudo:x:27:main-user

このコマンドにより、コマンド実行時点でsudoグループに所属しているユーザの一覧が確認できます。
さっそく、beginnerをグループに追加します。

$ sudo usermod -aG sudo beginner

$ groups beginner
beginner : beginner sudo

$ cat /etc/group | grep sudo
sudo:x:27:main-user,beginner

sudoグループに、beginner が追加されました。

sudo コマンドを実行する

beginnersudoers に設定された条件を満たしたので、sudoが実行可能になりました。

$ su beginner
Password:

$ sudo cat /etc/passwd
[sudo] password for beginner:       #先ほどは正しいパスワードを入力しても閲覧できなかったが、現時点では閲覧可能に
root:x:0:0:root:/root:/bin/bash
...
main-user:x:1000:1000:,,,:/home/main-user:/bin/bash
beginner:x:1003:1003:,,,:/home/beginner:/bin/bash

この時点」ではエラーが出ていましたが、グループに所属したことで sudo が実行できるようになりました。

もちろんグループから外せば、元通り sudo は実行できなくなります。

$ exit      #beginnerからログアウト
exit

$ sudo gpasswd -d beginner sudo     #beginnerをsudoグループから外す
Removing user beginner from group sudo

$ cat /etc/group | grep sudo    #sudoグループにbeginnerは残っていない
sudo:x:27:main-user

$ groups beginner       #beginnerの所属グループはbeginnerのみ
beginner : beginner

$ su beginner
Password:   #beginnerにスイッチ

$ sudo cat /etc/passwd
beginner is not in the sudoers file.  This incident will be reported.

以上により、
任意のユーザを sudo グループに追加することで、sudo コマンドが実行可能となることが分かりました。

特定ユーザ専用の定義を追加する

ここまでは「sudores に記載されてるグループに、sudo を実行したいユーザを所属させる」という方法を取りました。
もう1つの方法として、root ユーザのように「特定のユーザの設定を記載する」ことでも sudo の実行権限を与えることが可能です。

sudores の編集は visudo を使います。vim などのテキストエディタによる編集も可能ですが、sudores 自体が sudo コマンドの動作を制御する重要なファイルなため、誤った編集によりシステムを不安定にする可能性があります。visudo にはファイルを保存する際に構文エラーをチェックしたり、同時編集による問題を防ぐ機能がありますので、sudores の編集にはこのエディタを利用します。

/etc/sudores
$ sudo cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
~
@includedir /etc/sudoers.d

また、設定ファイルの注意書きに「/etc/sudores を直接編集するのではなく、/etc/sudoers.d/ に追加してください」とありますので、この指示に従います。

$ sudo visudo -f /etc/sudoers.d/privilegedUsers
/etc/sudoers.d/privilegedUsers
beginner        ALL=(ALL:ALL) ALL

visudo はファイル保存直前に構文チェックが起動します。文法ミスがあれば編集を再開して修正しましょう。

$ sudo visudo -f /etc/sudoers.d/privilegedUsers
/etc/sudoers.d/privilegedUsers:1:14: syntax error
beginner        ALL-(ALL:ALL) ALL   #「=」にすべきところ「-」となっている
             ^
What now?
Options are:
  (e)dit sudoers file again
  (x)it without saving changes to sudoers file
  (Q)uit and save changes to sudoers file (DANGER!)

beginner の設定追記が完了したら、ユーザを切り替えて動作確認します。

$ su beginner
Password:

念のため、sudoグループに所属していないことを確認します。

$ groups
beginner    #beginnerユーザが所属するのは、beginnerグループのみ

$ cat /etc/group | grep sudo
sudo:x:27:main-user     #sudoグループに所属するのは、main-userのみ

以下のコマンドにより、/etc/sudoers.d/privilegedUsers への設定通り、beginnersudo を実行出来ることが確認できました。

$ sudo cat /etc/passwd
[sudo] password for beginner:
root:x:0:0:root:/root:/bin/bash
~
main-user:x:1000:1000:,,,:/home/main-user:/bin/bash
beginner:x:1003:1003:,,,:/home/beginner:/bin/bash

ここまでの作業を整理すると

①グループに権限を付与して、そのグループへの所属を通して、ユーザにsudo実行権限を与える
②ユーザに直接直接sudo実行権限を付与する

の2パターンが確認してきました。

以降からは、sudores で使える便利なオプションを解説します。

「NOPASSWD」の利用

「NOPASSWD」を設定すると、sudo コマンド実行時のパスワード要求をスキップできます。

ex. beginner に NOPASSWD を設定する

sudo visudo -f /etc/sudoers.d/privilegedUsers
/etc/sudoers.d/privilegedUsers
beginner        ALL=(ALL:ALL) NOPASSWD:ALL

NOPASSWD設定後からは、 sudo 利用時のパスワード要求が無くなります。

$ su beginner
Password:

$ sudo cat /etc/passwd  #パスワード要求なし
~
main-user:x:1000:1000:,,,:/home/main-user:/bin/bash
beginner:x:1003:1003:,,,:/home/beginner:/bin/bash

利用場面には注意ですが、動作検証を優先する場合などで活用できます。

「エイリアス」の利用

sudores には、以下4つのエイリアスがあります。

  • User_Alias
  • Runas_Alias
  • Host_Alias
  • Cmnd_Alias

例えば、sudores の記載内容が以下の状態だったとします。

/etc/sudoers.d/privilegedUsers
eins-user   ALL=(ALL:ALL) ALL
zwei-user   ALL=(ALL:ALL) ALL
drei-user   ALL=(ALL:ALL) ALL
vier-user   ALL=(ALL:ALL) ALL

これらはエイリアスを使うことで、以下のようにまとめられます。

/etc/sudoers.d/privilegedUsers
User_Alias USERS = eins-user,zwei-user,drei-user,view-user
USERS   ALL=(ALL:ALL) ALL

エイリアスの利用により、ファイルの見通しが良くなりました。

おわりに

本記事では「そういえば、sudoって、どういう権限制御になっているんだっけ?」という疑問から、sudo 権限周りの設定方法についてハンズオン形式で解説してきました。このような「枯れた技術への質問」であれば ChatGPT が高い精度で回答してくれるのは間違いありませんが、1つ1つのコマンドを実際に試すことで「知っている」から「使える」にまで昇華することは、引き続き重要だなと感じました。

フューチャー Advent Calendar 2023 はまだまだ続きます。明日の記事も、お楽しみに!

11
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?