概要
外部ユーザー向けに、SFTPサーバーを立てる要件があり、AWS Transfer Familyで立てられるようだったので、構築をしてみました。
情報はいろいろありますが、テンプレートを一部修正しないと動かなかったので修正箇所についても記載しています。
S3バケットを使用したものになります。
こちらはユーザー認証にユーザーIDとパスワードを使用します。
SFTPでユーザーIDとSSHのパブリックキーを使用する場合は、こちらの記事をご確認ください。
SSHのパブリックキーを使用するパターンの方が構築は簡単だと思いますし、セキュリティ的にも良いと思います。
ただ、ユーザーにSSHキーの作成を依頼する点のハードルが高い場合等はこちらの選択肢もあるかと思います。
構築に当たり参考にさせて頂いたサイト:
https://dev.classmethod.jp/articles/awssftp-password-auth-logical-dir/
公式:
https://docs.aws.amazon.com/ja_jp/transfer/latest/userguide/what-is-aws-transfer-family.html
それにしても、料金が高いんですね(後で知りました)
サーバーが停止含めて立ってるだけで月 $216
ちょっとした使用程度だと、ちょっと通らない金額だなーと思いました。
https://dev.classmethod.jp/articles/202210-aws-transfer-family-sftp/
https://aws.amazon.com/jp/aws-transfer-family/pricing/
前提
- AWSコンソールに接続出来る
- 各サービスの作成、編集が出来る権限を持っている
- ID・パスワードで接続出来る様にする
- ユーザーの指定ディレクト以外は操作できないようにする
事前準備
サーバー構築前に必要な設定を行っておきます。
S3バケットの作成
S3にバケットを作成します。
今回は sftp-server-bucket-atf
を作成しました。
バケット名以外はすべてデフォルト設定のままです。
ロールの作成
SFTPの接続ユーザーに操作を許可するためのロールが必要になるため事前に作成しておきます。
ポリシーを作成
ロールに紐つけるポリシーを作成します。
ユーザー自身のディレクトリ以外は操作できないようなポリシーの作成方法もありますが、この条件は今回はSecretManagerのシークレット値で設定するため(論理ディレクトリ)、指定バケット以下は操作可能な汎用ポリシーを作成します。
- IAMのポリシーから「ポリシーの作成」を選択します
- 「アクセス許可を指定」:「JSON」での編集モードにします
- 以下の内容を記載します
- Resourceの
バケット名
は各自が作成したバケット名に変更してください。
- Resourceの
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject",
"s3:GetObjectVersion"
],
"Resource": [
"arn:aws:s3:::sftp-server-bucket-atf",
"arn:aws:s3:::sftp-server-bucket-atf/*"
]
}
]
}
- すべての操作を許可したい場合
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::sftp-server-bucket-atf",
"arn:aws:s3:::sftp-server-bucket-atf/*"
]
}
]
}
ロールを作成
- IAMのロールから「ロールの作成」を選択します
- 「信頼されたエンティティを選択」:
- 「許可を追加」:先程作成したポリシー
SftpS3UserAccessPolicy
を選択し「次へ」
- 「名前、確認、および作成」:ロール名などを入力
- 「ロールを作成」する
- 作成したロールの
arn
を後で使用します
CloudFormationのテンプレート準備
SFTPでパスワード認証を実現する場合、IDプロバイダーのサービスマネージドは使用できず、カスタムIDプロバイダーを使用する必要があります。
その際に使用するLambdaや必要サービスの構築にCloudFormationを使用します。
基本的にテンプレートベースになりますが、テンプレートの内容を少しだけ変更する必要があるので、先に準備をしておきます。
公式テンプレートのダウンロード
まずは公式テンプレートをダウンロードします。
カスタムIDプロバイダーはLambdaを使用したものとAPI-Gateway(+Lambda)の2パターンを選べます。
今回はLambdaを使用したものを使うため、使用するテンプレートは異なりますが、修正箇所は同じになります。
ユーザー管理はSecretsManagerを使用します。
- AWS Lambda を使用してアイデンティティプロバイダーを接続する場合
- Amazon API Gateway を使用してアイデンティティプロバイダーを接続する場合
- その他、公式の情報やテンプレート等はこちらをご確認ください
今回は「AWS Lambda を使用してアイデンティティプロバイダーを接続する場合」で進めて行きます。
- ダウンロードしたファイルをテキストエディタなどで開く
-
LamdaSecretsPolicy
のResource
、Fn::sub
のarnを修正
# 107行目
- arn:${AWS::Partition}:secretsmanager:${SecretsRegion}:${AWS::AccountId}:secret:aws/transfer/*
↓
arn:${AWS::Partition}:secretsmanager:${SecretsRegion}:${AWS::AccountId}:secret:*
# 修正後のLambdaSecretsPolicyの内容
- PolicyName: LambdaSecretsPolicy
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- secretsmanager:GetSecretValue
Resource:
Fn::Sub:
- arn:${AWS::Partition}:secretsmanager:${SecretsRegion}:${AWS::AccountId}:secret:*
- SecretsRegion:
Fn::If:
- SecretsManagerRegionProvided
- Ref: SecretsManagerRegion
- Ref: AWS::Region
-
GetUserConfigLambda
のZipFile
、Fn::Sub
の内容を修正
# 147行目
resp = get_secret("aws/transfer/" + input_serverId + "/" + input_username)
↓
resp = get_secret("SFTP/" + input_username)
構築
SFTPサーバーの構築、必要なLambda関数などをCloudFormationで作成します。
- CloudFormationに接続し、スタックページから「スタックの作成」→「新しいリソースを使用(標準)」を選択します
- 「スタックの作成」:
- 「スタックの詳細を指定」:
- 「スタックオプションの設定」:基本的に何も変更しないで「次へ」
- 「レビュー」:最後のチェックボックスにチェックして「送信」
- スタックの完了(
CREATE_COMPLETE
)を待機する -
AWS Transfer Family
サービスページでサーバーを確認する
ユーザー作成
ユーザーの管理はAWS Secrets Manager
を使用します。
- AWS Secrets Managerに接続し、「シークレット」→「新しいシークレットを保存する」を選択
- 「シークレットのタイプを選択」:
- 「シークレットのタイプ」:その他のシークレットのタイプ
- 「キー/値のペア」:3行を追加します
- 「Password」:パスワードを指定
- 「Role」:最初に作成したロールのarnを指定
- 「HomeDirectoryDetails」:
[{"Entry": "/", "Target": "/sftp-server-bucket-atf/${Transfer:UserName}"}]
- 「Target」部分に「バケット名」が入っています。自身の作成したバケット名に変更してください。
-
${Transfer:UserName}
の部分が接続ユーザー名になり、自身のユーザー名のディレクトリを指定しています。 - このキー値を「HomeDirectory」とし、値を「/sftp-server-bucket-atf/sftp-user01/」としても接続などは可能ですが、上位のディレクトリなども見れるようになります。
- 「HomeDirectory」指定でユーザー自身のディレクトリのみを制限する場合はIAMのポリシーなどで制御が必要になります
- 「暗号化キー」:デフォルトのまま
- 「次」
- 「シークレットを設定」:シークレットの名前、説明を記入する
- 「ローテーションを設定 - オプション」:デフォルトのまま何も設定せずに「次」
- 「レビュー」:内容を確認して「保存
」 - リフレッシュすると追加したユーザーが表示されます
接続・確認
接続はSFTP接続が出来るクライアント等を使用して確認してください。
例としてCyberduckでの設定を記載します
-
サーバー(エンドポイント):AWS Transfer Familyのサーバー詳細ページのエンドポイント
-
ユーザー名:作成したユーザー
sftp-user01
その他:SFTP管理者用のユーザー作成
全ユーザーの内容を確認・修正出来る管理者的なユーザーの作成になります。
基本的に「ユーザー作成」と同じで、「HomeDirectoryDetails」のTarget部分が少し違うだけになります。
- 「キー/値のペア」:3行を追加します
- 「Password」:パスワードを指定
- 「Role」:最初に作成したロールのarnを指定
- 「HomeDirectoryDetails」:
[{"Entry": "/", "Target": "/sftp-server-bucket-atf"}]
- Targetの部分の
/${Transfer:UserName}
を削除し、/バケット名
のみにする
- Targetの部分の
あとはsftp-admin
みたいなユーザー名とかで同じ様に作成していけば大丈夫です。
以上です。