AWS Transfer Family with SFTP Service by AWS CDK

2021-07-10 AWS

前陣子同事在詢問怎麼讓外部使用者有授權的訪問 Amazon S3,當下第一時間想到的就是 AWS Transfer family 這個 Service,Transfer family 支援 FTP、FTPS、SFTP 三種協定,以安全性來說都建議至少採用 FTPS (SSL) 或 SFTP (SSH) 加密協定,在這篇也是紀錄一下如何透過 AWS CDK 建立一套 Transfer family。

這篇所有的 CDK 程式碼都放在 Github:shazi7804/cdk-samples 有興趣的可以看完整版。

Transfer family Server

首先必須要有一個 Amazon S3 bucket 存放使用者上傳下載的位置:

const bucket = new s3.Bucket(this, 'BucketOfHome', {
    bucketName: 'transfer-family-sftp-' + this.region + '-' + this.account,
    encryption: s3.BucketEncryption.S3_MANAGED,
    versioned: true
});

建議 encryption 跟 versioned 都打開,防止意外刪除或覆蓋造成的杯具 …

再來是 Transfer Family 所使用的 Service-Role

const role = new iam.Role(this, 'AWSTransferFamilyServiceRole', {
    roleName: 'AWSTransferLoggingAccess',
    assumedBy: new iam.ServicePrincipal('transfer.amazonaws.com'),
})
        role.addManagedPolicy(iam.ManagedPolicy.fromAwsManagedPolicyName('service-role/AWSTransferLoggingAccess'))

AWSTransferLoggingAccess 這個 Managed Policy 提供了 Transfer family 有權限將使用者訪問紀錄寫到 Cloudwatch logs,而預設 Cloudwatch logs 預設保存 Never expire 如果不需要長期保存記得將時間設定到適當的時間。

每一個 User 也必須定義 IAM Role 的訪問權限

const userRole = new iam.Role(this, 'AWSTransferUsersAccessRole', {
    roleName: 'AWSTransferUsersAccess',
    assumedBy: new iam.ServicePrincipal("transfer.amazonaws.com"),
});

userRole.addToPolicy(
    new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: ['s3:ListBucket'],
        resources: [bucket.bucketArn],
    })
);

userRole.addToPolicy(
    new iam.PolicyStatement({
        effect: iam.Effect.ALLOW,
        actions: [
            's3:GetObject',
            's3:GetObjectAcl',
            's3:GetObjectVersion',
            's3:PutObject',
            's3:PutObjectACL',
            's3:DeleteObject',
            's3:DeleteObjectVersion'
        ],
        resources: [`${bucket.bucketArn}/*`],
    })
);

產生出來的 IAM Policy 會長的像這樣:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "s3:ListBucket",
            "Resource": "arn:aws:s3:::${BUCKET}",
            "Effect": "Allow"
        },
        {
            "Action": [
                "s3:GetObject",
                "s3:GetObjectAcl",
                "s3:GetObjectVersion",
                "s3:PutObject",
                "s3:PutObjectACL",
                "s3:DeleteObject",
                "s3:DeleteObjectVersion"
            ],
            "Resource": "arn:aws:s3:::${BUCKET}/*",
            "Effect": "Allow"
        }
    ]
}

最後就是 Transfer family Server,由於作者在寫 AWS CDK 的時候 Transfer family 還沒有 Layer 2 resource,所以會用 Cfn 撰寫:

const server = new tf.CfnServer(this, 'TransferFamilyServer', {
    protocols: ['SFTP'],
    identityProviderType: 'SERVICE_MANAGED',
    loggingRole: role.roleArn
});

指定 SFTP Protocol 和驗證方式後,也是很簡單的幾行就搞定。

cdk deploy 後會建立幾個 resources:

  • Amazon S3 bucket
  • IAM Role for Transfer family service
  • IAM Role for Transfer family users
  • Transfer family server

接著畫面跳轉到 AWS Transfer family 的 Management Console 就可以找到剛剛建立的 Transfer server

當狀態變成 Online 後就可以 Add user 訪問權限啦:

Role 記得選擇 AWSTransferUsersAccess,而 Home directory 也要選到與 Role Policy 相同的 S3 bucket,否則即便登入也沒辦法訪問 Home 目錄。

Restricted 打勾時使用者會被鎖在自己的家目錄下而無法訪問其他層級的目錄,這是在 FTP 上很常見的權限處理方式。

由於 Transfer family SFTP 的驗證是採用 SSH public/private keys 進行驗證,如果是 macOS/Linux 可以用 ssh-keygen 來產生 ssh key (Windows 也有 OpenSSH 或是 puttygen 可以用)

$ ssh-keygen -P "" -m PEM -f shazi7804

拿到兩隻檔案分別是 shazi7804 (private key) 和 shazi7804.pub (public key),將 public key 填上 Add user 欄位內。

Transfer family users

在使用者端可以選擇有支援 SFTP Client 的 FileZilla 並且了解以下資訊:

  • Transfer family endpoint:s-xxxxxx.server.transfer.${region}.amazonaws.com
  • Protocol:SFTP
  • SSH Private key (shazi7804)

建立站台後就可以成功連上 Transfer family server 啦!!

而在 Cloudwatch logs 上每一個 user 都會有獨立的 Log stream 紀錄 login, read, write 等資料:

shazi7804.2291717934357386 CONNECTED SourceIP=36.231.106.61 User=shazi7804 HomeDir=LOGICAL Client=SSH-2.0-FileZilla_3.54.1 Role=arn:aws:iam::0123456789:role/AWSTransferUsersAccess Kex=curve25519-sha256@libssh.org Ciphers=aes256-gcm@openssh.com,aes256-gcm@openssh.com
shazi7804.2291717934357386 OPEN Path=/transfer-family-sftp-us-east-1-0123456789/shazi7804/.zshrc Mode=CREATE|TRUNCATE|WRITE
shazi7804.2291717934357386 CLOSE Path=/transfer-family-sftp-us-east-1-0123456789/shazi7804/.zshrc BytesIn=3208
shazi7804.2291717934357386 OPEN Path=/transfer-family-sftp-us-east-1-0123456789/shazi7804/.zshrc Mode=READ
shazi7804.2291717934357386 CLOSE Path=/transfer-family-sftp-us-east-1-0123456789/shazi7804/.zshrc BytesOut=3208

3 Replies to “AWS Transfer Family with SFTP Service by AWS CDK”

  1. Delphi表示:

    您好

    目前在衡量透過 Transfer Family 的服務與 EC2 自架 SFTP Server 兩個方案,

    兩者都希望能夠透過 lambda 搭配 cdk 與 event bridge, 在下班時間自動關機, 上班時間自動開機以達成節費的需求

    目前想到應 poc 的內容包括:

    Transfer Family 部分 cdk 的撰寫 ( 建立 Transfer family / 刪除 Transfer family / 固定提供給 user 的 host / 建立 user 綁定 public key …)
    EC2 部分 cdk 的撰寫 ( 建立 EC2 / 刪除 EC2 / 固定提供給 user 的 host / 建立 user 綁定 public key … )

    由於不確定設想是否完備, 想請問您是否有類似的場境經驗呢 ?

    • shazi7804表示:

      Hello, 基本上兩者都沒什麼問題,依你的需求都可以達到

      兩者差別在是否 AWS Managed,選擇 EC2 要花費的力氣還要兼顧 HA,假設你有多台 EC2 還要採用 EFS 作為集中儲存的地方,但 EC2 可客製化的地方就更多

  2. Delphi表示:

    Hello 您好

    目前測試網誌中的 WordPress, Google, Facebook Auth 的留言方式

    目前都會失敗 XD

    非常感謝您的回應!!

    經過幾個諮詢後, 建議也與您所提到的項目大同小異

    在考慮 EC2 需每季進行一次弱掃,

    相較於 focus 在維運的工程人員,

    focus 在開發的工程人員需要耗費的維運成本會更高

    在降低需要 focus 在開發的工程人員維運與預算可以接受的前提下

    最終選擇了採用 Transfer Family 的服務

    非常感謝您的回應

給 Mr. 沙先生一點建議

彙整

分類

展開全部 | 收合全部

License

訂閱 Mr. 沙先生 的文章

輸入你的 email 用於訂閱