ちゃんと匿名アクセスはブロックされるのかな
こんにちは、のんピ(@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
イベントで確認できる - デフォルトのファイルシステムポリシーでは匿名クライアントへのフルアクセスを許可している
やってみた
検証環境
検証環境は以下の通りです。
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 ポリシーとリソースポリシーの両方で権限を付与する必要はありません。
Principalで指定しているのはEC2インスタンスにアタッチしているIAMロールのARNです。
Principalの毎のリソースポリシーの評価については以下記事が参考になります。
IAM認証でEFSファイルシステムをマウント
まず、IAM認証でEFSファイルシステムをマウントできることを確認します。
IAM認証を行う場合は、EFSマウントヘルパーを使用する必要があります。
IAM 認証を使用してクライアントによるアクセスをコントロールするには、EFS マウントヘルパーを使用して Amazon EFS ファイルシステムをマウントする必要があります。詳細については、「IAM 認証を使用してマウントする」を参照してください。
ということで下準備として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.6
のtcp/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のセッションを張っていることはパケットキャプチャーの結果からも分かります。
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マウントヘルパーを使わずに再マウントした場合でもNewClientConnection
でAccessDenied
となっていました。
{
"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 を使用せず、マウントターゲットを使用してファイルシステムに接続できる匿名クライアントへのフルアクセスを許可します。デフォルトポリシーは、ファイルシステムの作成時を含め、ユーザーが設定したファイルシステムポリシーが有効でない場合は常に有効になります。
このことから、ファイルポリシーを正しく設定することで匿名アクセスを防止できそうです。
ファイルシステムポリシーを活用しよう
Amazon EFSにIAM認証のみを許可するファイルシステムポリシーを設定した場合に匿名アクセスはブロックされるのか確認してみました。
ファイルポリシーを正しく設定することで匿名アクセスを防止できるため、正しく活用していきたいですね。
さらに、アクセスポイントと組み合わせて扱うことで、よりきめ細かやかなアクセス制御ができるかと思います。アクセスポイントの詳細は以下記事が参考になります。
アクセスポイントとファイルシステムポリシーを組み合わせた例は以下AWS公式ドキュメントが参考になります。
この記事が誰かの助けになれば幸いです。
以上、AWS事業本部 コンサルティング部の のんピ(@non____97)でした!