SFTP on EC2 から透過的に AWS Transfer for SFTP に切り替えてみた #reinvent

これまで 「S3 に直接 SFTP したい」 という要望はたくさんあったかと思います。しかし、従来は対応していなかったため EC2 に一度アップロードしてから、S3 に持っていくなどの対応が必要でした。

今回、新たにリリースされた AWS Transfer for SFTP によって、直接 S3 に SFTP できるようになりましたので、「だったら、そっちに移行したいなぁ」とお考えの方も少なくないと思いますので、ユーザから透過的に切り替えられるか試してみよう、と思ったのでやってみました。

やりたいこと

今回やりたいことは、図にするとこんな感じです。アクセス先をユーザから透過的に AWS Transfer for SFTP に切り替えて、クライアント側の設定はそのままでアクセスできることを確認します。

前提

移行環境の前提は下記のとおりです。

  • 既存の FTP アクセスはドメイン名を使用している
    • IP アドレス指定だと、指定アドレスは変わるので透過的とは言えなくなります。。
  • 既存環境で利用している SSH 公開鍵、秘密鍵 が必要です

検証環境

以下の環境で検証しています。

  • EC2: t2.micro
  • AMI: amzn2-ami-hvm-2.0.20181114-x86_64-gp2 (ami-0a2de1c3b415889d2)
  • DNS: Route 53
  • FTP クライアント: Cyberduck バージョン6.8.3 (29107)
  • S3 バケット: cm-sftp-test-bucket

やってみる

移行前の環境を確認します。下記のとおり、接続先は EC2 になっています。

$ dig sftp.xxxxx.xxxxxxx.info +short
ec2-xxx-xxx-xxx-98.ap-northeast-1.compute.amazonaws.com.
13.xxx.xxx.98

まず、SFTP on EC2 の環境に接続できることを確認しておきます。

問題なくアクセスできていますね。

SFTP ユーザ用の IAM ポリシー作成

今回は、SFTP ユーザ毎に利用できるホームディレクトリを制限するために、スコープダウンポリシーで IAM ポリシーを作成しました。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ListHomeDir",
            "Effect": "Allow",
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::${transfer:HomeBucket}"
        },
        {
            "Sid": "AWSTransferRequirements",
            "Effect": "Allow",
            "Action": [
                "s3:ListAllMyBuckets",
                "s3:GetBucketLocation"
            ],
            "Resource": "*"
        },
        {
            "Sid": "HomeDirObjectAccess",
            "Effect": "Allow",
            "Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:DeleteObjectVersion",
                "s3:DeleteObject",
                "s3:GetObjectVersion"
            ],
            "Resource": "arn:aws:s3:::${transfer:HomeDirectory}*"
        }
    ]
}

また、IAM ロールに割り当てる用に、オールアクセスポリシーとして以下のようなポリシーを作成します。(バケット名は環境にあわせて、変更してください)

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:ListBucket"],
      "Resource": ["arn:aws:s3:::cm-sftp-test-bucket"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:GetObject",
        "s3:DeleteObject"
      ],
      "Resource": ["arn:aws:s3:::cm-sftp-test-bucket/*"]
    }
  ]
}

スコープダウンポリシーを IAM ロールに使えば良いんじゃないの? と思われるかもしれませんが、スコープダウンポリシーは IAM ロールの割当に使用できないようですので、その点、ご注意ください。

There is also a third variable called ${transfer:UserName}. You can use these variables only in the scope-down policy. You can't use them in IAM policies attached to the user's role.

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

次に SFTP ユーザ用の IAM ロールを作成し、先程作成した オールアクセスポリシーをアタッチします。IAM ロールを作る際には、transfer.amazonaws.comAssumeRole アクションを許可して作成する必要がありますが、IAM ロール作成時に指定できる AWS サービスの選択メニューのなかに AWS Transfer for SFTP が見当たらないので、一旦、EC2 を選択して次に進みます。

ポリシーは先程作成した、IAM ポリシーを選択して次に進みます。

タグは適宜追加するなり、スキップするなりで次に進み、ロール名を指定して作成を完了します。

作成できましたら、信頼関係 が EC2 になっているので、これを AWS Transfer for SFTP 用に変更します。作成した IAM ロールを開き、信頼関係 タブをクリックし、信頼関係の編集 を開きます。ec2.amazonaws.com の部分を、 transfer.amazonaws.com に変更し、更新します。

SFTP エンドポイントの作成

サービスメニューから AWS Transfer for SFTP を開き、Create Sever をクリックします。

Create Server メニューの DNS configuration を設定します。今回は Route 53 を使用していますので、Amazon Route53 DNS alias を選択し、ドメイン名を入力します。Identity provider は、Service managed を選択しています。

CloudWatch logs にログを PUT する場合、Logging role を指定しますが、今回は指定せずに進みます。必要に応じて Tag を指定したら、Create server をクリックすると、SFTP のエンドポイントが作成されます。

SFTP ユーザの追加

先程作成された SFTP エンドポイントにチェックを入れ Add user をクリックします。

Add user 画面が開きますので、ユーザ名を既存にあわせて入力します。次に先程作成した IAM ロールを選択します。今回はスコープダウンポリシーを使用しますので、Select a policy from IAM を選択し、先程作成した IAM ポリシーを選択します。対象の S3 バッケットを選択し、Home directory も既存にあわせて入力します。今回は /home/sftpuser を指定しました。

次に対象のユーザが既存の SFTP サーバに設置していた SSH 公開鍵を入力し、Add します。

AWS Transfer for SFTP の設定は以上です。

Route 53 の設定

それでは Route 53 のホストゾーンで SFTP サーバ用のレコードを、AWS Transfer for SFTP に差し替えます。SFTP エンドポイント作成時に指定したドメイン名でパブリックホストゾーンが作成されています。既存で利用しているホストゾーンでも、同じ名前のものが作成されるようです。新規作成されたほうのホストゾーンは今回使用しません。

AWS Transfer for SFTP のエンドポイントを確認し、既存側のホストゾーンに登録されている SFTP on EC2 サーバ用の CNAME レコードを AWS Transfer for SFTP のエンドポイントアドレスに変更します。

dig コマンドで確認します。

$ dig sftp.xxxxx.xxxxxx.info +short
s-9f67xxxxxxxxxx.server.transfer.ap-northeast-1.amazonaws.com.
13.xxx.xxx.xxx
46.xxx.xxx.xxx

ターゲットが AWS Transfer for SFTP のエンドポイントに変わったことが確認できました。

接続してみる!

確認用にホームディレクトリの s3://cm-sftp-test-bucket には /home/sftpuser を作成し、testfile-S3 をアップロードしておきました。それでは、FTP クライアント側の設定を何も変えずにアクセスしてみます。

正常に S3 のホームディレクトリが見えていますね!試しに一階層上に移動してみます。

ちゃんとブロックされているので、スコープダウンポリシーが効いているのが判りますね!もちろん、ホームディレクトリでは問題なくアップロード、ダウンロードできることも確認できました!

さいごに

既存の公開鍵のアップロードと、CNAME ターゲットの入れ替えでユーザから透過的に AWS Transfer for SFTP に移行できることが確認できました!あくまで「透過的」と言っているのは、セッションの接続部分になりますので、既存環境でアクセスディレクトリなどを細かく制限されている場合は、スコープダウンポリシーを使用して既存環境にあわせた制限を設定する必要があります。

今回、リリース後はじめて AWS Transfer for SFTP を触ってみましたが、非常に簡単に S3 への SFTP を実現することが出来ました!これまで、EC2 → S3 sync で泣く泣く中継させていたユーザは是非お試しあれ!(現状は EC2 のときのように単体では IP 制限等をする手段が無さそうですので、IP 制限環境での置換え時はよく検討してください!)

以上!大阪オフィスの丸毛(@marumo1981)でした!