Skip to content

Import the two CloudTrail trails and their log buckets into Terraform #191

Description

@ale210

Overview

We need to bring the account's two CloudTrail trails and their two log buckets into devops-security/terraform, because audit logging is a security control that currently exists only as console configuration — no issue or file in any of our repos so much as mentions CloudTrail. It is also the largest cluster of unmanaged resources left in 035866691871: 4 of the 19 in the 2026-09-06 coverage run.

Action Items

  • Add a cloudtrail.tf under terraform/ declaring both trails and both buckets, and put the import blocks in the existing terraform/imports.tf alongside the IAM ones.
  • Import the two trails. aws_cloudtrail takes the trail name as its import id. Both are multi-region and both are currently logging:
    - devops-security-tf-backend-logs — log file validation on, one advanced event selector for S3 data events (resources.ARN = arn:aws:s3:::hfla-ops-terraform-state/, resources.type = AWS::S3::Object)
    - management-events — log file validation off, one advanced event selector named "Management events selector" for eventCategory = Management
  • Import the two buckets. A bucket is not one resource. In AWS provider v4 and later the policy, public access block, encryption and ownership controls are each their own resource with their own import, all taking the bucket name — the same trap terraform/import.tf in hackforla/incubator documents for the civictechindex bucket. Verified live 2026-09-07:
    - aws-cloudtrail-logs-035866691871-4b8654bf → bucket, bucket policy, public access block (all four settings true), server-side encryption (AES256), ownership controls (BucketOwnerEnforced)
    - aws-cloudtrail-logs-035866691871-6539ef03 → the same minus ownership controls, which this bucket does not have. Do not declare that resource for this bucket; declaring it would create one rather than import one, which is a live change.
  • Get both bucket policies in verbatim. Each carries the AWSCloudTrailAclCheck20150319 and AWSCloudTrailWrite20150319 statements that let CloudTrail deliver to the bucket at all. A policy that drifts on apply stops log delivery, and it fails silently — nothing alerts, the trail simply stops writing.
  • Do not add a lifecycle configuration, KMS encryption or a CloudWatch Logs destination in this PR, even though all three are missing on both buckets. Adopt as-is so the plan stays reviewable; each of those changes live behaviour and belongs in its own ticket.
  • Confirm the plan meets the adoption bar and state that bar in the PR body: 0 to add, 0 to destroy, no replacements, every change tags-only. All four resources are untagged today, so each should gain managed-by = terraform-devops-security from the provider's default_tags and nothing else.
  • After the PR merges, run scripts/aws-terraform-coverage.ps1 from hackforla/devops and confirm the four resources have moved out of unmanaged.
  • Also after the merge, run aws cloudtrail get-trail-status on both trails and confirm IsLogging: true with a LatestDeliveryTime after the apply. The plan cannot tell you the trails are still delivering; only this can.

Resources/Instructions

  • Precedent for an adoption PR of exactly this shape, including how the 0-add/0-destroy bar is stated for a reviewer: hackforla/incubator#186 (Cognito) and hackforla/incubator#193 (shared platform).

  • The multi-resource S3 import trap is written up in terraform/import.tf in hackforla/incubator.

  • Live state verified 2026-09-07; values may drift.

    Trail Bucket What it captures Log file validation
    devops-security-tf-backend-logs aws-cloudtrail-logs-035866691871-4b8654bf S3 data events on hfla-ops-terraform-state only on
    management-events aws-cloudtrail-logs-035866691871-6539ef03 account management events off
  • devops-security-tf-plan carries ReadOnlyAccess, which covers cloudtrail:DescribeTrails / GetEventSelectors and the S3 getters, so the plan job needs no new permissions. devops-security-tf-apply has AdministratorAccess.

  • Two questions already answered, so nobody re-investigates them:
    - devops-security-tf-backend-logs watches hfla-ops-terraform-state, the live devops-security Terraform backend bucket — not the hlfa-incubator-terragrunt bucket that was deleted under hackforla/incubator#170. That bucket exists and the trail is delivering, so the trail is worth importing rather than deleting.
    - The two trails do not overlap. With advanced event selectors, a trail logs only what its selectors name, and the first trail has no Management selector at all. So the account is not paying to record the same events twice — the trails are complementary, and importing both encodes a real design rather than a duplication.

  • Deliberately out of scope, each worth its own ticket: neither trail is KMS-encrypted (KmsKeyId: null on both — they use SSE-S3); neither ships to CloudWatch Logs (CloudWatchLogsLogGroupArn: null, so there is no alerting path off either); neither bucket has a lifecycle configuration, so logs accumulate indefinitely and the storage bill only grows (the smaller bucket already holds 413,363 objects); and the two trails disagree on log file validation, which is an inconsistency to resolve rather than reproduce.

  • Both trails have IsOrganizationTrail: false, so neither covers the payer account 504695638931. Whether org-level trail coverage is wanted is a separate decision, and it would live in an account that has no Terraform at all.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions