Skip to content

rvn-aws-compliance: add per-Region CloudTrail trails (on by default) - #236

Open
devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/1792862783-compliance-cloudtrail
Open

devin-ai-integration[bot] wants to merge 5 commits into
mainfrom
devin/1792862783-compliance-cloudtrail

Conversation

@devin-ai-integration

@devin-ai-integration devin-ai-integration Bot commented Oct 24, 2026 •

Copy link
Copy Markdown
Contributor
  • In merge queue
  • Prioritize

Summary

CloudTrail is the main AWS audit-log control SOC 2 auditors look for, and no module set it up. rvn-aws-compliance 0.3.0 now creates one single-Region trail (ravion-compliance, is_multi_region_trail = false) in each Region of the existing regions input, the same list that drives GuardDuty and ECR scanning. Each trail records read and write management events only, no data events, with log file validation on.

resource "aws_cloudtrail" "this" {
  for_each = var.cloudtrail_enabled ? local.regions : toset([])
  region   = each.key
  include_global_service_events = each.key == "us-east-1"
  ...
}
  • Global service events (IAM, CloudFront, global STS) are only delivered to a single-Region trail in us-east-1 (AWS docs). The module doesn't add us-east-1 for you; the README and input help say to include it.
  • Cost: the first copy of management events in each Region is free. In a Region that already has a trail (for example an organization trail), ours is a paid second copy; turn cloudtrail_enabled off there.

New inputs:

  • cloudtrail_enabled (default true).
  • cloudtrail_log_retention_days (default 365; 0 keeps logs forever): S3 lifecycle expiry for current and noncurrent versions.
  • cloudtrail_kms_key_arn (optional, SSE-S3 when empty): must be in the runner Region, where the bucket lives, even for trails in other Regions (AWS docs), and its policy must allow cloudtrail.amazonaws.com.

Log bucket (ravion-cloudtrail-<account>-<random>, one per account in the runner Region, shared by all trails):

  • All public access blocked, BucketOwnerEnforced, versioning on.
  • Bucket policy allows writes only from the selected trails (aws:SourceArn = list of trail ARNs) and denies non-HTTPS requests.
  • force_destroy = false, so destroying the module or turning CloudTrail off fails while logs remain (documented).

Outputs: cloudtrail_arns (Region → trail ARN, empty when disabled), cloudtrail_bucket_name, cloudtrail_bucket_arn.

Runner permissions: the default Terraform apply role (AdministratorAccess) covers this. Stacks that replace the apply policy need CloudTrail trail management plus S3 bucket management.

Review note: existing instances that upgrade without a stored value for cloudtrail_enabled will likely get trails too.

Tests: security/compliance/tests/cloudtrail.tftest.hcl covers one trail per Region, global events only in us-east-1, no automatic us-east-1, bucket policy listing every trail, disabled means no resources, retention 0/custom, KMS, invalid inputs. tofu test 27/27, npm test 178/178. Nothing deployed to a live AWS account.

Related: #235 (other SOC 2 defaults).

Link to Devin session: https://app.devin.ai/sessions/ab65775fc9bb47ee82cf651c062055f1
Open in Devin Desktop: https://app.devin.ai/desktop/session/ab65775fc9bb47ee82cf651c062055f1?variant=devin

devin-ai-integration Bot and others added 2 commits October 24, 2026 17:28
Co-Authored-By: brandon <brandon@flightcontrol.dev>
Co-Authored-By: brandon <brandon@flightcontrol.dev>
@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

I'll fix CI failures and address comments from users with write access. I'll skip comments containing "(aside)".

  • Disable automatic comment, CI, and merge conflict monitoring

@github-actions

github-actions Bot commented Oct 24, 2026 •

Copy link
Copy Markdown

Ravion Module Publish Plan

Dry run only. No Ravion API mutations were made.

Module Current Version New Version Description
rvn-aws-compliance 0.2.0 0.3.0 Record management events in each selected Region with CloudTrail trails sharing a private, versioned log bucket and configurable retention.

Diffs

rvn-aws-compliance n/a -> 0.3.0

--- remote
+++ compiled
-description: Manages an AWS compliance baseline with GuardDuty threat detection and registry-wide ECR image scanning across selected Regions.
+description: Manages an AWS compliance baseline with GuardDuty, ECR image scanning, and regional CloudTrail audit trails.
 moduleCategories:
   - security
 name: AWS Compliance

rvn-aws-compliance 0.2.0 -> 0.3.0

--- remote
+++ compiled
     label: Compliance regions
     type: section
   - add_button_label: Add Region
-    description: AWS Regions where GuardDuty and Basic ECR scan-on-push are enabled. ECR scanning covers every repository and replaces existing Enhanced scanning or custom filters. Use one module per account with all required Regions; each Region must already be enabled.
+    description: Regions for GuardDuty, ECR scanning and CloudTrail. Include us-east-1 for IAM changes; each Region must be enabled.
     id: regions
     label: Regions
     required: true
     type: string_array
     values: $values:aws/regions
+  - id: section_cloudtrail
+    label: CloudTrail
+    type: section
+  - default: true
+    description: One trail per selected Region. Turn off if an organization trail already covers them.
+    id: cloudtrail_enabled
+    label: CloudTrail
+    type: boolean
+  - default: 365
+    description: S3 lifecycle expiry; 0 keeps logs forever.
+    id: cloudtrail_log_retention_days
+    label: Log retention (days)
+    min: 0
+    show_when:
+      cloudtrail_enabled: true
+    type: number
+  - description: Leave blank for SSE-S3. Use a bucket-Region key whose policy allows cloudtrail.amazonaws.com for every trail.
+    id: cloudtrail_kms_key_arn
+    label: KMS key ARN
+    required: false
+    show_when:
+      cloudtrail_enabled: true
+    type: string
   - id: section_protection_plans
     label: GuardDuty protection plans
     type: section
@@
     type: string
     values: $values:ravion/execution_environments
 readme: |
-  Manages an AWS compliance baseline with GuardDuty threat detection and Basic ECR image scanning on push across selected Regions.
+  Manages an AWS compliance baseline with GuardDuty, ECR image scanning, and regional CloudTrail audit trails.
 
   ## Account-level setup
 
-  Deploy one module for an AWS account and select every Region you want covered. The runner Region controls where Terraform executes; the Regions list controls where both services are configured. Every selected Region must already be enabled for the account.
+  Deploy one module for an AWS account and select every Region you want covered. The runner Region controls where Terraform executes and hosts the shared CloudTrail bucket; the Regions list controls GuardDuty, ECR scanning and CloudTrail trails. Every selected Region must already be enabled for the account.
 
-  Each Region receives a GuardDuty detector with explicitly managed protection plans and an ECR registry scanning rule covering all existing and future private repositories. The module supports threat-detection and vulnerability-scanning controls; application alarms, log retention, and other compliance controls remain in their respective modules.
+  Each selected Region receives a GuardDuty detector with explicitly managed protection plans, an ECR registry scanning rule covering all existing and future private repositories, and a CloudTrail trail when enabled. Application alarms and application log retention remain in their respective modules.
 
   ## GuardDuty
 
@@
 
   Basic scans check operating-system vulnerabilities on new image pushes. They do not provide continuous scanning or automatically scan all images pushed before this configuration was enabled.
 
+  ## CloudTrail
+
+  CloudTrail is enabled by default and creates one single-Region trail in each selected Region. Each records read and write management events with log file validation and no data events. The trails share one bucket in the runner Region.
+
+  Include us-east-1 in Regions to capture IAM changes and other global service events (CloudFront and the STS global endpoint). Only that trail includes global service events; us-east-1 is not added automatically. STS regional-endpoint events are recorded in their respective Regions.
+
+  Logs go to a dedicated private S3 bucket with public access blocked, bucket-owner-enforced ownership, versioning, and encryption. Log retention (days) sets lifecycle expiry for current and noncurrent object versions; 365 is the default and 0 keeps them forever. With versioning, current-object expiry makes a version noncurrent, then noncurrent expiry applies.
+
+  Leave KMS key ARN blank for SSE-S3, or supply a key in the bucket's runner Region, even for trails in other Regions. Its policy must allow cloudtrail.amazonaws.com to encrypt logs for every selected trail. This module does not manage the key policy.
+
+  The first copy of management events per Region is free; S3 storage and optional KMS usage incur charges. If an existing trail already records those events in a Region, the additional copy is paid. Turn CloudTrail off if an organization trail already provides coverage.
+
+  Destroy fails while the bucket contains logs or object versions: force deletion is disabled. Disabling CloudTrail also attempts to remove its bucket, so preserve or explicitly remove retained logs before doing so.
+
   ## Existing resources and ownership
 
   GuardDuty detectors and ECR scanning configurations are shared by the whole account in each Region. Keep exactly one Terraform owner per account and Region; do not deploy overlapping instances or also manage them from a VPC or service module.
@@
   | --- | --- | --- |
   | AWS account | Required | Account whose regional security settings are managed. |
   | Region | Required | Terraform runner Region. |
-  | Regions | Required | Regions covered by both GuardDuty and ECR scanning. |
+  | Regions | Required | Regions covered by GuardDuty, ECR scanning and CloudTrail. Include us-east-1 for IAM changes. |
   | ECR scanning | Basic scan-on-push for all repositories | Always enabled by this module. |
+  | CloudTrail | Enabled | One single-Region management-event trail in each selected Region, sharing a runner-Region bucket. |
+  | Log retention (days) | 365 | S3 lifecycle expiry; 0 keeps logs forever. |
+  | KMS key ARN | None (SSE-S3) | Key in the bucket's runner Region whose policy permits encryption for every trail. |
   | S3, EKS, malware, RDS, Lambda protection | Enabled | GuardDuty protection plans. |
   | Runtime monitoring | Disabled | Optional workload security agents. |
   | Automated agent management | EKS, ECS Fargate, EC2 | Used when Runtime Monitoring is enabled. |
   | Finding publishing frequency | Every 15 minutes | Export cadence for updated GuardDuty findings. |
-  | Tags | Standard Ravion tags | Additional tags for GuardDuty detectors; ECR registry scanning does not support tags. |
+  | Tags | Standard Ravion tags | Additional tags for GuardDuty, CloudTrail and its bucket; ECR registry scanning does not support tags. |
 
   ## Learn more
 
   - [Amazon GuardDuty](https://docs.aws.amazon.com/guardduty/latest/ug/what-is-guardduty.html)
   - [GuardDuty protection plans](https://docs.aws.amazon.com/guardduty/latest/ug/guardduty-features-activation-model.html)
   - [ECR scanning filters](https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-scanning-filters.html)
-  - [Source module](https://github.com/ravionhq/modules/tree/rvn-aws-compliance@0.2.0/security/compliance)
+  - [Source module](https://github.com/ravionhq/modules/tree/rvn-aws-compliance@0.3.0/security/compliance)
 stack:
   pipelines:
     change:
@@
         branch: main
         execution_environment_id: << module.input.execution_environment_id >>
         plan_permissions: '<< module.input.terraform_plan_default_policies_enabled == false ? {"replace": module.input.terraform_plan_iam_policy_arns} : (module.input.terraform_plan_iam_policy_arns ? {"attach": module.input.terraform_plan_iam_policy_arns} : nil) >>'
-        ref: rvn-aws-compliance@0.2.0
+        ref: rvn-aws-compliance@0.3.0
         repo: https://github.com/ravionhq/modules
         stack_id: <<stack.id>>
         terraform_variables:
           ...overrides: << module.input.advanced_terraform_variables >>
+          cloudtrail_enabled: << module.input.cloudtrail_enabled >>
+          cloudtrail_kms_key_arn: << module.input.cloudtrail_kms_key_arn || nil >>
+          cloudtrail_log_retention_days: "<< module.input.cloudtrail_log_retention_days != nil ? module.input.cloudtrail_log_retention_days : 365 >>"
           eks_protection_enabled: << module.input.eks_protection_enabled >>
           finding_publishing_frequency: << module.input.finding_publishing_frequency || "FIFTEEN_MINUTES" >>
           lambda_protection_enabled: << module.input.lambda_protection_enabled >>

Comment thread security/compliance/README.md Outdated
Co-Authored-By: brandon <brandon@flightcontrol.dev>
@github-actions
github-actions Bot requested a review from flybayer October 24, 2026 17:34
@flybayer
flybayer requested a review from mabadir October 24, 2026 17:35

Copy link
Copy Markdown
Member

@devin-ai-integration Can we instead enable cloud trail per region? So you just manually specify the regions you want

@devin-ai-integration

Copy link
Copy Markdown
Contributor Author

Yes. I'll switch to one single-Region trail per Region in the module's existing Regions list (the one GuardDuty and ECR scanning use), all writing to the one private bucket in the runner Region. Each trail is still the first copy of management events in its Region, so it stays free.

One catch: a single-Region trail only records global service events (IAM, STS, CloudFront) when it's in us-east-1, so the docs will say to include us-east-1 to capture IAM changes. I'll push the change here shortly.

devin-ai-integration Bot and others added 2 commits October 25, 2026 16:28
Co-Authored-By: brandon <brandon@flightcontrol.dev>
Co-Authored-By: brandon <brandon@flightcontrol.dev>

Copy link
Copy Markdown
Member

@mabadir 👆

@mabadir

mabadir commented Oct 25, 2026

Copy link
Copy Markdown
Contributor

That makes sense. If there is an existing management trail will it still provision one or skip the region?

@devin-ai-integration

devin-ai-integration Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor Author

@mabadir It still provisions one. The module doesn't look for existing trails: it creates a ravion-compliance trail in every Region listed in regions while cloudtrail_enabled is on. AWS allows several trails per Region, so nothing fails, but in a Region that already has a management-event trail ours becomes the second copy, which is billed (about $2 per 100,000 management events; the first copy per Region is free).

Today the way out is to turn cloudtrail_enabled off. Since regions also drives GuardDuty and ECR scanning, you can't drop just one Region for CloudTrail. If you want per-Region skipping, I can add an optional cloudtrail_regions input (defaulting to regions) so you list only the Regions without an existing trail. Auto-detecting at plan time isn't practical: the AWS provider has no data source that lists trails.

Written by Devin

@devin-ai-integration devin-ai-integration Bot changed the title rvn-aws-compliance: add a multi-Region CloudTrail trail (on by default) rvn-aws-compliance: add per-Region CloudTrail trails (on by default) Oct 25, 2026
@flybayer
flybayer requested a review from mabadir October 25, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants