How to upload a file from AWS S3 bucket to FTP server using AWS Python Lambda.
I gone through a requirement recently to connect the FTP server using AWS Lambda function and uploading the s3 bucket object to the FTP. Also this process should be automated , when the object is uploaded successfully to s3, it should automatically copied to the FTP server.
In addition to that for security reasons, I have created the MD5 hash of the zip file and stored in FTP with the ZIP file, so user can validate the hash of the ZIP when using it.
Below is the lambda Function code:
from io import BytesIO,StringIO
from ftplib import FTP
from hashlib import md5
import boto3
import os
import sys
BUCKET_KEY = "files/test.zip"
ENVIRONMENT = os.environ["ENVIRONMENT"]
FTP_SERVER = os.environ["FTP_SERVER"]
FTP_FILE_PATH = os.environ["FTP_FILE_PATH"]
BUCKET_NAME = os.environ["METADATA_EXPORTS_BUCKET"]
FTP_USERNAME = os.environ["FTP_USER"]
FTP_PASSWORD = os.environ["FTP_PASSWORD"]
def lambda_handler(event, context)
try:
ftp = FTP(FTP_SERVER)
ftp.login(FTP_USERNAME, FTP_PASSWORD)
ftp.dir()
ftp.cwd(FTP_FILE_PATH)
s3_resource = boto3.resource('s3')
zip_obj = s3_resource.Object(bucket_name=BUCKET_NAME, key=BUCKET_KEY)
buffer = BytesIO(zip_obj.get()["Body"].read())
ftp.storbinary('STOR test.zip', buffer)
md5sum = md5(buffer.getbuffer())
hexaDigestmd5Sum = md5sum.hexdigest()
print(hexaDigestmd5Sum)
md5Sum = BytesIO()
md5Sum.write(hexaDigestmd5Sum.encode())
md5Sum.seek(0)
ftp.storlines('STOR test.md5', md5Sum)
except Exception as E:
print("Excepton occured while connecting to FTP::::", E)
Cloud formation for automated way to copy file to FTP just when object is successfully uploaded to S3 bucket:
FtpCopyFilesFunction:
Type: AWS::Serverless::Function
Properties:
Handler: ftp-connector.lambda_handler
Layers:
- !Ref TempConversionDepLayer
Runtime: python3.8
CodeUri: src/lambda-functions/
Role: !GetAtt FtpCopyFilesFuntionRole.Arn
Timeout: 120
MemorySize: 1024
Environment:
Variables:
ENVIRONMENT: #PUT VALUE
AWS_REGION_KEY: !Ref AWS::Region
METADATA_EXPORTS_BUCKET: # PUT S3 BUCKET
FTP_SERVER: #PUT VALUE
FTP_FILE_PATH: #PUT VALUE
FTP_USER: #PUT VALUE
FTP_PASSWORD: #PUT VALUE
FtpCopyFilesFunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${FtpCopyFilesFunction}
RetentionInDays: 7
FtpCopyFilesFuntionRole:
Type: AWS::IAM::Role
Properties:
RoleName: ftp-copy-files-funtion-role
AssumeRolePolicyDocument:
Statement:
- Effect: Allow
Principal:
Service: [lambda.amazonaws.com]
Action: ['sts:AssumeRole']
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
- arn:aws:iam::aws:policy/AmazonS3FullAccess
PermissionForEventsToInvokeFTPLambda:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !Ref FtpCopyFilesFunction
Action: lambda:InvokeFunction
Principal: events.amazonaws.com
EventRuleToCopyInFTP:
Type: AWS::Events::Rule
Properties:
Description: EventRule
State: ENABLED
EventPattern:
source:
- aws.s3
detail:
eventSource:
- s3.amazonaws.com
eventName:
- CopyObject
- PutObject
- CompleteMultipartUpload
- RestoreObject
requestParameters:
bucketName:
- # PUT S3 BUCKET
key:
- prefix: 'files/test.zip'
Targets:
- Arn: !GetAtt FtpCopyFilesFunction.Arn
Id: FtpCopyFilesFunctionTarget