Transfer Family (SFTP / FTPS)
SFTP Port - 22 FTP(S) Port - 21
Create a VPC
- Create a VPC
- Create Subnets (Public); need at least one
- Create internet gateway
- Security Group must allow the following rules
Policy to access S3 Bucket
There are two steps here to create a "Scope-down" policy to only allow users access to their home directory
1. Create an IAM Role
This step will create a role that allows allows read and write access to a specific Amazon S3 bucket. This IAM role CANNOT containe the AWS Transfer variables (i.e. ${transfer:XXXXXX}), those can only be used in the next step.
{
"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/*"]
}
]
}
2. Further scope-down Policy
The previous step allows users to acces the bucket, and do various actions. Only that must exisit with the IAM Role policy.
For a custom authorizer, we can now additionally pass down a scope-down policy to limit the users access to specific directories.
Only the below extra attached policy is able to resolve the transfer service variables
import {PolicyDocument} from 'aws-lambda'
const bucketArn = process.env.BUCKET_ARN || ''
const roleArn = process.env.TRADING_PARTNER_ROLE_ARN || ''
const bucketName = process.env.BUCKET_NAME || ''
type AuthResponse = {
Role: string
HomeDirectory?: string
Policy: string
HomeDirectoryType?: string
HomeDirectoryDetails?: string
PublicKeys?: string[]
}
type PolicyParameters = {
username: string
effect?: string
resource?: string
context?: any
}
function directoryMap(username) {
return [
{
Entry: '/',
Target: '/' + bucketName + '/' + username
}
]
}
// // IMPORTANT NOTE: Policy parameter must be a string, it doesn’t work with an object type.
export const generatePolicy = ({username, effect, resource, context}: PolicyParameters) => {
const authResponse: AuthResponse = {
Role: roleArn, // ARN of the IAM Role that contains the policy used to provide the user access to your S3 bucket.
Policy: JSON.stringify(userPolicy),
HomeDirectoryType: 'LOGICAL',
HomeDirectoryDetails: JSON.stringify(directoryMap(username))
}
return authResponse
}
const userPolicy: PolicyDocument = {
Version: '2012-10-17',
Statement: [
{
Sid: 'AllowListingOfUserFolder',
Action: ['s3:ListBucket', 's3:GetBucketLocation'],
Effect: 'Allow',
Resource: [bucketArn],
Condition: {
StringLike: {
's3:prefix': ['${transfer:UserName}/*', '${transfer:UserName}']
}
}
},
{
Sid: 'HomeDirObjectAccess',
Effect: 'Allow',
Action: [
's3:PutObject',
's3:GetObject',
's3:DeleteObject',
's3:DeleteObjectVersion',
's3:GetObjectVersion',
's3:GetObjectACL',
's3:PutObjectACL'
],
Resource: 'arn:aws:s3:::' + bucketName + '/${transfer:UserName}/*'
},
{
Sid: 'DenyMkdir',
Action: ['s3:PutObject'],
Effect: 'Deny',
Resource: `${bucketArn}/*/`
}
]
}
So when our authorizer returns a response to AWS Transfer, it will supply the role for the user which gives the user permission to access the S3 bucket, and then the additional policy we provide in the response limits the user's access to only their home folder.
Copied from AWS Docs:
- The transfer:HomeBucket parameter is replaced with the first component of HomeDirectory.
- The transfer:HomeFolder parameter is replaced with the remaining portions of the HomeDirectory parameter.
- The transfer:HomeDirectory parameter has the leading forward slash (/) removed so that it can be used as part of an S3 Amazon Resource Name (ARN) in a Resource statement.
For example, assume that the HomeDirectory parameter that is configured for the transfer user is /home/bob/amazon/stuff/.
- transfer:HomeBucket is set to /home.
- transfer:HomeFolder is set to /bob/amazon/stuff/.
- transfer:HomeDirectory becomes home/bob/amazon/stuff/.
See here for details on user policies: https://docs.aws.amazon.com/transfer/latest/userguide/users-policies.html
Logical directories
Building the folder structure that you want for your users is easily done using logical directories. Each logical directory is an object with two fields: Entry and Target. The Entry is the name of the folder that the user will see and the Target is the S3 folder path.
https://aws.amazon.com/blogs/storage/simplify-your-aws-sftp-structure-with-chroot-and-logical-directories/ https://github.com/aws-samples/transfer-for-sftp-logical-directories
Another way: Key: HomeDirectoryDetails Value: [{"Entry": "/pics", "Target": "/bucket1/pics"}, {"Entry": "/reporting", "Target": "/bucket2/path/reporting"}] Remember when I mentioned the HomeDirectoryType=LOGICAL setting? This is automatically included in the response header by the AWS Lambda integration when it finds the HomeDirectoryDetails key in the user config.
You can't use Transfer variable except UserName with Logical
From this Forum question: https://forums.aws.amazon.com/message.jspa?messageID=882611 "As of now, we only support ${transfer:Username} variable when using a scopedown policy in combination with Logical Directories. The reason being that multiple mappings(Entry, Target values) can be provided when using Logical Directories and we would not be able to pass all the values to a single ${transfer:Home*} variable. Also, when using Logical Directories, the User will be mapped to the specified directory and therefore you could skip the option of using a scopedown policy to restrict access to the HomeDirectory. "
"TLS resumption"
Error from FileZilla:
"This server does not support TLS session resumption on the data connection. TLS session resumption on the data connection is an important security feature to protect against data connection stealing attacks. If you continue, transferred files may be intercepted or their contents replaced by an attacker."
https://www.ibexlabs.com/aws-transfer-for-sftp-explained/
Detailed AWS docs
https://docs.aws.amazon.com/transfer/latest/userguide/transferfamily-ug.pdf
Useful links:
Architecture diagram: https://www.proud2becloud.com/managing-an-amazon-s3-bucket-via-sftp-using-aws-transfer-family/
Final Working Setup
AWS Transfer Dashboard
AWS Transfer Server Details
VPC Dash
VPC Details
VPC Security Groupgs
VPC Subnets
Subnet Detail
Subnet Route Table
Subnet: Network ACL, Rules
Route Table
SG Inbound Rules
SG Outbound Rules
Network Interface