ELBv2 Application Load Balancer Access Logging
Overview
This check verifies that your Application Load Balancers (ALBs) have access logging enabled to Amazon S3. When enabled, ALB access logs capture detailed request information including timestamps, client IP addresses, request paths, latencies, and HTTP response codes.
Risk
Without ALB access logs enabled:
- Security incidents go undetected - malicious activities like credential stuffing, DDoS attempts, or data exfiltration attempts leave no trace
- Incident investigation is impossible - you cannot perform forensic analysis when something goes wrong
- No visibility into traffic patterns - making it difficult to detect anomalies or abuse
- Compliance gaps - many security frameworks require load balancer activity logging for audit purposes
Remediation Steps
Prerequisites
- AWS account access with permission to modify Elastic Load Balancing settings
- An S3 bucket to store the access logs (you can create one during this process)
S3 bucket requirements for ALB logs
The S3 bucket must:
- Be in the same region as your load balancer
- Have the correct bucket policy allowing ELB to write logs
Here is the required bucket policy (replace <BUCKET_NAME> and <ACCOUNT_ID> with your values):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "logdelivery.elasticloadbalancing.amazonaws.com"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/AWSLogs/<ACCOUNT_ID>/*"
}
]
}
For us-east-1 region, you can also use the ELB account ID directly:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::127311923021:root"
},
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/AWSLogs/<ACCOUNT_ID>/*"
}
]
}
Note: The ELB account ID varies by region. For us-east-1, it is 127311923021. See AWS documentation for other regions.
AWS Console Method
- Sign in to the AWS Management Console
- Navigate to EC2 > Load Balancers (in the left navigation under "Load Balancing")
- Select the Application Load Balancer you want to configure
- Click the Attributes tab
- Click Edit (or scroll to find the Edit button for attributes)
- Find Access logs and toggle it to On
- For S3 URI, enter your bucket name and optional prefix (e.g.,
s3://my-alb-logs-bucket/alb-logs/) - Click Save changes
If you see an error about bucket permissions, you need to add the correct bucket policy (see Prerequisites section above).
AWS CLI (optional)
First, list your load balancers to find the ARN:
aws elbv2 describe-load-balancers --region us-east-1
Enable access logging on your ALB:
aws elbv2 modify-load-balancer-attributes \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:<ACCOUNT_ID>:loadbalancer/app/<ALB_NAME>/<ALB_ID> \
--attributes \
Key=access_logs.s3.enabled,Value=true \
Key=access_logs.s3.bucket,Value=<BUCKET_NAME> \
Key=access_logs.s3.prefix,Value=<LOG_PREFIX> \
--region us-east-1
Parameters:
access_logs.s3.enabled- Set totrueto enable loggingaccess_logs.s3.bucket- Name of your S3 bucket (not the full ARN)access_logs.s3.prefix- Optional prefix for log files (e.g.,alb-logs)
If you do not need a prefix, you can omit that attribute:
aws elbv2 modify-load-balancer-attributes \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:<ACCOUNT_ID>:loadbalancer/app/<ALB_NAME>/<ALB_ID> \
--attributes \
Key=access_logs.s3.enabled,Value=true \
Key=access_logs.s3.bucket,Value=<BUCKET_NAME> \
--region us-east-1
CloudFormation (optional)
This template creates an S3 bucket with the correct policy and configures an ALB with access logging:
AWSTemplateFormatVersion: '2010-09-09'
Description: Enable access logging for Application Load Balancer
Parameters:
LogBucketName:
Type: String
Description: Name of the S3 bucket for ALB access logs
LogPrefix:
Type: String
Default: alb-logs
Description: Prefix for log files in the S3 bucket
Resources:
ALBLogsBucket:
Type: AWS::S3::Bucket
Properties:
BucketName: !Ref LogBucketName
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
LifecycleConfiguration:
Rules:
- Id: ExpireOldLogs
Status: Enabled
ExpirationInDays: 90
ALBLogsBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref ALBLogsBucket
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service: logdelivery.elasticloadbalancing.amazonaws.com
Action: s3:PutObject
Resource: !Sub 'arn:aws:s3:::${ALBLogsBucket}/${LogPrefix}/AWSLogs/${AWS::AccountId}/*'
Outputs:
LogBucketName:
Description: S3 bucket for ALB access logs
Value: !Ref ALBLogsBucket
LogBucketArn:
Description: ARN of the log bucket
Value: !GetAtt ALBLogsBucket.Arn
If you already have an ALB defined in CloudFormation, add the LoadBalancerAttributes property:
Resources:
ApplicationLoadBalancer:
Type: AWS::ElasticLoadBalancingV2::LoadBalancer
Properties:
Name: my-alb
Type: application
Subnets:
- !Ref SubnetA
- !Ref SubnetB
SecurityGroups:
- !Ref ALBSecurityGroup
LoadBalancerAttributes:
- Key: access_logs.s3.enabled
Value: 'true'
- Key: access_logs.s3.bucket
Value: !Ref ALBLogsBucket
- Key: access_logs.s3.prefix
Value: alb-logs
Deploy the template:
aws cloudformation deploy \
--template-file alb-logging.yaml \
--stack-name alb-logging-stack \
--parameter-overrides \
LogBucketName=my-alb-logs-bucket \
LogPrefix=alb-logs \
--region us-east-1
Terraform (optional)
First, create an S3 bucket with the required policy:
data "aws_caller_identity" "current" {}
data "aws_region" "current" {}
resource "aws_s3_bucket" "alb_logs" {
bucket = "my-alb-logs-bucket"
}
resource "aws_s3_bucket_public_access_block" "alb_logs" {
bucket = aws_s3_bucket.alb_logs.id
block_public_acls = true
block_public_policy = true
ignore_public_acls = true
restrict_public_buckets = true
}
resource "aws_s3_bucket_server_side_encryption_configuration" "alb_logs" {
bucket = aws_s3_bucket.alb_logs.id
rule {
apply_server_side_encryption_by_default {
sse_algorithm = "AES256"
}
}
}
resource "aws_s3_bucket_lifecycle_configuration" "alb_logs" {
bucket = aws_s3_bucket.alb_logs.id
rule {
id = "expire-old-logs"
status = "Enabled"
expiration {
days = 90
}
}
}
resource "aws_s3_bucket_policy" "alb_logs" {
bucket = aws_s3_bucket.alb_logs.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Principal = {
Service = "logdelivery.elasticloadbalancing.amazonaws.com"
}
Action = "s3:PutObject"
Resource = "${aws_s3_bucket.alb_logs.arn}/alb-logs/AWSLogs/${data.aws_caller_identity.current.account_id}/*"
}
]
})
}
Then configure your ALB with access logging:
resource "aws_lb" "main" {
name = "my-alb"
internal = false
load_balancer_type = "application"
security_groups = [aws_security_group.alb.id]
subnets = var.subnet_ids
access_logs {
bucket = aws_s3_bucket.alb_logs.id
prefix = "alb-logs"
enabled = true
}
}
If you have an existing ALB, simply add the access_logs block to enable logging.
Verification
After enabling logging, verify the configuration:
- Go to EC2 > Load Balancers
- Select your ALB and click the Attributes tab
- Confirm Access logs shows as enabled with the correct S3 bucket
- Wait a few minutes and send some traffic to your ALB
- Check the S3 bucket for log files (they appear every 5 minutes if there is traffic)
CLI verification commands
Check if access logging is enabled:
aws elbv2 describe-load-balancer-attributes \
--load-balancer-arn arn:aws:elasticloadbalancing:us-east-1:<ACCOUNT_ID>:loadbalancer/app/<ALB_NAME>/<ALB_ID> \
--region us-east-1
Look for these attributes in the output:
{
"Attributes": [
{
"Key": "access_logs.s3.enabled",
"Value": "true"
},
{
"Key": "access_logs.s3.bucket",
"Value": "my-alb-logs-bucket"
},
{
"Key": "access_logs.s3.prefix",
"Value": "alb-logs"
}
]
}
Check that logs are being written to S3:
aws s3 ls s3://<BUCKET_NAME>/<PREFIX>/AWSLogs/<ACCOUNT_ID>/elasticloadbalancing/us-east-1/ --region us-east-1
Additional Resources
- Access logs for your Application Load Balancer
- Enable access logging for your ALB
- Bucket permissions for access logs
- Access log entries
Notes
- Log delivery delay: Access logs are delivered every 5 minutes. There may be some delay before logs appear in S3.
- Bucket region: The S3 bucket must be in the same region as your load balancer.
- Bucket encryption: Consider enabling S3 encryption (SSE-S3 or SSE-KMS) on your log bucket to protect logs at rest.
- Lifecycle policies: Set up S3 lifecycle policies to automatically delete or archive old logs to manage storage costs.
- Log format: ALB logs are stored in a specific format. See AWS documentation for parsing and analysis guidance.
- Cost considerations: You pay for S3 storage and requests. With high-traffic load balancers, log storage costs can add up - plan accordingly.
- Network Load Balancers: This check applies to Application Load Balancers. Network Load Balancers (NLBs) have a different logging mechanism using flow logs.