From f05174466b93f1ffcd33b936e75b109a5808eee1 Mon Sep 17 00:00:00 2001 From: Chris Lu Date: Sat, 14 Feb 2026 14:13:29 -0800 Subject: [PATCH] S3 STS: Use caller identity when RoleArn is missing - Fallback to PrincipalArn/Context in AssumeRole if RoleArn is empty - Handle User ARNs in prepareSTSCredentials - Fix PrincipalArn generation for env var credentials --- weed/iam/sts/sts_service.go | 4 ---- weed/s3api/auth_credentials.go | 3 ++- weed/s3api/s3api_sts.go | 32 ++++++++++++++++---------------- 3 files changed, 18 insertions(+), 21 deletions(-) diff --git a/weed/iam/sts/sts_service.go b/weed/iam/sts/sts_service.go index a9f019cbb..f3df00fd2 100644 --- a/weed/iam/sts/sts_service.go +++ b/weed/iam/sts/sts_service.go @@ -105,10 +105,6 @@ type STSConfig struct { // Defaults to "111122223333" if not specified AccountId string `json:"accountId,omitempty"` - // DefaultRole is the default role ARN to assume if RoleArn is missing - // Defaults to "root" role if not specified - DefaultRole string `json:"defaultRole,omitempty"` - // Providers configuration - enables automatic provider loading Providers []*ProviderConfig `json:"providers,omitempty"` } diff --git a/weed/s3api/auth_credentials.go b/weed/s3api/auth_credentials.go index 822b2cbf3..9c567026b 100644 --- a/weed/s3api/auth_credentials.go +++ b/weed/s3api/auth_credentials.go @@ -300,7 +300,8 @@ func (iam *IdentityAccessManagement) loadEnvironmentVariableCredentials() { Actions: []Action{ s3_constants.ACTION_ADMIN, }, - IsStatic: true, + PrincipalArn: generatePrincipalArn(identityName), + IsStatic: true, } iam.m.Lock() diff --git a/weed/s3api/s3api_sts.go b/weed/s3api/s3api_sts.go index a79b71106..1dcac3151 100644 --- a/weed/s3api/s3api_sts.go +++ b/weed/s3api/s3api_sts.go @@ -303,8 +303,16 @@ func (h *STSHandlers) handleAssumeRole(w http.ResponseWriter, r *http.Request) { return } } else { + // If RoleArn is missing, default to the caller's identity (User Context) + // This allows the user to "assume" a session for themselves, inheriting their own permissions. + roleArn = identity.PrincipalArn + glog.V(2).Infof("AssumeRole: no RoleArn provided, defaulting to caller identity: %s", roleArn) + + // We still enforce a global "sts:AssumeRole" check, similar to how we'd check if they can assume *any* role. + // However, for self-assumption, this might be implicit. + // For safety/consistency with previous logic, we keep the check but strictly it might not be required by AWS for GetSessionToken. + // But since this IS AssumeRole, let's keep it. // Admin/Global check when no specific role is requested - // Ensure caller has sts:AssumeRole permission globally (on "arn:aws:s3:::*") if authErr := h.iam.VerifyActionPermission(r, identity, Action("sts:AssumeRole"), "", ""); authErr != s3err.ErrNone { glog.Warningf("AssumeRole: caller %s attempted to assume role without RoleArn and lacks global sts:AssumeRole permission", identity.Name) h.writeSTSErrorResponse(w, r, STSErrAccessDenied, fmt.Errorf("access denied")) @@ -499,22 +507,14 @@ func (h *STSHandlers) prepareSTSCredentials(roleArn, roleSessionName string, expiration := time.Now().Add(duration) // Extract role name from ARN for proper response formatting - // Extract role name from ARN for proper response formatting - roleName := utils.ExtractRoleNameFromArn(roleArn) + roleName := utils.ExtractRoleNameFromPrincipal(roleArn) if roleName == "" { - if roleArn != "" { - roleName = roleArn // Fallback to full ARN if extraction fails - } else { - // Check if a default role is configured - if h.stsService != nil && h.stsService.Config != nil && h.stsService.Config.DefaultRole != "" { - roleName = utils.ExtractRoleNameFromArn(h.stsService.Config.DefaultRole) - if roleName == "" { - roleName = "root" // Fallback if configured default role ARN is invalid - } - } else { - roleName = "root" - } - } + // Try to extract user name if it's a user ARN (for "User Context" assumption) + roleName = utils.ExtractUserNameFromPrincipal(roleArn) + } + + if roleName == "" { + roleName = roleArn // Fallback to full ARN if extraction fails } accountID := h.getAccountID()