mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-10-31 17:30:42 +01:00
s3: audit the assumed-role principal and the STS caller (#10519)
* s3: log the requester's principal ARN in the audit entry An STS session authenticates as an opaque session subject, so requester alone gave an operator no way back to the assumed role or the session name. Record the principal ARN next to the identity name and emit it as requester_arn. * s3: record the caller identity in the STS handlers AssumeRole, GetFederationToken and GetCallerIdentity verify the caller themselves and are not wrapped by the auth middleware that records the identity, so every audit entry for minting a session had an empty requester. * s3: resolve the audit principal ARN the way policy evaluation does A JWT-authenticated identity carries no PrincipalArn — the auth layer hands the principal over in a request header — so reading the field directly left requester_arn empty for OIDC callers. buildPrincipalARN is the resolver the policy path already uses: header first, then the identity's own ARN, then a synthesized user ARN for legacy identities that have none.
This commit is contained in:
1 parent
fa432f9a6a
commit
1ce106e69d
9 files changed
+220
-27
No files matched your search
@@ -1467,15 +1467,27 @@ func (iam *IdentityAccessManagement) AuthPostPolicy(f http.HandlerFunc, action A
|
||||
}
|
||||
}
|
||||
|
||||
// recordIdentityInContext stores the authenticated identity, its name and its
|
||||
// principal ARN in the request context. An STS session's name is only an opaque
|
||||
// subject, so the ARN is what carries the assumed role and session name to the
|
||||
// audit log. A JWT-authenticated identity carries no PrincipalArn of its own,
|
||||
// hence the resolution through buildPrincipalARN.
|
||||
func recordIdentityInContext(r *http.Request, identity *Identity) context.Context {
|
||||
if identity == nil {
|
||||
return r.Context()
|
||||
}
|
||||
ctx := s3_constants.SetIdentityNameInContext(r.Context(), identity.Name)
|
||||
ctx = s3_constants.SetPrincipalArnInContext(ctx, buildPrincipalARN(identity, r))
|
||||
// Also store the full identity object for handlers that need it (e.g., ListBuckets)
|
||||
// This is especially important for JWT users whose identity is not in the identities list
|
||||
return s3_constants.SetIdentityInContext(ctx, identity)
|
||||
}
|
||||
|
||||
func (iam *IdentityAccessManagement) handleAuthResult(w http.ResponseWriter, r *http.Request, identity *Identity, errCode s3err.ErrorCode, f http.HandlerFunc) {
|
||||
if errCode == s3err.ErrNone {
|
||||
// Store the authenticated identity in request context (secure, cannot be spoofed)
|
||||
if identity != nil && identity.Name != "" {
|
||||
ctx := s3_constants.SetIdentityNameInContext(r.Context(), identity.Name)
|
||||
// Also store the full identity object for handlers that need it (e.g., ListBuckets)
|
||||
// This is especially important for JWT users whose identity is not in the identities list
|
||||
ctx = s3_constants.SetIdentityInContext(ctx, identity)
|
||||
r = r.WithContext(ctx)
|
||||
r = r.WithContext(recordIdentityInContext(r, identity))
|
||||
}
|
||||
f(w, r)
|
||||
return
|
||||
|
||||
Reference in new issue
Block a user