Working with identity providers - AWS Transfer Family

Working with identity providers

To integrate your existing identity provider into AWS Transfer Family, provide a RESTful interface with a single Amazon API Gateway method. Transfer Family calls this method to authenticate your users.

This single method authenticates and authorizes your users for access to Amazon S3. After you configure the method, attach it to your server when you create a new server. You can create a new server using the AWS Transfer Family console or CreateServer API operation.

For more information about working with API Gateway, see the API Gateway Developer Guide.

Authenticate using custom identity providers

To create a custom identity provider for Transfer Family, use API Gateway, which provides a highly secure way for you to create and provide APIs. With API Gateway, you can create an HTTPS endpoint so that all incoming API calls are transmitted with greater security. For more details on the API Gateway service, see the API Gateway Developer Guide.

API Gateway offers an authentication method named AWS_IAM, which gives you the same authentication based on AWS Identity and Access Management (IAM) that AWS uses internally. If you enable authentication with AWS_IAM, only callers with explicit permissions to call an API can reach that API's API Gateway method.

To use API Gateway as a custom identity provider for Transfer Family, enable IAM for your API Gateway gateway. As part of this process, you provide an IAM role with permissions for Transfer Family to use your gateway.

To use API Gateway for custom authentication with Transfer Family

  1. Create an AWS CloudFormation stack. To do this:

    1. Open the AWS CloudFormation console at https://console.aws.amazon.com/cloudformation/.

    2. Follow the instructions on deploying an AWS CloudFormation stack from an existing template in Selecting a stack template in the AWS CloudFormation User Guide.

    3. Use one of the following basic templates for creating a AWS Lambda-backed API Gateway for use as a custom identity provider in Transfer Family:

    Deploying one of these stacks is the easiest way to integrate a custom identity provider into the Transfer Family workflow. The stack uses the Lambda function to support a gateway based on API Gateway. You can then use this gateway as a custom identity provider in Transfer Family. By default, the Lambda function authenticates a single user called myuser with a password of MySuperSecretPassword. You can edit these credentials or update the Lambda function code to do something different after deployment.

    After the stack has been deployed, you can view details about it on the Outputs tab. These details include the stack Amazon Resource Name (ARN), the ARN of the IAM role that the stack created, and the URL for your new gateway.

    Note

    If you are using the custom identity provider option to enable password–based authentication for your users, and you enable API Gateway's request and response logging, it will log your users' passwords to your Amazon CloudWatch Logs. We don't recommend using this log in your production environment. For more information, see Set up CloudWatch API logging in API Gateway in the API Gateway Developer Guide.

  2. Check the API Gateway configuration for your server. To do this:

    1. Open the API Gateway console at https://console.aws.amazon.com/apigateway/.

    2. Choose the Transfer Custom Identity Provider basic template API that the AWS CloudFormation template generated.

      The following screenshot shows the complete API configuration. In this example, the method is backed by a Lambda function, but many other integration types are also possible.

    3. In the Resources pane, choose GET, and then choose Method Request. The following screenshot shows the correct method configuration that includes protocol, serverId, sourceIp, and username as part of the parameters.

    At this point, your gateway is ready to be deployed.

  3. For Actions, choose Deploy API. For Deployment stage, choose prod, and then choose Deploy.

    After the API is successfully deployed, view its performance in the Stage Editor section, as shown following.

    Note

    Copy the Invoke URL that appears at the top of the screen. You will need it for the next step.

  4. Open the AWS Transfer Family console at https://console.aws.amazon.com/transfer/.

    Choose Create server to open the Create server page. For Choose an identity provider, choose Custom, as shown following.

    For Custom provider, paste the Invoke URL of the API Gateway endpoint that you created in the previous step.

    For Invocation role, choose the IAM role that was created by the AWS CloudFormation template. This role allows Transfer Family to invoke your gateway.

    The invocation role contains the AWS CloudFormation stack name you selected for the stack you created in step 1. It has the following format: CloudFormation-stack-name-TransferIdentityProviderRole-ABC123DEF456GHI.

  5. Fill in the remaining boxes and choose Create server.

Test your configuration

To test your configuration in the console

  1. Open the AWS Transfer Family console at https://console.aws.amazon.com/transfer/.

  2. On the Servers page, choose your new server, choose Actions, and then choose Test.

  3. Enter the text for Username and Password that you set when you deployed the AWS CloudFormation stack. If you kept the default options, the username is myuser and the password is MySuperSecretPassword.

  4. Choose the Server protocol and enter the IP address for Source IP, if you set them when you deployed the AWS CloudFormation stack.

    If user authentication succeeds, the test returns a StatusCode: 200 HTML response and a JSON object containing the details of the user's roles and permissions, as shown following.

To test your configuration in the AWS CLI:

  1. Run the test-identity-provider command.

    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. Enter the server ID.

  3. Enter the username and password that you set when you deployed the AWS CloudFormation stack. If you kept the default options, the user name is myuser and the password is MySuperSecretPassword.

  4. Enter the server protocol and source IP, if you set them when you deployed the AWS CloudFormation stack.

    If user authentication succeeds, the command returns a StatusCode: 200 HTML response and a JSON object containing the details of the user's roles and permissions.

    { "Response": "{\"Policy\": \"{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n{\n \"Sid\": \"ReadAndListAllBuckets\",\n \"Effect\": \"Allow\",\n \"Action\": [\n \"s3:ListAllMybuckets\",\n \"s3:GetBucketLocation\",\n \"s3:ListBucket\",\n \"s3:GetObjectVersion\",\n \"s3:GetObjectVersion\"\n],\n \"Resource\":\"*\"\n}\n]\n}\",\"Role\": \"arn:aws:iam::000000000000:role/MyUserS3AccessRole\",\"HomeDirectory\": \"/\"}", "StatusCode": 200, "Message": "", "Url": "https://abcde1234.execute-api.us-east-2.amazonaws.com/prod/servers/s-123a4567bcd891e23/users/myuser/config" }

Implement your API Gateway method

To create a custom identity provider for Transfer Family, your API Gateway gateway must implement a single method that has a resource path of /servers/serverId/users/username/config. The serverId and username values come from the RESTful resource path. Optionally, you can add the sourceIp and protocol values to the RESTful resource path.

If Transfer Family attempts password authentication for your user, the service supplies a Password: header field. In the absence of a Password: header, Transfer Family attempts public key authentication to authenticate your user.

When using an identity provider to authenticate and authorize end users, in addition to validating their credentials, you can now allow or deny access requests based on the IP addresses of clients used by your end users. This enables you to ensure that data stored in your S3 buckets can be accessed over the supported protocols only from IP addresses that you have specified as trusted. To enable this, you must include the sourceIp value in the RESTful resource path.

If you have multiple protocols enabled for your server and want to provide access using the same username over multiple protocols, you can do so as long as the credentials specific to the protocol have been set up in your identity provider. To enable this, you must include the protocol value in the RESTful resource path.

This method should always return HTTP status 200. Any other HTTP status code means an error accessing the API.

The response body is a JSON document of the following form.

{ "Role": "IAM role with configured S3 permissions", "PublicKeys": [ "ssh-rsa public-key1", "ssh-rsa public-key2" ], "Policy": "STS Assume role scope down policy", "HomeDirectory": "User's home directory" }

The Role field shows that successful authentication occurred. When doing password authentication (when you supply a Password: header), you don't need to provide SSH public keys. Also, the Policy and HomeDirectory fields are optional. When no home directory is provided, Transfer Family defaults to the parent S3 bucket. If a user can't be authenticated, for example if the password is incorrect, your method should return a response without Role set. An example is an empty JSON object.

Include user policies in the Lambda function in JSON format. For more information about configuring user policies in Transfer Family, see Editing the user configuration.

Example Lambda functions for authentication

To implement different authentication strategies, edit the Lambda function that your gateway uses. To help you meet your application's needs, you can find the following example Lambda functions in Python. For more information on Lambda, see the AWS Lambda Developer Guide.

Default Lambda function

The following Lambda function takes your username, password (in the header field), IAM access role, public SSH key, and protocol. You can use the protocol field to look up your identity provider. Supported protocol values are SFTP, FTPS, and FTP.

Note

If you have multiple protocols enabled for your server and want to provide access using the same username over multiple protocols, you can do so as long as the credentials specific to the protocol have been set up in your identity provider. For FTP, we recommend maintaining separate credentials from SFTP and FTPS. This is because, unlike SFTP and FTPS, FTP transmits credentials in cleartext. By isolating FTP credentials from SFTP or FTPS, if FTP credentials are shared or exposed, your workloads using SFTP or FTPS remain secure.

The Lambda authenticates them, and, if successful, returns the relevant IAM access role and policy. This Lambda function is the same one that is used in the example AWS CloudFormation template.

The commented-out section of the following example demonstrates how to use logical directories in your Transfer Family architecture. By using logical directories, you can delegate access to specific pathways within your AWS setup on a user-by-user basis. For example, you can delegate access to different sections of an S3 bucket. To use logical directories, set your function's HomeDirectoryType parameter to LOGICAL. Also, in the HomeDirectoryDetails parameter, provide a list of Entry and Target pairs.

// GetUserConfig Lambda exports.handler = (event, context, callback) => { console.log("Username:", event.username, "ServerId: ", event.serverId); var response; // Check if the user name presented for authentication is correct. This doesn't check the value of the serverId, 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 == '${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); };

Lambda function for use with AWS Secrets Manager

To use AWS Secrets Manager as your identity provider, you can work with the Lambda function in the sample AWS CloudFormation template. It queries the Secrets Manager service with your credentials and, if successful, returns a designated secret. For more information on Secrets Manager, see the AWS Secrets Manager User Guide.

To download a sample AWS CloudFormation template that uses this Lambda function, go to the Amazon S3 bucket provided by AWS Transfer Family.