Resource: aws_cloudtrail

Provides a CloudTrail resource.

Example Usage

Basic

Enable CloudTrail to capture all compatible management events in region. For capturing events from services like IAM, include_global_service_events must be enabled.

resource "aws_cloudtrail" "example" {
  depends_on = [aws_s3_bucket_policy.example]

  name                          = "example"
  s3_bucket_name                = aws_s3_bucket.example.id
  s3_key_prefix                 = "prefix"
  include_global_service_events = false
}

resource "aws_s3_bucket" "example" {
  bucket        = "tf-test-trail"
  force_destroy = true
}

data "aws_iam_policy_document" "example" {
  statement {
    sid    = "AWSCloudTrailAclCheck"
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }

    actions   = ["s3:GetBucketAcl"]
    resources = [aws_s3_bucket.example.arn]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"]
    }
  }

  statement {
    sid    = "AWSCloudTrailWrite"
    effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["cloudtrail.amazonaws.com"]
    }

    actions   = ["s3:PutObject"]
    resources = ["${aws_s3_bucket.example.arn}/prefix/AWSLogs/${data.aws_caller_identity.current.account_id}/*"]

    condition {
      test     = "StringEquals"
      variable = "s3:x-amz-acl"
      values   = ["bucket-owner-full-control"]
    }
    condition {
      test     = "StringEquals"
      variable = "aws:SourceArn"
      values   = ["arn:${data.aws_partition.current.partition}:cloudtrail:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:trail/example"]
    }
  }
}

resource "aws_s3_bucket_policy" "example" {
  bucket = aws_s3_bucket.example.id
  policy = data.aws_iam_policy_document.example.json
}

data "aws_caller_identity" "current" {}

data "aws_partition" "current" {}

data "aws_region" "current" {}

Data Event Logging

CloudTrail can log Data Events for certain services such as S3 objects and Lambda function invocations. Additional information about data event configuration can be found in the following links:

Logging All Lambda Function Invocations By Using Basic Event Selectors

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type   = "AWS::Lambda::Function"
      values = ["arn:aws:lambda"]
    }
  }
}

Logging All S3 Object Events By Using Basic Event Selectors

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type   = "AWS::S3::Object"
      values = ["arn:aws:s3"]
    }
  }
}

Logging Individual S3 Bucket Events By Using Basic Event Selectors

data "aws_s3_bucket" "important-bucket" {
  bucket = "important-bucket"
}

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  event_selector {
    read_write_type           = "All"
    include_management_events = true

    data_resource {
      type = "AWS::S3::Object"

      # Make sure to append a trailing '/' to your ARN if you want
      # to monitor all objects in a bucket.
      values = ["${data.aws_s3_bucket.important-bucket.arn}/"]
    }
  }
}

Logging All S3 Object Events Except For Two S3 Buckets By Using Advanced Event Selectors

data "aws_s3_bucket" "not-important-bucket-1" {
  bucket = "not-important-bucket-1"
}

data "aws_s3_bucket" "not-important-bucket-2" {
  bucket = "not-important-bucket-2"
}

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  advanced_event_selector {
    name = "Log all S3 objects events except for two S3 buckets"

    field_selector {
      field  = "eventCategory"
      equals = ["Data"]
    }

    field_selector {
      field = "resources.ARN"

      not_starts_with = [
        "${data.aws_s3_bucket.not-important-bucket-1.arn}/",
        "${data.aws_s3_bucket.not-important-bucket-2.arn}/"
      ]
    }

    field_selector {
      field  = "resources.type"
      equals = ["AWS::S3::Object"]
    }
  }

  advanced_event_selector {
    name = "Log readOnly and writeOnly management events"

    field_selector {
      field  = "eventCategory"
      equals = ["Management"]
    }
  }
}

Logging Individual S3 Buckets And Specific Event Names By Using Advanced Event Selectors

data "aws_s3_bucket" "important-bucket-1" {
  bucket = "important-bucket-1"
}

data "aws_s3_bucket" "important-bucket-2" {
  bucket = "important-bucket-2"
}

data "aws_s3_bucket" "important-bucket-3" {
  bucket = "important-bucket-3"
}

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  advanced_event_selector {
    name = "Log PutObject and DeleteObject events for two S3 buckets"

    field_selector {
      field  = "eventCategory"
      equals = ["Data"]
    }

    field_selector {
      field = "eventName"

      equals = [
        "PutObject",
        "DeleteObject"
      ]
    }

    field_selector {
      field = "resources.ARN"

      #The trailing slash is intentional; do not exclude it.
      starts_with = [
        "${data.aws_s3_bucket.important-bucket-1.arn}/",
        "${data.aws_s3_bucket.important-bucket-2.arn}/"
      ]
    }

    field_selector {
      field  = "readOnly"
      equals = ["false"]
    }

    field_selector {
      field  = "resources.type"
      equals = ["AWS::S3::Object"]
    }
  }

  advanced_event_selector {
    name = "Log Delete* events for one S3 bucket"

    field_selector {
      field  = "eventCategory"
      equals = ["Data"]
    }

    field_selector {
      field       = "eventName"
      starts_with = ["Delete"]
    }

    field_selector {
      field = "resources.ARN"

      equals = [
        "${data.aws_s3_bucket.important-bucket-3.arn}/important-prefix"
      ]
    }

    field_selector {
      field  = "readOnly"
      equals = ["false"]
    }

    field_selector {
      field  = "resources.type"
      equals = ["AWS::S3::Object"]
    }
  }
}

Sending Events to CloudWatch Logs

resource "aws_cloudwatch_log_group" "example" {
  name = "Example"
}

resource "aws_cloudtrail" "example" {
  # ... other configuration ...

  cloud_watch_logs_group_arn = "${aws_cloudwatch_log_group.example.arn}:*" # CloudTrail requires the Log Stream wildcard
}

Argument Reference

The following arguments are required:

The following arguments are optional:

event_selector

data_resource

insight_selector

Advanced Event Selector Arguments

Field Selector Arguments

Attribute Reference

This resource exports the following attributes in addition to the arguments above:

Import

In Terraform v1.5.0 and later, use an import block to import Cloudtrail Trails using the arn. For example:

import {
  to = aws_cloudtrail.sample
  id = "arn:aws:cloudtrail:us-east-1:123456789012:trail/my-sample-trail"
}

Using terraform import, import Cloudtrails using the arn. For example:

% terraform import aws_cloudtrail.sample arn:aws:cloudtrail:us-east-1:123456789012:trail/my-sample-trail