# CloudTrail **Protocol:** JSON 1.1 (`X-Amz-Target: com.amazonaws.cloudtrail.v20131101.CloudTrail_20131101.*`) **Endpoint:** `POST http://localhost:4566/` Floci emulates a CloudTrail trail's full life cycle and emits S3 data events to the trail's destination bucket as gzipped JSON log files at the AWS-shaped key path: ``` ${prefix}AWSLogs/${accountId}/CloudTrail/${region}/yyyy/MM/dd/${accountId}_CloudTrail_${region}_${YYYYMMDDTHHMMZ}_${rand12}.json.gz ``` ## Supported Actions | Action | Description | | --- | --- | | `CreateTrail` | Creates a trail, optionally tagged via `TagsList`, and returns its ARN | | `DescribeTrails` | Returns the settings for one or more trails | | `DeleteTrail` | Deletes a trail | | `UpdateTrail` | Updates the settings of an existing trail | | `PutEventSelectors` | Configures the event selectors for a trail | | `GetEventSelectors` | - | | `StartLogging` | Starts logging for a trail | | `StopLogging` | Stops logging for a trail | | `GetTrailStatus` | Returns the logging status of a trail | | `LookupEvents` | - | | `ListTrails` | - | | `AddTags` | Adds or overwrites tags on a trail, identified by ARN | | `RemoveTags` | Removes the given tag keys from a trail, identified by ARN | | `ListTags` | Returns the tags for one or more trails, identified by ARN | Selector matching honors `ReadWriteType` (`All`, `ReadOnly`, `WriteOnly`) and `AWS::S3::Object` data resource ARNs in any of these forms: - `arn:aws:s3:::` — every bucket - `arn:aws:s3:::bucket/` — every key in the bucket - `arn:aws:s3:::bucket/prefix` — keys with the given prefix - `arn:aws:s3:::bucket/prefix/key` — exact key match ## S3 Hook Coverage Floci emits a CloudTrail data event whenever any of these S3 ops runs against a bucket matched by an active trail's selectors: - `PutObject`, `GetObject`, `HeadObject`, `DeleteObject`, `ListObjects`, `GetObjectAcl` Both success and `AwsException` paths emit; the latter populates `errorCode` / `errorMessage` (`NoSuchKey`, `NoSuchBucketPolicy`, etc.). If `floci.iam.enforcement-enabled` is set, IAM-deny responses also emit records with `errorCode: "AccessDenied"` for the same op set. ## Configuration | Variable | Default | Description | |---|---|---| | `FLOCI_SERVICES_CLOUDTRAIL_ENABLED` | `true` | Enable or disable the service | | `FLOCI_SERVICES_CLOUDTRAIL_FLUSH_INTERVAL_SECONDS` | `60` | How often the writer flushes buffered records into the destination bucket. Real CloudTrail delivers with ~5 minute latency; the local default is shorter for fast feedback loops. | ## Example ```bash export AWS_ENDPOINT_URL=http://localhost:4566 export AWS_DEFAULT_REGION=us-east-1 export AWS_ACCESS_KEY_ID=test AWS_SECRET_ACCESS_KEY=test aws s3 mb s3://my-source aws s3 mb s3://my-trail-logs aws cloudtrail create-trail \ --name my-trail \ --s3-bucket-name my-trail-logs aws cloudtrail put-event-selectors \ --trail-name my-trail \ --event-selectors '[{ "ReadWriteType": "All", "IncludeManagementEvents": false, "DataResources": [{ "Type": "AWS::S3::Object", "Values": ["arn:aws:s3:::my-source/"] }] }]' aws cloudtrail start-logging --name my-trail # Drive some traffic echo hello | aws s3 cp - s3://my-source/greeting.txt aws s3 cp s3://my-source/greeting.txt - # After ~60s, log files appear aws s3 ls s3://my-trail-logs/AWSLogs/ --recursive ```