s3tables: re-anchor legacy owners for federated STS sessions

A web-identity role session was keyed on its bare OIDC subject until
owners became issuer-scoped. Its sessions now carry the scoped aws:userid
but no asserted issuers, so the legacy subject check never applied and the
session lost the table buckets and namespaces it had created. Read the
configured issuer set for such sessions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Chris LuandClaude Opus 5.5 committed 2026-11-13 02:56:59 -08:00
1 parent a576398662
commit fc8f4c6ecb
3 files changed
+37 -3

No files matched your search

+19 -3
View File
@@ -11,6 +11,7 @@ import (
"strings"
"github.com/seaweedfs/seaweedfs/weed/glog"
"github.com/seaweedfs/seaweedfs/weed/iam/sts"
"github.com/seaweedfs/seaweedfs/weed/pb/filer_pb"
"github.com/seaweedfs/seaweedfs/weed/s3api/s3_constants"
)
@@ -79,6 +80,7 @@ type S3TablesHandler struct {
trusted bool // Trusted local tooling (shell/admin) bypasses authorization
iamAuthorizer IAMAuthorizer
localAccountIDs func(string) bool
oidcIssuers func(context.Context) []string
canEncrypt func() bool
}
@@ -123,6 +125,12 @@ func (h *S3TablesHandler) SetLocalAccountChecker(fn func(string) bool) {
h.localAccountIDs = fn
}
// SetTrustedIssuerSource injects the configured OIDC issuer set. A federated
// STS session carries no asserted issuers, so its legacy owner checks read it.
func (h *S3TablesHandler) SetTrustedIssuerSource(fn func(context.Context) []string) {
h.oidcIssuers = fn
}
// SetEncryptionChecker injects the predicate that tells whether the gateway
// holds an SSE-S3 key, so a bucket whose declared AES256 the write path
// applies is not created where every write would then fail.
@@ -390,8 +398,9 @@ func claimString(claims map[string]interface{}, key string) string {
return str
}
// trustedIssuers returns the OIDC issuers the auth layer asserted into the
// identity's claims; they re-anchor legacy owner checks in checkPermission.
// trustedIssuers returns the OIDC issuers that re-anchor legacy owner checks in
// checkPermission: those the auth layer asserted into a bearer token's claims,
// else, for a federated STS session, the configured set.
func (h *S3TablesHandler) trustedIssuers(r *http.Request) []string {
identityRaw := s3_constants.GetIdentityFromContext(r)
if identityRaw == nil {
@@ -404,7 +413,14 @@ func (h *S3TablesHandler) trustedIssuers(r *http.Request) []string {
if val.Kind() != reflect.Struct {
return nil
}
return strings.Fields(claimString(identityClaimsMap(val), "seaweed:oidc-issuers"))
claims := identityClaimsMap(val)
if _, asserted := claims["seaweed:oidc-issuers"]; asserted {
return strings.Fields(claimString(claims, "seaweed:oidc-issuers"))
}
if h.oidcIssuers != nil && sts.IsParentUserID(claimString(claims, "aws:userid")) {
return h.oidcIssuers(r.Context())
}
return nil
}
// normalizePrincipalID collapses ARN and identity strings to a key that is stable within a single account.