Browse Source

fix(auth): pass STS session token to IAM authorization for V4 signature auth

CRITICAL FIX: Session tokens were not being passed to the authorization
check when using AWS Signature V4 authentication with STS credentials.

The bug:
1. AWS SDK sends request with X-Amz-Security-Token header (V4 signature)
2. validateSTSSessionToken validates the token, creates Identity with PrincipalArn
3. authorizeWithIAM only checked X-SeaweedFS-Session-Token (JWT auth header)
4. Since it was empty, fell into 'static V4' branch which set SessionToken = ''
5. AuthorizeAction returned ErrAccessDenied because SessionToken was empty

The fix (in authorizeWithIAM):
- Check X-SeaweedFS-Session-Token first (JWT auth)
- If empty, fallback to X-Amz-Security-Token header (V4 STS auth)
- If still empty, check X-Amz-Security-Token query param (presigned URLs)
- When session token is found with PrincipalArn, use 'STS V4 signature' path
- Only use 'static V4' path when there's no session token

This ensures:
- JWT Bearer auth with session tokens works (existing path)
- STS V4 signature auth with session tokens works (new path)
- Static V4 signature auth without session tokens works (existing path)

Logging updated to distinguish:
- 'JWT-based IAM authorization'
- 'STS V4 signature IAM authorization' (new)
- 'static V4 signature IAM authorization' (clarified)
pull/7944/head
Chris Lu 1 month ago
parent
commit
fa8830c71d
  1. 27
      weed/s3api/auth_credentials.go

27
weed/s3api/auth_credentials.go

@ -955,27 +955,44 @@ func (iam *IdentityAccessManagement) authenticateJWTWithIAM(r *http.Request) (*I
func (iam *IdentityAccessManagement) authorizeWithIAM(r *http.Request, identity *Identity, action Action, bucket string, object string) s3err.ErrorCode {
ctx := r.Context()
// Get session info from request headers (for JWT-based authentication)
// Get session info from request headers
// First check for JWT-based authentication headers (X-SeaweedFS-Session-Token)
sessionToken := r.Header.Get("X-SeaweedFS-Session-Token")
principal := r.Header.Get("X-SeaweedFS-Principal")
// Fallback to AWS Signature V4 STS token if JWT token not present
// This handles the case where STS AssumeRoleWithWebIdentity generates temporary credentials
// that include an X-Amz-Security-Token header (in addition to the access key and secret)
if sessionToken == "" {
sessionToken = r.Header.Get("X-Amz-Security-Token")
if sessionToken == "" {
// Also check query parameters for presigned URLs with STS tokens
sessionToken = r.URL.Query().Get("X-Amz-Security-Token")
}
}
// Create IAMIdentity for authorization
iamIdentity := &IAMIdentity{
Name: identity.Name,
Account: identity.Account,
}
// Handle both session-based (JWT) and static-key-based (V4 signature) principals
// Handle both session-based (JWT and STS) and static-key-based (V4 signature) principals
if sessionToken != "" && principal != "" {
// JWT-based authentication - use session token and principal from headers
iamIdentity.Principal = principal
iamIdentity.SessionToken = sessionToken
glog.V(3).Infof("Using JWT-based IAM authorization for principal: %s", principal)
} else if sessionToken != "" && identity.PrincipalArn != "" {
// STS V4 signature authentication - use session token (from X-Amz-Security-Token) with principal ARN
iamIdentity.Principal = identity.PrincipalArn
iamIdentity.SessionToken = sessionToken
glog.V(3).Infof("Using STS V4 signature IAM authorization for principal: %s with session token", identity.PrincipalArn)
} else if identity.PrincipalArn != "" {
// V4 signature authentication - use principal ARN from identity
// Static V4 signature authentication - use principal ARN without session token
iamIdentity.Principal = identity.PrincipalArn
iamIdentity.SessionToken = "" // No session token for static credentials
glog.V(3).Infof("Using V4 signature IAM authorization for principal: %s", identity.PrincipalArn)
iamIdentity.SessionToken = ""
glog.V(3).Infof("Using static V4 signature IAM authorization for principal: %s", identity.PrincipalArn)
} else {
glog.V(3).Info("No valid principal information for IAM authorization")
return s3err.ErrAccessDenied

Loading…
Cancel
Save