Detection rules › Panther
AWS CloudTrail Management Events Enabled
This policy ensures that at least one CloudTrail has management (control plane) operations logged.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth | T1562 Impair Defenses |
Rule body yaml
AnalysisType: policy
Filename: aws_cloudtrail_enabled.py
PolicyID: "AWS.CloudTrail.Enabled"
DisplayName: "AWS CloudTrail Management Events Enabled"
Enabled: true
ResourceTypes:
- AWS.CloudTrail.Meta
Tags:
- AWS
- Security Control
- Defense Evasion:Impair Defenses
Reports:
CIS:
- 2.1
PCI:
- 10.5.4
MITRE ATT&CK:
- TA0005:T1562
Severity: High
Description: >
This policy ensures that at least one CloudTrail has
management (control plane) operations logged.
Runbook: >
https://docs.runpanther.io/alert-runbooks/built-in-policies/aws-cloudtrail-enabled-in-all-regions
Reference: >
https://docs.aws.amazon.com/awscloudtrail/latest/userguide/cloudtrail-user-guide.html
Tests:
- Name: Global CloudTrail Is Enabled
ExpectedResult: true
Resource:
{
"GlobalEventSelectors":
[
{
"DataResources": null,
"IncludeManagementEvents": true,
"ReadWriteType": "All",
},
{
"DataResources":
[{ "Type": "AWS::S3::Object", "Values": ["arn:aws:s3"] }],
"IncludeManagementEvents": true,
"ReadWriteType": "All",
},
],
"Trails": ["trail1"],
}
- Name: CloudTrail Enabled with ReadOnly Management Events
ExpectedResult: false
Resource:
{
"GlobalEventSelectors":
[
{
"DataResources": null,
"IncludeManagementEvents": true,
"ReadWriteType": "Read",
},
],
"Trails": ["trail1"],
}
- Name: No Global CloudTrail Enabled
ExpectedResult: false
Resource: { "GlobalEventSelectors": null, "Trails": [] }
- Name: Advanced Selector With Management
ExpectedResult: true
Resource:
{
"Trails":
["arn:aws:cloudtrail:us-east-1:123456789012:trail/write_to_bucket"],
"GlobalAdvancedEventSelectors":
[
{
"Name": "Management events selector",
"FieldSelectors":
[{ "Field": "eventCategory", "Equals": ["Management"] }],
},
{
"Name": "LambdaDataEvents",
"FieldSelectors":
[
{ "Field": "eventCategory", "Equals": ["Data"] },
{
"Field": "resources.type",
"Equals": ["AWS::Lambda::Function"],
},
],
},
{
"Name": "S3DataEvents",
"FieldSelectors":
[
{ "Field": "eventCategory", "Equals": ["Data"] },
{
"Field": "eventName",
"NotEquals": ["HeadObject", "UploadPart"],
},
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
],
},
],
}
- Name: Advanced Selector With Management and readOnly
ExpectedResult: false
Resource:
{
"Trails":
["arn:aws:cloudtrail:us-east-1:123456789012:trail/write_to_bucket"],
"GlobalAdvancedEventSelectors":
[
{
"Name": "Management events selector",
"FieldSelectors":
[
{ "Field": "eventCategory", "Equals": ["Management"] },
{ "Field": "readOnly", "Equals": ["true"] },
],
},
{
"Name": "LambdaDataEvents",
"FieldSelectors":
[
{ "Field": "eventCategory", "Equals": ["Data"] },
{
"Field": "resources.type",
"Equals": ["AWS::Lambda::Function"],
},
],
},
{
"Name": "S3DataEvents",
"FieldSelectors":
[
{ "Field": "eventCategory", "Equals": ["Data"] },
{
"Field": "eventName",
"NotEquals": ["HeadObject", "UploadPart"],
},
{ "Field": "resources.type", "Equals": ["AWS::S3::Object"] },
],
},
],
}
- Name: None Global Selector, Valid Advanced Selector
ExpectedResult: true
Resource:
{
"AccountId": "123456789012",
"GlobalEventSelectors": null,
"GlobalAdvancedEventSelectors":
[
{
"FieldSelectors":
[
{
"EndsWith": null,
"Equals": ["Data"],
"Field": "eventCategory",
"NotEndsWith": null,
"NotEquals": null,
"NotStartsWith": null,
"StartsWith": null,
},
{
"EndsWith": null,
"Equals": null,
"Field": "eventName",
"NotEndsWith": null,
"NotEquals": ["UploadPart", "HeadObject"],
"NotStartsWith": null,
"StartsWith": null,
},
{
"EndsWith": null,
"Equals": ["AWS::S3::Object"],
"Field": "resources.type",
"NotEndsWith": null,
"NotEquals": null,
"NotStartsWith": null,
"StartsWith": null,
},
],
"Name": "S3DataEvents",
},
{
"FieldSelectors":
[
{
"EndsWith": null,
"Equals": ["Data"],
"Field": "eventCategory",
"NotEndsWith": null,
"NotEquals": null,
"NotStartsWith": null,
"StartsWith": null,
},
{
"EndsWith": null,
"Equals": ["AWS::Lambda::Function"],
"Field": "resources.type",
"NotEndsWith": null,
"NotEquals": null,
"NotStartsWith": null,
"StartsWith": null,
},
],
"Name": "LambdaDataEvents",
},
{
"FieldSelectors":
[
{
"EndsWith": null,
"Equals": ["Management"],
"Field": "eventCategory",
"NotEndsWith": null,
"NotEquals": null,
"NotStartsWith": null,
"StartsWith": null,
},
],
"Name": "Management events selector",
},
],
"Name": "AWS.CloudTrail.Meta",
"Region": "global",
"ResourceId": "123456789012::AWS.CloudTrail.Meta",
"ResourceType": "AWS.CloudTrail.Meta",
"Trails": ["arn:aws:cloudtrail:us-east-1:123456789012/bucket"],
}
Detection logic
Condition
not (Trails is_not_null and (GlobalEventSelectors is_not_null or GlobalAdvancedEventSelectors is_not_null) and ((GlobalEventSelectors is_not_null and GlobalEventSelectors array_any) or GlobalAdvancedEventSelectors is_not_null))
This rule also runs imperative logic the parser cannot express as a filter; the conditions above are the structured part it could extract.
Exclusions
Top-level NOT(...) conjuncts: predicates this rule actively suppresses.
| Field | Kind | Excluded values |
|---|---|---|
GlobalEventSelectors | array_any | |
GlobalEventSelectors | is_not_null | |
GlobalAdvancedEventSelectors | is_not_null | |
GlobalAdvancedEventSelectors | is_not_null | |
GlobalEventSelectors | is_not_null | |
Trails | is_not_null |