AWS Lambda を使用して ID プロバイダーを統合する - AWS Transfer Family

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

AWS Lambda を使用して ID プロバイダーを統合する

カスタム ID プロバイダーに接続する AWS Lambda 関数を作成します。Okta、Secrets Manager、、 OneLoginまたは認証ロジックを含むカスタムデータストアなど、任意のカスタム ID プロバイダーを使用できます。

注記

Lambda を ID プロバイダーとして使用する Transfer Family サーバーを作成する前に、関数を作成する必要があります。サンプルの Lambda 関数については、「Lambda 関数の例」を参照してください。または、 のいずれかを使用する CloudFormation スタックをデプロイすることもできますLambda 関数のテンプレート。また、Lambda 関数が Transfer Family と信頼関係にあるリソースベースのポリシーを使用していることを確認してください。ポリシーの例については、「Lambda リソースベースのポリシー」を参照してください。

  1. AWS Transfer Family コンソールを開きます。

  2. [Create server] (サーバーの作成) を選択すると [Create server] (サーバーの作成) ページが開きます。[Choose an identity provider] (ID プロバイダーの選択) で [Custom Identity Provider] (カスタム ID プロバイダー) を選択します (次の画面例を参照)。

    
                [ID プロバイダーの選択] コンソールセクションで、[カスタム ID プロバイダー] が選択されています。また、ユーザーはパスワードまたはキーのいずれかを使用して認証できるというデフォルト値が選択されています。
    注記

    認証方法を選択できるのは、Transfer Familyサーバーのプロトコルの1つとしてSFTPを有効にした場合のみです。

  3. デフォルト値 AWS Lambda を使用して ID プロバイダー を接続する が選択されていることを確認します。

  4. AWS Lambda 関数」では、Lambda 関数の名前を選択します。

  5. 残りのフィールドに値を入力してから [Create server] (サーバーの作成) を選択します。サーバーを作成するための残りの手順の詳細については、「SFTP、FTPS、または FTP サーバーエンドポイントの設定」を参照してください。

Lambda リソースベースのポリシー

Transfer Family サーバーと Lambda ARN を参照するポリシーが必要です。たとえば、ID プロバイダーに接続する Lambda 関数で次のポリシーを使用できます。ポリシーは、JSON で文字列としてエスケープされます。

"Policy": "{ "Version": "2012-10-17", "Id": "default", "Statement": [ { "Sid": "AllowTransferInvocation", "Effect": "Allow", "Principal": { "Service": "transfer.amazonaws.com" }, "Action": "lambda:InvokeFunction", "Resource": "arn:aws:transfer:region:account-id:function:my-lambda-auth-function", "Condition": { "ArnLike": { "AWS:SourceArn": "arn:aws:transfer:region:account-id:server/server-id" } } } ] }"
注記

上記のポリシー例では、各「ユーザー入力プレースホルダー」をあなた自身の情報で置き換えます。

イベントメッセージの構造

SFTP サーバーからカスタム IDP のオーソライザー Lambda 関数に送信されるイベントメッセージ構造は次のとおりです。

{ 'username': 'value', 'password': 'value', 'protocol': 'SFTP', 'serverId': 's-abcd123456', 'sourceIp': '192.168.0.100' }

ここで、usernameおよびpasswordはサーバーに送信されるサインイン認証情報の値です。

例えば、以下のコマンドを入力して接続する:

sftp bobusa@server_hostname

その後、パスワードの入力を求められる:

Enter password: mysecretpassword

Lambda 関数内から渡されたイベントを出力することで、Lambda 関数からこれを確認できます。以下のテキストブロックのように見えるはずです。

{ 'username': 'bobusa', 'password': 'mysecretpassword', 'protocol': 'SFTP', 'serverId': 's-abcd123456', 'sourceIp': '192.168.0.100' }

イベントの構造は FTP と FTPS で似ています。唯一の違いは、SFTP ではなく、これらの値がprotocolパラメータに使用されることです。

認証用の Lambda 関数

さまざまな認証戦略を実装するには、Lambda 関数を編集します。アプリケーションのニーズを満たすために、 CloudFormation スタックをデプロイできます。Lambda の詳細については、AWS Lambda デベロッパーガイドまたは「Node.js による Lambda 関数の構築」を参照してください。

Lambda 関数のテンプレート

認証に Lambda 関数を使用する AWS CloudFormation スタックをデプロイできます。ログイン認証情報を使用してユーザーを認証および承認するテンプレートがいくつか用意されています。これらのテンプレートまたは AWS Lambda コードを変更して、ユーザーアクセスをさらにカスタマイズできます。

注記

テンプレートで FIPS 対応のセキュリティポリシーを指定 AWS CloudFormation することで、 を使用して FIPS 対応 AWS Transfer Family サーバーを作成できます。使用可能なセキュリティポリシーについては、のセキュリティポリシー AWS Transfer Familyで説明しています。

認証に使用する AWS CloudFormation スタックを作成するには
  1. https://console.aws.amazon.com/cloudformation で AWS CloudFormation コンソールを開きます。

  2. AWS CloudFormation ユーザーガイド」の AWS CloudFormation 「スタックテンプレートの選択」にある既存のテンプレートから スタックをデプロイする手順に従います。

  3. 以下のテンプレートのいずれかを使用して、Transfer Family で認証に使用するLambda 関数を作成します。

    • クラシック (Amazon Cognito) スタックテンプレート

      でカスタム ID プロバイダー AWS Lambda として使用する を作成するための基本的なテンプレート AWS Transfer Family。Amazon Cognito に対してパスワードベースの認証を行い、パブリックキーベースの認証が使用されている場合、パブリックキーは Amazon S3 バケットから返されます。デプロイ後に Lambda 関数コードを変更すれば異なる処理を実行できます。

    • AWS Secrets Manager スタックテンプレート

      サーバー AWS Lambda と を使用して Secrets Manager AWS Transfer Family を ID プロバイダーとして統合する基本的なテンプレート。形式のエントリに対して認証 AWS Secrets Manager されますaws/transfer/server-id/username。さらに、シークレットは、Transfer Family に返されるすべてのユーザープロパティのキーバリューペアを保持する必要があります。デプロイ後に Lambda 関数コードを変更すれば異なる処理を実行できます。

    • Okta スタックテンプレート: が AWS Transfer Family サーバー AWS Lambda を使用して Okta をカスタム ID プロバイダーとして統合する基本的なテンプレート。

    • Okta-mfa スタックテンプレート: が AWS Transfer Family サーバー AWS Lambda と使用して、カスタム ID プロバイダーとして Okta と MultiFactor 認証を統合する基本的なテンプレート。

    • Azure Active Directory テンプレート: このスタックの詳細は、ブログ記事「Authenticating to AWS Transfer Family with Azure Active Directory and AWS Lambda」で説明されています。

    スタックがデプロイされたら、 CloudFormation コンソールの出力タブでスタックの詳細を表示できます。

    これらのスタックのいずれかをデプロイすることが、カスタム ID プロバイダーをTransfer Family ワークフローに統合するうえで最も簡単な方法です。

有効な Lambda 値

次の表は、カスタム ID プロバイダーに使用される Lambda 関数について Transfer Family が受け入れる値の詳細についての説明です。

説明 必須

Role

Amazon S3 バケットまたは Amazon EFS ファイルシステムへのユーザーのアクセスを制御する IAM ロールの Amazon Resource Name (ARN) を指定します。このロールにアタッチされたポリシーにより、ファイルを Amazon S3 または Amazon EFS ファイルシステム間で転送する際のユーザーに付与するアクセスのレベルが決定されます。IAM ロールには、ユーザーの転送リクエストを処理する際に、サーバーによるリソースへのアクセスを許可する信頼関係も含まれる必要があります。

信頼関係の確立の詳細については、信頼関係を確立するには を参照してください。

必須

PosixProfile

ユーザーの Amazon EFS ファイルシステムへのアクセスを制御する、ユーザー ID (Uid)、グループ ID (Gid)、およびセカンダリグループ ID (SecondaryGids) を含む完全な POSIX ID。ファイルシステム内のファイルとディレクトリに設定される POSIX アクセス許可によって、Amazon EFS ファイルシステムとの間でファイルを転送するときにユーザーが得るアクセスのレベルが決まります。

Amazon EFS バッキングストレージに必須

PublicKeys

このユーザーに有効な SSH パブリックキー値のリスト。空のリストはこれが有効なログインではないことを示します。パスワード認証中に返してはなりません。

オプションです。

Policy

複数のユーザーに同じ IAM ロールの使用を可能にするユーザーのセッションポリシー。このポリシーは、ユーザーアクセスのスコープを Amazon S3 バケットの一部に絞り込みます。

オプションです。

HomeDirectoryType

ユーザーがサーバーにログインするときにホームディレクトリにするランディングディレクトリ (フォルダ) のタイプ。

  • PATH に設定した場合、ユーザーにはファイル転送プロトコルクライアント内の Amazon S3 バケットまたは Amazon EFS の絶対パスが表示されます。

  • LOGICAL に設定した場合、Amazon S3 または Amazon EFS のパスをユーザーから見えるようにするには、HomeDirectoryDetails パラメーターでマッピングを提供する必要があります。

オプションです。

HomeDirectoryDetails

ユーザーに表示する Amazon S3 または Amazon EFS のパスとキー、およびそれらをどのように表示するかを指定する論理ディレクトリマッピング。「Entry」と「Target」のペアを指定する必要があり、Entry はパスの表示方法を示し、Target は実際の Amazon S3 または Amazon EFS のパスです。

HomeDirectoryTypeLOGICAL の値がある場合に必須

HomeDirectory

ユーザーがクライアントを使用してサーバーにログインするときの、ユーザーのランディングディレクトリ。

オプションです。

注記

HomeDirectoryDetailsはJSON マップの文字列表現です。これは、実際のJSONマップ・オブジェクトであるPosixProfileや、文字列のJSON配列であるPublicKeysとは対照的です。言語固有の詳細については、コード例を参照してください。

Lambda 関数の例

このセクションでは、NodeJS と Python の両方で使用される Lambda 関数の例をいくつか紹介します。

注記

これらの例では、ユーザー、ロール、POSIX プロファイル、パスワード、ホームディレクトリの詳細はすべて例であり、実際の値に置き換える必要があります。

Logical home directory, NodeJS

以下の NodeJS サンプル関数は、「論理ホームディレクトリ」を持つユーザーの詳細を提供します。

// 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 server ID, only that it is provided. if (event.serverId !== "" && event.username == 'example-user') { var homeDirectoryDetails = [ { Entry: "/", Target: "/fs-faa1a123" } ]; response = { Role: 'arn:aws:iam::123456789012:role/transfer-access-role', // The user is authenticated if and only if the Role field is not blank PosixProfile: {"Gid": 65534, "Uid": 65534}, // Required for EFS access, but not needed for S3 HomeDirectoryDetails: JSON.stringify(homeDirectoryDetails), HomeDirectoryType: "LOGICAL", }; // Check if password is provided if (!event.password) { // If no password provided, return the user's SSH public key response['PublicKeys'] = [ "ssh-rsa abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" ]; // Check if password is correct } else if (event.password !== 'Password1234') { // 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); };
Path-based home directory, NodeJS

以下の NodeJS サンプル関数は、パスベースのホーム・ディレクトリを持つユーザーの詳細を提供します。

// 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 server ID, only that it is provided. // There is also event.protocol (one of "FTP", "FTPS", "SFTP") and event.sourceIp (e.g., "127.0.0.1") to further restrict logins. if (event.serverId !== "" && event.username == 'example-user') { response = { Role: 'arn:aws:iam::123456789012:role/transfer-access-role', // The user is authenticated if and only if the Role field is not blank Policy: '', // Optional, JSON stringified blob to further restrict this user's permissions HomeDirectory: '/fs-faa1a123' // 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'] = [ "ssh-rsa abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" ]; // Check if password is correct } else if (event.password !== 'Password1234') { // 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); };
Logical home directory, Python

以下の Python サンプル関数は、「論理ホームディレクトリ」を持つユーザーの詳細を提供します。

# GetUserConfig Python Lambda with LOGICAL HomeDirectoryDetails import json def lambda_handler(event, context): print("Username: {}, ServerId: {}".format(event['username'], event['serverId'])) response = {} # Check if the username presented for authentication is correct. This doesn't check the value of the server ID, only that it is provided. if event['serverId'] != '' and event['username'] == 'example-user': homeDirectoryDetails = [ { 'Entry': '/', 'Target': '/fs-faa1a123' } ] response = { 'Role': 'arn:aws:iam::123456789012:role/transfer-access-role', # The user will be authenticated if and only if the Role field is not blank 'PosixProfile': {"Gid": 65534, "Uid": 65534}, # Required for EFS access, but not needed for S3 'HomeDirectoryDetails': json.dumps(homeDirectoryDetails), 'HomeDirectoryType': "LOGICAL" } # Check if password is provided if event.get('password', '') == '': # If no password provided, return the user's SSH public key response['PublicKeys'] = [ "ssh-rsa abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" ] # Check if password is correct elif event['password'] != 'Password1234': # 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 = {} return response
Path-based home directory, Python

以下の Python サンプル関数は、パスベースのホームディレクトリを持つユーザーの詳細を提供します。

# GetUserConfig Python Lambda with PATH HomeDirectory def lambda_handler(event, context): print("Username: {}, ServerId: {}".format(event['username'], event['serverId'])) response = {} # Check if the username presented for authentication is correct. This doesn't check the value of the server ID, only that it is provided. # There is also event.protocol (one of "FTP", "FTPS", "SFTP") and event.sourceIp (e.g., "127.0.0.1") to further restrict logins. if event['serverId'] != '' and event['username'] == 'example-user': response = { 'Role': 'arn:aws:iam::123456789012:role/transfer-access-role', # The user will be authenticated if and only if the Role field is not blank 'Policy': '', # Optional, JSON stringified blob to further restrict this user's permissions 'HomeDirectory': '/fs-fs-faa1a123', 'HomeDirectoryType': "PATH" # Not strictly required, defaults to PATH } # Check if password is provided if event.get('password', '') == '': # If no password provided, return the user's SSH public key response['PublicKeys'] = [ "ssh-rsa abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789" ] # Check if password is correct elif event['password'] != 'Password1234': # 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 = {} return response

設定をテストする

カスタム ID プロバイダーを作成したら、設定をテストする必要があります。

Console
AWS Transfer Family コンソールを使用して設定をテストするには
  1. AWS Transfer Family コンソールを開きます。

  2. [Servers] (サーバー) ページで新しいサーバーを選択し、[Actions] (アクション) を選択してから [Test] (テスト) を選択します。

  3. AWS CloudFormation スタックをデプロイしたときに設定したユーザー名とパスワードのテキストを入力します。デフォルトのオプションのままだと、ユーザー名は myuser、パスワードは MySuperSecretPassword となります。

  4. AWS CloudFormation スタックのデプロイ時に設定した場合は、サーバープロトコルを選択し、送信元 IP の IP アドレスを入力します。

CLI
AWS CLI を使用して設定をテストするには
  1. test-identity-provider コマンドを実行します。以降のステップで説明するように、それぞれの user input placeholder を独自の情報に置き換えます。

    aws transfer test-identity-provider --server-id s-1234abcd5678efgh --user-name myuser --user-password MySuperSecretPassword --server-protocol FTP --source-ip 127.0.0.1
  2. サーバー ID を入力します。

  3. AWS CloudFormation スタックをデプロイしたときに設定したユーザー名とパスワードを入力します。デフォルトのオプションのままだと、ユーザー名は myuser、パスワードは MySuperSecretPassword となります。

  4. AWS CloudFormation スタックのデプロイ時にサーバープロトコルと送信元 IP アドレスを設定した場合は、入力します。

ユーザー認証が成功した場合、テストはStatusCode: 200 HTTP レスポンス、空の文字列Message: ""(これがなければ失敗の理由を含む)、およびResponseフィールドを返します。

注記

以下のレスポンス例では、Responseフィールドは「文字列化」された (プログラム内で使用できるフラットな JSON 文字列に変換された) JSON オブジェクトで、ユーザーのロールと権限の詳細が含まれています。

{ "Response":"{\"Policy\":\"{\\\"Version\\\":\\\"2012-10-17\\\",\\\"Statement\\\":[{\\\"Sid\\\":\\\"ReadAndListAllBuckets\\\",\\\"Effect\\\":\\\"Allow\\\",\\\"Action\\\":[\\\"s3:ListAllMybuckets\\\",\\\"s3:GetBucketLocation\\\",\\\"s3:ListBucket\\\",\\\"s3:GetObjectVersion\\\",\\\"s3:GetObjectVersion\\\"],\\\"Resource\\\":\\\"*\\\"}]}\",\"Role\":\"arn:aws:iam::000000000000:role/MyUserS3AccessRole\",\"HomeDirectory\":\"/\"}", "StatusCode": 200, "Message": "" }