別のAWS アカウントにあるS3バケットを使用するようにAWS Transfer for SFTPサーバーを設定してみた

2020.10.02

こんにちは〜onz(オンジー)です!

Transfer for SFTPで別アカウントのS3を使う機会があったのでやってみました。

SFTPサーバーとS3バケットはどちらもap-northeast-1(東京)、SFTPサーバーのエンドポイントはPublicで検証しています。

またS3バケットとその中にフォルダを作成済みの前提で進みます。

イメージとしては次のようになります。

やってみた

大まかな流れとしては以下になります。

  • IAMロールを作成
  • バケットポリシーを更新
  • SFTPサーバーユーザーを作成
  • アクセスできるか確認

IAMロールを作成

SFTPサーバーユーザーがS3バケットにアクセスするためのIAMロールを作成します。

IAMロールにアタッチするポリシーには次のように記述します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowListingBucketReadandWriteandDelete",
      "Effect": "Allow",
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:GetObject",
        "s3:DeleteObjectVersion",
        "s3:DeleteObject",
        "s3:GetObjectVersion",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::{S3のバケット名}/*",
        "arn:aws:s3:::{S3のバケット名}"
      ]
    }
  ]
}

IAMロールが作成できたら次の手順で必要になるのでロールのIDとARNを取得しておきます。

$ aws iam get-role --role-name "{作成したIAMロール名}"

次のように出力されるのでRoleIdArnの値を控えておきます。

{
    "Role": {
        "Description": "Allow AWS Transfer to call AWS services on your behalf.", 
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17", 
            "Statement": [
                {
                    "Action": "sts:AssumeRole", 
                    "Principal": {
                        "Service": "transfer.amazonaws.com"
                    }, 
                    "Effect": "Allow", 
                    "Sid": ""
                }
            ]
        }, 
        "MaxSessionDuration": 3600, 
        "RoleId": "XXXXXXXXXXYYYYYYYYYY", 
        "CreateDate": "2020-09-20T05:02:24Z", 
        "RoleName": "作成したIAMロール名", 
        "Path": "/", 
        "RoleLastUsed": {}, 
        "Arn": "arn:aws:iam::xxxxxxxxxxxxx:role/xxxxxxxxxxxxxxxxxxxxxxxxx"
    }
}

バケットポリシーを更新

作成したIAMロールへのアクセス権を付与するように、S3のバケットポリシーを次のように更新します。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "BucketPolicyForSFTP",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::{アカウントAのID}:root"
      },
      "Action": [
        "s3:PutObject",
        "s3:PutObjectAcl",
        "s3:GetObject",
        "s3:DeleteObjectVersion",
        "s3:DeleteObject",
        "s3:GetObjectVersion",
        "s3:ListBucket",
        "s3:GetBucketLocation"
      ],
      "Resource": [
        "arn:aws:s3:::{S3のバケット名}",
        "arn:aws:s3:::{S3のバケット名}/*"
      ],
      "Condition": {
        "StringLike": {
          "aws:userId": "{IAMロールのID}:*"
        }
      }
    }
  ]
}

SFTP サーバーユーザーを作成

SSHキーを作成します。今回は下記のコマンドでローカルでサクッと作りました。

$ ssh-keygen -P "" -f transfer-key

続いてSFTPサーバーを作成してサーバーIDを取得します。

マネジメントコンソールのメニューからAWS Transfer Familyに進みCreate serverで次のように設定して作成します。

  • protocols:SFTP
  • Identity provider:Service managed
  • Endpoint type:Publicly accessible
  • それ以外デフォルト

作成されたSFTPサーバーが一覧に表示されればサーバーIDが取得できます。

続いてAWS CLIを使用してSFTPサーバーユーザーを作成します。

マネジメントコンソールからだとユーザーのホームディレクトリを指定する際に別アカウントのS3バケットが選択肢に表示されないのでAWS CLIから作成する必要があります。

$ aws transfer create-user --user-name "{SFTPサーバーユーザーの名前}" --server-id "{SFTPサーバーID}"  --role "{IAMロールのARN}" --home-directory "/{S3バケット名}/{フォルダ名}" --ssh-public-key-body "{transfer-key.pubの内容}"

作成に成功すると次のように結果が表示されます。

{
  "ServerId": "MY_SERVER_ID",
  "UserName": "MY_SFTP_USER_NAME"
}

ホームディレクトリのみに読み書きを制限したい場合は次のブログを参考にスコープダウンポリシーを設定してください。

アクセスできるか確認

作成したユーザーとしてSFTPサーバーに接続してみます。

$ sftp -i transfer-key {SFTPサーバーユーザー名}@{SFTPサーバーエンドポイント}

エンドポイントはSFTPサーバーの詳細画面から取得できます。

無事に接続できたらファイルを参照・作成・削除してみたりします。

以上です!

参考