AWS Storage Blog

Enable session limits for AWS Transfer Family

Enterprises and organizations proficient in file transfers exchange a wide variety of files, such as digital media contents, images, or large data sets with their business partners or public users. When a large shared dataset is being downloaded by end users, a file transfer server often has a limit on concurrent connection per user to avoid the situation where a single user consumes all the resources and connections on the server.

AWS Transfer Family provides a fully managed transfer service that scales in real time to meet your needs, a single server can support up to 10,000 concurrent sessions. A session is defined as all the activities between a user “connect” and “disconnect” operations. A concurrent session can occur when a user logs in simultaneously or using a File Transfer client that initiates a large number of uploads or downloads simultaneously. In that case, you can limit the sessions per user to mitigate the impact of a single user.

In this post, we show you how to implement a concurrent session limit with AWS Transfer to control the maximum number of concurrent sessions a user can have per Transfer Server. We do this by integrating AWS Lambda functions, Amazon ElastiCache (Memcached), and CloudWatch Logging Group into a solution that enables you to limit the resource usage of each user by limiting the number of concurrent sessions for each user. With proper controls in place on session limits, you can  regulate server resources and ensure smooth file-transfer performance.

Solution overview

This post extends from the blog “Enable password authentication for AWS Transfer Family using AWS Secret Manager,” adding the mechanism to track session use Amazon ElastiCache and Lambda Functions. Refer to that blog post for more information about the authentication and authorization steps.

Here we describe the workflow kicked off when a user logs into the server (connect workflow) and when a user logs out of the server (disconnect workflow). The deployment we cover supports both workflows.

The steps for a connect workflow that would increment the login count as the AWS Lambda function is as follows:

Steps for the Connect Workflow

Figure 1: Steps for the Connect Workflow

  1. A user logs in to the AWS Transfer Family server with a user name and password (SFTP, FTPS or FTP), or a user name and locally stored private SSH key (SFTP).
  2. The server passes the parameters (for example, credentials) to the Lambda function created with the template.
  3. The AWS Lambda Function queries the user settings for this transfer server from AWS Secrets Manager.
  4. Secrets Manager returns the key-value pairs associated with the user or secret.
  5. The AWS Lambda function retrieves the number of active sessions count. If it is over the set limit, it will return and reject the connection. If it is under the session limit, it increments the active session count.
  6. The AWS Lambda function validates the login and returns any user configuration to the Transfer Family.

The disconnect workflow will decrement the login count as the DISCONNECT log event is generated when a user log out or disconnect from the AWS Transfer Family server. The steps are as follows for the disconnect workflow:

Steps for the Disonnect Workflow

Figure 2: Steps for the disconnect workflow

  1. A user disconnects by logging out of the FTP session or by disconnecting the session. (Note: user does not have to explicitly disconnect from the server)
  2. AWS Transfer Family Server generates a DISCONNECT log entry captured through CloudTrail.
  3. The log entry is picked up through the subscription filter and triggers a call to FTPSessionTracking Lambda function.
  4. The lambda function decrements the active session counts in ElastiCache.

Deploy and run

The deployment template uses the AWS Serverless Application Model (AWS SAM) format. To deploy, first make sure you have the AWS SAM CLI tools installed. Then, download and unzip this package and run:

sam deploy --guided

As you go through the guided deployment via SAM, prompts are provided for the following information:

  • Stack Name: Provide a friendly name.
  • AWS Region: The AWS Region identifier to deploy the stack into.
  • CreateServer: Do you want to also deploy the AWS Transfer Family Server, or just deploy the integration stack? Valid answers are true or false.
  • CreateCacheServer: Do you want to also deploy the Amazon ElastiCache for Session Tracking? Valid answers are true or false. If false, the Session Tracking is not enabled.
  • SecretsManagerRegion: If using a different Region for AWS Secrets Manager, provide it here, otherwise, leave it empty.
  • TransferEndpointType: Valid answers are PUBLIC or VPC.
  • TransferSubnetIDs: Specify the VPC subnets to deploy endpoints. The subnet IDs are comma separated with no spaces. Only needed if using a VPC deployment.
  • TransferVPCID: The ID of the VPC to be deployed into. Only needed if using a VPC deployment. (For more information on VPC deployment, refer to this post)
  • ElastiCacheLambdaSubnetIDs: Specify the VPC subnets to deploy ElastiCache server and Lambda function. The subnet IDs are comma separated with no spaces.
  • ElastiCacheLambdaVPCID: The ID of the VPC to be deployed ElastiCache server and Lambda function into.
  • DeploySecretsManagerVPCEndpoint: Do you want to deploy AWS Secret Manager VPC Endpoint? Secrets Manager VPC Endpoint is needed for AWS Lambda function to call AWS Secrets Manager to get user credentials and session limit. The only reason this should be disabled is if a VPC Endpoint for AWS Secrets Manager has already been setup for the selected ElastiCacheLambdaVPCID and ElastiCacheLambdaSubnetIDs.
  • CacheNodeType: Select the instance type for the ElastiCache instance. The default value is cache.t2.micro. Valid node type is listed here.
  • DefaultMaxSessionLimit: Set the limit on how many concurrent sessions each user can have. The default is 100. You may want to set this to a small number (e.g. 5) for initial testing.
  • Confirm changes before deploy [Y/n]: Yes to deploy the solution.
  • Allow SAM CLI IAM role creation [Y/n]: Yes to allow creation of IAM role.
  • Disable rollback [Y/n]: Yes to disable rollback to check on any errors or exceptions.
  • Save arguments to configuration file [Y/n]: Yes to save the arguments for redeployment.
  • SAM configuration file [default.toml]: Enter a name to save SAM configuration.
  • SAM configuration environment [default]: Enter a name for the SAM configuration environment.

Note: If CreateCacheServer is set to false, the ElastiCache instance will not be created. If CreateCacheServer is enabled, a valid ElastiCacheLambdaSubnetIDs and ElastiCacheLambdaVPCID must be provided in the inputs. Otherwise, the ElastiCache instance cannot be created as Amazon ElastiCache must be deployed to the valid vpc and subnet(s).

If a AWS Secrets Manager VPC endpoint has been created prior to this sam deployment, make sure that the VPC endpoint covers the ElastiCacheLambdaVPCID and ElastiCacheLambdaSubnetIDs. If not, either delete the VPC endpoint prior to this deployment and let this same deployment to create a new one for you by set DeploySecretsManagerVPCEndpoint parameter to true, or manually creating a new VPC endpoint that covers the ElastiCacheLambdaVPCID and ElastiCacheLambdaSubnetIDs.

Set up user and password

Once you have deployed the cloud formation template, you can start creating your users in AWS Secrets Manager. Note that this solution template creates users that are unique to a specific AWS Transfer Family Endpoint (Server ID).

  1. In the AWS Secrets Manager console, create a new secret by choosing Store a new secret.
  2. Choose Other Type of secret.
  3. Create the following key-value pairs. The key names are case sensitive.
  4. Save the secret in the following format: serverid/username
Key - Password
Example Value - mySup3rS3cr3tPa55w0rd
Explanation: This password is used for SFTP and FTPS protocols

Key - Role
Example Value - arn:aws:iam::xxxxxxxxxxxx:role/AWSTransferAccessRole
Explanation: Use one of the Role ARNs you created for AWS Transfer users earlier. This will define what access the user has to S3

Optional:
Key - HomeDirectory
Example Value: /bucket/home/myhomedirectory
Explanation: The path to the user home directory. Not valid if HomeDirectoryDetails is used

Key - HomeDirectoryDetails
Example Value: [{"Entry": "/", "Target": "/ bucket/home/myhomedirectory"}]
Explanation: Logical folders mapping template. Not valid if HomeDirectory is used

Key - PublicKey
Example Value - ssh rsa public-key
Explanation: Comma separated list of public SSH keys (up to two keys)

Key – AcceptedIpNetwork
Example Value – 192.168.1.0/24
Explanation: CIDR range of allowed source IP address for the client

Key – MaxSessionLimit
Example Value – 100
Explanation: The max number of sessions allowed for this user. If this is not provided, the global default session limit is used. The global default session limit is located in the environment variable in the GetUserConfigLambda lambda function. For testing, you may want to set this to a small number (e.g. 5).
Example of the values in AWS Secrets Manager per user

Figure 3: Example of the values in AWS Secrets Manager per user

How the active session count is stored in Amazon ElastiCache

This solution relies on maintaining the correct session count in the AWS ElastiCache.

The Log in increment is managed inside the Lambda Function <StackName>-GetUserConfigLambda-. Once a user is authenticated, the function checks the current count against the maximum session limit. If a user exceeds the maximum limit, the function fails the Transfer server authentication request.

The Log out decrement is managed in a separate Lambda Function. This design takes into the consideration when a user disconnects from the session without explicitly exiting the session. (e.g. use the command ‘exit’ in the FTP/SFTP/FTPS session). This is an example of log events generated from the transfer server.

An example of log events generated from the transfer server

Figure 4: An example of log events generated from the transfer server

By default, CloudTrail is enabled on all AWS accounts when the account is created. When activity occurs in AWS Transfer Family, that activity is recorded in a CloudTrail event along with other AWS service events in Event history. The CloudFormation script in this blog post creates a Logging Group /aws/transfer/<AWS Transfer Server Id> to collect the Transfer Server Log and a subscription filter for the Disconnect lambda trigger. Every time a user logs out of the transfer server, an event is generated and collected. The event triggers a call to the Lambda function <StackName>-FTPSessionTrackingLambda- to decrement the session counter.

Example of the log groups in AWS CloudWatch

Figure 5: Example of the log groups in AWS CloudWatch

Using an in-memory data store to manage session count, Amazon ElastiCache allows session management to be highly scalable. The session is stored as a key-value pair with the user name as the key and the count as the value. You can set the TTL (Time-to-Live) for stale counters to be cleared off the cache server after a certain period of time. More information on Amazon ElastiCache TTL.

Key                    Value

Username       Integer

Testing your setup

The AWS Transfer Family API provides a function to test whether the external authentication is working as expected. Swap in your server-id, plus the user name and password that you entered in AWS Secrets Manager:

aws transfer test-identity-provider --server-id "s-xxxxxxxxxx" --user-name user1 --user-password password

If you are using source and protocol checks, you can also include these on the call:

aws transfer test-identity-provider --server-id "s-xxxxxxxxxx" --user-name 
charlie --user-password password –source-ip "192.168.1.1" –server-protocol "FTP"

For session tracking, there are 2 ways to test the feature as follows:

  1. Set the DefaultMaxSessionLimit to a small number (e.g. 5) and manually spin up a few instances of SFTP to test the limit. As it approaches the session limit, you will notice those instances fail to log into the Transfer Server.
  2. Another way to test this automatically is by running SFTP with sshpass as follows:
pswd=`cat passwordfile`

for i in {1..20} 
do 
     (sshpass -p "$pswd" sftp <user>@<server-id>.server.transfer.us-east-1.amazonaws.com  > ./ftp$i.log 2>&1 <<EOF
!echo running process $i
!sleep 5
EOF
     ) &
     echo process $i started
done

If you’re interested to interact directly with ElastiCache to see the count in real time, this article outlines steps to connect to the ElasticCache deployed with this solution. ElastiCache is used to store the session count per user.

Cleaning up

If you are done with the resources, do not forget to clean up and check for any permissions and IAM roles that are no longer required. Keep in mind that this includes the AWS Transfer Family endpoint that you deployed. You can delete the stack from the AWS CloudFormation console.

Conclusion

In this blog, we showed you how to limit the concurrent session per user with AWS Transfer Family to control the usage of the File Transfer server. With that, you now have a fully managed, highly available transfer service that can support thousands of users with fine-grained session control for SFTP, FTPS and FTP protocols.

In addition, the integration with the AWS Secrets Manager adds features to limit access by IP range and Max Session per user or server. Should you want to extend the features of AWS Transfer Family, this guide and associated AWS Lambda function code should provide you with a great framework to do so.

Now, you can control the resources used by each AWS Transfer Family server user through the number of concurrent sessions each user can initiate. This helps to avoid the situation where a where a single user consumes all the resources and connections on the server.

Thanks for reading this blog post. If you have any comments or questions, please do not hesitate to leave them in the comments section.

Scott Ma

Scott Ma

Scott is a Senior Solutions Architect at Amazon Web Services who specializes in architecting and building cloud native applications which enables customers to use the best practices in their cloud journey. He is a builder at heart, with a passion for Security and Machine Learning. In his spare time, he enjoys traveling, boating and spending time with family and friends.

Brandon Miller

Brandon Miller

Brandon is an Account Manager with AWS focused on helping earth intelligence and space manufacturing companies run their workloads in AWS. He has been in the IT field for 21 years, the last 10 years focused on migrating and supporting workloads in AWS. He aims to share his passion for technology and customer service with any team he works with. In his spare time, he loves ministry, movies, online gaming and spending time with his wife and 4 kids.