Amazon EFSにIAM認証のみを許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみた

2023.05.12

ちゃんと匿名アクセスはブロックされるのかな

こんにちは、のんピ(@non____97)です。

皆さんはAmazon EFSでIAM認証を使っていますか? 私はあまり使っていませんでした。

IAM認証を使うことでクライアントを認識することができ、ポリシーに応じて権限を管理することが可能です。EFSはLDAPと連携してKerberos認証をすることができないので、匿名アクセスを許可しない場合に役立ちそうです。

実際の設定例は以下の通りです。

この例を見て私は「IAM認証はしていないが、EFSファイルシステムのセキュリティグループで許可しているIPアドレスからのアクセスもちゃんとブロックしてくれるのかな?」と不安になりました。

TCP/IPの世界とIAMによる認証の世界がイマイチリンクしませんでした。IAM認証を許可するようなファイルポリシーを設定しても通常のNFSのアクセスが通るようだと本末転倒な気もします。

そこで、実際にIAM認証を許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみました。

いきなりまとめ

  • Amazon EFSにIAM認証のみを許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされる
    • IAM認証はしていないが、EFSファイルシステムのセキュリティグループで許可しているIPアドレスからのアクセスもブロックされる
  • EFSファイルシステムのマウントはCloudTrailのNewClientConnectionイベントで確認できる
  • デフォルトのファイルシステムポリシーでは匿名クライアントへのフルアクセスを許可している

やってみた

検証環境

検証環境は以下の通りです。

Amazon EFSにIAM認証を許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみた検証環境構成図

NFSクライアントからEFSファイルシステムをマウントします。

検証環境はAWS CDKでデプロイします。使用したコードは以下リポジトリに保存しています。

デプロイされたEFSファイルシステムのファイルシステムポリシーは以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::<AWSアカウントID>:role/EfsStack-Ec2InstanceARole1C8989C2-E2ZXX688D8SP"
            },
            "Action": [
                "elasticfilesystem:ClientMount",
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientWrite"
            ],
            "Resource": "*",
            "Condition": {
                "Bool": {
                    "elasticfilesystem:AccessedViaMountTarget": "true"
                }
            }
        }
    ]
}

ファイルシステムへの読み書きとルートユーザーの使用を許可しています。

なお、"elasticfilesystem:ClientWrite""elasticfilesystem:ClientRootAccess"を許可してもマウントはできないため注意が必要です。(書き込み権限にマウントする権限は含まれない)

また、S3バケットなど他のリソースポリシーと同じく、アイデンティティポリシーとファイルシステムポリシーの両方で権限を付与する必要はありません。

ID ポリシーとリソースポリシーの両方で権限を付与する必要はありません。

IAM を使用してファイルシステムのデータアクセスを制御する - Amazon Elastic File System

Principalで指定しているのはEC2インスタンスにアタッチしているIAMロールのARNです。

Principalの毎のリソースポリシーの評価については以下記事が参考になります。

IAM認証でEFSファイルシステムをマウント

まず、IAM認証でEFSファイルシステムをマウントできることを確認します。

IAM認証を行う場合は、EFSマウントヘルパーを使用する必要があります。

IAM 認証を使用してクライアントによるアクセスをコントロールするには、EFS マウントヘルパーを使用して Amazon EFS ファイルシステムをマウントする必要があります。詳細については、「IAM 認証を使用してマウントする」を参照してください。

IAM を使用してファイルシステムのデータアクセスを制御する - Amazon Elastic File System

ということで下準備としてEFSマウントヘルパー(amazon-efs-utils)をインストールします。

$ sudo dnf install amazon-efs-utils
Last metadata expiration check: 0:01:43 ago on Fri May 12 04:50:32 2023.
Dependencies resolved.
=================================================================================================================
 Package                      Architecture       Version                           Repository               Size
=================================================================================================================
Installing:
 amazon-efs-utils             noarch             1.35.0-1.amzn2023                 amazonlinux              56 k
Installing dependencies:
 stunnel                      x86_64             5.58-1.amzn2023.0.2               amazonlinux             156 k

Transaction Summary
=================================================================================================================
Install  2 Packages

Total download size: 212 k
Installed size: 556 k
Is this ok [y/N]: y
Downloading Packages:
(1/2): amazon-efs-utils-1.35.0-1.amzn2023.noarch.rpm                             633 kB/s |  56 kB     00:00
(2/2): stunnel-5.58-1.amzn2023.0.2.x86_64.rpm                                    1.3 MB/s | 156 kB     00:00
-----------------------------------------------------------------------------------------------------------------
Total                                                                            909 kB/s | 212 kB     00:00
Running transaction check
Transaction check succeeded.
Running transaction test
Transaction test succeeded.
Running transaction
  Preparing        :                                                                                         1/1
  Installing       : stunnel-5.58-1.amzn2023.0.2.x86_64                                                      1/2
  Running scriptlet: stunnel-5.58-1.amzn2023.0.2.x86_64                                                      1/2
  Installing       : amazon-efs-utils-1.35.0-1.amzn2023.noarch                                               2/2
  Running scriptlet: amazon-efs-utils-1.35.0-1.amzn2023.noarch                                               2/2
  Verifying        : stunnel-5.58-1.amzn2023.0.2.x86_64                                                      1/2
  Verifying        : amazon-efs-utils-1.35.0-1.amzn2023.noarch                                               2/2

Installed:
  amazon-efs-utils-1.35.0-1.amzn2023.noarch                  stunnel-5.58-1.amzn2023.0.2.x86_64

Complete!

それではIAM認証でマウントします。

# マウントポイントの作成
$ sudo mkdir -p /mount/efs

# IAM認証でマウント
$ sudo mount -t efs -o tls,iam fs-096bc04e855823d2e /mount/efs

# マウントできたことを確認
$ df -hT -t nfs4
Filesystem     Type  Size  Used Avail Use% Mounted on
127.0.0.1:/    nfs4  8.0E     0  8.0E   0% /mount/efs

$ mount | grep nfs4
127.0.0.1:/ on /mount/efs type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,noresvport,proto=tcp,port=20898,timeo=600,retrans=2,sec=sys,clientaddr=127.0.0.1,local_lock=none,addr=127.0.0.1)

IAM認証でマウントできましたね。

マウント先を確認すると127.0.0.1でした。

EFSマウントヘルパーをインストールする際に依存関係でSSLトンネリングのアプリケーションであるStunnelがインストールされているので、恐らくStunnelが動作しているのではと予想します。

127.0.0.1でコネクションを張っているプロセスを確認します。

$ sudo ss -antp | grep 127.0.0.1
LISTEN 0      4096    127.0.0.1%lo:20898        0.0.0.0:*     users:(("stunnel",pid=1824,fd=9))
ESTAB  0      0          127.0.0.1:36734      127.0.0.1:20898
ESTAB  0      0       127.0.0.1%lo:20898      127.0.0.1:36734 users:(("stunnel",pid=1824,fd=3))

やはり、Stunnelですね。プロセスからもEFSファイルシステムのマウント時にStunnelが動作していることが分かります。

$ sudo ps aux | grep efs
root        1821  0.3  2.4 253612 22776 ?        Ss   08:52   0:02 /usr/bin/python3 /usr/bin/amazon-efs-mount-watchdog
root        1824  0.0  0.8 148416  7732 ?        Ssl  08:52   0:00 /usr/bin/stunnel /var/run/efs/stunnel-config.fs-096bc04e855823d2e.mount.efs.20898
ssm-user    2782  0.0  0.2 222312  2180 pts/0    S+   09:02   0:00 grep efs

Stunnelからどこに接続しているのか確認します。

$ sudo ss -antup | grep stunnel
tcp   LISTEN    0      4096                      127.0.0.1%lo:20898         0.0.0.0:*     users:(("stunnel",pid=1824,fd=9))
tcp   ESTAB     0      0                            10.1.1.10:49688        10.1.1.6:2049  users:(("stunnel",pid=1824,fd=10))
tcp   ESTAB     0      0                         127.0.0.1%lo:20898       127.0.0.1:36734 users:(("stunnel",pid=1824,fd=3))

10.1.1.6tcp/2049であることが分かります。10.1.1.6というのはEFSファイルシステムのマウントターゲットのIPアドレスです。

$ dig fs-096bc04e855823d2e.efs.us-east-1.amazonaws.com +short
10.1.1.6

ということで確かにEFSファイルシステムに接続していることが分かりますね。

Stunnelのログも確認しておきましょう。

$ sudo journalctl /usr/bin/stunnel --since "Fri May 12 08:50:00"
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: stunnel 5.58 on x86_64-amazon-linux-gnu platform
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: Compiled with OpenSSL 3.0.5 5 Jul 2022
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: Running  with OpenSSL 3.0.8 7 Feb 2023
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,OCSP,PSK,SNI
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: Reading configuration from file /run/efs/stunnel-config.fs-096bc04e855823d2e.mount.efs.20898
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: UTF-8 byte order mark not detected
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: FIPS mode disabled
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[ui]: Configuration successful
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[0]: Service [efs] accepted connection from 127.0.0.1:36732
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[0]: s_connect: connected 10.1.1.6:2049
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[0]: Service [efs] connected remote server from 10.1.1.10:49674
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[0]: Certificate accepted at depth=0: CN=*.efs.us-east-1.amazonaws.com
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG3[0]: transfer: s_poll_wait: TIMEOUTclose exceeded: closing
May 12 08:52:53 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[0]: Connection closed: 0 byte(s) sent to TLS, 0 byte(s) sent to socket
May 12 08:52:54 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[1]: Service [efs] accepted connection from 127.0.0.1:36734
May 12 08:52:54 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[1]: s_connect: connected 10.1.1.6:2049
May 12 08:52:54 ip-10-1-1-10.ec2.internal stunnel[1824]: LOG5[1]: Service [efs] connected remote server from 10.1.1.10:49688

EFSとTLSのセッションを張っていることが分かります。

TLSのセッションを張っていることはパケットキャプチャーの結果からも分かります。

EFSにIAM認証でアクセスするときのパケットキャプチャー結果

CloudTrailを確認するとNewClientConnectionというイベントが記録されていました。

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AssumedRole",
        "principalId": "AROA6KUFAVPU3TKXPFJB2:i-014dac38d632bc868",
        "arn": "arn:aws:sts::<AWSアカウントID>:assumed-role/EfsStack-Ec2InstanceARole1C8989C2-E2ZXX688D8SP/i-014dac38d632bc868",
        "accountId": "<AWSアカウントID>",
        "accessKeyId": "ASIA6KUFAVPUYGZE7VXV",
        "sessionContext": {
            "sessionIssuer": {
                "type": "Role",
                "principalId": "AROA6KUFAVPU3TKXPFJB2",
                "arn": "arn:aws:iam::<AWSアカウントID>:role/EfsStack-Ec2InstanceARole1C8989C2-E2ZXX688D8SP",
                "accountId": "<AWSアカウントID>",
                "userName": "EfsStack-Ec2InstanceARole1C8989C2-E2ZXX688D8SP"
            },
            "webIdFederationData": {},
            "attributes": {
                "creationDate": "2023-05-12T08:47:47Z",
                "mfaAuthenticated": "false"
            },
            "ec2RoleDelivery": "2.0"
        }
    },
    "eventTime": "2023-05-12T08:52:54Z",
    "eventSource": "elasticfilesystem.amazonaws.com",
    "eventName": "NewClientConnection",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "elasticfilesystem",
    "requestParameters": null,
    "responseElements": null,
    "eventID": "56014f24-ee11-464c-a163-fd55d72a1957",
    "readOnly": true,
    "resources": [
        {
            "accountId": "<AWSアカウントID>",
            "type": "AWS::EFS::FileSystem",
            "ARN": "arn:aws:elasticfilesystem:us-east-1:<AWSアカウントID>:file-system/fs-096bc04e855823d2e"
        }
    ],
    "eventType": "AwsServiceEvent",
    "managementEvent": true,
    "recipientAccountId": "<AWSアカウントID>",
    "serviceEventDetails": {
        "permissions": {
            "ClientRootAccess": true,
            "ClientMount": true,
            "ClientWrite": true
        },
        "sourceIpAddress": "10.1.1.10"
    },
    "eventCategory": "Management"
}

IAM認証を行わずにEFSファイルシステムをマウント

それでは、IAM認証を行わずにEFSファイルシステムをマウントしようとした時の挙動を確認します。

# アンマウント
$ sudo umount /mount/efs

# IAM認証を行わない and EFSマウントヘルパーを使わずに再マウント
$ sudo mount -t nfs fs-096bc04e855823d2e.efs.us-east-1.amazonaws.com:/ /mount/efs -v
mount.nfs: timeout set for Fri May 12 09:09:36 2023
mount.nfs: trying text-based options 'vers=4.2,addr=10.1.1.6,clientaddr=10.1.1.10'
mount.nfs: mount(2): Protocol not supported
mount.nfs: trying text-based options 'vers=4,minorversion=1,addr=10.1.1.6,clientaddr=10.1.1.10'
mount.nfs: mount(2): Permission denied
mount.nfs: trying text-based options 'vers=4,addr=10.1.1.6,clientaddr=10.1.1.10'
mount.nfs: mount(2): Permission denied
Created symlink /run/systemd/system/remote-fs.target.wants/rpc-statd.service → /usr/lib/systemd/system/rpc-statd.service.
mount.nfs: trying text-based options 'addr=10.1.1.6'
mount.nfs: prog 100003, trying vers=3, prot=6
mount.nfs: portmap query retrying: RPC: Timed out
mount.nfs: prog 100003, trying vers=3, prot=17
mount.nfs: portmap query failed: RPC: Timed out
mount.nfs: access denied by server while mounting fs-096bc04e855823d2e.efs.us-east-1.amazonaws.com:/

# IAM認証を行わない and EFSマウントヘルパーを使って再マウント
$ sudo mount -t efs -o tls fs-096bc04e855823d2e /mount/efs
b'mount.nfs4: access denied by server while mounting 127.0.0.1:/'

マウントできませんでしたね。

CloudTrailで確認すると、FSマウントヘルパーを使わずに再マウントした場合でもNewClientConnectionAccessDeniedとなっていました。

{
    "eventVersion": "1.08",
    "userIdentity": {
        "type": "AWSAccount",
        "principalId": "",
        "accountId": "ANONYMOUS_PRINCIPAL"
    },
    "eventTime": "2023-05-12T09:07:36Z",
    "eventSource": "elasticfilesystem.amazonaws.com",
    "eventName": "NewClientConnection",
    "awsRegion": "us-east-1",
    "sourceIPAddress": "AWS Internal",
    "userAgent": "elasticfilesystem",
    "errorCode": "AccessDenied",
    "requestParameters": null,
    "responseElements": null,
    "eventID": "a9cd45f5-7093-474d-a5c1-24dcb70771c9",
    "readOnly": true,
    "resources": [
        {
            "accountId": "HIDDEN_DUE_TO_SECURITY_REASONS",
            "type": "AWS::EFS::FileSystem",
            "ARN": "arn:aws:elasticfilesystem:us-east-1:<AWSアカウントID>:file-system/fs-096bc04e855823d2e"
        }
    ],
    "eventType": "AwsServiceEvent",
    "managementEvent": true,
    "recipientAccountId": "<AWSアカウントID>",
    "sharedEventID": "71fc6478-0c1e-416d-9fb1-bdbd5ad7424f",
    "serviceEventDetails": {
        "permissions": {
            "ClientRootAccess": false,
            "ClientMount": false,
            "ClientWrite": false
        },
        "sourceIpAddress": "10.1.1.10"
    },
    "eventCategory": "Management"
}

EFSマウントヘルパーを使った場合は、Stunnelが終了されています。

$ sudo journalctl /usr/bin/stunnel --since "May 12 11:25:00"
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: stunnel 5.58 on x86_64-amazon-linux-gnu platform
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Compiled with OpenSSL 3.0.5 5 Jul 2022
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Running  with OpenSSL 3.0.8 7 Feb 2023
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Threading:PTHREAD Sockets:POLL,IPv6 TLS:ENGINE,OCSP,PSK,SNI
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Reading configuration from file /run/efs/stunnel-config.fs-096bc04e855823d2e.mount.efs.20996
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: UTF-8 byte order mark not detected
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: FIPS mode disabled
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Configuration successful
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[0]: Service [efs] accepted connection from 127.0.0.1:33828
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[0]: s_connect: connected 10.1.1.6:2049
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[0]: Service [efs] connected remote server from 10.1.1.10:35486
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[1]: Service [efs] accepted connection from 127.0.0.1:33844
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[1]: s_connect: connected 10.1.1.6:2049
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[1]: Service [efs] connected remote server from 10.1.1.10:35500
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[0]: Certificate accepted at depth=0: CN=*.efs.us-east-1.amazonaws.com
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG3[0]: transfer: s_poll_wait: TIMEOUTclose exceeded: closing
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[0]: Connection closed: 0 byte(s) sent to TLS, 0 byte(s) sent to socket
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[1]: Certificate accepted at depth=0: CN=*.efs.us-east-1.amazonaws.com
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG3[1]: transfer: s_poll_wait: TIMEOUTclose exceeded: closing
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[1]: Connection closed: 344 byte(s) sent to TLS, 52 byte(s) sent to socket
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[2]: Service [efs] accepted connection from 127.0.0.1:33858
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[2]: s_connect: connected 10.1.1.6:2049
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[2]: Service [efs] connected remote server from 10.1.1.10:35514
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[2]: Certificate accepted at depth=0: CN=*.efs.us-east-1.amazonaws.com
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG3[2]: transfer: s_poll_wait: TIMEOUTclose exceeded: closing
May 12 11:27:04 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[2]: Connection closed: 300 byte(s) sent to TLS, 24 byte(s) sent to socket
May 12 11:28:11 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Terminated
May 12 11:28:11 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Terminating 1 service thread(s)
May 12 11:28:11 ip-10-1-1-10.ec2.internal stunnel[11685]: LOG5[ui]: Service threads terminated

デフォルトのファイルシステムポリシーでは匿名クライアントへのフルアクセスを許可します。

デフォルトの EFS ファイルシステムポリシーは、認証に IAM を使用せず、マウントターゲットを使用してファイルシステムに接続できる匿名クライアントへのフルアクセスを許可します。デフォルトポリシーは、ファイルシステムの作成時を含め、ユーザーが設定したファイルシステムポリシーが有効でない場合は常に有効になります。

IAM を使用してファイルシステムのデータアクセスを制御する - Amazon Elastic File System

このことから、ファイルポリシーを正しく設定することで匿名アクセスを防止できそうです。

ファイルシステムポリシーを活用しよう

Amazon EFSにIAM認証のみを許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみました。

ファイルポリシーを正しく設定することで匿名アクセスを防止できるため、正しく活用していきたいですね。

さらに、アクセスポイントと組み合わせて扱うことで、よりきめ細かやかなアクセス制御ができるかと思います。アクセスポイントの詳細は以下記事が参考になります。

アクセスポイントとファイルシステムポリシーを組み合わせた例は以下AWS公式ドキュメントが参考になります。

この記事が誰かの助けになれば幸いです。

以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!