AWS Transfer Family Migration
Migration Guide: FTP/FTPS/SFTP and AS2 Servers to AWS Transfer Family
Table of Contents
- Executive Summary
- Pre-Migration Assessment
- Architecture Planning
- Protocol-Specific Migration Guides
- 4.1 SFTP Migration
- 4.2 FTPS Migration
- 4.3 FTP Migration
- 4.4 AS2 Migration
- Identity Provider Configuration
- Testing and Validation
- Cutover Strategy
- Post-Migration Operations
- Troubleshooting
1. Executive Summary
This runbook provides a step-by-step guide for migrating existing file transfer servers (FTP, FTPS, SFTP, and AS2) to AWS Transfer Family. AWS Transfer Family is a fully managed service that enables file transfers over SFTP, FTPS, FTP, and AS2 directly into and out of Amazon S3 or Amazon EFS.
Benefits of Migration
• Fully managed infrastructure (no server patching or maintenance) • Native integration with AWS services (S3, EFS, CloudWatch, EventBridge) • Elastic scaling without capacity planning • Built-in high availability • Pay-per-use pricing model • Compliance support (HIPAA, PCI-DSS, SOC, FedRAMP)
2. Pre-Migration Assessment
2.1 Inventory Current Environment Document the following for each existing server:
| Item | Details | Notes |
|---|---|---|
| Server hostname/IP | ||
| Protocols in use | SFTP / FTPS / FTP / AS2 | |
| Number of users/partners | ||
| Authentication method | Password / SSH Key / Both | |
| Average daily transfer volume | GB/day | |
| Peak concurrent connections | ||
| File size range | Min/Max | |
| Storage backend | Local disk / NAS / SAN | |
| IP allowlisting by partners | Yes / No | Critical for cutover |
| DNS name used by partners | ||
| TLS certificates (FTPS) | Issuer / Expiry | |
| AS2 trading partners | Partner IDs | |
| Custom workflows/scripts | Pre/post processing | |
| Compliance requirements | HIPAA, PCI, etc. |
2.2 User Inventory
For each user, document:
| Username | Protocol | Auth Method | Home Directory | Permissions | IP Restrictions |
|---|
2.3 Network Dependencies
• [ ] Partners with IP allowlisting (will need Elastic IP for static IP)
• [ ] Firewall rules that reference current server IP
• [ ] VPN connections to the file transfer server
• [ ] DNS CNAME/A records pointing to current server
• [ ] Load balancer configurations
• [ ] Network ACLs or Security Groups
2.4 Data Flow Mapping
Document all automated processes that depend on file transfers:
| Process | Trigger | Source | Destination | Frequency | SLA |
| --- | --- | --- | --- | --- | --- |
3. Architecture Planning
3.1 Endpoint Type Selection
| Endpoint Type | Use Case | Accessibility | Static IP |
|---|---|---|---|
| PUBLIC | Internet-facing, no IP restriction needed | Internet | No (dynamic) |
| VPC with Internet Facing | Internet-facing with static IPs | Internet via EIP | Yes (Elastic IP) |
| VPC (Private) | Internal transfers only | Within VPC / VPN / Direct Connect | VPC Endpoint IPs |
Decision Matrix:
• Partners require a static IP to allowlist → VPC with Internet Facing (EIP) • No IP dependency and simplest setup → PUBLIC • Internal (VPN/Direct Connect) → VPC (Private)
3.2 Storage Backend Selection
| Backend | Best For | Considerations |
|---|---|---|
| Amazon S3 | Object storage, archival, data lake integration | No POSIX permissions, lifecycle policies available |
| Amazon EFS | Shared filesystem, POSIX compatibility needed | Supports NFS mount, maintains directory structure |
3.3 Identity Provider Selection
| Option | Best For | Complexity |
|---|---|---|
| Service Managed | Small user count, SSH key auth | Low |
| AWS Lambda | Custom auth logic, integration with existing directories | Medium |
| API Gateway + Lambda | Password auth with custom IdP | Medium-High |
| AWS Directory Service | Microsoft AD integration | Medium |
4. Protocol-Specific Migration Guides
4.1 SFTP Migration
4.1.1 Overview
SFTP (SSH File Transfer Protocol) runs over SSH on port 22. This is the most common protocol for secure file transfers.
4.1.2 Pre-Requisites
• [ ] SSH public keys for all users (if using key-based auth)
• [ ] User passwords stored securely (if using password auth)
• [ ] S3 bucket or EFS filesystem created
• [ ] IAM roles for Transfer Family and users
4.1.3 Step-by-Step Migration
Step 1: Create the Transfer Family Server
-
Navigate to AWS Transfer Family Console → Create server
-
Select protocol: SFTP
-
Choose Identity Provider:
-
Service Managed: For SSH key authentication
-
Custom Lambda: For password authentication or complex logic
-
Choose Endpoint Type based on Section 3.1
-
Choose Storage: S3 or EFS
-
Configure logging (CloudWatch structured logs recommended)
Step 2: Configure IAM Roles
Create a Transfer Family access role for each user/group:
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowS3Access", "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject", "s3:GetObjectVersion", "s3:GetBucketLocation" ], "Resource": [ "arn:aws:s3:::your-bucket-name/*" ] }, { "Sid": "AllowListBucket", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::your-bucket-name" } ] }
Step 3: Create Users
For Service Managed identity: 1. Add user with username matching current server 2. Set IAM role 3. Configure home directory (logical or physical mapping) 4. Add SSH public key(s)
Home Directory Mapping Example (Logical):
[ { "Entry": "/", "Target": "/your-bucket-name/home/${transfer:UserName}" } ]
Step 4: Migrate SSH Keys
• Export public keys from current server (typically in ~/.ssh/authorized_keys)
• Import into Transfer Family user configuration
• Format: ssh-rsa AAAA... user@host
Step 5: Test Connectivity
sftp -i private_key.pem username@server-id.server.transfer.region.amazonaws.com
4.1.4 SFTP-Specific Considerations
| Consideration | Details |
|---|---|
| Host key | Transfer Family generates a new host key. Partners will see a host key change warning. Communicate in advance. You can import your existing host key to avoid this. |
| Port | Always port 22 (cannot be changed) |
| Ciphers | Transfer Family supports a fixed set of ciphers. Verify compatibility with partner clients. |
| Banner | Custom banners can be configured via PreAuthenticationLoginBanner and PostAuthenticationLoginBanner |
| Session policy | Scope down permissions per session using session policies |
4.2 FTPS Migration
4.2.1 Overview
FTPS (FTP over TLS/SSL) uses TLS encryption on ports 21 (control) and passive data ports. Transfer Family supports both Explicit and Implicit FTPS.
4.2.2 Pre-Requisites
• [ ] TLS certificate imported into AWS Certificate Manager (ACM)
• [ ] Certificate must be in the same region as the Transfer Family server
• [ ] Certificate must be RSA 2048-bit (Transfer Family requirement)
• [ ] If using a custom domain, DNS configuration ready
• [ ] Passive port range awareness (Transfer Family manages this automatically)
4.2.3 Step-by-Step Migration
Step 1: Import TLS Certificate to ACM
If migrating an existing certificate:
aws acm import-certificate \ --certificate fileb://certificate.pem \ --private-key fileb://private-key.pem \ --certificate-chain fileb://certificate-chain.pem \ --region your-region
Or request a new certificate via ACM if using a custom domain.
Step 2: Create the Transfer Family Server
-
Select protocol: FTPS
-
Choose Identity Provider (same options as SFTP)
-
Choose Endpoint Type:
-
PUBLIC: Not available for FTPS — must use VPC endpoint
-
VPC with Internet Facing: For internet-accessible FTPS with EIP
-
VPC (Private): For internal FTPS
-
Attach the ACM certificate
-
Configure Security Policy (choose TLS version minimum)
Step 3: Configure Security Groups
For FTPS, the Security Group must allow:
| Port | Direction | Purpose |
|---|---|---|
| 21 | Inbound | FTP control channel |
| 8192-8200 | Inbound | Passive data channel (Transfer Family range) |
Important: Transfer Family uses passive port range 8192-8200 (not the traditional 1024-65535).
Step 4: Create Users
Same process as SFTP (Section 4.1.3, Step 3). Users can authenticate with: - Password (requires custom identity provider) - Certificate-based mutual TLS (not supported — use password)
Step 5: DNS Configuration
Point your custom domain CNAME to the Transfer Family VPC endpoint:
ftp.company.com → vpce-ID.vpce-svc-ID.region.vpce.amazonaws.com
Or if using Internet Facing with EIP, point to the Elastic IP.
Step 6: Test Connectivity
# Explicit FTPS curl --ftp-ssl --user username:password ftps://server-endpoint:21/ # Using lftp lftp -u username,password -e "set ftp:ssl-force true; ls; quit" server-endpoint
4.2.4 FTPS-Specific Considerations
| Consideration | Details |
|---|---|
| Implicit vs Explicit | Transfer Family supports both. Explicit is more common. |
| Passive ports | Fixed range 8192-8200 (communicate to partners for firewall rules) |
| PUBLIC endpoint | Not available for FTPS — must use VPC endpoint type |
| Certificate renewal | If using ACM-issued cert, renewal is automatic. For imported certs, plan manual renewal. |
| Security Policy | Choose TransferSecurityPolicy-2024-01 or newer for TLS 1.2+ |
| Active mode FTP | Not supported — only Passive mode |
4.3 FTP Migration
4.3.1 Overview
FTP (unencrypted) is supported by Transfer Family for backward compatibility. It should only be used within private networks where encryption is handled at the network layer (VPN, Direct Connect).
⚠️ Security Warning: FTP transmits data and credentials in plaintext. Use only within trusted networks. Migrate to SFTP or FTPS when possible.
4.3.2 Pre-Requisites
• [ ] VPC with private subnets (FTP is only available with VPC endpoint — not PUBLIC)
• [ ] Network-level encryption (VPN or Direct Connect) if traversing untrusted networks
• [ ] Security Groups configured
4.3.3 Step-by-Step Migration
Step 1: Create the Transfer Family Server
-
Select protocol: FTP
-
Choose Identity Provider:
-
Custom Lambda (recommended — password auth required for FTP)
-
API Gateway + Lambda
-
Endpoint Type: VPC (only option for FTP)
-
Internal or Internet Facing with EIP
-
Storage: S3 or EFS
Step 2: Configure Security Groups
| Port | Direction | Purpose |
|---|---|---|
| 21 | Inbound | FTP control channel |
| 8192-8200 | Inbound | Passive data channel |
Step 3: Identity Provider Setup
FTP requires password authentication. You must set up a custom identity provider:
• AWS Lambda function that validates credentials
• Can integrate with Parameter Store, Secrets Manager, LDAP, or external databases
• Return user role, home directory, and policy in response
Step 4: Create Users in Identity Provider
Store credentials in your chosen backend (e.g., Parameter Store):
/transfer/{server-id}/{username}
Value (JSON):
{ "Password": "hashed-or-encrypted-password", "Role": "arn:aws:iam::account-id:role/transfer-user-role", "HomeDirectoryType": "LOGICAL", "HomeDirectoryDetails": "[{\"Entry\": \"/\", \"Target\": \"/bucket/home/username\"}]", "Policy": "" }
Step 5: Test Connectivity
ftp server-vpc-endpoint-ip # Login with username and password
4.3.4 FTP-Specific Considerations
| Consideration | Details |
|---|---|
| Endpoint type | VPC only — PUBLIC not available |
| Authentication | Password only (no SSH keys) |
| Encryption | None — rely on network-layer encryption |
| Active mode | Not supported — Passive mode only |
| Migration path | Plan to migrate partners to SFTP/FTPS over time |
4.4 AS2 Migration
4.4.1 Overview
AS2 (Applicability Statement 2) is used for B2B EDI (Electronic Data Interchange) message exchange. It provides non-repudiation through MDN (Message Disposition Notifications) and uses digital signatures and encryption.
4.4.2 Pre-Requisites
• [ ] Trading partner AS2 IDs and certificates
• [ ] Your organization's AS2 ID
• [ ] Signing and encryption certificates (imported to ACM)
• [ ] Trading partner endpoint URLs (for outbound)
• [ ] S3 bucket for incoming messages
• [ ] Agreement on MDN type (Sync/Async) with each partner
4.4.3 Step-by-Step Migration
Step 1: Import Certificates
Import your signing and encryption certificates to ACM:
# Signing certificate aws acm import-certificate \ --certificate fileb://signing-cert.pem \ --private-key fileb://signing-key.pem \ --certificate-chain fileb://chain.pem \ --tags Key=Usage,Value=AS2-Signing # Encryption certificate aws acm import-certificate \ --certificate fileb://encryption-cert.pem \ --private-key fileb://encryption-key.pem \ --certificate-chain fileb://chain.pem \ --tags Key=Usage,Value=AS2-Encryption
Import trading partner certificates (public certificates only):
aws acm import-certificate \ --certificate fileb://partner-cert.pem \ --tags Key=Usage,Value=AS2-Partner-PartnerName
Step 2: Create the Transfer Family AS2 Server
-
Navigate to AWS Transfer Family Console → Create server
-
Select protocol: AS2
-
Endpoint Type: VPC with Internet Facing (recommended for B2B)
-
Configure Security Groups:
| Port | Direction | Purpose |
|---|---|---|
| 5080 | Inbound | AS2 HTTP messages |
Step 3: Create Local Profile
Your organization's AS2 identity: - AS2 ID: Your organization's AS2 identifier - Certificate: Your signing/encryption certificate from ACM
Step 4: Create Partner Profile
For each trading partner: - Partner AS2 ID - Partner certificate(s) from ACM
Step 5: Create Agreements (Inbound)
For each inbound trading partner connection: 1. Select Local Profile (your org) 2. Select Partner Profile 3. Configure S3 destination for incoming files 4. Set IAM access role 5. Configure MDN response (Signed/Unsigned, Sync/Async)
Step 6: Create Connectors (Outbound)
For each outbound connection to a trading partner: 1. Set partner AS2 endpoint URL 2. Select Local Profile 3. Select Partner Profile 4. Configure signing and encryption algorithms 5. Set MDN expectations
Step 7: Test with Trading Partners
# Send test file via connector aws transfer start-file-transfer \ --connector-id c-111111111111 \ --send-file-paths /bucket-name/outbound/test-file.edi
4.4.4 AS2-Specific Considerations
| Consideration | Details |
| --- | --- |
| Port | 5080 (not standard 80/443 — communicate to partners) |
| MDN | Synchronous MDN supported; Async MDN also supported |
| Algorithms | SHA-256 signing, AES-128/256 encryption recommended |
| Certificate rotation | Plan rotation well in advance — coordinate with all partners |
| Inbound URL | Format: https://server-id.server.transfer.region.amazonaws.com:5080 or via EIP |
| Message size | Max 50 MB per transfer |
| Monitoring | CloudWatch logs + EventBridge notifications for MDN failures |
4.5 Multi-Protocol Server Configuration
4.5.1 Overview
AWS Transfer Family supports enabling multiple protocols (SFTP, FTPS, FTP, AS2) on a single server. This simplifies management and reduces costs compared to running separate servers per protocol.
4.5.2 Supported Protocol Combinations
| Combination | Supported | Endpoint Type Required |
|---|---|---|
| SFTP + FTPS | ✅ Yes | VPC (Internet Facing or Private) |
| SFTP + FTP | ✅ Yes | VPC (Internet Facing or Private) |
| SFTP + FTPS + FTP | ✅ Yes | VPC (Internet Facing or Private) |
| SFTP only | ✅ Yes | PUBLIC, VPC, or VPC Internet Facing |
| AS2 + any other protocol | ❌ No | AS2 requires a dedicated server |
Important: If you need AS2 alongside SFTP/FTPS/FTP, you must create a separate Transfer Family server for AS2.
Important: PUBLIC endpoint type only supports SFTP. To enable FTPS or FTP, you must use a VPC endpoint.
4.5.3 When to Use Multi-Protocol
• Partners use different protocols (some SFTP, some FTPS)
• Migrating partners from FTP/FTPS to SFTP incrementally
• Need to support legacy FTP clients while offering SFTP for modern ones
• Want a single endpoint hostname and IP for all protocols
4.5.4 Step-by-Step: Enabling Multiple Protocols
Step 1: Plan Endpoint Type
Since FTPS and FTP require VPC endpoints, a multi-protocol server must use: - VPC with Internet Facing (for external partners) - VPC Private (for internal)
Step 2: Create the Server with Multiple Protocols
Console: 1. Create server → select multiple protocols (e.g., SFTP + FTPS) 2. Choose VPC endpoint type 3. Attach TLS certificate (required for FTPS)
CLI:
aws transfer create-server \ --protocols SFTP FTPS \ --endpoint-type VPC \ --endpoint-details \ VpcId=vpc-ID,SubnetIds=subnet-ID,subnet-yyyy,SecurityGroupIds=sg-ID,AddressAllocationIds=eipalloc-ID,eipalloc-yyyy \ --certificate arn:aws:acm:region:account:certificate/cert-id \ --identity-provider-type AWS_LAMBDA \ --function arn:aws:lambda:region:account:function:idp-function
Step 3: Configure Security Groups
For a multi-protocol server, open all required ports:
| Port | Protocol | Purpose |
|---|---|---|
| 22 | SFTP | SSH file transfer |
| 21 | FTPS / FTP | Control channel |
| 8192-8200 | FTPS / FTP | Passive data channel |
Step 4: Configure Identity Provider
For multi-protocol servers, the custom Lambda identity provider can differentiate behavior per protocol using the protocol field in the event:
def lambda_handler(event, context): protocol = event.get("protocol") # "SFTP", "FTPS", or "FTP" username = event.get("username") if protocol == "SFTP": # Return SSH key-based auth response return { "Role": "arn:aws:iam::account:role/sftp-role", "PublicKeys": ["ssh-rsa AAAA..."], "HomeDirectoryType": "LOGICAL", "HomeDirectoryDetails": json.dumps([{"Entry": "/", "Target": "/bucket/sftp-users/" + username}]) } elif protocol in ("FTPS", "FTP"): # Validate password and return response return { "Role": "arn:aws:iam::account:role/ftp-role", "HomeDirectoryType": "LOGICAL", "HomeDirectoryDetails": json.dumps([{"Entry": "/", "Target": "/bucket/ftp-users/" + username}]) }
Step 5: User Configuration
Users can be configured to access via specific protocols or all protocols: - Same username can work across protocols (if IdP supports it) - Different home directories per protocol (via Lambda logic above) - Different IAM roles per protocol for varied permissions
4.5.5 Multi-Protocol Considerations
| Consideration | Details |
|---|---|
| TLS Certificate | Required if FTPS is one of the protocols. Not needed for SFTP-only or FTP-only. |
| Identity Provider | Service Managed only works for SFTP (SSH keys). For FTPS/FTP password auth, custom Lambda is required. |
| Endpoint Type | Must be VPC if FTPS or FTP is included. PUBLIC only supports SFTP alone. |
| Host Key (SFTP) | Can import existing host key even on multi-protocol servers |
| Security Policy | Applies to FTPS TLS negotiation; separate SSH policies apply to SFTP |
| Adding protocols later | You can add/remove protocols from an existing server without recreating it |
| Billing | Charged per protocol enabled (per hour per protocol) |
4.5.6 Adding a Protocol to an Existing Server
# Add FTPS to an existing SFTP-only server aws transfer update-server \ --server-id s-111111111111 \ --protocols SFTP FTPS \ --certificate arn:aws:acm:region:account:certificate/cert-id # Note: You may need to update the endpoint type from PUBLIC to VPC first
⚠️ Warning: Changing endpoint type from PUBLIC to VPC requires server recreation (cannot be done in-place). Plan this as a new server migration if currently using PUBLIC.
5. Identity Provider Configuration
5.1 Service Managed (Simplest)
Best for: SFTP with SSH key auth and small number of users.
• Users created directly in Transfer Family
• SSH keys managed per user
• No password authentication support
5.2 Custom Lambda Identity Provider
Best for: Password auth, integration with existing user stores, dynamic user provisioning.
Architecture:
Client → Transfer Family → AWS Lambda → Parameter Store / Secrets Manager / LDAP / DB
Lambda Response Format:
{ "Role": "arn:aws:iam::account-id:role/transfer-role", "HomeDirectoryType": "LOGICAL", "HomeDirectoryDetails": "[{\"Entry\": \"/\", \"Target\": \"/bucket/prefix\"}]", "PublicKeys": ["ssh-rsa AAAA..."], "Policy": "session-policy-json" }
5.3 AWS Directory Service
Best for: Organizations using Microsoft Active Directory.
• Supports AD Connector or AWS Managed Microsoft AD
• Users authenticate with AD credentials
• Group-based access control
6. Testing and Validation
6.1 Functional Testing Checklist
| Test | Protocol | Status |
|---|---|---|
| User authentication (key) | SFTP | ☐ |
| User authentication (password) | SFTP/FTPS/FTP | ☐ |
| File upload (small file < 1MB) | All | ☐ |
| File upload (large file > 1GB) | All | ☐ |
| File download | All | ☐ |
| Directory listing | All | ☐ |
| Directory creation | All | ☐ |
| File deletion | All | ☐ |
| File rename/move | All | ☐ |
| Home directory isolation | All | ☐ |
| Concurrent connections | All | ☐ |
| AS2 message send | AS2 | ☐ |
| AS2 message receive | AS2 | ☐ |
| AS2 MDN validation | AS2 | ☐ |
| Session policy enforcement | All | ☐ |
| IP allowlist verification | All | ☐ |
6.2 Performance Testing
• [ ] Measure transfer speeds (compare with baseline from existing server)
• [ ] Test with maximum expected concurrent connections
• [ ] Test largest expected file size
• [ ] Verify timeout behavior for long-running transfers
6.3 Security Testing
• [ ] Verify users cannot access other users' directories
• [ ] Confirm TLS/cipher compatibility (FTPS)
• [ ] Validate SSH key rotation process
• [ ] Test failed authentication logging
• [ ] Verify CloudWatch logs capture all operations
6.4 Parallel Run
Run both old and new servers simultaneously:
-
Configure a subset of test users on Transfer Family
-
Have partners test with the new endpoint
-
Monitor for 1-2 weeks minimum
-
Compare transfer logs between old and new systems
-
Resolve any issues before full cutover
7. Cutover Strategy
7.1 Pre-Cutover Checklist
• [ ] All users tested and validated on Transfer Family
• [ ] All trading partners (AS2) confirmed connectivity
• [ ] Monitoring and alerting configured
• [ ] Rollback plan documented and tested
• [ ] Communication sent to all partners (48-72 hours advance notice minimum)
• [ ] DNS TTL lowered to 60 seconds (at least 48 hours before cutover)
7.2 Cutover Options
Option A: DNS Switchover (Recommended)
-
Partners use a DNS name (e.g., sftp.company.com)
-
Update DNS record to point to Transfer Family endpoint
-
Propagation happens within TTL window
-
Old server remains available as rollback
Option B: IP Preservation (VPC with EIP)
-
Allocate new Elastic IPs for Transfer Family
-
Communicate new IPs to partners who allowlist
-
Partners update firewall rules
-
Switch traffic
Option C: Import Host Key (SFTP — minimize disruption)
-
Export host key from existing server
-
Import into Transfer Family: aws transfer import-host-key
-
Partners won't see host key change warning
7.3 Cutover Day Procedure
| Time | Action | Owner |
|---|---|---|
| T-4h | Final sync of user data | Admin |
| T-2h | Verify all partners notified | PM |
| T-1h | Lower DNS TTL confirmed (should be done 48h ago) | Admin |
| T-0 | Update DNS / switch traffic | Admin |
| T+15m | Verify first connections on new server | Admin |
| T+30m | Monitor for errors in CloudWatch | Admin |
| T+1h | Confirm all active partners connected successfully | Admin |
| T+4h | Decision: proceed or rollback | Team |
| T+24h | Disable old server (keep for 7 days as rollback) | Admin |
| T+7d | Decommission old server | Admin |
7.4 Rollback Plan
If issues arise during cutover:
-
Revert DNS to original server IP
-
Or redirect traffic back via EIP reassociation
-
Investigate issue on Transfer Family
-
Schedule next cutover window
8. Post-Migration Operations
8.1 Monitoring Setup
CloudWatch Metrics to Monitor:
| Metric | Alarm Threshold | Description |
|---|---|---|
| FilesIn | Anomaly detection | Files received |
| FilesOut | Anomaly detection | Files sent |
| BytesIn | Anomaly detection | Data received |
| BytesOut | Anomaly detection | Data sent |
| InboundMessage (AS2) | = 0 for extended period | No messages received |
CloudWatch Logs:
• Enable structured logging on the Transfer Family server
• Set log retention policy (e.g., 30 days)
• Create metric filters for authentication failures
EventBridge Rules (Recommended):
• File upload completion → trigger downstream processing
• Authentication failure → alert security team
• AS2 MDN failure → alert operations team
8.2 Operational Procedures
| Procedure | Frequency | Owner |
|---|---|---|
| User onboarding/offboarding | As needed | Admin |
| SSH key rotation | Per security policy (90 days recommended) | Admin |
| Certificate renewal (FTPS/AS2) | Before expiry | Admin |
| Security policy review | Quarterly | Security |
| Access log review | Weekly/Monthly | Security |
| Capacity review | Monthly | Admin |
8.3 Cost Optimization
• Enable S3 lifecycle policies to move old files to cheaper storage classes
• Review and right-size EFS throughput mode if using EFS
• Consider S3 Intelligent-Tiering for unpredictable access patterns
• Monitor and disable unused protocols on the server
9. Troubleshooting
9.1 Common Issues
| Issue | Possible Cause | Resolution |
|---|---|---|
| Connection refused | Security Group not allowing port | Verify SG rules (22/21/5080) |
| Authentication failed | Wrong key format or expired credentials | Verify key format, check IdP logs |
| Host key changed (SFTP) | New server has different host key | Import old host key or have partner accept new |
| Passive mode timeout (FTPS/FTP) | Firewall blocking ports 8192-8200 | Update partner firewall rules |
| Permission denied on upload | IAM role missing s3:PutObject | Review user IAM role |
| Home directory not found | S3 prefix doesn't exist | Create the prefix or use Logical directory |
| AS2 MDN failure | Certificate mismatch or expired | Verify partner certificate in ACM |
| Slow transfers | Network path or S3 throttling | Check VPC routing, enable S3 Transfer Acceleration |
| Cannot list directory | Missing s3:ListBucket permission | Add ListBucket to IAM role |
9.2 Useful AWS CLI Commands
# List servers aws transfer list-servers # Describe server details aws transfer describe-server --server-id s-111111111111 # Test identity provider aws transfer test-identity-provider \ --server-id s-111111111111 \ --user-name testuser \ --server-protocol SFTP # List users aws transfer list-users --server-id s-111111111111 # Check structured logging aws transfer describe-server --server-id s-111111111111 \ --query 'Server.StructuredLogDestinations' # Import host key (SFTP) aws transfer import-host-key \ --server-id s-111111111111 \ --host-key-body file://host_key_rsa # Start AS2 file transfer aws transfer start-file-transfer \ --connector-id c-111111111111 \ --send-file-paths /bucket/path/file.edi
9.3 Log Locations
| Log Type | Location |
|---|---|
| Transfer Family structured logs | CloudWatch Logs: /aws/transfer/s-111111111111 |
| Lambda IdP logs | CloudWatch Logs: /aws/lambda/function-name |
| S3 access logs | S3 bucket (if enabled) |
| CloudTrail API calls | CloudTrail event history |
10. CloudFormation / IaC Examples
10.1 SFTP Server — Public Endpoint (Service Managed)
Simplest deployment: public SFTP with SSH key authentication.
AWSTemplateFormatVersion: '2010-09-09' Description: Transfer Family SFTP Server - Public Endpoint with Service Managed IdP Parameters: SftpUserName: Type: String Default: partner-upload Description: SFTP username SftpPublicKey: Type: String Description: SSH public key (ssh-rsa format) BucketName: Type: String Description: S3 bucket for file storage Resources: TransferBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName VersioningConfiguration: Status: Enabled TransferServer: Type: AWS::Transfer::Server Properties: EndpointType: PUBLIC IdentityProviderType: SERVICE_MANAGED Protocols: - SFTP LoggingRole: !GetAtt TransferLoggingRole.Arn StructuredLogDestinations: - !GetAtt TransferLogGroup.Arn TransferUser: Type: AWS::Transfer::User Properties: ServerId: !GetAtt TransferServer.ServerId UserName: !Ref SftpUserName Role: !GetAtt TransferUserRole.Arn HomeDirectoryType: LOGICAL HomeDirectoryMappings: - Entry: / Target: !Sub '/${BucketName}/home/${SftpUserName}' SshPublicKeys: - !Ref SftpPublicKey TransferUserRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: S3Access PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:DeleteObject - s3:GetObjectVersion Resource: !Sub 'arn:aws:s3:::${BucketName}/*' - Effect: Allow Action: s3:ListBucket Resource: !Sub 'arn:aws:s3:::${BucketName}' TransferLoggingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CloudWatchLogs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogDelivery - logs:GetLogDelivery - logs:UpdateLogDelivery - logs:DeleteLogDelivery - logs:ListLogDeliveries - logs:DescribeLogGroups - logs:DescribeResourcePolicies - logs:PutResourcePolicy Resource: '*' TransferLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/transfer/${AWS::StackName}' RetentionInDays: 30 Outputs: ServerEndpoint: Value: !Sub '${TransferServer.ServerId}.server.transfer.${AWS::Region}.amazonaws.com' ServerId: Value: !GetAtt TransferServer.ServerId
10.2 SFTP + FTPS Server — VPC with Internet Facing (Elastic IP)
Multi-protocol server with static IPs for partner allowlisting and custom Lambda IdP.
AWSTemplateFormatVersion: '2010-09-09' Description: Transfer Family Multi-Protocol (SFTP+FTPS) - VPC Internet Facing with EIP Parameters: VPCID: Type: AWS::EC2::VPC::Id Description: VPC for the Transfer Family server SubnetIDs: Type: List<AWS::EC2::Subnet::Id> Description: Subnets for the VPC endpoint (one per AZ) SecurityGroupID: Type: AWS::EC2::SecurityGroup::Id Description: Security Group allowing ports 22, 21, 8192-8200 EIPAllocationID1: Type: String Description: Elastic IP Allocation ID for first subnet EIPAllocationID2: Type: String Description: Elastic IP Allocation ID for second subnet CertificateArn: Type: String Description: ACM certificate ARN for FTPS TLS BucketName: Type: String Description: S3 bucket for file storage Resources: TransferBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName VersioningConfiguration: Status: Enabled TransferServer: Type: AWS::Transfer::Server Properties: EndpointType: VPC EndpointDetails: VpcId: !Ref VPCID SubnetIds: !Ref SubnetIDs SecurityGroupIds: - !Ref SecurityGroupID AddressAllocationIds: - !Ref EIPAllocationID1 - !Ref EIPAllocationID2 Protocols: - SFTP - FTPS Certificate: !Ref CertificateArn IdentityProviderType: AWS_LAMBDA IdentityProviderDetails: Function: !GetAtt IdPLambda.Arn LoggingRole: !GetAtt TransferLoggingRole.Arn StructuredLogDestinations: - !GetAtt TransferLogGroup.Arn SecurityPolicyName: TransferSecurityPolicy-2024-01 IdPLambda: Type: AWS::Lambda::Function Properties: FunctionName: !Sub '${AWS::StackName}-idp' Runtime: python3.12 Handler: index.lambda_handler Role: !GetAtt IdPLambdaRole.Arn Timeout: 30 Environment: Variables: SECRETS_REGION: !Ref 'AWS::Region' Code: ZipFile: | import os import json import boto3 region = os.environ['SECRETS_REGION'] client = boto3.client('ssm', region_name=region) def lambda_handler(event, context): server_id = event.get('serverId') username = event.get('username') protocol = event.get('protocol') password = event.get('password', '') print(f"Auth request: user={username}, protocol={protocol}, server={server_id}") # Lookup user in Parameter Store param_name = f"/transfer/{server_id}/{username}" try: resp = client.get_parameter(Name=param_name, WithDecryption=True) user_config = json.loads(resp['Parameter']['Value']) except client.exceptions.ParameterNotFound: print(f"User not found: {username}") return {} # Password validation for FTPS/FTP if protocol in ('FTPS', 'FTP'): stored_password = user_config.get(f'{protocol}Password', user_config.get('Password', '')) if password != stored_password: print("Password mismatch") return {} # Build response response = { "Role": user_config['Role'], "HomeDirectoryType": user_config.get('HomeDirectoryType', 'LOGICAL'), "HomeDirectoryDetails": user_config.get('HomeDirectoryDetails', '[]') } # Add SSH keys for SFTP if protocol == 'SFTP' and 'PublicKeys' in user_config: response['PublicKeys'] = user_config['PublicKeys'] return response IdPLambdaPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt IdPLambda.Arn Principal: transfer.amazonaws.com SourceArn: !GetAtt TransferServer.Arn IdPLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: SSMAccess PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - ssm:GetParameter Resource: !Sub 'arn:aws:ssm:${AWS::Region}:${AWS::AccountId}:parameter/transfer/*' TransferLoggingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CloudWatchLogs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogDelivery - logs:GetLogDelivery - logs:UpdateLogDelivery - logs:DeleteLogDelivery - logs:ListLogDeliveries - logs:DescribeLogGroups - logs:DescribeResourcePolicies - logs:PutResourcePolicy Resource: '*' TransferLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/transfer/${AWS::StackName}' RetentionInDays: 30 Outputs: ServerEndpoint: Value: !Sub '${TransferServer.ServerId}.server.transfer.${AWS::Region}.amazonaws.com' ServerId: Value: !GetAtt TransferServer.ServerId ElasticIPs: Description: Static IPs for partner allowlisting Value: !Sub 'EIP1: ${EIPAllocationID1}, EIP2: ${EIPAllocationID2}'
10.3 AS2 Server with Trading Partner Configuration
AWSTemplateFormatVersion: '2010-09-09' Description: Transfer Family AS2 Server with Trading Partner Agreement Parameters: VPCID: Type: AWS::EC2::VPC::Id SubnetIDs: Type: List<AWS::EC2::Subnet::Id> SecurityGroupID: Type: AWS::EC2::SecurityGroup::Id EIPAllocationID: Type: String Description: Elastic IP for AS2 inbound endpoint LocalAS2ID: Type: String Description: Your organization AS2 ID PartnerAS2ID: Type: String Description: Trading partner AS2 ID LocalCertificateArn: Type: String Description: ACM ARN for your signing/encryption certificate PartnerCertificateArn: Type: String Description: ACM ARN for partner public certificate InboundBucketName: Type: String Description: S3 bucket for received AS2 messages Resources: InboundBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref InboundBucketName VersioningConfiguration: Status: Enabled AS2Server: Type: AWS::Transfer::Server Properties: EndpointType: VPC EndpointDetails: VpcId: !Ref VPCID SubnetIds: !Ref SubnetIDs SecurityGroupIds: - !Ref SecurityGroupID AddressAllocationIds: - !Ref EIPAllocationID Protocols: - AS2 LoggingRole: !GetAtt AS2LoggingRole.Arn StructuredLogDestinations: - !GetAtt AS2LogGroup.Arn LocalProfile: Type: AWS::Transfer::Profile Properties: As2Id: !Ref LocalAS2ID ProfileType: LOCAL CertificateIds: - !Ref LocalCertificate PartnerProfile: Type: AWS::Transfer::Profile Properties: As2Id: !Ref PartnerAS2ID ProfileType: PARTNER CertificateIds: - !Ref PartnerCertificate LocalCertificate: Type: AWS::Transfer::Certificate Properties: Usage: SIGNING Certificate: !Ref LocalCertificateArn PartnerCertificate: Type: AWS::Transfer::Certificate Properties: Usage: ENCRYPTION Certificate: !Ref PartnerCertificateArn InboundAgreement: Type: AWS::Transfer::Agreement Properties: ServerId: !GetAtt AS2Server.ServerId LocalProfileId: !GetAtt LocalProfile.ProfileId PartnerProfileId: !GetAtt PartnerProfile.ProfileId BaseDirectory: !Sub '/${InboundBucketName}/inbound' AccessRole: !GetAtt AS2AccessRole.Arn Status: ACTIVE AS2AccessRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: S3Access PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - s3:PutObject - s3:GetObject - s3:GetObjectVersion Resource: !Sub 'arn:aws:s3:::${InboundBucketName}/*' - Effect: Allow Action: s3:ListBucket Resource: !Sub 'arn:aws:s3:::${InboundBucketName}' AS2LoggingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CloudWatchLogs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogDelivery - logs:GetLogDelivery - logs:UpdateLogDelivery - logs:DeleteLogDelivery - logs:ListLogDeliveries - logs:DescribeLogGroups - logs:DescribeResourcePolicies - logs:PutResourcePolicy Resource: '*' AS2LogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/transfer/${AWS::StackName}-as2' RetentionInDays: 30 Outputs: AS2Endpoint: Description: AS2 inbound endpoint URL Value: !Sub 'https://${AS2Server.ServerId}.server.transfer.${AWS::Region}.amazonaws.com:5080' ServerId: Value: !GetAtt AS2Server.ServerId
10.4 Private VPC Server (Internal)
For internal file transfers over VPN or Direct Connect.
AWSTemplateFormatVersion: '2010-09-09' Description: Transfer Family SFTP - Private VPC (internal access) Parameters: VPCID: Type: AWS::EC2::VPC::Id SubnetIDs: Type: List<AWS::EC2::Subnet::Id> SecurityGroupID: Type: AWS::EC2::SecurityGroup::Id BucketName: Type: String Resources: TransferBucket: Type: AWS::S3::Bucket Properties: BucketName: !Ref BucketName VersioningConfiguration: Status: Enabled TransferServer: Type: AWS::Transfer::Server Properties: EndpointType: VPC EndpointDetails: VpcId: !Ref VPCID SubnetIds: !Ref SubnetIDs SecurityGroupIds: - !Ref SecurityGroupID Protocols: - SFTP IdentityProviderType: SERVICE_MANAGED LoggingRole: !GetAtt TransferLoggingRole.Arn StructuredLogDestinations: - !GetAtt TransferLogGroup.Arn TransferLoggingRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: transfer.amazonaws.com Action: sts:AssumeRole Policies: - PolicyName: CloudWatchLogs PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - logs:CreateLogGroup - logs:CreateLogStream - logs:PutLogEvents - logs:CreateLogDelivery - logs:GetLogDelivery - logs:UpdateLogDelivery - logs:DeleteLogDelivery - logs:ListLogDeliveries - logs:DescribeLogGroups - logs:DescribeResourcePolicies - logs:PutResourcePolicy Resource: '*' TransferLogGroup: Type: AWS::Logs::LogGroup Properties: LogGroupName: !Sub '/aws/transfer/${AWS::StackName}' RetentionInDays: 30 Outputs: ServerId: Value: !GetAtt TransferServer.ServerId VPCEndpoint: Description: Connect via this VPC endpoint (accessible over VPN/DX) Value: !Sub '${TransferServer.ServerId}.server.transfer.${AWS::Region}.amazonaws.com'
10.5 EventBridge + Lambda Post-Upload Processing
Add this to any of the above templates to trigger automated processing when files arrive.
# Add to Resources section of any Transfer Family template FileUploadRule: Type: AWS::Events::Rule Properties: Name: !Sub '${AWS::StackName}-file-upload' Description: Triggers processing when a file upload completes EventPattern: source: - aws.transfer detail-type: - "SFTP Server File Upload Completed" detail: server-id: - !GetAtt TransferServer.ServerId Targets: - Arn: !GetAtt ProcessingLambda.Arn Id: processing-lambda FileUploadLambdaPermission: Type: AWS::Lambda::Permission Properties: Action: lambda:InvokeFunction FunctionName: !GetAtt ProcessingLambda.Arn Principal: events.amazonaws.com SourceArn: !GetAtt FileUploadRule.Arn ProcessingLambda: Type: AWS::Lambda::Function Properties: FunctionName: !Sub '${AWS::StackName}-file-processor' Runtime: python3.12 Handler: index.lambda_handler Role: !GetAtt ProcessingLambdaRole.Arn Timeout: 60 Code: ZipFile: | import json import boto3 import re s3 = boto3.client('s3') def lambda_handler(event, context): detail = event.get('detail', {}) file_path = detail.get('file-path', '') username = detail.get('username', '') server_id = detail.get('server-id', '') print(f"File received: path={file_path}, user={username}, server={server_id}") # Parse S3 bucket and key from file-path # Format: /<bucket-name>/<key> match = re.match(r'^/([^/]+)/(.+)$', file_path) if not match: print(f"Could not parse file path: {file_path}") return {'statusCode': 400} bucket = match.group(1) key = match.group(2) print(f"Processing: bucket={bucket}, key={key}") # Add your processing logic here # Example: copy to processed folder, trigger workflow, notify, etc. return {'statusCode': 200, 'body': f'Processed {key}'} ProcessingLambdaRole: Type: AWS::IAM::Role Properties: AssumeRolePolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Principal: Service: lambda.amazonaws.com Action: sts:AssumeRole ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: S3Access PolicyDocument: Version: '2012-10-17' Statement: - Effect: Allow Action: - s3:GetObject - s3:PutObject - s3:CopyObject Resource: !Sub 'arn:aws:s3:::${BucketName}/*'
10.6 Security Group Template (Reference)
Reusable Security Group for Transfer Family multi-protocol deployments.
TransferFamilySecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Security Group for AWS Transfer Family Server
VpcId: !Ref VPCID
SecurityGroupIngress:
# SFTP
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Description: SFTP access
# FTP/FTPS control channel
- IpProtocol: tcp
FromPort: 21
ToPort: 21
CidrIp: 0.0.0.0/0
Description: FTP/FTPS control channel
# FTP/FTPS passive data channel
- IpProtocol: tcp
FromPort: 8192
ToPort: 8200
CidrIp: 0.0.0.0/0
Description: FTP/FTPS passive data ports
# AS2
- IpProtocol: tcp
FromPort: 5080
ToPort: 5080
CidrIp: 0.0.0.0/0
Description: AS2 inbound messages
Tags:
- Key: Name
Value: !Sub '${AWS::StackName}-transfer-sg'
Appendix A: Security Policy Comparison
| Policy Name | Min TLS | Use Case |
|---|---|---|
| TransferSecurityPolicy-2024-01 | TLS 1.2 | Recommended default |
| TransferSecurityPolicy-2023-05 | TLS 1.2 | Previous default |
| TransferSecurityPolicy-FIPS-2024-01 | TLS 1.2 | FIPS compliance required |
| TransferSecurityPolicy-PQ-SSH-2023-04 | N/A | Post-quantum SSH |
Appendix B: Supported Ciphers and Key Exchange Algorithms
Refer to the latest AWS documentation: https://docs.aws.amazon.com/transfer/latest/userguide/security-policies.html
Appendix C: Pricing Considerations
| Component | Pricing Model |
|---|---|
| Server endpoint | Per hour (while enabled) |
| Data transfer (upload) | Per GB |
| Data transfer (download) | Per GB |
| AS2 messages | Per message |
| SFTP connectors | Per connector + per file |
Tip: Stop the Transfer Family server during off-hours if transfers are batch-scheduled to reduce hourly costs. Use aws transfer stop-server and aws transfer start-server.
- Language
- English
