0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

TransferFamilyへの認証認可をLambdaとSecretsManagerでお手軽に実装してみた

Last updated at Posted at 2022-11-13

はじめに

S3にFTPでファイルの送受信を行いたいと考えたとき、マネージドなFTP
のサービスであるTransfer Familyが第一候補にあがります。

Transfer Familyにファイルアップロードを行うにあたって必要になるのがユーザー管理です。
ユーザー管理には以下の3つのタイプがあります。

  1. AWS Transfer Familyのサービス管理
  2. AWS Directory Service for Microsoft Active Directory (AD管理)
  3. カスタム ID プロバイダー

ADを使えばユーザー管理やアクセス権限の制御はできるものの、例えばユーザー数が少ない場合には少し過剰な気もします。また、FTP(SFTPではない)を利用する場合には カスタムIDプロバイダー しか利用することができません。そのため、今回は以下のような想定で3.のカスタムIDプロバイダーによる認証を実装してみます。

  1. FTPを利用
  2. 利用者が数ユーザーのみと小規模

やること

今回はLambdaとSecretsManagerを利用した認証の仕組みを作成します。

IAMポリシーの作成

まずは、FTPを利用するユーザーの権限を管理するために、IAMポリシーを作成します。
IAMポリシーのダッシュボードから、ポリシーを作成 を押します。
2022-11-13-14-43-54.png

ポリシーをJSON形式で記載するので、JSON タブを選択します。
2022-11-13-14-44-21.png

FTPユーザーに「どのS3バケットの読み書き権限を与えるか」をポリシーで定義します。
以下のJSONの「bucketname」部分をユーザーにアクセスさせたいバケット名に置換して、マネジメントコンソールに貼り付けます。

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

貼り付けたら、次のステップ をを押します。
ここで記載したS3バケットに対して、FTPユーザーはアクセス権限が付与されます。
2022-11-13-14-47-32.png

タグの追加画面はデフォルトのままで、もう一度 次のステップ:確認 を押します。
2022-11-13-14-48-21.png

ポリシーに名前をつけます。
ここでは、「UserA」というFTPユーザーに対してのポリシーを想定しています。
ポリシーの作成をクリックして作成完了です。
2022-11-13-14-49-08.png

ユーザーごとに権限を変える場合は、ここでユーザーの数だけポリシーを作成すればOKです。

IAMロールの作成

次に、IAMロールを作成します。
LambdaでユーザーIDとパスワードの認証を行った後、IAMロールをReturnすることで、ユーザーがどのAWSリソースを操作できるのか、認可を行うために利用します。

IAMからロールを作成していきましょう
2022-11-13-14-41-09.png

信頼されたエンティティタイプで、AWSのサービス にチェックを入れます。
2022-11-13-14-41-43.png

ユースケースでは、他のAWSサービスのユースケースで「Transfer」を選択します。
そして 次へ を押します。
2022-11-13-14-42-11.png

次に、このIAMロールに許可されるポリシーを追加します。
AWSTransferFullAccess を検索して、チェックを入れましょう。
2022-11-13-14-50-41.png

これだけだと、TransferFamilyに対する許可しか付与されていません。
S3のアクセス権限を付与するため、先程作成したFTPTransfer-UserA-Policyも追加しましょう。
追加ができたら 次へ を押します。
2022-11-13-14-51-21.png

そして、このIAMロールに名前をつけます。
ここでは FTPTransder-UserA-Role としています。
2022-11-13-14-52-04.png

ステップ2: 許可を追加する で、2つのポリシーが付与されていることを確認します。
2つのポリシーが確認できたら ロールの作成 を押します。
2022-11-13-14-52-15.png

ロールの一覧画面に戻るので、作成したロールを検索します。
2022-11-13-14-53-09.png

ロール名をクリックすると詳細が表示されるので、ARN欄の値をコピーしておきましょう。
これは、Lambda関数でFTPユーザーに権限を払い出す際に利用します。
2022-11-13-14-53-35.png

Secret Managerの設定

いよいよSecretsManagerの設定です。
新しいシークレットを保存する を押します。
2022-11-13-14-39-54.png

そして、利用するシークレットの値を保存していきます。
ここでは、UserAというFTPユーザーのデータを保存します。
以下の通り設定しましょう。

  • シークレットのタイプ
    • その他のシークレットのタイプ
  • キー/値
    • Password / パスワードの値
    • Role / 先程コピーしたIAMロールのARN

設定できたら 次へ を押します。

2022-11-13_14-54-27.png

シークレットの名前をつけて、次へ
2022-11-13-14-57-20.png

ローテーションの設定は特に行わないので、次へ
2022-11-13-14-58-10.png

レビュー画面で設定を確認し、保存
2022-11-13-14-58-31.png

Lambda関数の作成

ここまでで、FTPユーザーであるUserAの各種設定ができました。
UserAがどのS3バケットを見ることができるのか、どんなパスワードでログインできるのか、といった情報などの設定ができているので、ここからはLambda関数で認証認可の部分を作っていきます。

実行権限の設定

Lambdaは既に空のLambdaが作成済みである想定です。
デフォルトのままだと、LambdaはSecretsManagerにアクセスする権限がないため、ここではLambdaのIAMロールにSecretsManagerへの実行権限を付与していきます。

Lambda関数を作成した後、設定 -> アクセス権限 から 実行ロール 欄を確認します。
ロール名を押して、Lambdaに付与されているIAMロールを編集していきましょう。
2022-11-13-15-13-19.png

許可を追加 -> ポリシーをアタッチ を押します。
2022-11-13-15-13-45.png

SecretsManagerReadWriteにチェックを入れて、ポリシーをアタッチ を押します。
これで、LambdaがSecretsManagerから値を取得することができるようになりました。
2022-11-13-15-14-08.png

それでは、Lambdaの実装を行います。
以下のコードをコピペしましょう。

import json
import boto3
from botocore.exceptions import ClientError

REGION_NAME = "ap-northeast-1"

def lambda_handler(event, context):
    
    secret_name = "FTP/{}".format(event["username"])
    
    # Screts Managerのクライアントを作成
    session = boto3.session.Session()
    client = session.client(
        service_name='secretsmanager',
        region_name=REGION_NAME
    )
    
    try:
        get_secret_value_response = client.get_secret_value(
            SecretId=secret_name
        )
    except ClientError as e:
        # For a list of exceptions thrown, see
        # https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
        raise e

    # 取得したシークレットの値を使いやすいように加工
    secret = json.loads(get_secret_value_response['SecretString'])
    PASSWORD = secret['Password']
    ROLE = secret['Role']
    
    # パスワードチェック
    if event["password"] == PASSWORD:
        return { 'Role': ROLE }
    else:
        return {}

実行していることは単純です。
ユーザーがFTPクライアントから接続する際に、ユーザーIDとパスワードを入力します。
それぞれの値がLambdaのeventにusername passwordとして渡されます。

このLambda関数では、渡されたusernameの値をキーとして、SecretsManagerからpasswordとS3へのアクセス権限を定義したRoleの値を取得します。

そして、ユーザーから入力されたパスワードの値と、SecretsManagerから取得したPasswordの値が等しいかを確認し、正しい場合はRoleをReturnしています。

    # 取得したシークレットの値を使いやすいように加工
    secret = json.loads(get_secret_value_response['SecretString'])
    PASSWORD = secret['Password']
    ROLE = secret['Role']
    
    # パスワードチェック
    if event["password"] == PASSWORD:
        return { 'Role': ROLE }
    else:
        return {}

動作確認

FTPクライアントからTransferFamilyに対して接続を行い、ユーザーIDにUserA、パスワードはSecretsManagerに設定したパスワードを入力し、ログイン確認を行いましょう。

事前にポリシーで定義したバケットにしかアクセス権限はないため、FTPクライアント側にバケットのパスを設定しておくことを忘れずに。

検証を通じてわかったこと

今回の記事では、Secret Managerを利用してセキュアにFTPのユーザー認証を行いました。
ですが、検証目的だったら以下に記載のような超シンプルなコードでも動きます。

def lambda_handler(event, context):
    if event["username"] == "hoge" and event["password"] == "hogehoge":
        return { 'Role': 'arn:aws:iam::{ARN}:role/{RoleName}' }
    else:
        return {}

まずはお手軽に検証を行った上で、最終的にはSecret Managerを使ってセキュアにするのが良いかもしれませんね。

参考URL

AWS Transfer Family のカスタムIDプロバイダーで AWS Secrets Manager を使用して パスワード認証を有効にしてみる | DevelopersIO

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?