AWSTemplateFormatVersion: '2010-09-09' Description: This template creates an S3 bucket in the same region where the stack is launched and copy the Lambda functions code from original bucket to the new bucket. (qs-1qp7e9tkk) Parameters: QSS3BucketName: AllowedPattern: "^[0-9a-zA-Z]+([0-9a-zA-Z-]*[0-9a-zA-Z])*$" ConstraintDescription: S3 bucket name can include numbers, lowercase letters,uppercase letters, and hyphens (-). It cannot start or end with a hyphen (-). Default: ravpn-quickstart-test Description: Alphanumeric string which identifies the S3 bucket name for the QuickStart assets. It's the bucket to store the copy of the Quick Start assets if you decided to customize or extend them for your own use. Type: String QSS3KeyPrefix: AllowedPattern: "^[0-9a-zA-Z-/._]*$" ConstraintDescription: S3 key prefix can include numbers, lowercase letters, uppercaseletters, hyphens (-), and forward slash (/). Default: quickstart-cisco-asav-ravpn/ Description: Alphanumeric string which identifies the S3 key prefix used to simulate a folder for your copy of the Quick Start assets if you decided to customize or extend them for your own use. Type: String Resources: CopyObjects: Properties: ServiceToken: Fn::GetAtt: - CopyObjectsFunction - Arn DestBucket: Ref: LambdaZipsBucket Objects: - functions/packages/lambda.zip SourceBucket: Ref: QSS3BucketName Prefix: Ref: QSS3KeyPrefix Type: AWS::CloudFormation::CustomResource CopyObjectsFunction: Properties: Code: ZipFile: Fn::Join: - "\n" - - import json - import logging - import threading - import boto3 - import cfnresponse - '' - '' - 'def copy_objects(source_bucket, dest_bucket, prefix, objects):' - " s3 = boto3.client('s3')" - " for o in objects:" - " key = prefix + o" - " copy_source = {" - " 'Bucket': source_bucket," - " 'Key': key" - " }" - " s3.copy_object(CopySource=copy_source, Bucket=dest_bucket, Key=key)" - '' - '' - 'def delete_objects(bucket):' - " client = boto3.client('s3')" - ' print(("Collecting data from" + bucket))' - " paginator = client.get_paginator('list_object_versions')" - " result = paginator.paginate(Bucket=bucket)" - " objects = []" - " for page in result:" - " try:" - " for k in page['Versions']:" - " objects.append({'Key':k['Key'],'VersionId': k['VersionId']})" - " try:" - " for k in page['DeleteMarkers']:" - " version = k['VersionId']" - " key = k['Key']" - " objects.append({'Key': key,'VersionId': version})" - " except:" - " pass" - ' print("deleting objects")' - " client.delete_objects(Bucket=bucket, Delete={'Objects': objects})" - " # objects = []" - " except:" - " pass" - ' print("bucket already empty")' - '' - '' - '' - 'def timeout(event, context):' - " logging.error('Execution is about to time out, sending failure response to CloudFormation')" - " cfnresponse.send(event, context, cfnresponse.FAILED, {}, None)" - '' - '' - 'def handler(event, context):' - " # make sure we send a failure to CloudFormation if the function is going to timeout" - " timer = threading.Timer((context.get_remaining_time_in_millis() / 1000.00) - 0.5, timeout, args=[event, context])" - " timer.start()" - '' - " print(('Received event: %s' % json.dumps(event)))" - " status = cfnresponse.SUCCESS" - " try:" - " source_bucket = event['ResourceProperties']['SourceBucket']" - " dest_bucket = event['ResourceProperties']['DestBucket']" - " prefix = event['ResourceProperties']['Prefix']" - " objects = event['ResourceProperties']['Objects']" - " if event['RequestType'] == 'Delete':" - " delete_objects(dest_bucket)" - " else:" - " copy_objects(source_bucket, dest_bucket, prefix, objects)" - " except Exception as e:" - " logging.error('Exception: %s' % e, exc_info=True)" - " status = cfnresponse.FAILED" - " finally:" - " timer.cancel()" - " cfnresponse.send(event, context, status, {}, None)" - '' Description: Copies objects from a source S3 bucket to a destination S3 bucket Handler: index.handler Role: Fn::GetAtt: - CopyObjectsRole - Arn Runtime: python3.7 Timeout: 240 Type: AWS::Lambda::Function CopyObjectsRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' ManagedPolicyArns: - !Sub arn:${AWS::Partition}:iam::${AWS::Partition}:policy/service-role/AWSLambdaBasicExecutionRole Path: "/" Policies: - PolicyDocument: Statement: - Action: - s3:GetObject Effect: Allow Resource: - Fn::Sub: arn:${AWS::Partition}:s3:::${QSS3BucketName}/${QSS3KeyPrefix}* - Action: - s3:PutObject - s3:DeleteObject - s3:GetObject - s3:ListBucket - s3:ListBucketVersions - s3:DeleteObjectVersion - s3:GetObjectVersion - s3:GetBucketVersioning Effect: Allow Resource: - Fn::Sub: arn:${AWS::Partition}:s3:::${LambdaZipsBucket}/${QSS3KeyPrefix}* - Fn::Sub: arn:${AWS::Partition}:s3:::${LambdaZipsBucket} Version: '2012-10-17' PolicyName: object-copier Type: AWS::IAM::Role LambdaZipsBucket: Properties: Tags: [] VersioningConfiguration: Status: Enabled Type: AWS::S3::Bucket CleanUpS3Bucket: Properties: DestBucket: Ref: LambdaZipsBucket ServiceToken: Fn::GetAtt: - CleanUpS3BucketFunction - Arn Type: AWS::CloudFormation::CustomResource CleanUpS3BucketFunction: Properties: Code: ZipFile: Fn::Join: - "\n" - - import json - import logging - import threading - import boto3 - import cfnresponse - client = boto3.client('s3') - '' - '' - 'def delete_NonVersionedobjects(bucket):' - ' print(("Collecting data from" + bucket))' - " paginator = client.get_paginator('list_objects_v2')" - " result = paginator.paginate(Bucket=bucket)" - " objects = []" - " for page in result:" - " try:" - " for k in page['Contents']:" - " objects.append({'Key': k['Key']})" - ' print("deleting objects")' - " client.delete_objects(Bucket=bucket, Delete={'Objects': objects})" - " objects = []" - " except:" - " pass" - ' print("bucket is already empty")' - '' - 'def delete_versionedobjects(bucket):' - ' print(("Collecting data from" + bucket))' - " paginator = client.get_paginator('list_object_versions')" - " result = paginator.paginate(Bucket=bucket)" - " objects = []" - " for page in result:" - " try:" - " for k in page['Versions']:" - " objects.append({'Key':k['Key'],'VersionId': k['VersionId']})" - " try:" - " for k in page['DeleteMarkers']:" - " version = k['VersionId']" - " key = k['Key']" - " objects.append({'Key': key,'VersionId': version})" - " except:" - " pass" - ' print("deleting objects")' - " client.delete_objects(Bucket=bucket, Delete={'Objects': objects})" - " # objects = []" - " except:" - " pass" - ' print("bucket already empty")' - '' - '' - '' - 'def timeout(event, context):' - " logging.error('Execution is about to time out, sending failure response to CloudFormation')" - " cfnresponse.send(event, context, cfnresponse.FAILED, {}, None)" - '' - '' - 'def handler(event, context):' - " # make sure we send a failure to CloudFormation if the function is going to timeout" - " timer = threading.Timer((context.get_remaining_time_in_millis() / 1000.00) - 0.5, timeout, args=[event, context])" - " timer.start()" - '' - " print(('Received event: %s' % json.dumps(event)))" - " status = cfnresponse.SUCCESS" - " try:" - " dest_bucket = event['ResourceProperties']['DestBucket']" - " if event['RequestType'] == 'Delete':" - " CheckifVersioned = client.get_bucket_versioning(Bucket=dest_bucket)" - " print(CheckifVersioned)" - " if 'Status' in CheckifVersioned:" - " print(CheckifVersioned['Status'])" - ' print ("This is a versioned Bucket")' - " delete_versionedobjects(dest_bucket)" - " else:" - ' print("This is not a versioned bucket")' - " delete_NonVersionedobjects(dest_bucket)" - " else:" - ' print("Nothing to do")' - " except Exception as e:" - " logging.error('Exception: %s' % e, exc_info=True)" - " status = cfnresponse.FAILED" - " finally:" - " timer.cancel()" - " cfnresponse.send(event, context, status, {}, None)" - '' Description: Empty the S3 Bucket Handler: index.handler Role: Fn::GetAtt: - S3CleanUpRole - Arn Runtime: python3.7 Timeout: 240 Type: AWS::Lambda::Function S3CleanUpRole: Properties: AssumeRolePolicyDocument: Statement: - Action: sts:AssumeRole Effect: Allow Principal: Service: lambda.amazonaws.com Version: '2012-10-17' ManagedPolicyArns: - !Sub arn:${AWS::Partition}:iam::${AWS::Partition}:policy/service-role/AWSLambdaBasicExecutionRole Path: "/" Policies: - PolicyDocument: Statement: - Action: - s3:PutObject - s3:DeleteObject - s3:GetObject - s3:ListBucket - s3:ListBucketVersions - s3:DeleteObjectVersion - s3:GetObjectVersion - s3:GetBucketVersioning Effect: Allow Resource: - Fn::GetAtt: - LambdaZipsBucket - Arn - Fn::Sub: arn:${AWS::Partition}:s3:::* Version: '2012-10-17' PolicyName: Empty-bucket Type: AWS::IAM::Role Outputs: LambdaZipsBucket: Description: S3 Bucket for the Lambda Function Code Value: Ref: LambdaZipsBucket