Skip to main content

CloudTrail Advanced Event Selectors

The organization CloudTrail records API activity across every account in your organization. By default it logs all management events and no data events. Advanced event selectors let you change what the trail records: enable data events for specific resources, filter management events, and target newer categories such as network activity events. They are configured through the advanced_event_selectors field on organization_trail.

What are event selectors?

Event selectors tell CloudTrail which events to record. CloudTrail offers two kinds, and a trail can use one or the other, never both:

  • Basic (classic) event selectors support data events for a fixed set of resource types (S3 objects, Lambda functions, DynamoDB tables) with limited filtering.
  • Advanced event selectors support management, data, and network activity events for all resource types, with field-level filtering on attributes like eventCategory, resources.type, resources.ARN, eventName, and readOnly.

NTC Organizations exposes advanced event selectors only. They are AWS's recommended, forward-looking option, and they are the only ones expressive enough to cover use cases like matching every state-backend bucket in the organization by ARN prefix. The module currently exposes no classic selector configuration, so there is nothing to migrate.

Which events are available?

Advanced event selectors filter events by category. The eventCategory field is required in every selector and determines which other fields you can use.

CategoryeventCategory valueWhat it captures
Management eventsManagementControl-plane operations, such as creating an EC2 instance or attaching an IAM policy. Logged by default.
Data eventsDataData-plane operations on resources, such as S3 GetObject, Lambda Invoke, or DynamoDB PutItem. Not logged by default.
Network activity eventsNetworkActivityVPC endpoint activity for supported services.

For data events, the fields most commonly used to filter are:

  • resources.type (required): the resource type, for example AWS::S3::Object, AWS::Lambda::Function, or AWS::DynamoDB::Table. Each selector can specify only one resources.type. To log more than one type, add another selector.
  • resources.ARN: the resource ARN. Use StartsWith to match all objects under a bucket or a shared naming prefix.
  • eventName: a specific API operation, for example GetObject.
  • readOnly: true for read events (Get*, Describe*) or false for write events (Put*, Delete*). Omit it to log both.

Why configure event selectors?

The default trail answers "who changed what" through management events. It does not answer "who read or wrote this data". Advanced event selectors close that gap and give you control over cost and noise.

  • Audit data access. Record who reads and writes sensitive objects, for example access to Terraform state files, secrets buckets, or customer data buckets.
  • Meet compliance requirements. Regulated environments often require an audit trail of data access, not only configuration changes.
  • Control cost. Data events are billed per event and can be high volume. Selectors let you log exactly the resources you care about instead of everything.
  • Filter management events. Drop read-only management events to reduce volume, or scope logging to specific event sources.

Default behavior is preserved

When you do not set advanced_event_selectors, the module emits no selector blocks and the trail keeps logging all management events exactly as before. Existing installations see no change.

Management events and advanced selectors

Defining any advanced event selector on a trail replaces its default behavior of logging all management events. To prevent management logging from silently disappearing, NTC Organizations automatically adds a management-events selector whenever you configure advanced_event_selectors. This is controlled by include_management_events, which defaults to true.

Implementation with NTC Organizations

The example below enables an organization-wide audit of access to the Terraform state backend buckets. Because this is an organization trail, one selector applies to every member account. A single StartsWith on the shared state-bucket naming prefix matches every account's bucket.

module "ntc_organizations" {
source = "github.com/nuvibit-terraform-collection/terraform-aws-ntc-organizations?ref=X.X.X"

# Other configuration...

organization_trail = {
enabled = true
kms_key_arn = "arn:aws:kms:eu-central-1:111111111111:key/..."
s3_bucket_name = "ntc-org-cloudtrail-logs"

# Advanced event selectors (generic passthrough of the CloudTrail shape).
advanced_event_selectors = {
# An "eventCategory Equals Management" selector is added automatically so
# management logging is preserved (defaults to true).
include_management_events = true

selectors = [
{
name = "tfstate-backend-audit"
field_selectors = [
{ field = "eventCategory", equals = ["Data"] },
{ field = "resources.type", equals = ["AWS::S3::Object"] },
# Verify the prefix against your state-backend bucket naming convention.
{ field = "resources.ARN", starts_with = ["arn:aws:s3:::ntc-tfstate-"] },
]
}
]
}
}

# Other organization configuration...
}
State locking

If your installations use S3-native state locking (use_lockfile), the .tflock object writes and deletes are captured by the same S3 selector for free. DynamoDB-based locking is a separate data source (AWS::DynamoDB::Table) and needs its own selector.

Configuration options

The advanced_event_selectors object is a passthrough of the CloudTrail advanced event selector shape, so any current or future selector can be expressed without a module change.

FieldTypeDefaultDescription
include_management_eventsbooltrueAutomatically add an eventCategory Equals "Management" selector so management logging is preserved.
selectorslist(object)[]One entry per advanced event selector.
selectors[].namestringnullOptional name for the selector.
selectors[].field_selectorslist(object)requiredThe field-level conditions for the selector.

Each field_selectors entry sets a field plus at least one operator: equals, not_equals, starts_with, ends_with, not_starts_with, or not_ends_with. Each operator takes a list of strings.

The module validates only the structure (a non-empty field and at least one operator). Field names and resource types are passed through and validated by CloudTrail at apply time, which keeps the interface compatible with new event categories as AWS adds them.

When to disable include_management_events

Leave include_management_events at its default of true whenever you add data-event selectors and still want complete management-event logging. Set it to false in two cases:

  • You want to filter management events yourself. The auto-included selector is deliberately unfiltered. If you write your own management selector (for example, write-only events), you must disable the auto one, otherwise CloudTrail logs both and the unfiltered selector wins.
  • You want a data-events-only trail. If management events are already captured elsewhere, set it to false and provide only data selectors.
advanced_event_selectors = {
# Take full control of management-event logging.
include_management_events = false

selectors = [
{
name = "management-write-only"
field_selectors = [
{ field = "eventCategory", equals = ["Management"] },
{ field = "readOnly", equals = ["false"] },
]
}
]
}

Further examples

Lambda invocation data events across the organization:

advanced_event_selectors = {
selectors = [
{
name = "lambda-invoke-audit"
field_selectors = [
{ field = "eventCategory", equals = ["Data"] },
{ field = "resources.type", equals = ["AWS::Lambda::Function"] },
]
}
]
}

DynamoDB item-level data events:

advanced_event_selectors = {
selectors = [
{
name = "dynamodb-item-audit"
field_selectors = [
{ field = "eventCategory", equals = ["Data"] },
{ field = "resources.type", equals = ["AWS::DynamoDB::Table"] },
]
}
]
}

Constraints to keep in mind

  • A trail cannot use both classic and advanced event selectors.
  • Each selector can specify only one resources.type. Use a separate selector per resource type.
  • Selectors do not support wildcards such as *. Use StartsWith, EndsWith, NotStartsWith, or NotEndsWith to match partial values.
  • A trail supports up to 500 values across all conditions and selectors combined.

References

Conclusion

Advanced event selectors turn the organization CloudTrail from a management-event recorder into a precise audit tool. Configure them to log the data access that matters for your compliance and security requirements, keep the default management logging in place with include_management_events, and scope selectors tightly to control cost. Because the input is a passthrough of the CloudTrail shape, you can express new selector types as AWS introduces them without waiting for a module change.