[初心者向け]今更喋るのも申し訳ないLinuxのパーミッションの話

# はじめに

Linuxのパーミッション、使いこなしていますか？
恥ずかしながら私は使いなこなせるようになったのはここ数年の話です。意外と難しいですよね。

近年だと、コンテナを使えば閉じた世界を作れるので、パーミッションをそこまで意識しなくてもよいという意見もあります。とはいえ、一度作ったら長く付き合う羽目になるのがシステムというモノ、せっかくながらパーミッションもしっかり考えたいところです。

全力で避けるほど、難しい話でもないので、今回はパーミッションの話をさせてください。

# 本記事執筆における確認環境

今回の記事はAmazon Linux 2023で動作確認しながら記述しています。

# lsコマンドの結果からパーミッションを読み解く

まず、`ls -l`コマンドでファイル一覧を表示してみます。

```bash
ls -l
total 36
-rwxr-xr-x 1 ec2-user ec2-user 11754 Sep 24 04:31 file_A.txt
-rwxrw-rw- 1 ec2-user ec2-user 23508 Sep 24 04:31 file_B.txt
drwxrwxr-x 2 ec2-user ec2-user 6 Sep 24 04:35 sub_dir
```

この結果を読み解いていきます。

## ファイルタイプとパーミッション

この結果の左から10文字目までに着目します。
10文字目までのルールは以下の通りです。

| 文字の位置 | 説明                                         | 例                 |
|------------|----------------------------------------------|--------------------|
| 1          | ファイルタイプ                               | `-` 通常のファイル</br>`d` ディレクトリ</br>`l` シンボリックリンク[^1] |
| 2          | 所有者の読み込みパーミッション               | `r` 読み込み可</br>`-` 読み込み不可     |
| 3          | 所有者の書込パーミッション               | `w` 書込可</br>`-` 書込不可     |
| 4          | 所有者の実行パーミッション                   | `x` 実行可</br>`-` 実行不可         |
| 5          | グループの読み込みパーミッション             | `r` 読み込み可</br>`-` 読み込み不可     |
| 6          | グループの書込パーミッション             | `w` 書込可</br>`-` 書込不可     |
| 7          | グループの実行パーミッション                 | `x` 実行可</br>`-` 実行不可         |
| 8          | その他のユーザーの読み込みパーミッション     | `r` 読み込み可</br>`-` 読み込み不可     |
| 9          | その他のユーザーの書込パーミッション     | `w` 書込可</br>`-` 書込不可     |
| 10         | その他のユーザーの実行パーミッション         | `x` 実行可</br>`-` 実行不可         |

このルールに基づき`ls -l`読み解くと、以下のことがわかります。

| 項目       | タイプ   | 所有者</br>(読取) | 所有者</br>(書込) | 所有者</br>(実行) | グループ</br>(読取) | グループ</br>(書込) | グループ</br>(実行) | その他</br>(読取) | その他</br>(書込) | その他</br>(実行) |
|------------|-------------------|--------------|--------------|--------------|----------------|----------------|----------------|--------------|--------------|--------------|
| file_A.txt | ファイル     | あり         | あり         | あり         | あり           | なし           | あり           | あり         | なし         | あり         |
| file_B.txt | ファイル     | あり         | あり         | あり         | あり           | あり           | なし           | あり         | あり         | なし         |
| sub_dir    | ディレクトリ       | あり         | あり         | あり         | あり           | あり           | あり           | あり         | なし         | あり         |

## ユーザーとグループ

次に、`ec2-user ec2-user`の部分を読み解きます。この部分は、`ファイルの所有者 ファイルのグループ`を指します。と言いましても、`ec2-user ec2-user`とユーザー名とグループ名が同じなので、あまりわかりやすくありません。なので、プライマリーグループを`ec2-user`にした、新たなユーザー`kaneyasu`を作ってファイルを作り直してみます。[^2]

作り直した後のファイル一覧を表示してみます。

```bash

```bash
ls -l
total 36
-rwxr-xr-x 1 ec2-user ec2-user 11754 Sep 24 04:31 file_A.txt
-rwxrw-rw- 1 ec2-user ec2-user 23508 Sep 24 04:31 file_B.txt
-rw-r--r-- 1 kaneyasu ec2-user     0 Sep 24 05:13 file_C.txt
drwxrwxr-x 2 ec2-user ec2-user 6 Sep 24 04:35 sub_dir
```

この結果を読み解くと、`kaneyasu`だけが編集可能なことがわかります。
ちょっと変更して、グループも編集可能にします。

```bash
sudo chmod 764 file_C.txt
ls -l file_C.txt 
-rwxrw-r-- 1 kaneyasu ec2-user 0 Sep 24 05:13 file_C.txt
```

これで、グループ`ec2-user`に所属しているユーザー全員が、ファイル`file_C.txt`を編集できるようになりました。

## ディレクトリのパーミッションの意味はファイルと異なる

ディレクトリのパーミッションの意味は、ファイルとは結構異なります。書込権限の動きが、特に忘れやすいので要注意です。

- 読取権限 (`r`)
  - ディレクトリ内のアイテム名のリストを表示することができる。
    - ファイルを開けるかどうかはファイル側のパーミッションに依存。
    - ファイルだけに読取があってディレクトリにない場合、直接参照は可能だが、リスト表示はできない。

- 書込権限 (`w`)
  - ディレクトリ内でのファイルやサブディレクトリの作成、削除、名前変更ができる。
    - ファイルを編集できるかどうかはファイル側のパーミッションに依存。
    - ディレクトリに書込権限がなく、ファイルだけにある場合、ファイルの編集はできるが、ファイルの作成、削除、名前の変更はできない。

- 実行権限 (`x`)
  - ディレクトリ内の特定のファイルへのアクセス(存在確認など)やサブディレクトリへの移動などができる。
    - ファイルを実行できるかどうかはファイル側のパーミッションに依存。

# パーミッションの数字表記

```bash
sudo chmod 764 file_C.txt
```

上の方で少し触れましたが、パーミッションで数字で表現することができます。こちらの方が、馴染みのある人も多いでしょう。
この数字表記、1桁目は所有者、2桁目はグループ、3桁目はその他のユーザーのパーミッションを表します。
以下に、数字表記と記号表記の対応表を示します。

この表をじっくり見ていくと、**数字が大きい方が権限が大きいと言い難い**ことがわかります。この数字は、**単純な整数ではなくビット演算の結果なのです。**
「6」は、何気に実行権限がないのは地味にハマりやすいポイントです。（Linuxのベンダー試験でも問われるいやらしいポイントです。）

| 数字 | 記号表記                 | 2進数表示 | 計算                               | 説明                   |
|------|--------------------------|----------|------------------------------------|------------------------|
| 0    | `---`                    | 000      | 0×4 + 0×2 + 0×1 = 0                | 何もできない             |
| 1    | `--x`                    | 001      | 0×4 + 0×2 + 1×1 = 1                | 実行のみ可能             |
| 2    | `-w-`                    | 010      | 0×4 + 1×2 + 0×1 = 2                | 書込のみ可能             |
| 3    | `-wx`                    | 011      | 0×4 + 1×2 + 1×1 = 3                | 書込と実行が可能         |
| 4    | `r--`                    | 100      | 1×4 + 0×2 + 0×1 = 4                | 読取のみ可能             |
| 5    | `r-x`                    | 101      | 1×4 + 0×2 + 1×1 = 5                | 読取と実行が可能         |
| 6    | `rw-`                    | 110      | 1×4 + 1×2 + 0×1 = 6                | 読取と書込が可能         |
| 7    | `rwx`                    | 111      | 1×4 + 1×2 + 1×1 = 7                | 読取と書込と実行が可能   |

パーミションの数字表記は、ファイルやディレクトリのパーミションを変えるコマンドでよく使うので、覚えておくと便利です。

```bash
sudo chmod 764 file_C.txt
```

`chmod`コマンドはchange modeを意味します。

# よくあるパーミッション

| 種類                   | パーミッション | 数字表記 | 記号表記     | 説明                                       |
|------------------------|------------|----------|--------------|--------------------------------------------------|
| 静的HTMLファイル       | 読取専用      | 644      | `rw-r--r--`  | Apacheはファイルの内容を読むだけで、変更する必要はないため。他のユーザーは変更を加えるべきではない。             |
| PHPや実行可能スクリプト | 実行可能      | 744      | `rwxr--r--`  | Apacheはファイルを読んで実行する必要があるが、他のユーザーは変更や実行をするべきではない。                      |
| ディレクトリ            | 読取・実行    | 755      | `rwxr-xr-x`  | Apacheはディレクトリ内のファイルにアクセスするために実行権限が必要。他のユーザーはファイルを追加・削除するべきではない。 |
| 全権限（非推奨）        | 全権限        | 777      | `rwxrwxrwx`  | すべてのユーザーが全ての操作を行えるが、セキュリティ上のリスクが高いため通常は推奨されない。                       |

[^1]: ファイルタイプは他にもキャラクタデバイスなどがあります。
[^2]: Linuxで特に何も指定せずにユーザーを作ると、ユーザー名と同じグループを作り、そこをプライマリーグループとする動きをします。ここがわかりづらいですよね。

# ファイルの所有者は、作成したユーザーで決まる

多くのLinuxディストリビューションのデフォルト設定では、ファイルは作成時に所有者のみが編集権限を持つことが一般的です。
例えば、`kaneyasu`ユーザーでファイルを作成すると、ファイルの所有者は`kaneyasu`になります。

この状態で、他のユーザーが編集可能にするには、以下の方法が考えられます。

1. ファイルのグループのパーミッションを書込可能にした上で、他のユーザーを所有者と同じグループに入れる。
2. 所有者になって編集する
    - `sudo -u kaneyasu vi file_C.txt`
3. ファイルの所有者を変更する
    - `sudo chown userA file_C.txt`
4. 全員を編集可能にする

3.と4.の方法は、セキュリティ上のリスクが高いので、基本的には避けるべきでですが、意外と散見します。
2.のやり方を知らない方が結構いるのかなと思います。

2.のやり方の例を書きます。
`cron`とPHPの組み合わせで、考えてみます。
PHPはApacheで動いているとします。`cron`で指定したコマンドは、`root`ユーザで動作するとします。
`cron`とPHPが同じファイルを編集する場合、`root`ユーザーが作成したファイルは、`root`ユーザーしか編集できないので、PHPから編集不可になることがあります。

![`cron`とPHPが同じファイルを編集する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/43af3012-9834-e288-0240-6ed28c8c0dd3.png)

これを回避するには、`cron`の設定を変更。コマンドをApacheのユーザーで実行するようにします。
これにより、PHPから編集できるようになります。

![`cron`側で実行ユーザーを指定する](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1959433/e35e1181-9998-7e45-8ead-fb42177fc75c.png)

この手法（というほどのものではありませんが）、結構重要です。
この手法を知らないとパーミッションをしっかり設定すると、全然動かなくなるから嫌だという感覚に陥ります。

# 最後に

Linuxのパーミッションシステムは長年にわたり実績を積み重ねており、多くのシステムやアプリケーションで参考や再利用がされています。
押さえておくと、きっと応用の幅が広がると思います。