Back to Checks
CloudWatch log group has a retention policy of at least the configured minimum days or never expires
cloudwatch_log_group_retention_policy_specific_days_enabled
Service: cloudwatchSeverity: medium
OfficialBuilt-inVerified
Categories:loggingforensics-ready
Resource Type:AwsLogsLogGroup
CloudWatch Log Groups are assessed for a retention period at or above the configured threshold (e.g., 365 days) or for being set to never expire. Log groups with shorter retention are identified.
Risk
Short log retention erodes audit evidence. Adversaries can wait out the window, creating gaps in detection, forensics, and compliance reporting. This degrades the availability of historical logs and the integrity of incident timelines.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks cloudwatch_log_group_retention_policy_specific_days_enabledRecommendation
Define a minimum retention baseline (e.g., >=365 days) aligned to legal and investigative needs. Apply it consistently with documented exceptions. Automate enforcement, monitor changes, and restrict who can modify retention under least privilege and defense in depth.
Remediation
CLI
aws logs put-retention-policy --log-group-name <LOG_GROUP_NAME> --retention-in-days <DAYS>Terraform
# Set retention on a CloudWatch Log Group
resource "aws_cloudwatch_log_group" "<example_resource_name>" {
name = "<example_resource_name>"
retention_in_days = <DAYS> # Critical: set to at least the required minimum to pass the check
}NativeIaC
# CloudFormation: set retention on a CloudWatch Log Group
Resources:
<example_resource_name>:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: "<example_resource_name>"
RetentionInDays: <DAYS> # Critical: sets log retention to the required minimum to pass the checkOther
1In the AWS Console, go to CloudWatch > Log groups
2Select the target log group
3In the Expire events after/Retention column, click the current value
4Choose a retention value >= <DAYS> or select Never expire
5Click Save
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.cloudwatch.logs_client import logs_client
class cloudwatch_log_group_retention_policy_specific_days_enabled(Check):
def execute(self):
findings = []
# log_group_retention_days, default: 365 days
specific_retention_days = logs_client.audit_config.get(
"log_group_retention_days", 365
)
if logs_client.log_groups:
for log_group in logs_client.log_groups.values():
report = Check_Report_AWS(metadata=self.metadata(), resource=log_group)
if (
log_group.never_expire is False
and log_group.retention_days < specific_retention_days
):
report.status = "FAIL"
report.status_extended = f"Log Group {log_group.name} has less than {specific_retention_days} days retention period ({log_group.retention_days} days)."
else:
report.status = "PASS"
if log_group.never_expire is True:
report.status_extended = f"Log Group {log_group.name} comply with {specific_retention_days} days retention period since it never expires."
else:
report.status_extended = f"Log Group {log_group.name} comply with {specific_retention_days} days retention period since it has {log_group.retention_days} days."
findings.append(report)
return findingsReferences
- https://trendmicro.com/trendaivisiononecloudriskmanagement/knowledge-base/aws/CloudWatchLogs/cloudwatch-logs-retention-period.html
- https://boto3.amazonaws.com/v1/documentation/api/1.26.93/reference/services/logs/client/put_retention_policy.html
- https://medium.com/pareture/aws-cloudwatch-log-group-retention-periods-bb8a2fb9c358
- https://www.blinkops.com/blog/cloudwatch-retention
- https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/AWS_Logs.html