mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2026-08-19 05:36:58 +00:00
fix: extract role information from JWT token in presigned URL validation
The TestPresignedURLIAMValidation was failing because the presigned URL validation was hardcoding the principal ARN as 'PresignedUser' instead of extracting the actual role from the JWT session token. ### Problem: - Test used session token from S3ReadOnlyRole - ValidatePresignedURLWithIAM hardcoded principal as PresignedUser - Authorization checked wrong role permissions - PUT operation incorrectly succeeded instead of being denied ### Solution: - Extract role and session information from JWT token claims - Use parseJWTToken() to get 'role' and 'snam' claims - Build correct principal ARN from token data - Use 'principal' claim directly if available, fallback to constructed ARN ### Test Results: ✅ TestPresignedURLIAMValidation: All 4 test cases now pass ✅ GET with read permissions: ALLOWED (correct) ✅ PUT with read-only permissions: DENIED (correct - was failing before) ✅ GET without session token: Falls back to standard auth ✅ Invalid session token: Correctly rejected ### Technical Details: - Principal now correctly shows: arn:seaweed:sts::assumed-role/S3ReadOnlyRole/presigned-test-session - Authorization logic now validates against actual assumed role - Maintains compatibility with existing presigned URL generation tests - All 20+ presigned URL tests continue to pass This ensures presigned URLs respect the actual IAM role permissions from the session token, providing proper security enforcement.
This commit is contained in:
@@ -70,9 +70,38 @@ func (iam *IdentityAccessManagement) ValidatePresignedURLWithIAM(r *http.Request
|
||||
return s3err.ErrNone
|
||||
}
|
||||
|
||||
// Create IAM identity for authorization
|
||||
// Use a proper ARN format for the principal
|
||||
principalArn := fmt.Sprintf("arn:seaweed:sts::assumed-role/PresignedUser/%s", identity.Name)
|
||||
// Parse JWT token to extract role and session information
|
||||
tokenClaims, err := parseJWTToken(sessionToken)
|
||||
if err != nil {
|
||||
glog.V(3).Infof("Failed to parse JWT token in presigned URL: %v", err)
|
||||
return s3err.ErrAccessDenied
|
||||
}
|
||||
|
||||
// Extract role information from token claims
|
||||
roleName, ok := tokenClaims["role"].(string)
|
||||
if !ok || roleName == "" {
|
||||
glog.V(3).Info("No role found in JWT token for presigned URL")
|
||||
return s3err.ErrAccessDenied
|
||||
}
|
||||
|
||||
sessionName, ok := tokenClaims["snam"].(string)
|
||||
if !ok || sessionName == "" {
|
||||
sessionName = "presigned-session" // Default fallback
|
||||
}
|
||||
|
||||
// Use the principal ARN directly from token claims, or build it if not available
|
||||
principalArn, ok := tokenClaims["principal"].(string)
|
||||
if !ok || principalArn == "" {
|
||||
// Fallback: extract role name from role ARN and build principal ARN
|
||||
roleNameOnly := roleName
|
||||
if strings.Contains(roleName, "/") {
|
||||
parts := strings.Split(roleName, "/")
|
||||
roleNameOnly = parts[len(parts)-1]
|
||||
}
|
||||
principalArn = fmt.Sprintf("arn:seaweed:sts::assumed-role/%s/%s", roleNameOnly, sessionName)
|
||||
}
|
||||
|
||||
// Create IAM identity for authorization using extracted information
|
||||
iamIdentity := &IAMIdentity{
|
||||
Name: identity.Name,
|
||||
Principal: principalArn,
|
||||
|
||||
Reference in New Issue
Block a user