【AWS】Transfer family for FTPを構築する

## きっかけ
- とある案件で現行システムを大体AWSにリフトアップする案件があり、既存FTPサーバをTransfer family for FTPを含む構成で実現したく、事前にカスタムIdp含む構築手順の検証をするため

## 構築Step
1. Lambda 構築
1. API Gateway 構築
1. Transfer Family For FTP 構築
1. 動作確認(カスタムIDプロバイダ)
 
### 1. Lambda 構築
- 新規Lambdaをデフォルト設定で作成
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3437393838362f32306664316662302d656334612d383264332d613566302d35656135343364393964396.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/19e2362a-c17f-5601-a8bf-cd57ddb61181.png)

- ソースコードを以下に修正、デプロイ実施(https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/custom-identity-provider-users.html を参考)

```javascript:index.js
'use strict';
// GetUserConfig Lambda

exports.handler = (event, context, callback) => {
  console.log("Username:", event.username, "ServerId: ", event.serverId);

    var response;
    // Check if the username presented for authentication is correct. This doesn't check the value of the serverId, only that it is provided.
    if (event.password == '' && ( event.protocol == 'FTP' || event.protocol == 'FTPS')) {
        // Return HTTP status 200 but with no role in the response to indicate authentication failure
        response = {};
  } else if (event.serverId !== "" && event.username == '${UserName}') {
        response = {
            Role: '${UserRoleArn}', // 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: '${UserHomeDirectory}' // Not required, defaults to '/'
        };

        // Check if password is provided
        if (event.password == "") {
            // If no password provided, return the user's SSH public key
            response['PublicKeys'] = [ "${UserPublicKey1}" ];
            // Check if password is correct
        } else if (event.password !== '${UserPassword}') {
            // Return HTTP status 200 but with no role in the response to indicate authentication failure
            response = {};
        }
    } else {
        // Return HTTP status 200 but with no role in the response to indicate authentication failure
        response = {};
    }
    callback(null, response);
};

```

- 環境変数に以下5つを設定
    - UserHomeDirectory:FTP接続時のルート
    - Username: FTP認証用ユーザ
    - UserRoleArn: 認証成功時に渡すロール(S3FullAccessを付与)
    - UserPassword: FTP認証用パスワード
    - UserPublicKey1: 返却するssh鍵
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3437393838362f38356165666133372d643834352d373563612d636462612d643837373.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/8ea80f59-a6a5-defb-a068-9f2bc6f8529d.png)


### API Gateway 構築
- API GatewayをRESTで新規構築
![スクリーンショット 2021-08-18 135131.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/3d4787a8-0b11-e652-0f62-1fdd324a9e5e.png)

- モデルを以下内容で新規作成
{
  "$schema" : "http://json-schema.org/draft-04/schema#",
  "title" : "Error Schema",
  "type" : "object",
  "properties" : {
    "message" : { "type" : "string" }
  }
}
![スクリーンショット 2021-08-18 135825.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/5f239caa-7b77-5372-2b70-ea5a276dd2ef.png)


- APIのリソースを順に作成。(リソース名は任意) リソースパスを順にserver > {serverId} >users > {username} > config と作成
![スクリーンショット 2021-08-18 140349.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/5f35bb04-bc1d-c699-d45c-792d8233e6e9.png)

- GETメソッドの中身を設定。統合タイプをLambda関数とし、作成したLambda関数と紐づけ
![スクリーンショット 2021-08-18 140442.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/491e16f6-7861-7cdd-0052-741c353fefd6.png)

- メソッドレスポンスの200の場合を修正。レスポンス本文をコンテンツタイプ:application/json, モデルを作成したモデルに修正
![スクリーンショット 2021-08-18 141256.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/97099e89-1058-b2b1-c83b-2e12d79b9b98.png)

- 統合リクエストのマッピングテンプレートを修正。パススルーを'テンプレートが定義されていない場合 (推奨) 'とし、コンテンツタイプをapplication/json、テンプレートを以下の内容で設定
{ 
　"username": "$input.params('username')", 
　"password":"$util.escapeJavaScript($input.params('Password')).replaceAll("\\'","'")",
　"serverId": "$input.params('serverId')", 
　"protocol": "$input.params('protocol')","sourceIp": "$input.params('sourceIp')" 
}
![スクリーンショット 2021-08-18 140813.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/6bcf1013-633f-4a56-7536-1b29376743cd.png)

### 3. Transfer Family For FTP 構築
- 以下権限を付与したIAMロールを作成
![スクリーンショット 2021-08-18 143103.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/acbdcab1-a95f-c87b-395e-3414458df178.png)

- FTPを選択
![スクリーンショット 2021-08-18 143405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/27f2829d-d912-f32f-7ad9-ade008e60d4e.png)

- IDプロバイダをカスタム、カスタムプロバイダはデプロイしたAPI GatewayのURL, ロールを事前に作成したロールを設定
![スクリーンショット 2021-08-18 143438.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/c708564b-6337-3608-72df-d86b4f98dce9.png)

- VPCでホストを選択、適当に作成したVPC,サブネットを設定、SGはデフォルトで設定
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3437393838362f31316562306330332d623932612d626364322d303035632d336637373.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/1961a882-fd23-9d3d-25d2-e878cf2db024.png)

- ドメインはS3を選択(画像取り忘れてます…)

- デフォルト設定のまま
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3437393838362f31316562306330332d623932612d626364322d303035632d336637373.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/1961a882-fd23-9d3d-25d2-e878cf2db024.png)


- 設定内容を確認し、サーバを作成
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3437393838362f32316365343336312d613934362d653935652d666565342d306335623.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/6de7e981-15f3-8d7a-f29d-3a5e2d3245a3.png)

### 4. 動作確認(カスタムIDプロバイダ)
- 作成したサーバ画面からテストを実施。Lambda上でパラメータ設定したユーザ名、パスワードを設定、サーバプロトコルはFTP、送信元IPはVPC内の適当なIPを入力し、テストを実施
- StatusCode:200が返ってくればOK
![スクリーンショット 2021-08-18 143707.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479886/f1f9d488-bbe2-0b5a-4110-52fb05d70aa6.png)


## 参考URL

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

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

https://aws.amazon.com/jp/premiumsupport/knowledge-center/transfer-customize-identity-provider/