Skip to content

rfc: make the Forge bucket policy an AWS bucket policy document - #34

Merged
pyropy merged 4 commits into
mainfrom
srdjan/rfc-aws-policy-document
Oct 15, 2026
Merged

pyropy merged 4 commits into
mainfrom
srdjan/rfc-aws-policy-document

Conversation

@pyropy

@pyropy pyropy commented Oct 12, 2026 •

Copy link
Copy Markdown
Member

📖 Preview

The Forge bucket policy becomes an AWS bucket policy document, so AWS tooling can build and check it and Ingot can serve the policy operations through versitygw's own S3 handlers instead of answering them ahead of versitygw's route table.

The changes in the tenant IAM RFC:

  • The document gains Version and Resource. Principals are written arn:aws:iam:::user/<principalId> with an empty account field, because the bucket fixes the tenant. {"AWS": "*"} is a second spelling of "*".
  • Resource names the whole bucket: the bucket ARN for s3:ListBucket* and the /* ARN for object actions. Forge grants authority per bucket, so key prefixes are refused.
  • The refusal list now covers Version, Resource, ARN shape, Condition and NotPrincipal.
  • The canonical form and the ETag cover Version and Resource. Compare-and-set is unchanged.
  • The Ingot section says the operations go through versitygw's handlers and that versitygw's own validator runs before Hilt's.
  • The default Owner and Admin statements are gone. The console writes one statement naming a bucket's creator under an ordinary label, a role change touches no policy, the migration creates principals only, and the orchestrator serving a region fixes its access model.

References

🤖 Generated with Claude Code

… document

Version, ARN principals with an empty account field, and whole-bucket
Resource values, so AWS policy tooling works on Forge policies. Ingot
serves the policy operations through versitygw's handlers.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t with its statements as a list

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ument; the receipt carries none

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
pyropy added a commit to fil-forge/ingot that referenced this pull request Oct 14, 2026
…lers (#194)

Serves `GET`, `PUT` and `DELETE /{bucket}?policy` through versitygw's
own route table, auth and controllers. ingot's backend forwards each
operation to Hilt's `/s3/bucket/policy`. The policy document is now an
AWS bucket policy (fil-forge/hilt#96), so versitygw's `PutBucketPolicy`
validator accepts it and rejects anything that isn't AWS-shaped before
Hilt sees it. Hilt's stricter checks still decide.

- `s3frontend/policy.go`: `PutBucketPolicy`, `GetBucketPolicy` and
`DeleteBucketPolicy` forward the signed request from `reqscope`.
`GetBucketPolicy` forwards only a signed `GET ?policy`. versitygw's own
access checks get `NoSuchBucketPolicy`, so they never reach Hilt or
evaluate a policy, and an anonymous request is `AccessDenied`.
- `server.go`: a `policyHeaders` middleware sets the `ETag` Hilt
returned and `application/json` on a `GET`, because the backend
interface returns no headers. Preconditions reach Hilt in the signed
request.
- `iam`: `GetUserAccount` resolves `arn:aws:iam:::user/<id>`, so
versitygw's validator accepts ARN principals. Hilt checks that the
principal exists.
- `policy_routes.go` and its test are deleted.
- `itest/forge_bucket_policy_test.go` sends AWS-shaped documents and
covers a bare-name principal (refused by versitygw) and a missing
`Version` (refused by Hilt).

A policy request now reaches Hilt twice: versitygw's auth calls
`/s3/request/authorize`, then the backend calls `/s3/bucket/policy`.

## Change log

- `chore`: temporary pin of hilt to fil-forge/hilt#96 (`b2da449`), to be
re-pinned to main before merge. libforge stays pinned to
fil-forge/libforge#80.
- `feat(iam)`: resolve user ARNs for versitygw's policy validation.
- `feat(s3frontend)`: serve the bucket policy operations through the
backend.
- `refactor(s3)`: serve `?policy` through versitygw's controllers;
delete the route intercept.
- `test(itest)`: drive the bucket policy scenario with AWS-shaped
documents.

e2e: the `policies-local` suite passed against a fresh smelt running
hilt#96 and ingot#194, with the console from fil-one/fil-one#812 (102 of
103 passed; PU3 was flaky on its first attempt while the fresh Owner org
was still unnamed).

## References

- fil-one/RFC#30, the tenant IAM RFC; fil-one/RFC#34 updates it to the
AWS document.
- fil-one/fil-one#696, the bucket access ADR.
- fil-forge/hilt#96, the AWS-shaped policy document in Hilt.
- fil-forge/libforge#80.
- #178, the PR below this one in the stack.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
The console writes one statement naming a bucket's creator under an
ordinary label, a role change touches no policy, the migration creates
principals only, and the orchestrator serving a region fixes its access
model.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@pyropy
pyropy merged commit 1663fca into main Oct 15, 2026
2 checks passed
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