[実践]Ubuntu24.04でEFSを使ってみよう

![001samune.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/e4ff8de8-37d6-46f1-ac34-ad945f36a53d.png)

# 概要
タイトルの通り、Ubuntu24.04にEFSのファイルシステムをマウントして利用する方法を備忘録として残します。
今回実装する構成は以下の通りです。
* UbuntuからはEFSマウントヘルパーを使用してファイルシステムをマウント
* マウントポイントを使用し、ファイルシステム内の「/App」をルートディレクトリとしてマウント
* IAM認証を使用し、クライアント(Ubuntu)からのアクセスを制御

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/12f11f72-1358-4d45-a014-f62716f3031a.png)

:::note warn
Ubuntu24.04は執筆時点(2025/3/13)で検証されていませんが試していきます。
:::

https://github.com/aws/efs-utils/blob/master/README.md


# EFSについて
NFSによる共有ファイルシステムストレージをサーバーレスで提供するフルマネージドサービスです。
Linux OSのEC2やオンプレミスのサーバーから利用でき、ファイルシステムの簡単な作成・管理が可能で、ストレージは自動拡張・縮小してくれます。


### マウント方式
マウント方式は「**標準の Linux NFS クライアント**」「**EFS マウントヘルパー**」の二つです。
ファイルシステムを作成すると親切に各方式でのマウントコマンドを提供してくれます。

![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/0c329b76-47c9-4bd6-a801-1d7a272a727e.png)

![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/56f0513e-5c21-4a08-a69d-c09edd12c471.png)

:::note info
後述するマウントポイントを作成した場合、マウントポイント毎のマウントコマンドが提供されます
:::

:::note info
NFSクライアントでのマウントオプションはAWS推奨の値となっています。
:::

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/mounting-fs-nfs-mount-settings.html


どちらの方式を選ぶかは自由ではありますが、基本**EFSマウントヘルパーでのマウントがおススメ**です。
公式でもおススメされていますし、**後述するIAM認証またはアクセスポイントを利用する場合はEFSマウントヘルパーの利用が必須**です。

:::note info
> EFS ファイルシステムをマウントするには、EFS マウントヘルパーを使用することをお勧めします。
:::

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/mounting-fs.html

:::note info
> EFS マウントヘルパーを使用することによってのみ、EFS アクセスポイントを使用して EFS ファイルシステムをマウントできます。
:::

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/mounting-access-points.html

:::note info
> IAM 認可を使用してクライアントによるアクセスをコントロールするには、EFS マウントヘルパーを使用して Amazon EFS ファイルシステムをマウントする必要があります。
:::

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/iam-access-control-nfs-efs.html


### アクセスポイント
ファイルシステム内のディレクトリに対するアクセス制限をするための機能です。
アクセスポイント毎に「**対象のルートディレクトリ**」「**POSIXユーザー**」「**POSIXグループ**」を設定します。
クライアント(接続元)はアクセスポイントに対してマウントを実施し、アクセスポイント経由でファイルの作成・閲覧・削除を行います。
**アクセスポイント経由で作成したファイル**は、**アクセスポイントに設定したPOSIXユーザー及びグループの権限**となります。
つまり、クライアントによらない権限の設定が可能になります。

![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/a725d1c4-c937-4013-9c64-63445a886a9b.png)

**NFSクライアントでマウント**した場合は、**EFSファイルシステムの`/`(ルートディレクトリ)をマウントする**ことになります。その場合の **権限は`root:root 0755`** となります。
また、ファイルシステムにアクセスする際の権限は接続元ユーザーの権限になるためデフォルトではrootユーザー以外の書き込みができない状態です。
仮にマウントポイントを`/`に設定した場合でも、書き込む際の権限は設定したPOSIXユーザー・グループの権限になるため書き込みができません。
どうしてもという場合は、`/`の権限を変更する必要があります。

:::note info
ちなみに、Security HubコントロールのEFS.3ではアクセスポイントで`/`を利用することは非推奨です。
:::

> Path の値が / (ファイルシステムのデフォルトのルートディレクトリ) に設定されていると、このコントロールは失敗します。

https://docs.aws.amazon.com/ja_jp/securityhub/latest/userguide/securityhub-controls-reference.html#fsbp-efs-3

### IAM認証
アイデンティティベースポリシー(IAMポリシー)もしくはファイルシステムポリシー(バケットポリシーのようなリソースベースポリシー)を使った、ファイルシステムに対するアクセスを制御をするための機能です。
バケットポリシーと同じ考え方で、どちらか一方で許可されていれば指定したアクションが許可されます。
ファイルシステム作成時のファイルシステムポリシーは何も記載されていないので(フルアクセス許可)、ファイルシステムには匿名のクライアントからアクセスすることが可能です。そのため、デフォルトではマウントターゲットに紐づけるセキュリティグループでのIP制限のみとなります。

:::note info
ちなみに、ファイルシステムポリシーで制御できるActionは以下３つです。

|Action|概要|
|:-|:-|
|elasticfilesystem:ClientMount|ファイルシステムへの読み取り専用アクセス|
|elasticfilesystem:ClientWrite|ファイルシステムへの書き込みアクセス|
|elasticfilesystem:ClientRootAccess|rootユーザーを使用したファイルシステムへのアクセス|

:::

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/iam-access-control-nfs-efs.html


# 実践
それでは実際にEC2からEFSファイルシステムをマウントしていきます。
環境はGitHubで公開しています。
各コードとデプロイ方法を用意してますのでお試しください。

https://github.com/tyskJ/aws-efs-iam-authentication/tree/main

### EFSの設定
#### ファイルシステムポリシー
ファイルシステムポリシーは以下の通りです。
* 1つ目のStatementで、EC2のIAMロール(iam-role-ec2)からマウントターゲット経由でのみ、「rootユーザーの使用」「書き込み」「読み込み」を許可しています
* 2つ目のStatementで、クライアントからファイルシステムへの接続にTLSを強制しています

```json:FileSystemPolicy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowEFSAccess",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::[AccountID]:role/iam-role-ec2"
            },
            "Action": [
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientMount"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "elasticfilesystem:AccessedViaMountTarget": "true"
                }
            }
        },
        {
            "Sid": "DenyNotTls",
            "Effect": "Deny",
            "Principal": {
                "AWS": "*"
            },
            "Action": "*",
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}
```

#### アクセスポイント
##### ルートディレクトリパス
ルートディレクトリパスは`/App`としています。

![画像7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/7d256799-32e9-4f11-9493-b3b004f57300.png)

##### POSIXユーザーID・POSIXグループID
ユーザーIDは`1500`、グループIDは`1500`としています。
今回セカンダリグループIDは未設定です。

![画像12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/7bab23e9-0ddd-4578-8b67-9e33273965f9.png)


:::note info
[**セカンダリグループIDの利用用途**]
ファイルシステム内のディレクトリが階層構造(親子関係)となっている際、
子側のディレクトリ内に、親側のPOSIXユーザーからのファイル操作を許可したい場合などが考えられます。
子側のアクセスポイントのセカンダリグループIDに、親側のPOSIXグループIDを設定することで実現します。
:::

![画像9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/7eb629af-aa1d-4f78-9470-6027a2e099d7.png)

#### ルートディレクトリ作成のアクセス許可
設定は以下の通りです。

![画像13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/c092becd-4ca7-4092-ad9a-9531c2bf103d.png)


この機能は、`ルートディレクトリパス`で指定したディレクトリがファイルシステム内に無い場合に、指定したユーザーID/グループID/権限でディレクトリを作成してくれる機能となります。
手動で作成済みの場合は不要ですし、その場合に本設定で指定した値に上書きされることはありません。
ただし存在しない場合に指定していないとマウントエラーになります。

> アクセスポイントのルートディレクトリがマウント時間前にすでに存在する場合、既存のアクセス許可はアクセスポイントによって上書きされません。

> Amazon EFS では、OwnUid、OwnGID、およびパーミッションがディレクトリに指定されている場合にのみ、アクセスポイントルートディレクトリが作成されます。この情報を指定しない場合、Amazon EFS はルートディレクトリを作成しません。ルートディレクトリが存在しない場合に、アクセスポイントを使用してマウントしようとすると、失敗します。

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/enforce-root-directory-access-point.html


### クライアントの設定
#### EFSマウントヘルパーインストール
Ubuntu24.04にEFSマウントヘルパーをインストールしていきます。

:::note warn
バージョンによっては`AWS Systems Manager Distributor`というSystems Managerマネージドノードに対してパッケージ化したソフトウェアを配信する機能を使ってインストール可能ですが、Ubuntu24.04は対象外です。

![画像11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/30022abb-cb6a-4fb7-b983-67c63903c4e7.png)

:::

https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/distributor.html

EFSマウントヘルパーが含まれる`amazon-efs-utils`パッケージは、Amazon Linux AMIリポジトリで公開されています。
つまり、Amazon Linux以外のLinux OSはbuildする必要があります。
そのため、GitHubのREADMEを参考にbuildしていきます。

https://docs.aws.amazon.com/ja_jp/efs/latest/ug/installing-amazon-efs-utils.html#installing-other-distro

https://github.com/aws/efs-utils?tab=readme-ov-file#on-other-linux-distributions

##### パッケージリスト更新
```shell-session
$ sudo apt-get update
Hit:1 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu noble InRelease
Hit:2 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu noble-updates InRelease
Hit:3 http://ap-northeast-1.ec2.archive.ubuntu.com/ubuntu noble-backports InRelease
Hit:4 http://security.ubuntu.com/ubuntu noble-security InRelease
Reading package lists... Done
```

##### 必要なパッケージインストール
```shell-session
$ sudo apt-get -y install git binutils rustc cargo pkg-config libssl-dev gettext
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
~省略~
Running kernel seems to be up-to-date.

Restarting services...
 /etc/needrestart/restart.d/systemd-manager
 systemctl restart acpid.service chrony.service cron.service irqbalance.service multipathd.service packagekit.service polkit.service rsyslog.service systemd-journald.service systemd-networkd.service systemd-resolved.service systemd-udevd.service udisks2.service

Service restarts being deferred:
 systemctl restart ModemManager.service
 /etc/needrestart/restart.d/dbus.service
 systemctl restart getty@tty1.service
 systemctl restart networkd-dispatcher.service
 systemctl restart serial-getty@ttyS0.service
 systemctl restart snap.amazon-ssm-agent.amazon-ssm-agent.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.

```

##### リポジトリClone
```shell-session
$ cd && git clone https://github.com/aws/efs-utils
Cloning into 'efs-utils'...
remote: Enumerating objects: 1864, done.
remote: Counting objects: 100% (395/395), done.
remote: Compressing objects: 100% (127/127), done.
remote: Total 1864 (delta 315), reused 273 (delta 265), pack-reused 1469 (from 3)
Receiving objects: 100% (1864/1864), 907.76 KiB | 13.75 MiB/s, done.
Resolving deltas: 100% (1176/1176), done.
```

##### build
```shell-session
$ cd efs-utils && ./build-deb.sh
+ pwd
+ BASE_DIR=/home/ssm-user/efs-utils
+ BUILD_ROOT=/home/ssm-user/efs-utils/build/debbuild
+ VERSION=2.2.1
+ RELEASE=1
+ dpkg --print-architecture
+ ARCH=amd64
+ DEB_SYSTEM_RELEASE_PATH=/etc/os-release
+ export VERSION RELEASE ARCH
+ echo Cleaning deb build workspace
Cleaning deb build workspace
+ rm -rf /home/ssm-user/efs-utils/build/debbuild
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild
+ echo Creating application directories
Creating application directories
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/etc/amazon/efs
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/etc/init/
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/etc/systemd/system
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/sbin
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/usr/bin
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/var/log/amazon/efs
+ mkdir -p /home/ssm-user/efs-utils/build/debbuild/usr/share/man/man8
+ echo Building efs-proxy
Building efs-proxy
+ cd src/proxy
+ cargo build --release --manifest-path /home/ssm-user/efs-utils/src/proxy/Cargo.toml
~省略~
+ DEB=/home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb
+ ar r /home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb /home/ssm-user/efs-utils/build/debbuild/debian-binary
ar: creating /home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb
+ ar r /home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb /home/ssm-user/efs-utils/build/debbuild/control.tar.gz
+ ar r /home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb /home/ssm-user/efs-utils/build/debbuild/data.tar.gz
+ echo Copying deb to output directory
Copying deb to output directory
+ cp /home/ssm-user/efs-utils/build/debbuild/amazon-efs-utils-2.2.1-1_amd64.deb build/
```

##### amazon-efs-utilsパッケージインストール
```shell-session
$ sudo apt-get -y install ./build/amazon-efs-utils*deb
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Note, selecting 'amazon-efs-utils' instead of './build/amazon-efs-utils-2.2.1-1_amd64.deb'
~省略~
Running kernel seems to be up-to-date.

Restarting services...

Service restarts being deferred:
 /etc/needrestart/restart.d/dbus.service
 systemctl restart getty@tty1.service
 systemctl restart networkd-dispatcher.service
 systemctl restart serial-getty@ttyS0.service
 systemctl restart systemd-logind.service
 systemctl restart unattended-upgrades.service

No containers need to be restarted.

No user sessions are running outdated binaries.

No VM guests are running outdated hypervisor (qemu) binaries on this host.
N: Download is performed unsandboxed as root as file '/home/ssm-user/efs-utils/build/amazon-efs-utils-2.2.1-1_amd64.deb' couldn't be accessed by user '_apt'. - pkgAcquire::Run (13: Permission denied)
```

##### インストール済み確認
```shell-session
$ dpkg -l | grep amazon-efs-utils
ii  amazon-efs-utils                2.2.1-1                                 amd64        This package provides utilities for simplifying the use of EFS file systems
```

#### アクセスポイントのマウント
アクセスポイントページ画面右上の`アタッチ`を押すと、当該アクセスポイントへのEFSマウントヘルパーを使ったマウントコマンドが表示されます。こちらのコマンドを今回の要件に合わせてオプションやマウント先ディレクトリを修正してマウントしていきます。

![画像15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/4a1e90b2-2fdd-4230-b6a6-bf8046810be3.png)

![画像16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3984127/3f504606-0ea7-4b4b-b7fa-5e446cf8b0bf.png)

今回は以下の条件に合わせてマウントしていきます。
* tlsでの接続
* IAM認証での接続
* `ssm-user`の`/home/ssm-user/efs`にマウント

```shell-session
$ id
uid=1001(ssm-user) gid=1001(ssm-user) groups=1001(ssm-user)
$
$
$ cd && mkdir efs && ls -al
total 36
drwxr-x---  5 ssm-user ssm-user 4096 Mar 13 06:46 .
drwxr-xr-x  4 root     root     4096 Mar 13 05:26 ..
-rw-r--r--  1 ssm-user ssm-user  220 Mar 31  2024 .bash_logout
-rw-r--r--  1 ssm-user ssm-user 3771 Mar 31  2024 .bashrc
drwxr-xr-x  3 ssm-user ssm-user 4096 Mar 13 05:43 .cargo
-rw-------  1 ssm-user ssm-user   20 Mar 13 05:59 .lesshst
-rw-r--r--  1 ssm-user ssm-user  807 Mar 31  2024 .profile
drwxr-xr-x  2 ssm-user ssm-user 4096 Mar 13 06:46 efs
drwxr-xr-x 10 ssm-user ssm-user 4096 Mar 13 05:43 efs-utils
$
$
$ df -h
Filesystem       Size  Used Avail Use% Mounted on
/dev/root        6.8G  3.7G  3.1G  55% /
tmpfs            3.9G     0  3.9G   0% /dev/shm
tmpfs            1.6G  892K  1.6G   1% /run
tmpfs            5.0M     0  5.0M   0% /run/lock
efivarfs         128K  4.1K  119K   4% /sys/firmware/efi/efivars
/dev/nvme0n1p16  881M   76M  744M  10% /boot
/dev/nvme0n1p15  105M  6.1M   99M   6% /boot/efi
$
# ファイルシステムID及びアクセスポイントIDは環境に合わせて修正
$ sudo mount -t efs -o tls,iam,accesspoint=fsap-XXXX fs-XXXX:/ /home/ssm-user/efs
/home/ssm-user/efs is already mounted, please run 'mount' command to verify
$
$
$ df -h
Filesystem       Size  Used Avail Use% Mounted on
/dev/root        6.8G  4.1G  2.7G  61% /
tmpfs            3.9G     0  3.9G   0% /dev/shm
tmpfs            1.6G  976K  1.6G   1% /run
tmpfs            5.0M     0  5.0M   0% /run/lock
efivarfs         128K  4.1K  119K   4% /sys/firmware/efi/efivars
/dev/nvme0n1p16  881M  133M  687M  17% /boot
/dev/nvme0n1p15  105M  6.1M   99M   6% /boot/efi
127.0.0.1:/      8.0E     0  8.0E   0% /home/ssm-user/efs
```

マウントしたディレクトリは`ルートディレクトリのアクセス許可`で設定した権限になっていますね。
```shell-session
$ ls -al
total 36
drwxr-x---  5 ssm-user ssm-user 4096 Mar 13 06:46 .
drwxr-xr-x  4 root     root     4096 Mar 13 05:26 ..
-rw-r--r--  1 ssm-user ssm-user  220 Mar 31  2024 .bash_logout
-rw-r--r--  1 ssm-user ssm-user 3771 Mar 31  2024 .bashrc
drwxr-xr-x  3 ssm-user ssm-user 4096 Mar 13 05:43 .cargo
-rw-------  1 ssm-user ssm-user   20 Mar 13 05:59 .lesshst
-rw-r--r--  1 ssm-user ssm-user  807 Mar 31  2024 .profile
drwxr-xr-x  2     1500     1500 6144 Mar 13 06:47 efs
drwxr-xr-x 10 ssm-user ssm-user 4096 Mar 13 05:43 efs-utils
```

再起動後も自動マウントするために`/etc/fstab`に設定を追記します。
```shell:/etc/fstab
# ファイルシステムID及びアクセスポイントIDは環境に合わせて修正
fs-XXXX:/ /home/ssm-user/efs efs defaults_netdev,noresvport,tls,iam,accesspoint=fsap-XXXX 0 0
```


### 動作確認
実際にファイルをマウントした`/home/ssm-user/efs`ディレクトリに作成してみます。
作成したファイルは`POSIXユーザー`で設定したUID/GIDになっていますね。
```shell-session
$ id && pwd && ls -al
uid=1001(ssm-user) gid=1001(ssm-user) groups=1001(ssm-user)
/home/ssm-user
total 36
drwxr-x---  5 ssm-user ssm-user 4096 Mar 13 07:13 .
drwxr-xr-x  4 root     root     4096 Mar 13 05:26 ..
-rw-r--r--  1 ssm-user ssm-user  220 Mar 31  2024 .bash_logout
-rw-r--r--  1 ssm-user ssm-user 3771 Mar 31  2024 .bashrc
drwxr-xr-x  3 ssm-user ssm-user 4096 Mar 13 05:43 .cargo
-rw-------  1 ssm-user ssm-user   20 Mar 13 05:59 .lesshst
-rw-r--r--  1 ssm-user ssm-user  807 Mar 31  2024 .profile
drwxr-xr-x  2     1500     1500 6144 Mar 13 07:13 efs
drwxr-xr-x 10 ssm-user ssm-user 4096 Mar 13 05:43 efs-utils
$
$
$ touch efs/test.txt
$
$
$ ls -al efs
total 12
drwxr-xr-x 2     1500     1500 6144 Mar 13 07:14 .
drwxr-x--- 5 ssm-user ssm-user 4096 Mar 13 07:13 ..
-rw-r--r-- 1     1500     1500    0 Mar 13 07:14 test.txt
```

# まとめ
今回、Ubuntu24.04にEFSマウントヘルパーを使用してEFSファイルシステムをマウントしました。
冒頭でも記載したように公式ではUbuntu24.04の検証がされていないという状況なので、
本番運用での使用は要検討かと思いますが、一応動きはするという結果になりました。
この記事が誰かの役に立てば幸いです。


# 参考資料
### リファレンス
* [Amazon Elastic File System ユーザーガイド - Amazon EFS クライアントを自動的にインストールまたは更新する -](https://docs.aws.amazon.com/ja_jp/efs/latest/ug/manage-efs-utils-with-aws-sys-manager.html)
### ブログ
* [便利になった AWS Systems Manager Distributor を使ってソフトウェアを最新に保とう！！](https://dev.classmethod.jp/articles/keep-software-latest-version-ssm-distributor/)
* [[アップデート] Amazon EFSでIAM認証とアクセスポイントの設定が可能に](https://dev.classmethod.jp/articles/update-for-amazon-efs-iam-authorization-and-access-points/)
* [EFSアクセスポイントのルートディレクトリ作成のアクセス許可とPOSIXユーザー指定を試してみた](https://dev.classmethod.jp/articles/efs-accesspoint-option-settings/#toc-)
* [Amazon EFSにIAM認証のみを許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみた](https://dev.classmethod.jp/articles/amazon-efs-iam-auth-deny-anonymous-access/#toc-)
* [EFSのマウントについて理解する。](https://qiita.com/sakai00kou/items/3ee37db9eb31a726f558#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB)