Skip to content

Native S3 access log delivery to CloudWatch #8297

Description

@hannes-ucsc

(Posted by Claude Code)

Every S3 server access log in the system reaches CloudWatch by way of a Lambda function we wrote ourselves. Buckets are configured with aws_s3_bucket_logging to deposit access logs into the shared logs bucket, an aws_s3_bucket_notification on that bucket triggers the forward_s3_logs function in the indexer app, and S3AccessLogForwardingService reads each object, parses it and writes the records to the function's own log group.

The buckets currently covered are trail, aws_config and shared in the shared component, storage and the provisioned mirror and mamirror buckets in the main component, and the Data Browser site buckets in the browser component.

Since this design was adopted, AWS has added delivery of S3 server access logs to CloudWatch Logs as a first-class feature, by way of vended log delivery. That is the same transformation the forwarder performs by hand, so we are maintaining a reimplementation of a managed service capability.

The cost of the reimplementation is concentrated in three places.

The parsing is ours to keep correct. S3AccessLogForwardingService carries a Latin-1 decode to avoid decoding failures on undocumented encoding, a double unquote of the key field, a reconstruction of the time field from two CSV columns because AWS does not quote it, and a hard-coded field list that has to track the documented log record format as AWS extends it. None of this is wrong, but all of it is ours to maintain, and it fails in the direction of dropped or malformed audit records.

The function is not narrowly privileged. manage_iam_role is false for the indexer app, so forward_s3_logs runs under the same role as every other indexer function, which carries OpenSearch, SQS, DynamoDB, mirror bucket read/write and secretsmanager:GetSecretValue on secret:*. A managed delivery path needs no execution role of ours at all.

Extending the design across an account boundary requires opening one. #8039 needs access logging for mirror buckets that live in accounts we do not control, and because S3 server access logs must be delivered to a bucket in the same account as their source, those logs land in a foreign bucket. #8219 therefore adds a resource-based policy on the forward_s3_logs alias that permits a bucket in another account to invoke it. The security design review on that PR records the consequences: the permission pins a reclaimable bucket name rather than an account, the resulting audit trail for our mirror buckets is authored and retained in an account we do not control, and the foreign side of the pipeline cannot be managed by our Terraform, so its absence would be silent.

Note that only the S3 half of the forwarder is at stake. forward_alb_logs handles a log type the S3 feature does not cover, so the function and its plumbing would survive in some form regardless.

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

    Labels

    infra[subject] Project infrastructure like CI/CD, build and deployment scripts

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions