# 🤖 Scoped credentials for the Litestream canary — the shape per-instance # (later per-box) credentials take: confined to one prefix of the instances # bucket, so a leaked key exposes one instance's ciphertext, not the fleet's. # No access key is declared here (it would land in state); mint one with # aws iam create-access-key --user-name litestream-canary # and store it in 1Password. resource "aws_iam_user" "litestream_canary" { name = "litestream-canary" } data "aws_iam_policy_document" "litestream_canary" { statement { sid = "ListCanaryPrefix" actions = ["s3:ListBucket"] resources = [aws_s3_bucket.state["instances"].arn] condition { test = "StringLike" variable = "s3:prefix" values = ["canary/*", "canary"] } } statement { sid = "ReadWriteCanaryObjects" actions = [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject", ] resources = ["${aws_s3_bucket.state["instances"].arn}/canary/*"] } } resource "aws_iam_user_policy" "litestream_canary" { name = "litestream-canary-prefix" user = aws_iam_user.litestream_canary.name policy = data.aws_iam_policy_document.litestream_canary.json }