Keep an account audit trail
$ grim infra:aws-cloudtrail --preset=minimal
Sooner or later someone asks who opened that port, who deleted that bucket, or when that access key was created. Without a trail, AWS keeps ninety days of that history, one region at a time. grim infra:aws-cloudtrail sets up the record before you need it: one trail for the whole account, every region, written to a bucket nothing else can write to.
The decision it asks of you is how much to record, because past the basic level CloudTrail charges by the event.
Usage
$ grim infra:aws-cloudtrail --dry-run # pick a preset, see the estimate, create nothing
$ grim infra:aws-cloudtrail --preset=minimal # account activity only
$ grim infra:aws-cloudtrail --preset=compliance # plus writes to your buckets, plus Insights
$ grim infra:aws-cloudtrail --preset=s3-audit-only --buckets=acme-shared-assets --s3-event-type=writeRun it from anywhere. It needs the aws CLI, terraform and working AWS credentials; grim infra:doctor checks them. One trail per account: the state is keyed by the account number.
Arguments and options
Set up an account-wide multi-region audit trail with opinionated preset library
Usage
grim infra:aws-cloudtrail [--preset PRESET] [--region REGION] [--name NAME] [--buckets BUCKETS] [--s3-event-type S3-EVENT-TYPE] [--cw-logs-retention CW-LOGS-RETENTION] [--insights] [--data-events] [--profile PROFILE] [--dry-run] [--force]Options
| Option | Description |
|---|---|
--preset=PRESET |
Preset bundle: minimal | compliance | security-focused | s3-audit-only |
--region=REGION |
Home region for the trail + log bucket (default: eu-central-1) |
--name=NAME |
Trail name (default: grim-audit-trail) |
--buckets=BUCKETS |
Comma-separated list of S3 bucket names to audit (overrides interactive picker) |
--s3-event-type=S3-EVENT-TYPE |
For s3-audit-only preset: read | write | all (default: all) |
--cw-logs-retention=CW-LOGS-RETENTION |
For security-focused preset: CW Logs retention in days (default: 90) |
--insights |
Enable Insights (ignored when --preset is set) |
--data-events |
DEPRECATED — use --preset=s3-audit-only or --preset=security-focused |
--profile=PROFILE |
AWS CLI profile to use |
--dry-run |
Show plan only, do not provision |
--force |
Allow re-using an existing state directory |
The four presets
Management events are the control-plane calls: IAM changes, instance launches, bucket creation, every KMS call. Every preset records them. Data events are reads and writes of objects inside buckets and invocations of Lambda functions, and they are what makes a trail expensive.
| Preset | Adds to management events | The wizard's own price label |
|---|---|---|
minimal |
Nothing | ~$2/mo |
compliance |
Writes to the buckets you pick, and Insights | ~$5-10/mo |
security-focused |
Reads and writes on the buckets you pick, Lambda invocations, Insights, and a live copy of the trail in CloudWatch Logs | $10-50+/mo |
s3-audit-only |
Data events on the buckets you pick: read, write or all |
varies |
Those labels are rough. The plan prints an estimate for your preset from the price snapshot built into grim, and says itself that the real bill follows the number of API calls. Without --preset the wizard asks, with minimal preselected; a run without interaction takes minimal.
What it actually does
Printed as Step 1/5 to Step 5/5.
- Shows the AWS identity and asks whether to create resources in that account. The default answer is no.
- Resolves the preset.
- Fills in the configuration. Trail name
grim-audit-trail, home regioneu-central-1, log bucketgrim-cloudtrail-<account>-<region>. For presets with bucket events it offers the buckets made bygrim infra:aws-s3, all ticked.--bucketstakes any bucket names instead, and a run without interaction takes all of grim's. - Prints the estimate. With
--dry-runit stops here. - Runs Terraform in
~/.grim/infra/cloudtrail-<account>/after a second confirmation, then records the trail underaws_resourcesin~/.grim/servers.jsonascloudtrail-<account>with the preset and every setting.
What exists in AWS afterwards
The trail, multi-region, with global service events and log file validation on. Validation writes digest files next to the logs, so a log that was altered later can be told from one that was not.
The log bucket, private and encrypted, whose policy lets only the CloudTrail service write into it. Logs land under AWSLogs/<account>/CloudTrail/ and move to the Glacier Instant Retrieval class after 30 days. Nothing ever expires them.
With security-focused only, a CloudWatch log group and the IAM role that lets CloudTrail write to it. The log group keeps entries for 90 days, or --cw-logs-retention.
Pitfalls
Changing the preset means starting over
CloudTrail state already exists for this account. stops a second run. Run grim infra:destroy cloudtrail-<account> first, then create the trail with the new preset. The message also offers --force, and warns in the same breath that Terraform will fail on the resources that already exist.
Event type and retention are never asked
--s3-event-type and --cw-logs-retention have defaults, all and 90, so the wizard takes those and moves on. all on a busy bucket is the costly choice. Pass the flag when you want write or a longer retention.
The old --data-events flag records every bucket
With the minimal preset, --data-events turns on read and write events for every bucket in the account. The command itself calls it deprecated. Use --preset=s3-audit-only and name the buckets.
The log bucket outlives the trail
The bucket refuses deletion while it holds objects, and grim has no option that empties it. After grim infra:destroy the trail stops recording, the destroy reports a failure on the bucket, and the history stays where it was. Empty and delete the bucket in the AWS console if you really want it gone.
After it finishes
Logs start arriving in the bucket and cost storage from then on. The trail shows in grim infra:list with its preset and estimate.
$ grim infra:list
$ aws s3 ls s3://grim-cloudtrail-123456789012-eu-central-1/AWSLogs/ --recursive | headQuestions
Does s3-audit-only really record nothing else?
It adds no data events beyond your buckets, but management events are part of every trail this command makes. AWS does not charge for the first copy of those in an account.
Do I need this if I am the only one with access?
That is when it is cheapest to have. The trail is how you find out that you were not the only one.
Related spells
grim infra:aws-s3
Conjure a private bucket
Create a private S3 bucket and an IAM user that can reach nothing else, then print the .env lines Laravel needs to use it.
grim infra:aws-budget
Set a spending alarm
Create a monthly AWS budget that mails you at 50, 80 and 100 percent of a limit, and when AWS forecasts the month will end above it.
grim infra:aws-alarms
Set a watch on a server
Attach two CloudWatch alarms to an EC2 instance, for sustained high CPU and for failed status checks, and have AWS mail you when either fires.
grim infra:list
Survey what runs on AWS
List every server and AWS resource grim has created, with a monthly cost estimate for each and the ids that infra:destroy takes.
grim infra:destroy
Unmake what grim made
Remove a server or AWS resource that grim created, after checking the account and making you type its name, and stop it from being billed.