Skip to content

Instantly share code, notes, and snippets.

@ipmb
Created February 3, 2021 16:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ipmb/fb79a061ae071e6a09417cd1ddac4b5e to your computer and use it in GitHub Desktop.
Save ipmb/fb79a061ae071e6a09417cd1ddac4b5e to your computer and use it in GitHub Desktop.
Snippet of Cloudformation template to enable load balancer logging
{
"Mappings": {
"LBAccountId": {
"af-south-1": {
"AccountId": "098369216593"
},
"ap-east-1": {
"AccountId": "754344448648"
},
"ap-northeast-1": {
"AccountId": "582318560864"
},
"ap-northeast-2": {
"AccountId": "600734575887"
},
"ap-northeast-3": {
"AccountId": "383597477331"
},
"ap-south-1": {
"AccountId": "718504428378"
},
"ap-southeast-1": {
"AccountId": "114774131450"
},
"ap-southeast-2": {
"AccountId": "783225319266"
},
"ca-central-1": {
"AccountId": "985666609251"
},
"eu-central-1": {
"AccountId": "054676820928"
},
"eu-north-1": {
"AccountId": "897822967062"
},
"eu-south-1": {
"AccountId": "635631232127"
},
"eu-west-1": {
"AccountId": "156460612806"
},
"eu-west-2": {
"AccountId": "652711504416"
},
"eu-west-3": {
"AccountId": "009996457667"
},
"me-south-1": {
"AccountId": "076674570225"
},
"sa-east-1": {
"AccountId": "507241528517"
},
"us-east-1": {
"AccountId": "127311923021"
},
"us-east-2": {
"AccountId": "033677994240"
},
"us-west-1": {
"AccountId": "027434742980"
},
"us-west-2": {
"AccountId": "797873946194"
}
}
},
"Resources": {
"EmptyLoadBalancerLogsBucketCustomResource": {
"Properties": {
"BucketName": {
"Ref": "LoadBalancerLogsBucket"
},
"ServiceToken": {
"Fn::GetAtt": [
"EmptyLoadBalancerLogsBucketCustomResourceLambdaFunction",
"Arn"
]
}
},
"Type": "AWS::CloudFormation::CustomResource"
},
"EmptyLoadBalancerLogsBucketCustomResourceLambdaFunction": {
"Properties": {
"Code": {
"ZipFile": "import logging\n\nimport boto3\nimport cfnresponse\n\nlog = logging.getLogger(__name__)\nlog.setLevel(logging.INFO)\n\n\ndef empty_bucket(name: str):\n s3 = boto3.resource(\"s3\")\n bucket = s3.Bucket(name)\n log.info(\"Emptying S3 bucket '%s'\", name)\n bucket.objects.delete()\n bucket.object_versions.delete()\n\n\ndef lambda_handler(event: dict, context) -> None:\n bucket_name = None\n status = cfnresponse.SUCCESS\n if \"BucketName\" not in event[\"ResourceProperties\"]:\n log.error(\"BucketName not provided in ResourceProperties\")\n status = cfnresponse.FAILED\n elif event[\"RequestType\"] == \"Update\":\n if (\n event[\"ResourceProperties\"][\"BucketName\"]\n != event[\"OldResourceProperties\"][\"BucketName\"]\n ):\n bucket_name = event[\"OldResourceProperties\"][\"BucketName\"]\n elif event[\"RequestType\"] == \"Delete\":\n bucket_name = event[\"ResourceProperties\"][\"BucketName\"]\n else:\n log.debug(\"No action needed.\")\n\n if bucket_name:\n try:\n empty_bucket(bucket_name)\n status = cfnresponse.SUCCESS\n except Exception:\n log.error(\"Error emptying S3 bucket '%s'\", bucket_name, exc_info=True)\n status = cfnresponse.FAILED\n\n cfnresponse.send(event, context, status, {})\n"
},
"Handler": "index.lambda_handler",
"Role": {
"Fn::GetAtt": [
"EmptyLoadBalancerLogsBucketCustomResourceRole",
"Arn"
]
},
"Runtime": "python3.7",
"Timeout": 30
},
"Type": "AWS::Lambda::Function"
},
"EmptyLoadBalancerLogsBucketCustomResourceLogs": {
"DeletionPolicy": "Retain",
"Properties": {
"LogGroupName": {
"Fn::Join": [
"/",
[
"/aws/lambda",
{
"Ref": "EmptyLoadBalancerLogsBucketCustomResourceLambdaFunction"
}
]
]
},
"RetentionInDays": 7
},
"Type": "AWS::Logs::LogGroup",
"UpdateReplacePolicy": "Retain"
},
"EmptyLoadBalancerLogsBucketCustomResourceRole": {
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Sid": ""
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
"arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
],
"Path": "/apppack/",
"Policies": [
{
"PolicyDocument": {
"Statement": [
{
"Action": [
"s3:DeleteObject*"
],
"Effect": "Allow",
"Resource": [
"arn:aws:s3:::*/*"
],
"Sid": "EmptyBuckets"
},
{
"Action": [
"s3:ListBucket",
"s3:ListBucketVersions"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::*",
"Sid": "ListBuckets"
}
],
"Version": "2012-10-17"
},
"PolicyName": "apppack-EmptyLoadBalancerLogsBucket"
}
]
},
"Type": "AWS::IAM::Role"
},
"LoadBalancer": {
"Properties": {
"LoadBalancerAttributes": [
{
"Key": "routing.http.drop_invalid_header_fields.enabled",
"Value": "true"
},
{
"Key": "access_logs.s3.enabled",
"Value": "true"
},
{
"Key": "access_logs.s3.bucket",
"Value": {
"Ref": "LoadBalancerLogsBucket"
}
}
],
"Name": {
"Ref": "Name"
},
"SecurityGroups": [
{
"Ref": "HttpSecurityGroup"
}
],
"Subnets": [
{
"Ref": "PublicSubnet0"
},
{
"Ref": "PublicSubnet1"
},
{
"Ref": "PublicSubnet2"
}
]
},
"Type": "AWS::ElasticLoadBalancingV2::LoadBalancer"
},
"LoadBalancerLogsBucket": {
"Properties": {
"AccessControl": "Private",
"BucketEncryption": {
"ServerSideEncryptionConfiguration": [
{
"ServerSideEncryptionByDefault": {
"SSEAlgorithm": "AES256"
}
}
]
},
"LifecycleConfiguration": {
"Rules": [
{
"ExpirationInDays": 30,
"Id": "Delete after 30 days",
"Status": "Enabled"
}
]
},
"PublicAccessBlockConfiguration": {
"BlockPublicAcls": "true",
"BlockPublicPolicy": "true",
"IgnorePublicAcls": "true",
"RestrictPublicBuckets": "true"
},
"VersioningConfiguration": {
"Status": "Enabled"
}
},
"Type": "AWS::S3::Bucket"
},
"LoadBalancerLogsBucketPolicy": {
"Properties": {
"Bucket": {
"Ref": "LoadBalancerLogsBucket"
},
"PolicyDocument": {
"Statement": [
{
"Action": "*",
"Condition": {
"Bool": {
"aws:SecureTransport": "false"
}
},
"Effect": "Deny",
"Principal": "*",
"Resource": {
"Fn::Join": [
"/",
[
{
"Fn::GetAtt": [
"LoadBalancerLogsBucket",
"Arn"
]
},
"*"
]
]
}
},
{
"Action": "s3:PutObject",
"Effect": "Allow",
"Principal": {
"AWS": {
"Fn::Join": [
":",
[
"arn:aws:iam:",
{
"Fn::FindInMap": [
"LBAccountId",
{
"Ref": "AWS::Region"
},
"AccountId"
]
},
"root"
]
]
}
},
"Resource": {
"Fn::Sub": "${LoadBalancerLogsBucket.Arn}/*AWSLogs/${AWS::AccountId}/*"
}
},
{
"Action": "s3:PutObject",
"Condition": {
"StringEquals": {
"s3:x-amz-acl": "bucket-owner-full-control"
}
},
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Resource": {
"Fn::Sub": "${LoadBalancerLogsBucket.Arn}/*AWSLogs/${AWS::AccountId}/*"
}
},
{
"Action": "s3:GetBucketAcl",
"Effect": "Allow",
"Principal": {
"Service": "delivery.logs.amazonaws.com"
},
"Resource": {
"Fn::GetAtt": [
"LoadBalancerLogsBucket",
"Arn"
]
}
}
],
"Version": "2012-10-17"
}
},
"Type": "AWS::S3::BucketPolicy"
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment