Skip to content

Instantly share code, notes, and snippets.

@wparad
Created April 7, 2021 17:00
Show Gist options
  • Save wparad/406272534ae7e5dfb3d76779a5eb6b97 to your computer and use it in GitHub Desktop.
Save wparad/406272534ae7e5dfb3d76779a5eb6b97 to your computer and use it in GitHub Desktop.
Cloudformation template to log requests from CloudFront to S3 and trigger a Lambda to process them.
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Store and process user surveys",
"Parameters": {
"serviceName": {
"Type": "String",
"Description": "The name of the microservice"
},
"deploymentBucketName": {
"Type": "String",
"Description": "The bucket where deployment artifacts are kept"
},
"deploymentKeyName": {
"Type": "String",
"Description": "The location of the s3 lambda.zip file in the bucket"
},
"dnsName": {
"Type": "String",
"Default": "",
"Description": "The service DNS name."
}
},
"Resources": {
"LambdaFunction": {
"Type": "AWS::Lambda::Function",
"Properties": {
"FunctionName": { "Ref": "serviceName" },
"Description": "Lambda Function",
"Handler": "index.handler",
"Runtime": "nodejs12.x",
"TracingConfig": {
"Mode": "PassThrough"
},
"Code": {
"S3Bucket": { "Fn::Sub": "${deploymentBucketName}-${AWS::Region}" },
"S3Key": { "Ref": "deploymentKeyName" }
},
"MemorySize": 128,
"Timeout": 30,
"Role": { "Fn::GetAtt": ["LambdaRole", "Arn"] },
"Tags": [
{
"Key": "Service",
"Value": { "Ref": "serviceName" }
}
]
}
},
"LambdaFunctionVersion": {
"Type": "AWS::Lambda::Version",
"Properties": {
"FunctionName": { "Ref": "LambdaFunction" },
"Description": "Initial Production Deployed Version"
}
},
"ProductionAlias": {
"Type": "AWS::Lambda::Alias",
"Properties": {
"Description": "The production alias",
"FunctionName": { "Fn::GetAtt": ["LambdaFunction", "Arn"] },
"FunctionVersion": { "Fn::GetAtt": ["LambdaFunctionVersion", "Version"] },
"Name": "production"
}
},
"LambdaRole": {
"Type": "AWS::IAM::Role",
"Properties": {
"RoleName": { "Fn::Sub": "${serviceName}LambdaRole" },
"AssumeRolePolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [ "lambda.amazonaws.com" ]
},
"Action": [ "sts:AssumeRole" ]
}
]
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole",
"arn:aws:iam::aws:policy/AWSXrayWriteOnlyAccess"
],
"Policies": [
{
"PolicyName": "MicroservicePolicy",
"PolicyDocument": {
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DynamoDbWrite",
"Effect": "Allow",
"Action": "dynamodb:*",
"Resource": [
{ "Fn::Sub": "arn:aws:dynamodb:*:*:table/${serviceName}-*" }
]
},
{
"Sid": "SQSReader",
"Effect": "Allow",
"Action": "sqs:*",
"Resource": { "Fn::Sub": "arn:aws:sqs:*:*:${serviceName}-*" }
},
{
"Sid": "S3Reader",
"Effect": "Allow",
"Action": "s3:getObject",
"Resource": { "Fn::Sub": "${LogBucket.Arn}/*" }
}
]
}
}
],
"Path": "/"
}
},
"LogProcessingSQS": {
"Type": "AWS::SQS::Queue",
"Properties": {
"QueueName": { "Fn::Sub": "${serviceName}-LogProcessing-prod" },
"MessageRetentionPeriod": 1209600,
"VisibilityTimeout": 300,
"ReceiveMessageWaitTimeSeconds": 20
}
},
"LogProcessingEventSourceMapping": {
"Type": "AWS::Lambda::EventSourceMapping",
"Properties": {
"BatchSize": 10,
"Enabled": true,
"EventSourceArn": { "Fn::Sub": "${LogProcessingSQS.Arn}" },
"FunctionName": { "Ref": "ProductionAlias" }
}
},
"LogBucket": {
"Type": "AWS::S3::Bucket",
"Properties": {
"BucketName": { "Fn::Sub": "${dnsName}.logs" },
"AccessControl": "Private",
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": true,
"BlockPublicPolicy": true,
"IgnorePublicAcls": true,
"RestrictPublicBuckets": true
},
"LifecycleConfiguration": {
"Rules": [{
"Id": "Delete old objects",
"Status": "Enabled",
"AbortIncompleteMultipartUpload": { "DaysAfterInitiation": 30 },
"ExpirationInDays": 60
}]
},
"NotificationConfiguration": {
"QueueConfigurations": [
{
"Event": "s3:ObjectCreated:*",
"Queue": { "Fn::Sub": "${LogProcessingSQS.Arn}" }
}
]
},
"Tags": [
{
"Key": "Service",
"Value": { "Ref": "serviceName" }
}
]
}
},
"PermissionForLogBucketToPublishToSQSQueue2": {
"Type": "AWS::SQS::QueuePolicy",
"Properties": {
"PolicyDocument": {
"Id": "LogBucketQueuePolicy",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "LogBucketAllowPublishToSQS",
"Effect": "Allow",
"Principal": { "Service": "s3.amazonaws.com" },
"Action": ["SQS:SendMessage"],
"Resource": { "Fn::GetAtt": ["LogProcessingSQS", "Arn"] },
"Condition": { "ArnLike": { "aws:SourceArn": { "Fn::Sub": "arn:aws:s3:::${dnsName}.logs" } } }
}
]
},
"Queues": [{ "Ref": "LogProcessingSQS" }]
}
},
"CloudFrontDistribution": {
"Type": "AWS::CloudFront::Distribution",
"Properties": {
"DistributionConfig": {
"Aliases": [
{ "Fn::Sub": "${dnsName}" },
{ "Fn::Sub": "*.${dnsName}" }
],
"DefaultCacheBehavior": {
"AllowedMethods": ["GET", "HEAD", "OPTIONS", "PUT", "PATCH", "POST", "DELETE"],
"CachedMethods": ["GET", "HEAD", "OPTIONS"],
"Compress": true,
"OriginRequestPolicyId": "216adef6-5c7f-47e4-b989-5492eafa07d3",
"TargetOriginId": "Origin",
"ViewerProtocolPolicy": "redirect-to-https"
},
"Enabled": true,
"HttpVersion": "http2",
"Logging": {
"Bucket": { "Fn::GetAtt": ["LogBucket", "DomainName"] },
"IncludeCookies": false,
"Prefix": "CloudFrontAccessLogs/"
},
"PriceClass": "PriceClass_100",
"Origins": [
{
"Id": "Origin"
}
],
"ViewerCertificate": {
"AcmCertificateArn": "...",
"MinimumProtocolVersion": "TLSv1.2_2018",
"SslSupportMethod": "sni-only"
}
},
"Tags": [
{
"Key": "Service",
"Value": { "Ref": "serviceName" }
}
]
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment