Skip to content

Instantly share code, notes, and snippets.

@latesr
Last active June 16, 2020 14:31
Show Gist options
  • Save latesr/a5f41e195d4d6897c6bd51c724f9ff18 to your computer and use it in GitHub Desktop.
Save latesr/a5f41e195d4d6897c6bd51c724f9ff18 to your computer and use it in GitHub Desktop.
AWS cdk for V1 bucket replication that propagates soft deletes
//References:
//For permissions required for replication:
// https://docs.aws.amazon.com/AmazonS3/latest/dev/setting-repl-config-perm-overview.html
//To understand delete propagation and the differences between V1 and V2 replication:
// https://aws.amazon.com/blogs/storage/managing-delete-marker-replication-in-amazon-s3/
//
//Summary:
//This creates:
// 1) Two private buckets (archive and replica)
// 2) A role with a policy supporting replication from archive to replica
// 3) A V1 replication configuration that allows the propogation of 'soft-deletes'
import * as cdk from '@aws-cdk/core';
import {RemovalPolicy} from '@aws-cdk/core';
import * as s3 from '@aws-cdk/aws-s3';
import * as iam from '@aws-cdk/aws-iam';
import {BlockPublicAccess} from "@aws-cdk/aws-s3";
export interface ReplicationRoleProps {
srcBucket: s3.Bucket;
dstBucket: s3.Bucket;
}
export class ReplicationRole extends iam.Role {
constructor(scope: cdk.Construct, id: string, props: ReplicationRoleProps) {
super(scope, id, {assumedBy: new iam.ServicePrincipal('s3.amazonaws.com')});
this.addToPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:GetReplicationConfiguration',
's3:ListBucket',
],
resources: [props.srcBucket.bucketArn],
}));
this.addToPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:GetObjectVersion',
's3:GetObjectVersionAcl',
's3:GetObjectVersionTagging'
],
resources: [props.srcBucket.bucketArn + '/*'],
}));
this.addToPolicy(new iam.PolicyStatement({
effect: iam.Effect.ALLOW,
actions: [
's3:ReplicateObject',
's3:ReplicateDelete',
's3:ReplicateTags',
],
resources: [props.dstBucket.bucketArn + '/*'],
}));
}
}
export class S3ReplicaStack extends cdk.Stack {
constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
super(scope, id, props);
const replica = new s3.Bucket(this, 'replica', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: RemovalPolicy.DESTROY,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
});
const archive = new s3.Bucket(this, 'archive', {
versioned: true,
encryption: s3.BucketEncryption.S3_MANAGED,
removalPolicy: RemovalPolicy.DESTROY,
blockPublicAccess: BlockPublicAccess.BLOCK_ALL,
});
const role = new ReplicationRole(this, 'MyReplicationRole', {srcBucket: archive, dstBucket: replica});
const cfnArchive = archive.node.defaultChild as s3.CfnBucket;
cfnArchive.replicationConfiguration = {
role: role.roleArn,
rules: [
{
status: "Enabled",
id: "ReplicationRule",
prefix: "",
destination: {
bucket: replica.bucketArn,
storageClass: "ONEZONE_IA",
}
}
]
};
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment