AWS Transfer FamilyとカスタムIDプロバイダーでFTP環境を構築してみる

AWS Transfer Familyとカスタム ID プロバイダーを利用してFTP環境を構築してみました。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、AWS事業本部のニシヤマです。

前回はID プロバイダーにMSAD(AWS Directory Service for Microsoft Active Directory)を利用してTransfer FamilyでFTP対応サーバーの作成を行いましたが、今度はカスタム ID プロバイダーを利用してTransfer FamilyでFTP対応サーバーの作成する方法をご紹介します。

前回はID プロバイダーにMSADを利用しましたが、例えばFTPを利用するユーザが1ユーザの場合などにMSADを用意するとなると少々コストが高めとなってしまいます。 その場合にはカスタム ID プロバイダーを利用することでMSADが無くてもTransfer FamilyのFTP対応サーバーの作成が可能です。

注意点

プロトコルFTPの場合、ID プロバイダーは以下の2つから選択が可能です。

  • AWS Directory Service for Microsoft Active Directory (MSAD)
  • カスタム ID プロバイダー

また、パブリックにアクセス可能なエンドポイントはサポートされていません。

前提

前回と同様なサブネットを用意しておきます。

やってみる

ではやってみます。

FTPサーバ専用のセキュリティグループを作成

こちらも前回同様FTPサーバ専用のセキュリティグループを作成しておきます。(手順は省略)

https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/create-server-ftp.html

Transfer Family 用の FTP サーバは、ポート 21(コントロールチャネル)およびポート範囲 8192-8200(データチャネル)で動作します。

それではTransfer Familyの作成に進みます。まず初めにTransfer FamilyでFTP対応サーバー作成する際に指定するカスタム ID プロバイダーを作成する必要があります。

こちらはありがたいことに以下のドキュメントの基本的なスタックテンプレートのリンクからダウンロードが可能ですので取得しておきます。

https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/custom-identity-provider-users.html

FTP用ユーザのIAMロール作成

では、早速作成と行きたいところですがカスタム ID プロバイダーを作成するにあたり、FTP用ユーザのIAMロールを指定する必要があるので作成します。

作成してください。

ここは省略しますが前回同様に信頼されたエンティティでtransfer.amazonaws.comを選択、また今回ポリシーはAmazonElasticFileSystemClientFullAccessをアタッチしておきます。

スタックテンプレートの実行

それでは先ほどダウンロードしたスタックテンプレートをCloudFormationで実行していきます。

CloudFormationのスタックの作成からテンプレートを指定して次へをクリックします。

次にスタックの名前と、パラメータを指定します。

この際パラメータの一番目にCreateServerというパラメータが存在します。こちらがtrueの場合、スタックの実行時にTransfer Familyサーバが作成されますがプロトコルがSFTPとなります。なので今回は自分でプロトコルFTPのサーバを作成するためにfalseにしておきます。

また、UserNameUserPasswordにはデフォルトの値が入っていますが必要に応じて変更してください。今回はこのままで進めます。 UserPublicKey1はそのままでOKです。最後にUserRoleArnに先ほど作成したFTP用ユーザのIAMロールのARNを入力して次へをクリックします。

次のスタックオプションの設定画面も次へをクリックします。

最後にレビュー画面でIAMリソースの作成を承認にチェックを入れ、スタックの作成をクリックします。

スタックのステータスがCREATE_COMPLETEになるのを待ちます。

保存先がEFSの場合

次にアップロードしたファイルの保存先のEFSを作成します。ここは前回同様で以下ブログを参照してください。

Amazon EFSを使ってみた

EFSの作成が完了しました。

API Gateway URLを確認

ここでTransfer Familyの設定に行きたいところですが、先にCloudFormationのテンプレートで作成した API Gateway URLを確認します。

API Gatewayの画面に移動すると、Transfer Custom Identity Provider basic template APIというAPIがあるので名前をクリックします。

API Gatewayの詳細画面でAPI>ステージ>prodをクリックすると、URLが表示されるのでこちらを控えておいてください。

呼び出しロールを確認

もう一つ事前に確認する値があります。CloudFormationのテンプレートで作成されているTransfer FamilyからAPIを呼び出すIAMロールが作成されているのでこちらを確認します。

APIを呼び出すIAMロールはCloudFormationの出力タブでキーTransferIdentityProviderInvocationRoleの値になります。

FTPサーバを作成

それではTransfer Familyの設定を行っていきます。Transfer Familyの画面でサーバの作成をクリックします。

プロトコルを選択で「FTP」を選択して次へをクリックします。

ID プロバイダーを選択の画面でカスタム ID プロバイダーを選択し、API Gateway URLと呼び出しロールを入力し次へをクリックします。

エンドポイントを選択の画面でも前回同様以下のパラメータを指定して次へをクリックします。

  • エンドポイントのタイプ:VPC でホスト
  • アクセス:内部
  • VPC:事前に作成していたVPC ID
  • アベイラビリティーゾーン:任意のAZにチェックを入れサブネットを指定
  • セキュリティグループ:FTPサーバ専用のセキュリティグループを指定

ドメインを選択ではAmazon EFSを選択し次へをクリックします。

次の画面でも次へをクリックします。

最後に確認画面でサーバを作成をクリックします。

少し待つとサーバの作成ができました。

サーバ一覧のユーザの列に関してはActive Directoryを利用した場合とは異なりカスタムと表示されています。

FTPでアクセスしてみる

それでは実際にFTPでアクセスしてみます。前回同様はVPC内にAmazon Linux 2のEC2を起動して確認してみます。

ホームディレクトリの作成

ここも前回同様にEFSをマウントしファイル保存先のディレクトリを作成します。

(初心者向け)EC2インスタンスにEFSをマウントしてみた

$ sudo mkdir /mnt/efs-mount-point
$ sudo mount -t nfs -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-0c948f039836562b1.efs.ap-northeast-1.amazonaws.com:/   /mnt/efs-mount-point
$ sudo mkdir /mnt/efs-mount-point/customidp_ftpuser1
$ sudo chown ec2-user:ec2-user /mnt/efs-mount-point/customidp_ftpuser1
$ sudo ls -ld /mnt/efs-mount-point/customidp_ftpuser1

Lambdaの修正

ここでFTPでアクセスを行いたいところですが、以下のドキュメントにある通りカスタム ID プロバイダーでEFSにアクセスする場合はLambdaを修正する必要があります。

https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/gateway-api-tutorial.html#lambda-posix

ではLambdaの画面で対象のLambda関数の名前をクリックし詳細画面を開きます。

コードソースの項目でRoleのARNが書いてある箇所を探して、PosixProfile: {"Gid": <ユーザID>, "Uid": <グループID>},を追記します。

変更前

   response = {
     Role: 'arn:aws:iam::XXXXXXXXXXXX:role/AWS-Custom-Transfer-User-Role', // The user will be authenticated if and only if the Role field is not blank
     Policy: '', // Optional JSON blob to further restrict this user's permissions
     HomeDirectory: '/' // Not required, defaults to '/'
   };

変更後

   response = {
     Role: 'arn:aws:iam::XXXXXXXXXXXX:role/AWS-Custom-Transfer-User-Role', // The user will be authenticated if and only if the Role field is not blank
     Policy: '', // Optional JSON blob to further restrict this user's permissions
     PosixProfile: {"Gid": 1000, "Uid": 1000},
     HomeDirectory: '/fs-0c948f039836562b1' // Not required, defaults to '/'
   };

また、HomeDirectoryの値にEFSのファイルシステムIDを追記しDeployを押下して反映させます。

FTPでアクセス

それではFTPでアクセスします。

前回同様アクセスするFTPサーバのDNS名をVPCエンドポイントの画面から確認して接続してみます。

$ ftp vpce-0a2697725b67b098f-ncs59owm.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com
Trying 10.0.11.168...
Connected to vpce-0a2697725b67b098f-ncs59owm.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com (10.0.11.168).
220 Service ready for new user.
Name (vpce-0a2697725b67b098f-ncs59owm.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com:ec2-user): myuser
331 User name okay, need password for myuser.
Password:
230 User logged in, proceed.
Remote system type is UNIX.
ftp> pwd
257 "/fs-0c948f039836562b1" is current directory.

CloudFormationのパラメータに指定したUserNameUserPasswordで接続できました!続いてファイルもアップロードしてみます。

## カレントディレクトリを確認してから移動

ftp> pwd
257 "/fs-0c948f039836562b1" is current directory.
ftp> ls 
227 Entering Passive Mode (10,0,11,168,32,6)
150 File status okay; about to open data connection.
drwxr-xr-x   2 1000 1000         6144 Dec  9 08:36 ftpuser1
226 Closing data connection.
ftp> cd ftpuser1
250 Directory changed to /fs-0c948f039836562b1/ftpuser1

## バイナリモードに変更してファイルをアップロード

ftp> !ls
custom_idp_ftp_upload_file.txt
ftp> bin
200 Command TYPE okay.
ftp> put custom_idp_ftp_upload_file.txt
local: custom_idp_ftp_upload_file.txt remote: custom_idp_ftp_upload_file.txt
227 Entering Passive Mode (10,0,11,168,32,0)
150 File status okay; about to open data connection.
226 Transfer complete.
31 bytes sent in 3.3e-05 secs (939.39 Kbytes/sec)
ftp> ls -l
227 Entering Passive Mode (10,0,11,168,32,6)
150 File status okay; about to open data connection.
-rw-rw-rw-   1 1000 1000           31 Dec  9 09:09 custom_idp_ftp_upload_file.txt
226 Closing data connection.

別途立ち上げておいたターミナルからも確認できます。

$ ls -l /mnt/efs-mount-point/ftpuser1/
合計 4
-rw-rw-rw- 1 ec2-user ec2-user 31 12月  9 09:09 custom_idp_ftp_upload_file.txt

もちろんダウンロードも可能です。

ftp> ls -l
227 Entering Passive Mode (10,0,11,168,32,8)
150 File status okay; about to open data connection.
-rw-rw-rw-   1 1000 1000           31 Dec  9 09:09 custom_idp_ftp_download_file.txt
-rw-rw-rw-   1 1000 1000           31 Dec  9 09:09 custom_idp_ftp_upload_file.txt
226 Closing data connection.
ftp> get custom_idp_ftp_download_file.txt
local: custom_idp_ftp_download_file.txt remote: custom_idp_ftp_download_file.txt
227 Entering Passive Mode (10,0,11,168,32,3)
150 File status okay; about to open data connection.
226 Transfer complete.
31 bytes received in 0.15 secs (0.21 Kbytes/sec)
ftp> !ls
custom_idp_ftp_download_file.txt  custom_idp_ftp_upload_file.txt

カスタム ID プロバイダーを利用してEFSにFTP接続してファイル操作することができました。

保存先がS3バケットの場合

今回もS3へのアクセスも試してみます。

FTPサーバを作成の手順のドメインを選択でS3バケットを変更します。

また、FTP用ユーザのIAMロールにもアップロード先S3バケットへの読み書きの権限をアタッチしておいてください。

Lambdaの更新

ここでLambdaのHomeDirectoryの値に指定したパスを変更します。

ではVPCエンドポイントのDNS名を確認してFTPアクセスしてみます。

$ ftp vpce-0905fb4af4befa6e6-9nmabxv5.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com
Trying 10.0.11.128...
Connected to vpce-0905fb4af4befa6e6-9nmabxv5.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com (10.0.11.128).
220 Service ready for new user.
Name (vpce-0905fb4af4befa6e6-9nmabxv5.vpce-svc-0c6fc1c14ceb5b0d8.ap-northeast-1.vpce.amazonaws.com:ec2-user): myuser  
331 User name okay, need password for myuser.
Password:
230 User logged in, proceed.
Remote system type is UNIX.
ftp> pwd
257 "/custom-idp-ftptest-s3-bucket" is current directory.
ftp> ls -l
227 Entering Passive Mode (10,0,11,128,32,1)
150 File status okay; about to open data connection.
226 Closing data connection.

ログインできました。ちゃんとパスがS3バケットのものに変わっています。続いてファイルもアップロードしてみます。

ftp> bin 
200 Command TYPE okay.
ftp> !ls 
custom_idp_ftp_download_file.txt  custom_idp_ftp_upload_file.txt
ftp> put custom_idp_ftp_upload_file.txt
local: custom_idp_ftp_upload_file.txt remote: custom_idp_ftp_upload_file.txt
227 Entering Passive Mode (10,0,12,77,32,2)
150 File status okay; about to open data connection.
226 Transfer complete.
31 bytes sent in 3e-05 secs (1033.33 Kbytes/sec)
ftp> ls -l
227 Entering Passive Mode (10,0,12,77,32,8)
150 File status okay; about to open data connection.
-rwxr--r--   1 - -           31 Dec  9 10:21 custom_idp_ftp_upload_file.txt
226 Closing data connection.

S3バケットへのアップロードもできてます!

ちゃんとダウンロードもできます!

ftp> bin 
200 Command TYPE okay.
ftp> !ls 
custom_idp_ftp_download_file.txt  custom_idp_ftp_upload_file.txt
ftp> put custom_idp_ftp_upload_file.txt
local: custom_idp_ftp_upload_file.txt remote: custom_idp_ftp_upload_file.txt
227 Entering Passive Mode (10,0,12,77,32,2)
150 File status okay; about to open data connection.
226 Transfer complete.
31 bytes sent in 3e-05 secs (1033.33 Kbytes/sec)
ftp> ls -l
227 Entering Passive Mode (10,0,12,77,32,8)
150 File status okay; about to open data connection.
-rwxr--r--   1 - -           31 Dec  9 10:21 custom_idp_ftp_upload_file.txt
226 Closing data connection.

以上です。

まとめ

いかがでしたでしょうか。FTPを利用したいけど、少ないユーザのみの場合にActive Directoryを用意するにはちょっとコストが大きくなってしまいます。そんな時にカスタム ID プロバイダーとTransfer Familyを利用することで簡単にEFS、S3を利用したFTPサーバーの構築ができるようになりました。 これで前回のブログと合わせてFTPユーザが多い場合にも、少ない場合にもFTPサーバーの構築は怖くないですね。

また、以下ブログにある2021年11月のアップデートでカスタムIDプロバイダーに直接Lambdaを指定することもできるようになったので合わせて検討してみてください。

AWS Transfer FamilyのカスタムIDプロバイダー構成でLambdaを直接統合出来るようになりました