S3バケットへのファイル転送にAWS Transfer for SFTPを使ってみる

皆さん、初めまして。Retty技術部所属インフラエンジニアの廣田と申します。

最近、S3バケットへのファイル転送をSFTPで実行したい、という要望があったのを切っ掛けに、AWS Transfer for SFTPを検討して使い始めましたので、サービスと利用方法について簡単にまとめてみました。

AWS Transfer for SFTPとは

aws.amazon.com

上記公式ページの説明通り、S3バケットへのSFTPによるファイル転送を可能とする、フルマネージド型のサービスになります。 2018年のre:Inventで発表され、現在、デフォルト有効化されているリージョンの全てで利用可能です。

本サービスがリリースされるまでは、EC2インスタンスにSFTPサーバーを構築し、s3fsでS3バケットをマウントする等して同様のことを行えましたが、このフルマネージドサービスによって、そのようなサーバー管理からは解放されることになりました。 また、エンドポイントのカスタム名にRoute53や、カスタム認証にAPI Gateway&Lambda等、他のAWSサービスとの連携も容易にとれ、利便性の高いサービスとなっています。

使用料金

料金 - AWS Transfer for SFTP | AWS

AWS Transfer for SFTP自体にかかる料金は下記の通りで、このエントリを記載している2020年3月時点では、全てのリージョンで同一の料金となっています。

  • エンドポイントのプロビジョニング料金:$0.3/時間
  • データアップロード:$0.04/ギガバイト
  • データダウンロード:$0.04/ギガバイト

注意しなければならないのは、「エンドポイントのプロビジョニング料金は、SFTPサーバーを作成してから削除するまで課金される」という点です。 SFTPサーバーには停止機能(エンドポイントタイプ変更時に必要)があるものの、EC2のコンピューティング料金等とは異なり、停止をしている間も課金はされ続けます。 エンドポイントのプロビジョニング料金だけでも1ヶ月に$216はかかりますので、ホビーや検証等で一時的に利用する場合は、利用が終わり次第、必ず削除することをオススメします。

なお、その他のAWSリソースとして、標準ではS3、カスタムするオプション次第でRoute53、VPC、PrivateLink、API Gateway、Lambda、CloudWatch Logs/Events、CloudTrailの利用料金がかかります。

SFTPサーバーを作ってみる

SFTPサーバーは、エンドポイントタイプをPublicかVPCかで選択することができ、デフォルトはPublicとなっています。 今回は最もお手軽に作成できるPublicを選択することにします。 エンドポイントをPublicで作成する場合のAWSリソース構成を簡単に示した図が以下のものです。

f:id:rettydev:20200302221338p:plain

事前準備

SFTPサーバーを作成する前に、まずファイル置き場としてのS3バケットと、S3の操作権限を持つIAMポリシー、そのIAMポリシーをアタッチするIAMサービスロール(SFTPユーザー用)を作成する必要があります。 S3バケットとIAMポリシー、IAMサービスロールの作成手順については、各々の公式ドキュメントを参照してください。

S3バケットには適当な名前を、ここでは「retty-sftp-sample-bucket」とでも名付けておきます。

f:id:rettydev:20200302203058p:plain

S3の操作権限を持つIAMポリシーには下記のものを設定し、「retty-sftp-sample-policy」と名付けて保存します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListingOfUserFolder",
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::retty-sftp-sample-bucket"
            ]
        },
        {
            "Sid": "HomeDirObjectAccess",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObjectVersion",
                "s3:DeleteObject",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::retty-sftp-sample-bucket/*"
        }
    ]
}

f:id:rettydev:20200302204035p:plain

なお、S3バケットをKMSで暗号化する場合は、KMSの操作権限も必要になります。IAMサービスロールか後述するスコープダウンポリシーに下記のようなポリシーを設定してください。

{
    "Sid": "",
    "Action": [
        "kms:Decrypt",
        "kms:Encrypt",
        "kms:GenerateDataKey"
    ],
    "Effect": "Allow",
    "Resource": "arn:aws:kms:region:account-id:key/kms-key-id"
}

「kms-key-id」には実際に利用するKMSキーのIDを指定します。このポリシーではKMSのキーポリシーにルートを許可する必要がありますが、ルートを許可しない場合は、KMSキーポリシー側にIAMサービスロールを設定してください。

IAMポリシー「retty-sftp-sample-policy」をアタッチした「retty-sftp-sample-role」を作成します。

f:id:rettydev:20200302211433p:plain

信頼ポリシーには下記を設定します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "transfer.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

f:id:rettydev:20200302211449p:plain

SFTPサーバー作成

それでは、事前準備が整ったので、SFTPサーバーを作成していきます。 まずは、サービスメニューから「AWS Transfer for SFTP」を選択します。

f:id:rettydev:20200302212454p:plain

次に、TOP画面の「Create server」ボタンを押します。

f:id:rettydev:20200302212849p:plain

サーバー作成画面では以下のような設定を行えます。

  • エンドポイントタイプ
    • Public、VPC(Internal)、VPC(Internet facing)から選択
    • Publicだとインターネットに公開されるが、VPCの場合は指定のサブネットにインターフェースVPCエンドポイントが作成され、ネットワークACLやセキュリティグループでアクセス制御が可能
    • VPC(Internet facing)の場合は、PublicサブネットとENIにアタッチするElastic IPも必要となる
  • カスタムホスト名
    • 無し、Route53、その他のDNSサーバーから選択
    • 無しだと自動生成されたSFTPサーバーIDと規定サービスドメインを組み合わせたホスト名が割り振られる
    • Route53を選択してホスト名を入力すると、AWSアカウント内に指定したPublic Hosted Zoneが存在する場合は、そこにCNAMEレコードが作成され、Public Hosted Zoneが存在しない場合、Hosted Zoneも合わせて作成される
      • Private Hosted Zoneの場合は指定してもレコードが作成されず、代わりに同名のPublic Hosted Zoneが作成されてしまう為、Route53を手動で修正(Public Hosted Zoneを削除の上、Private Hosted Zoneにレコード追加)しなければならない
      • 追加されるレコードはCNAMEとなる為、Aレコードのエイリアスにする場合は手動で変更が必要
      • Route53から他の設定に変更した場合、追加されたPublic Hosted Zoneやレコードは削除されない為、手動で削除する必要がある
    • その他のDNSサーバーを選択した場合は、当該DNSサーバー管理者がレコードを追加する必要がある
  • IDプロバイダタイプ
    • サービスマネージド、カスタムから選択
    • サービスマネージドを選択した場合は、AWS Transfer for SFTP自体のSFTPユーザー機能だけでユーザー管理する形式となる
    • カスタムを選択すると、API GatewayやLambdaを活用し、任意のIdPと連携をとることができる
  • ロギングロール
    • CloudWatch Logsの操作権限ポリシーを付与したIAMロールを選択
    • 「/aws/transfer/SFTPサーバーID」といった名前のロググループが作成され、SFTPセッション毎のログストリームと、ERRORSログストリームが吐き出される
    • 必要となるIAMポリシーは下記の通り
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "",
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogStreams",
                "logs:CreateLogGroup",
                "logs:PutLogEvents"
            ],
            "Resource": "*"
        }
    ]
}
  • タグ
    • キー&バリュー値を複数設定可能

今回はデフォルト設定のまま、何も変更せずに「Create server」ボタンを押すことにします。

f:id:rettydev:20200302213905p:plain f:id:rettydev:20200302213945p:plain

SFTPサーバーの作成が完了すると、サーバーのステータスが「Online」と表示されます。

f:id:rettydev:20200302231107p:plain

SFTPサーバーが作成できたら、「Add user」ボタンを押してSFTPユーザーを作成します。

f:id:rettydev:20200302231241p:plain

ユーザー作成画面の方では以下のような設定を行えます。

  • ユーザー名
    • 3~32文字で英大文字小文字、数字、アンダースコア、ハイフン(頭文字は不可)を利用可能
  • アクセス
    • S3の操作権限ポリシーをアタッチしたIAMサービスロールを選択
  • ポリシー(スコープダウンポリシー)
    • 無し、IAMポリシーから選択
    • スコープダウンポリシーは、SFTPユーザーをS3バケットの特定部分に制限する為のIAMポリシーで、IAMロールを介さずに直接SFTPユーザーに適用する
    • AWS Transfer for SFTP専用の変数が定義されており、例えばSFTPユーザー毎に自身の名前のディレクトリをホームディレクトリとして制限する場合等に、汎用的なグループポリシーとして利用することが可能
  • ホームディレクト
    • IAMサービスロールに設定しているS3バケットを選択、ログイン時のフォルダを設定
    • S3バケットを選択せず空のままにすると、S3のルートディレクトリが使用される
    • フォルダは予めS3バケットに作成しておき、スコープダウンポリシーと合わせて制御することが可能
  • Ristricted
    • ホームディレクトリ以外のアクセス制限可否
    • チェックすると、ホームディレクトリ以外のアクセスが制限され、かつ、S3バケット、またはフォルダ名を表示することができなくなる
  • SSHの公開鍵
    • SFTPログイン時に利用するSSHキーペアの公開鍵を設定
    • 1つのSFTPユーザーに対して、SSHの公開鍵は複数設定することができるので、ローテートが可能
  • タグ
    • キー&バリュー値を複数設定可能

今回はユーザー名に「retty-sftp-sample-user」を入力し、IAMサービスロールには「retty-sftp-sample-role」、ホームディレクトリのS3バケットには「retty-sftp-sample-bucket」をそれぞれ選択します。 加えて、こちらを参考にssh-keygenコマンドで作成した適当な公開鍵を設定し、「Add」ボタンを押します。

f:id:rettydev:20200302231448p:plain f:id:rettydev:20200304181712p:plain

SFTPユーザーを作成すると、サーバーの詳細画面にリスト表示されます。

f:id:rettydev:20200304181342p:plain

SFTPサーバーとS3バケットは、IAMサービスロールを付与したSFTPユーザーを介して疎結合する為、1つのSFTPサーバーであっても、SFTPユーザー毎に異なるS3バケットへの操作が行える、柔軟なアーキテクチャとなっています。

SFTPサーバー接続&ファイル転送確認

構築作業が完了したら、SFTPサーバーへの接続とファイル転送を確認してみます。 SFTPクライアントですが、公式には下記のクライアントがサポートされています。

各クライアントの操作方法はAWSのドキュメントの方に簡単なまとめがありますので、そちらを参考にしてください。 今回の検証にはOpenSSHのsftpコマンドを利用しており、確認内容は下記の通りとなります。

f:id:rettydev:20200304185547p:plain

若干細かい表示で申し訳ありませんが、SFTPサーバーへの接続と、S3バケットへのファイル転送ができました。S3バケットの方も確認してみると、SFTPで追加されたファイルが表示されています。

f:id:rettydev:20200304190205p:plain

一通りの検証を終えたら、作成したAWSリソースを削除して完了となります。

最後に

AWS Transfer for SFTPは、サービスとしては非常に簡単で扱い易いものとなっています。 エンドポイントをVPCに配置すれば、下記のような構成でよりセキュアに、可用性も考慮された形で利用することが可能で、サーバーのスケールもマネージドで行われます。

f:id:rettydev:20200304193308p:plain

検討される方の環境と利用シーンによっては、恐らく料金と転送速度がネックとなる可能性はあり得ますが、それらの点が問題にならないのであれば、S3に対するファイル転送の手段として、積極的な利用をオススメしたいサービスです。