{ "AWSTemplateFormatVersion": "2010-09-09", "Metadata": { "AWS::CloudFormation::Designer": { "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c": { "size": { "width": 60, "height": 60 }, "position": { "x": 30, "y": 60 }, "z": 0, "embeds": [] }, "a52902b8-f027-45a8-9151-3e56ced5fb42": { "size": { "width": 60, "height": 60 }, "position": { "x": 30, "y": 140 }, "z": 0, "embeds": [] }, "674a64fc-3703-4222-91b9-4878490489e2": { "size": { "width": 60, "height": 60 }, "position": { "x": 250, "y": 100 }, "z": 0, "embeds": [], "isassociatedwith": [ "5c314e8e-535b-4b09-8bb7-c089794a3829" ] }, "5c314e8e-535b-4b09-8bb7-c089794a3829": { "size": { "width": 60, "height": 60 }, "position": { "x": 250, "y": 210 }, "z": 0, "embeds": [] }, "3da9a376-afc1-4b37-add1-9cf0df20b0a0": { "size": { "width": 60, "height": 60 }, "position": { "x": 360, "y": 100 }, "z": 0, "embeds": [] }, "7fd11cc7-5574-44f3-99df-877b6f0f2a74": { "size": { "width": 60, "height": 60 }, "position": { "x": 130, "y": 60 }, "z": 0, "embeds": [], "isassociatedwith": [ "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c" ] }, "1d8a8e19-2661-44d4-99c0-4a2c88c8557d": { "size": { "width": 60, "height": 60 }, "position": { "x": 130, "y": 140 }, "z": 0, "embeds": [], "isassociatedwith": [ "a52902b8-f027-45a8-9151-3e56ced5fb42" ] }, "e29c9a81-85ad-4511-ab1e-018fe50f1573": { "size": { "width": 60, "height": 60 }, "position": { "x": 30, "y": 220 }, "z": 0, "embeds": [] }, "1388662c-85e1-4f6e-9b80-0f1888a6e07d": { "size": { "width": 60, "height": 60 }, "position": { "x": 130, "y": 220 }, "z": 0, "embeds": [], "isassociatedwith": [ "e29c9a81-85ad-4511-ab1e-018fe50f1573" ] }, "236600ec-46ca-4770-8d7c-61532a6d8c27": { "size": { "width": 60, "height": 60 }, "position": { "x": 30, "y": 300 }, "z": 0, "embeds": [] }, "454a6298-2f35-48d7-8cd5-3152d78a585b": { "size": { "width": 60, "height": 60 }, "position": { "x": 130, "y": 300 }, "z": 0, "embeds": [] } } }, "Resources": { "Blobs": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Fn::Join": [ "-", [ { "Ref": "OverleafEditorBucketPrefix" }, "blobs" ] ] }, "VersioningConfiguration": { "Status": "Enabled" }, "LifecycleConfiguration": { "Rules": [ { "NoncurrentVersionExpirationInDays": 90, "Status": "Enabled" } ] }, "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "ServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "ee78c12d-0d1e-4ca0-8fa9-ba02f49d071c" } } }, "Chunks": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Fn::Join": [ "-", [ { "Ref": "OverleafEditorBucketPrefix" }, "chunks" ] ] }, "VersioningConfiguration": { "Status": "Enabled" }, "LifecycleConfiguration": { "Rules": [ { "NoncurrentVersionExpirationInDays": 80, "Status": "Enabled" } ] }, "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "ServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "a52902b8-f027-45a8-9151-3e56ced5fb42" } } }, "APIUser": { "Type": "AWS::IAM::User", "Properties": { "Groups": [ { "Ref": "APIGroup" } ] }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "674a64fc-3703-4222-91b9-4878490489e2" } } }, "APIGroup": { "Type": "AWS::IAM::Group", "Properties": {}, "Metadata": { "AWS::CloudFormation::Designer": { "id": "5c314e8e-535b-4b09-8bb7-c089794a3829" } } }, "APIUserAccessKey": { "Type": "AWS::IAM::AccessKey", "Properties": { "UserName": { "Ref": "APIUser" } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "3da9a376-afc1-4b37-add1-9cf0df20b0a0" } } }, "BlobsPolicy": { "Type": "AWS::S3::BucketPolicy", "Properties": { "Bucket": { "Ref": "Blobs" }, "PolicyDocument": { "Id": "BlobsPolicy", "Version": "2012-10-17", "Statement": [ { "Sid": "BlobsPolicyAPIUser", "Action": [ "s3:GetObject", "s3:PutObject" ], "Effect": "Allow", "Resource": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "Blobs" }, "/*" ] ] }, "Principal": { "AWS": { "Fn::GetAtt": [ "APIUser", "Arn" ] } } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "7fd11cc7-5574-44f3-99df-877b6f0f2a74" } } }, "ChunksPolicy": { "Type": "AWS::S3::BucketPolicy", "Properties": { "Bucket": { "Ref": "Chunks" }, "PolicyDocument": { "Id": "ChunksPolicy", "Version": "2012-10-17", "Statement": [ { "Sid": "ChunksPolicyAPIUser", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Effect": "Allow", "Resource": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "Chunks" }, "/*" ] ] }, "Principal": { "AWS": { "Fn::GetAtt": [ "APIUser", "Arn" ] } } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "1d8a8e19-2661-44d4-99c0-4a2c88c8557d" } } }, "Zips": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Fn::Join": [ "-", [ { "Ref": "OverleafEditorBucketPrefix" }, "zips" ] ] }, "BucketEncryption": { "ServerSideEncryptionConfiguration": [ { "ServerSideEncryptionByDefault": { "SSEAlgorithm": "AES256" } } ] }, "LifecycleConfiguration": { "Rules": [ { "ExpirationInDays": 1, "Status": "Enabled" } ] }, "PublicAccessBlockConfiguration": { "BlockPublicAcls": true, "BlockPublicPolicy": true, "IgnorePublicAcls": true, "RestrictPublicBuckets": true } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "e29c9a81-85ad-4511-ab1e-018fe50f1573" } } }, "ZipsPolicy": { "Type": "AWS::S3::BucketPolicy", "Properties": { "Bucket": { "Ref": "Zips" }, "PolicyDocument": { "Id": "ZipsPolicy", "Version": "2012-10-17", "Statement": [ { "Sid": "ZipsPolicyAPIUser", "Action": [ "s3:GetObject", "s3:PutObject" ], "Effect": "Allow", "Resource": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "Zips" }, "/*" ] ] }, "Principal": { "AWS": { "Fn::GetAtt": [ "APIUser", "Arn" ] } } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "1388662c-85e1-4f6e-9b80-0f1888a6e07d" } } }, "Analytics": { "Type": "AWS::S3::Bucket", "Properties": { "BucketName": { "Fn::Join": [ "-", [ { "Ref": "OverleafEditorBucketPrefix" }, "analytics" ] ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "236600ec-46ca-4770-8d7c-61532a6d8c27" } } }, "AnalyticsPolicy": { "Type": "AWS::S3::BucketPolicy", "Properties": { "Bucket": { "Ref": "Analytics" }, "PolicyDocument": { "Id": "AnalyticsPolicy", "Version": "2012-10-17", "Statement": [ { "Sid": "AnalyticsPolicyAPIUser", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Effect": "Allow", "Resource": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "Analytics" }, "/*" ] ] }, "Principal": { "AWS": { "Fn::GetAtt": [ "APIUser", "Arn" ] } } }, { "Sid": "AnalyticsPolicyAPIUserBucketPerms", "Action": "s3:ListBucket", "Effect": "Allow", "Resource": { "Fn::Join": [ "", [ "arn:aws:s3:::", { "Ref": "Analytics" } ] ] }, "Principal": { "AWS": { "Fn::GetAtt": [ "APIUser", "Arn" ] } } } ] } }, "Metadata": { "AWS::CloudFormation::Designer": { "id": "454a6298-2f35-48d7-8cd5-3152d78a585b" } } } }, "Parameters": { "OverleafEditorBucketPrefix": { "Description": "Prefix for the S3 bucket names (e.g. production-overleaf-editor or staging-overleaf-editor)", "Type": "String" } }, "Outputs": { "APIUserAccessKey": { "Value": { "Ref": "APIUserAccessKey" } }, "APIUserSecretKey": { "Value": { "Fn::GetAtt": [ "APIUserAccessKey", "SecretAccessKey" ] } } } }