Overview
Centralizing AWS WAF logs across multiple AWS Organizations and accounts is essential for maintaining security visibility, reducing costs, and enabling efficient threat analysis at scale. This guide provides a step-by-step approach to implementing centralized WAF logging following AWS best practices.
Why Centralize WAF Logs?
Operational Benefits:
- Single pane of glass for security analysis across all accounts
- Reduced investigation time from hours to minutes
- Consistent log retention and lifecycle policies
- Simplified compliance reporting
Cost Benefits:
- Eliminate duplicate logging infrastructure
- Reduce CloudWatch Logs costs by 90%+ by writing directly to S3
- Optimize storage with lifecycle policies
- Predictable, scalable cost model
Security Benefits:
- Organization-wide threat visibility
- Cross-account attack pattern detection
- Centralized access control
- Immutable audit trail
Architecture Overview
The solution uses a three-account architecture following AWS best practices:
- Client Accounts: Where WAF Web ACLs protect CloudFront distributions and other resources
- Tooling Account: Hosts AWS Firewall Manager and Kinesis Data Firehose for log transformation
- Logging Account: Dedicated account for centralized log storage, Glue Data Catalog, and Athena
Data Flow
Client Accounts (WAF Web ACLs)
↓ WAF Logs
Tooling Account (Kinesis Data Firehose → Transform)
↓ Transformed Logs
Logging Account (S3 → Glue → Athena)
↓ S3 Access Points
Client Accounts (Account-level log access)
Prerequisites
Before implementing this solution, ensure you have:
- AWS Organizations set up with multiple accounts
- Administrative access to the management account
- A dedicated Tooling account for centralized management
- A dedicated Logging account for log storage
- Terraform for infrastructure as code
- Understanding of IAM cross-account permissions
Step 1: Set Up AWS Firewall Manager in Tooling Account
AWS Firewall Manager provides centralized management of WAF policies across accounts and Organizations.
Key Configuration:
- Deploy FMS in the Tooling account using Terraform
- Enable FMS as the delegated administrator in AWS Organizations
- Create shared WAF RuleGroups for consistent protection
- Configure FMS policies to deploy WAF Web ACLs to target accounts
Benefits:
- Automatic WAF deployment to new accounts
- Consistent rule enforcement across all accounts
- Centralized policy management with version control
- Infrastructure as code for auditability
Step 2: Configure WAF Logging to Kinesis Data Firehose
Configure all WAF Web ACLs to send logs to Kinesis Data Firehose in the Tooling account.
Why Kinesis Data Firehose?
- Enables log transformation before storage
- Buffers and batches logs for efficient S3 writes
- Supports cross-account delivery
- Significantly cheaper than CloudWatch Logs
Configuration Steps:
- Create Kinesis Data Firehose delivery stream in Tooling account
- Configure WAF Web ACLs to log to the Firehose stream
- Set up log transformation for enrichment and optimization
- Configure buffering and compression settings (GZIP recommended)
Cost Savings: Switching from CloudWatch Logs to S3 via Kinesis can save $20,000+ per month for high-volume environments.
Step 3: Set Up Dedicated Logging Account
Following AWS best practices, use a dedicated account for centralized log storage.
S3 Bucket Configuration
- Create central S3 bucket for WAF logs
- Enable versioning and encryption (AWS KMS)
- Configure lifecycle policies for cost optimization
- Set up bucket policies for cross-account access from Kinesis
S3 Access Points
- Create S3 Access Points for each client account
- Enable account-level log access control
- Simplify IAM permissions management
- Provide secure, isolated access to account-specific logs
AWS Glue Data Catalog
- Create Glue database for WAF logs
- Define table schema matching WAF log format
- Configure projected partitioning (no crawlers needed)
- Enable automatic partition discovery
Amazon Athena
- Set up Athena workgroup in Logging account
- Configure query result location
- Create saved queries for common investigations
- Set up query cost controls
Step 4: Configure Cross-Account Permissions
Proper IAM configuration is critical for secure cross-account log delivery.
Kinesis Data Firehose Role (Tooling Account):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:PutObjectAcl"],
"Resource": "arn:aws:s3:::logging-account-waf-logs/*"
}
]
}
S3 Bucket Policy (Logging Account):
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowKinesisFromToolingAccount",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::TOOLING-ACCOUNT-ID:role/KinesisFirehoseRole"
},
"Action": ["s3:PutObject", "s3:PutObjectAcl"],
"Resource": "arn:aws:s3:::logging-account-waf-logs/*"
}
]
}
S3 Access Point Policy (Per Client Account):
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::CLIENT-ACCOUNT-ID:root"
},
"Action": ["s3:GetObject", "s3:ListBucket"],
"Resource": [
"arn:aws:s3:REGION:LOGGING-ACCOUNT-ID:accesspoint/client-ap/*",
"arn:aws:s3:REGION:LOGGING-ACCOUNT-ID:accesspoint/client-ap"
],
"Condition": {
"StringLike": {
"s3:prefix": "CLIENT-ACCOUNT-ID/*"
}
}
}
]
}
Step 5: Implement Projected Partitioning for Athena
Projected partitioning eliminates the need for Glue Crawlers and enables instant partition discovery.
Athena Table Definition:
CREATE EXTERNAL TABLE waf_logs (
timestamp bigint,
formatversion int,
webaclid string,
terminatingruleid string,
terminatingruletype string,
action string,
httpsourcename string,
httpsourceid string,
rulegrouplist array<struct<...>>,
httprequest struct<...>
)
PARTITIONED BY (
account string,
region string,
year string,
month string,
day string
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe'
LOCATION 's3://logging-account-waf-logs/'
TBLPROPERTIES (
'projection.enabled' = 'true',
'projection.account.type' = 'enum',
'projection.account.values' = '111111111111,222222222222',
'projection.region.type' = 'enum',
'projection.region.values' = 'us-east-1,eu-west-1,eu-west-2',
'projection.year.type' = 'integer',
'projection.year.range' = '2024,2030',
'projection.month.type' = 'integer',
'projection.month.range' = '1,12',
'projection.month.digits' = '2',
'projection.day.type' = 'integer',
'projection.day.range' = '1,31',
'projection.day.digits' = '2',
'storage.location.template' =
's3://logging-account-waf-logs/${account}/${region}/${year}/${month}/${day}'
);
Benefits of Projected Partitioning:
- No Glue Crawlers required (eliminates operational overhead and cost)
- Instant partition discovery
- Faster query performance
- Lower costs
Step 6: Create Athena Query Library
Build a library of common queries for security investigations.
Top Blocked IP Addresses:
SELECT
httprequest.clientip AS client_ip,
COUNT(*) AS block_count
FROM waf_logs
WHERE action = 'BLOCK'
AND year = '2026' AND month = '03'
GROUP BY httprequest.clientip
ORDER BY block_count DESC
LIMIT 100;
Rule Effectiveness Analysis:
SELECT
terminatingruleid,
terminatingruletype,
action,
COUNT(*) AS hit_count
FROM waf_logs
WHERE year = '2026' AND month = '03'
GROUP BY terminatingruleid, terminatingruletype, action
ORDER BY hit_count DESC;
Geographic Traffic Distribution:
SELECT
httprequest.country AS country,
action,
COUNT(*) AS request_count
FROM waf_logs
WHERE year = '2026' AND month = '03'
GROUP BY httprequest.country, action
ORDER BY request_count DESC;
Account-Specific Investigation:
SELECT
timestamp,
httprequest.clientip,
httprequest.uri,
action,
terminatingruleid
FROM waf_logs
WHERE account = '111111111111'
AND year = '2026' AND month = '03' AND day = '01'
AND action = 'BLOCK'
ORDER BY timestamp DESC;
Multi-Organization Considerations
When working across multiple AWS Organizations:
- Separate Firewall Manager Instances: Deploy FMS in each Organization's Tooling account, all sending logs to the same central Logging account
- Cross-Organization IAM: Use IAM roles with trust relationships across Organizations, implement least-privilege access
- Log Segregation: Use S3 prefixes to separate logs by Organization, create separate S3 Access Points per Organization
- Cost Allocation: Use S3 bucket tagging for cost tracking per Organization
Best Practices
Security:
- Enable S3 bucket encryption with AWS KMS
- Use separate KMS keys per Organization for isolation
- Enable S3 Object Lock for compliance requirements
- Implement least-privilege IAM policies
- Use S3 Access Points for fine-grained access control
Cost Optimization:
- Implement S3 lifecycle policies (transition to Glacier after 90 days)
- Enable Kinesis Data Firehose compression (GZIP)
- Set appropriate Kinesis buffer sizes (5 MB / 300 seconds)
- Use Athena query result caching
- Partition data by account, region, and date
Operational Excellence:
- Use Infrastructure as Code (Terraform)
- Create runbooks for common scenarios
- Set up automated alerting for log delivery failures
- Monitor Kinesis Data Firehose metrics
- Document query patterns and use cases
Common Challenges and Solutions
| Challenge | Solution |
|---|---|
| High log volume | Implement sampling, use Kinesis buffering, enable compression |
| Cross-account permission errors | Use CloudTrail to debug IAM denials, validate trust relationships |
| Query performance | Always use partition filters, limit date ranges, use projected partitioning |
| Cost management | Implement lifecycle policies, use S3 Intelligent-Tiering, set Athena query limits |
Results
Organizations implementing this architecture typically achieve:
- 85% reduction in security noise requiring investigation
- $20,000+ per month savings by switching from CloudWatch Logs to S3
- Investigation time reduced from hours to minutes
- Consistent security controls across all accounts and Organizations
Need Help?
Cloudignyte specializes in implementing centralized AWS security logging solutions across complex multi-account and multi-organization environments. We've helped organizations manage 2,500+ AWS accounts and reduce logging costs by $20,000+ per month while improving security visibility.
Contact us to discuss your centralized logging requirements.
Related: