AQ Tech Blog

AWS Transfer for SFTPで、別アカウントの複数のEFSへ接続してみた

作成者: tsuyoshi.watanabe|2023年11月17日

はじめに

クラウドインテグレーション部の渡邊です。
今回はAWS Transfer for SFTP(以降、Transfer Familyと呼ぶ)によって、別アカウントの複数のEFSへ接続します。
Transfer Familyのエンドポイントタイプとして、インターネット向けアクセスを持つVPCエンドポイント(EndpointType=VPC)を使用します。

やってみた

Transfer FamilyユーザのIAMロール設定

Transfer FamilyユーザにIAMロールをアタッチします。
IAMロールに付与したポリシーの内容は以下です。
こちらのIAMロールのARNは、このあとに設定するEFSファイルシステムポリシーで使用するため、値を控えておきましょう。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "RootFileSystemAccess",
            "Effect": "Allow",
            "Action": [
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientMount"
            ],
            "Resource": [
                "<接続先のEFS ARN1>",
                "<接続先のEFS ARN2>"
            ]
        }
    ]
}

 

EFSファイルシステムポリシーの設定

Amazon Elastic File System ユーザーガイドを参考にポリシーを設定しました。
マウントターゲットを経由したアクセス許可と、該当するIAMロールによるアクセス許可を設定しています。

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "NFS-client-read-write-via-fsmt",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": [
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientMount"
            ],
            "Resource": "<本ポリシーを設定するEFSのARN>",
            "Condition": {
                "Bool": {
                    "elasticfilesystem:AccessedViaMountTarget": "true"
                }
            }
        },
        {
            "Sid": "Grant-transfer-role-access",
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "<Transfer Familyユーザのiamロールarn>"
                ]
            },
            "Action": [
                "elasticfilesystem:ClientRootAccess",
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientMount"
            ],
            "Resource": "<本ポリシーを設定するEFSのARN>"
        }
    ]
}</transferfamilyユーザのiamロールarn>

1つ目のSid値 NFS-client-read-write-via-fsmtのブロックに関しては、ドキュメントにも記載があるように、Transfer Familyからのアクセスを許可するためにパブリックアクセスのブロックをする必要があるため記述しています。

Amazon EFS を AWS Transfer Family で使用する場合、ファイルシステムがパブリックアクセスを許可していると、ファイルシステムとは異なるアカウントが所有する Transfer Family サーバーから受信したファイルシステムのアクセス要求がブロックされます。Amazon EFS はファイルシステムの IAM ポリシーを評価し、ポリシーがパブリックである場合は、リクエストをブロックします。AWS Transfer Family のファイルシステムへのアクセスを許可するには、ファイルシステムポリシーを更新し、パブリックと見なされないようにします。

引用元:AWS Transfer Family を使用したパブリックアクセスのブロック

2つ目のSid値 Grant-transfer-role-accessのブロックに関しては、ドキュメントで記述されているアクションに、rootユーザとしてのアクセスを許可するアクションClientRootAccessを追加しました。
また、Principalにワイルドカード(*)を指定しても、別アカウントのIAMロールでアクセスできないので明示的に指定する必要があります。

他のアカウントのプリンシパルの場合、アカウント内にリソースへのアクセスを許可する ID ベースのアクセス許可がある必要があります。これはクロスアカウントアクセスと呼ばれます。

引用元:すべてのプリンシパル

※ドキュメント記載の以下該当部分は、同じアカウントに対してどちらも設定した場合、SidGrant-transfer-role-accessは機能しませんので注意してください。
1つ目のSidGrant-cross-account-accessでアカウントごと許可しているためです。

        {
            "Sid": "Grant-cross-account-access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:root"
            },
            "Action": [
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientMount"
            ]
        },
        {
            "Sid": "Grant-transfer-role-access",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111122223333:role/EFS-role-for-transfer"
            },
            "Action": [
                "elasticfilesystem:ClientWrite",
                "elasticfilesystem:ClientMount"
            ]
        }

引用元:Transfer Family クロスアカウントアクセスの設定

 

EFSのディレクトリマッピング設定 & ユーザ作成

コンソール画面上で別アカウントのEFSディレクトリを指定することができないため、AWS CLIでTransfer Familyユーザを作成します(私は、AWS CloudShellから実行しました)。
ユーザ作成時にディレクトリのマッピング設定も同時にやります。

まず、環境変数を用意してください。

EFS_ID1=<接続先のEFS ID1>
EFS_ID2=<接続先のEFS ID2>
SERVER=<Transfer FamilyのサーバID>
IAM_ROLE=<ユーザにアタッチするロールARN>
PUBLIC_KEY=<公開鍵情報>

次にユーザを作成するために、以下コマンドを実行します。

aws transfer create-user \
    --home-directory-type "LOGICAL" \
    --home-directory-mappings "[ { \"Entry\": \"/efs1\", \"Target\": \"/${EFS_ID1}\" }, { \"Entry\": \"/efs2\", \"Target\": \"/${EFS_ID2}\" }]" \
    --posix-profile "Uid=0,Gid=0" \
    --role "${IAM_ROLE}" \
    --server-id "${SERVER}" \
    --ssh-public-key-body "${PUBLIC_KEY}" \
    --user-name "test"

マウントした複数のEFSのパスは以下のように表示される想定です。

/
├── efs1
└── efs2

この表示されるパスの名前は--home-directory-mappingsEntryで指定できるのでご自由に指定可能です。
今回はルートユーザを作成するためUIDとGIDは0を指定しました。

 

動作確認

ローカルからTransfer FamilyへSFTP接続して動作確認をします。

sftp -i <秘密鍵のパス> test@<Transfer Familyのエンドポイント名>

Connected to <Transfer Familyのエンドポイント名>

接続できたのでファイルをアップロードできるかを確認してみます。

sftp> put /Users/XXXX/Downloads/tmp /efs1
Uploading /Users/XXXX/Downloads/tmp to /efs1/tmp
tmp 100% 0 0.0KB/s 00:00
sftp> pwd
Remote working directory: /
sftp> ls
efs1 efs2
sftp> cd /efs1
sftp> ls
tmp

アップロードできました。マウントした各EFSのパスも想定通りです。
今回は、単一のアカウントにある複数のEFSへ接続することを想定しましたが、同様の方法で複数のアカウントにある複数のEFSに対しても接続が可能です。
Transfer Familyから複数のEFSを一括管理できるのはありがたいですね。

今回、Transfer Familyのエンドポイントとは別のVPCにある、マウントターゲットに対して接続を行いました。
その際に、Transit GatewayやVPCピアリングなどの、VPC間接続用のネットワークサービスの作成やEFS側のセキュリティグループの設定を行わず、接続に成功しました。

よって、Transfer Family用に、VPC間接続用のサービスの追加やEFS側のセキュリティグループの追加設定は不要です。

ちなみに、EFSポリシーのPrincipalを明示的にIAMロール指定した記述をワイルドカード(*)へ変更したところ、やはり見られなくなりました。 

sftp> ls
remote readdir("/efs1"): Permission denied

まとめ

  • 別アカウントのEFSに接続する設定のために以下が必要
    • EFSファイルシステムポリシーにおいて、マウントターゲットを経由したアクセスを許可する設定と、該当するIAMロールがアクセスする設定
    • Transfer Familyユーザのディレクトリマッピング
    • Transfer FamilyユーザのIAMロール
  • Principalにワイルドカード(*)を指定しても、別アカウントのIAMロールでアクセスできないので、EFSファイルシステムポリシーで明示的に指定必須

【参考】

Transfer Family を使用して SFTP 経由でファイルを EFS に直接アップロードしてみた(VPCインターネット向け-鍵認証のみ編)

Virtual Private Cloud でサーバーを作成する