Uploading Data to AWS S3 Over a VPN: Ensuring Secure Transfers from On-Premise Servers
In this blog post, we’ll explore how organisations with strict security requirements can securely upload data to an Amazon S3 bucket over a VPN/Direct connect, ensuring that sensitive information never traverses the public internet.
The Challenge: Strict Security Requirements
Many organizations, particularly those handling sensitive or regulated data, need to adhere to stringent security policies. One such requirement is ensuring that data being uploaded from an on-premise server to cloud storage (like AWS S3) does not pass through the public internet. Instead, all communication must occur over a secure VPN connection. Additionally, organizations often enforce strict user access controls and bucket policies to limit data access to only approved IP addresses or corporate networks.
Key Requirements:
- No Data Traversing the Public Internet: The entire data upload process must occur within a secure, encrypted VPN tunnel/ over Direct Connect.
- User Controls & Access Restrictions: Only authorised users and devices from approved IP addresses can access the data in the S3 bucket.
- Enforced S3 Bucket Policies: Custom bucket policies need to be enforced to ensure access is limited to specific IP addresses or corporate networks.
Architecture
Let’s walk through the architecture setup for securely transferring data to AWS S3 over a VPN:
Prerequisites:
- Centralised Network in AWS: Ensure that a centralised network architecture is already in place within AWS, and that either a VPN tunnel or AWS Direct Connect is established between AWS and your corporate datacenter.
- Hybrid DNS Resolution: Hybrid DNS resolution should be configured using Amazon Route 53. This involves setting up inbound and outbound resolvers, as well as forwarding rules in your on-premise DNS, ensuring smooth resolution of AWS resources from your corporate network.
- Firewall Configuration: Proper firewall rules must be in place to allow traffic between your on-premise servers and AWS over the VPN.
- AWS CLI installed on source server.
- AWS IAM user credentials (Accesskey and Secret Key) is configured on source server.
Data Flow Overview
Once the s3 sync
command is initiated, the following steps outline how data securely flows from the on-premise server to the S3 bucket over a VPN:
- DNS Resolution: The source server uses the S3 bucket’s URL to resolve its corresponding IP address. The on-premise DNS server forwards this request to the Route 53 inbound resolver, following the pre-configured forwarding rules.
- Route 53 Resolver: The Route 53 inbound resolver, which is integrated with the VPC, resolves the request to the S3 interface endpoint’s IP address. This resolution is enabled by a private hosted zone that is attached to the VPC, ensuring that the S3 bucket is accessed via a private IP through the interface endpoint.
- Data Flow through VPN and TGW: Once the IP address is resolved, the data is transmitted through the VPN tunnel. The traffic passes through the Transit Gateway (TGW) for routing between the on-premise network and AWS infrastructure.
- Firewall Inspection: The traffic is inspected by the firewall, ensuring compliance with security rules before continuing the journey.
- Egress VPC and S3 Interface: After passing through the firewall, the traffic reaches the egress VPC and S3 interface endpoint. From there, it traverses the AWS core network infrastructure to reach the target S3 bucket.
- Central Network Account and S3 Bucket VPC: Notably, the VPCs in the central network account and the S3 bucket account do not need to be directly attached to the Transit Gateway. The private interface endpoint ensures that data flows securely and directly to S3 without the need for TGW attachment.
- Security Checks: Before the data is uploaded to the bucket, AWS performs checks such as user authentication, IAM permissions, and bucket policies to ensure the request is authorised.
IAM User Policy for Uploading Data to S3: Following Least Privilege Best Practices
Let’s take a look at the CFN template to deploy the resources required.
CloudFormation Template Overview:
This template creates the following resources:
- IAM User & Policy:
- Creates an IAM user with least-privileged access, granting only the necessary permissions for uploading files to an S3 bucket.
- The IAM user’s access key and secret key can be used in a source server to securely upload files to the bucket.
- S3 Bucket
- A highly secure S3 bucket for storing uploaded files.
- The bucket is encrypted using a Customer Managed Key (CMK) from AWS Key Management Service (KMS) for enhanced security.
- Bucket Policy:
- A strict bucket policy that applies the principle of least privilege.
- Explicitly denies access except for specified users and IP ranges.
- Allows access only from the provided Breakglass users and specified VPC endpoints (interface and gateway) to ensure secure connectivity.
Required Input Parameters:
iamuser
: The IAM username for upload access.S3BucketName
: The name of the S3 bucket.S3kmskey
: The KMS Key ID used to encrypt the bucket.Breakglassuser1
: The first breakglass (emergency access) IAM user.Breakglassuser2
: The second breakglass (emergency access) IAM user.S3InterfaceEndpointId
: The VPC interface endpoint ID for accessing S3.VPCGatewayEPId
: The VPC gateway endpoint ID for accessing S3.
⚠️ Caution:
Ensure that all input values are entered correctly, especially the IP addresses and IAM user details. Incorrect values can result in being locked out of the S3 bucket. If access is lost, only the breakglass users will have access to recover the bucket. In case of emergency, contact AWS Support for assistance.
#This cloudformation template deploys S3 bucket with restricted access make sure you supply correct values else you will be locked out of this bucket!!
#Create a S3bucket and programmatic user with a polciy to only upload files to s3 bucket and s3 bucket should have CMK
AWSTemplateFormatVersion: 2010-09-09
Description: Create a S3bucket and programmatic user with a polciy to only upload files to s3 bucket and s3 bucket should have CMK
Parameters:
iamuser:
Type: String
Description: IAM user for S3 bucket upload
S3InterfaceEndpointId:
Type: String
Description: S3InterfaceEndpointId in Network Account
S3BucketName:
Type: String
Description: S3BucketName
S3kmskey:
Type: String
Description: S3kmskey
Breakglassuser1:
Type: String
Description: Breakglassuser1 for emergency in case we locked out from S3 bucket
Breakglassuser2:
Type: String
Description: Breakglassuser2 Breakglassuser1 for emergency in case we locked out from S3 bucket
VPCGatewayEPId:
Type: String
Description: Vpc gateway EndpointId for S3 in s3 bucket account
Resources:
S3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref S3BucketName
#add encryption to s3 bucket using CMK
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: 'aws:kms'
KMSMasterKeyID: !Ref S3kmskey
VersioningConfiguration:
Status: Enabled
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: Name
Value: !Ref S3BucketName
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref S3Bucket
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- s3:*
Effect: Allow
Principal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/${Breakglassuser1}'
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/${Breakglassuser2}'
Resource:
- !Sub "arn:aws:s3:::${S3Bucket}"
- !Sub "arn:aws:s3:::${S3Bucket}/*"
- Action:
- s3:GetObject
- s3:ListBucket
Effect: Allow
Principal: "*"
Resource:
- !Sub "arn:aws:s3:::${S3Bucket}"
- !Sub "arn:aws:s3:::${S3Bucket}/*"
Condition:
IpAddress:
aws:SourceIp:
- "X.X.X.X/X" #Replace with IPs from Where S3 bucket can be accesed make sure you entere this correct
- "X.X.X.X/X" #Replace with IPs from Where S3 bucket can be accesed make sure you entere this correct
- Action:
- s3:*
Effect: Allow
Principal: "*"
Resource:
- !Sub "arn:aws:s3:::${S3Bucket}"
- !Sub "arn:aws:s3:::${S3Bucket}/*"
Condition:
StringEquals:
aws:sourceVpce:
- !Ref S3InterfaceEndpointId
- !Ref VPCGatewayEPId
- Action:
- s3:*
Effect: Deny
NotPrincipal:
AWS:
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/${Breakglassuser1}'
- !Sub 'arn:aws:iam::${AWS::AccountId}:user/${Breakglassuser2}'
Resource:
- !Sub "arn:aws:s3:::${S3Bucket}"
- !Sub "arn:aws:s3:::${S3Bucket}/*"
Condition:
NotIpAddress:
aws:SourceIp:
- "X.X.X.X/X" #replace this with IP address
- "X.X.X.X/X" #replace this with IP address
StringNotEquals:
aws:sourceVpce:
- !Ref S3InterfaceEndpointId #Interface ID
- !Ref VPCGatewayEPId #GatewayEndpointID if you would like to force it, but it does not allow transitive traffic
MyUser:
Type: AWS::IAM::User
Properties:
UserName: !Ref iamuser
MyMigUserPolicy:
Type: AWS::IAM::Policy
Properties:
PolicyName: AllowUploadToMyMigBucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- s3:PutObject
- s3:PutObjectAcl
- s3:List*
Resource:
- !GetAtt S3Bucket.Arn
- !Join
- ''
- - !GetAtt S3Bucket.Arn
- '/*'
Users:
- Ref: MyUser
Conclusion
The above approach ensures that all traffic flows through a VPN tunnel/ Direct connect, providing controlled and secure access to the S3 bucket. By implementing IP-based restrictions, even users with administrative privileges are denied access if they attempt to access the bucket from unauthorised IP addresses. Additionally, data uploads are restricted to occur only through the specified VPC S3 interface endpoint, further securing the flow of data and preventing access from unapproved sources.