π fix: RBAC follow-ups β CORS POST, reuse agentAuthHeaders, accurate header comment#8198
π fix: RBAC follow-ups β CORS POST, reuse agentAuthHeaders, accurate header comment#8198clubanderson merged 1 commit intomainfrom
Conversation
β¦header comment (#8188) Addresses three Copilot review comments on merged #8185: 1. handleCanIHTTP is a POST endpoint but setCORSHeaders was defaulting Access-Control-Allow-Methods to "GET, OPTIONS", so browser preflight requests for POST would fail. Generalized setCORSHeaders with a variadic methods parameter β back-compat preserved because callers that pass nothing still get defaultCORSAllowedMethods ("GET, OPTIONS"). handleCanIHTTP now passes http.MethodPost + http.MethodOptions. 2. useClusterPermissions re-implemented the agent auth-header logic and sent "Authorization: ''" when no token was stored, which the agent rejects. Refactored to reuse the existing agentAuthHeaders() helper (it correctly omits the header when no token is configured). 3. server_rbac.go file header comment called the pre-#8185 behavior a "privilege-escalation vector". Rewrote it to describe the actual impact: misleading RBAC display β CheckCanI ran under the pod SA, so the UI showed system permissions instead of the caller's. No real privilege escalation occurred (mutations already flowed through kc-agent under the user's identity). Added server_rbac_test.go covering the POST CORS preflight for handleCanIHTTP plus the setCORSHeaders back-compat default and explicit methods paths. Fixes #8188 Signed-off-by: Andy Anderson <[email protected]>
β Deploy Preview for kubestellarconsole ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
π Hey @clubanderson β thanks for opening this PR!
This is an automated message. |
There was a problem hiding this comment.
Pull request overview
Follow-up fixes for RBAC introspection via kc-agent (#7993 Phase 6), focused on CORS correctness for POST, reusing frontend auth-header logic, and correcting prior commentary about the impact of pod-SA RBAC checks.
Changes:
- Generalize kc-agent
setCORSHeadersto accept optional allowed methods and update/rbac/can-ito advertisePOST, OPTIONS. - Refactor
useClusterPermissionsto reuseagentAuthHeaders()(avoids sending an emptyAuthorizationheader). - Add kc-agent unit tests covering CORS method defaults/overrides and update RBAC handler header comment to reflect accurate impact.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| web/src/hooks/useUsers.ts | Reuses agentAuthHeaders() for /rbac/permissions fetch to avoid empty Authorization header. |
| pkg/agent/server_rbac_test.go | Adds tests for CORS method handling and POST preflight behavior for /rbac/can-i. |
| pkg/agent/server_rbac.go | Updates file header comment and ensures /rbac/can-i advertises POST in CORS methods. |
| pkg/agent/server_http.go | Updates setCORSHeaders to support optional allowed-method overrides with a back-compat default. |
| allowed := defaultCORSAllowedMethods | ||
| if len(methods) > 0 { | ||
| allowed = strings.Join(methods, ", ") | ||
| } | ||
| w.Header().Set("Access-Control-Allow-Methods", allowed) |
There was a problem hiding this comment.
setCORSHeaders still defaults Access-Control-Allow-Methods to "GET, OPTIONS" unless callers pass an explicit method list. There are existing kc-agent handlers that serve POST/DELETE (e.g., /serviceaccounts, /rolebindings, /namespaces, /serviceexports, gitops endpoints) that currently call setCORSHeaders(w,r) without overriding the header, so browser CORS preflight for those mutating requests will still fail. Please update those handlers to pass the full allowed method set into setCORSHeaders (or have setCORSHeaders automatically include the current request method + OPTIONS) so POST/DELETE routes work reliably from the web UI.
|
Thank you for your contribution! Your PR has been merged. Check out what's new:
Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey |
|
Post-merge build verification passed β Both Go and frontend builds compiled successfully against merge commit |
β Post-Merge Verification: passedCommit: |
Copilot review on merged PR #8198 flagged that setCORSHeaders still defaults Access-Control-Allow-Methods to "GET, OPTIONS" unless callers pass an explicit method list, and that several existing kc-agent handlers serving POST/DELETE (e.g. /serviceaccounts) were still calling setCORSHeaders(w, r) without methods, so their preflight responses advertised only GET/OPTIONS and browsers rejected cross-origin POST/DELETE. This PR audits every setCORSHeaders caller in pkg/agent and updates the non-GET handlers to pass an explicit method list. The default of "GET, OPTIONS" is preserved for back-compat and remains correct for the read-only handlers. Handlers updated to advertise correct Allow-Methods on preflight: server_http.go - handleNamespacesHTTP GET, POST, DELETE, OPTIONS - handleServiceAccountsHTTP GET, POST, DELETE, OPTIONS - handleServiceExportsHTTP POST, DELETE, OPTIONS - handleRoleBindingsHTTP GET, POST, DELETE, OPTIONS - handleScaleHTTP POST, OPTIONS (consolidated from inline) - handleDeployWorkloadHTTP POST, OPTIONS (consolidated from inline) - handleDeleteWorkloadHTTP POST, OPTIONS (consolidated from inline) - handleAutoUpdateConfig GET, POST, OPTIONS (was OPTIONS-only) - handleAutoUpdateTrigger POST, OPTIONS (was OPTIONS-only) - handleAutoUpdateCancel POST, OPTIONS (was OPTIONS-only) - handleKubeconfigRemoveHTTP POST, OPTIONS (consolidated from inline) server_helm.go - handleHelmRollback POST, OPTIONS - handleHelmUninstall POST, OPTIONS - handleHelmUpgrade POST, OPTIONS server_gitops.go - handleDetectDrift POST, OPTIONS - handleGitopsSync POST, OPTIONS server_console_cr.go - handleConsoleCRManagedWorkloads POST, PUT, DELETE, OPTIONS - handleConsoleCRClusterGroups POST, PUT, DELETE, OPTIONS - handleConsoleCRWorkloadDeployments POST, DELETE, OPTIONS - handleConsoleCRWorkloadDeploymentStatus PUT, OPTIONS server_argocd.go - handleArgoCDSync POST, OPTIONS (consolidated from inline) server_gpu_health.go - handleGPUHealthCronJob POST, DELETE, OPTIONS server_operations.go - handleLocalClusters GET, POST, DELETE, OPTIONS - handleLocalClusterLifecycle POST, OPTIONS - handleVClusterCreate POST, OPTIONS - handleVClusterConnect POST, OPTIONS - handleVClusterDisconnect POST, OPTIONS - handleVClusterDelete POST, OPTIONS GET-only handlers (gpu-nodes, nodes, pods, events, deployments, replicasets, statefulsets, daemonsets, cronjobs, ingresses, services, configmaps, secrets, jobs, hpas, pvcs, roles, resourcequotas, limitranges, resolvedeps, clusterhealth, autoupdatestatus, kagenti/*, kagent-crds/*, prometheus query, vCluster list/check, cloudCLIStatus, localClusterTools, rbac/permissions, permissions/summary) keep the default and remain correct. Also updates the setCORSHeaders doc comment with an explicit audit rule so future handlers serving non-GET methods don't silently regress. Adds a regression test (TestHandleServiceAccounts_CORSMethodsHeader) that pins the fix on the specific handler Copilot called out. Fixes #8201 Signed-off-by: Andy Anderson <[email protected]>
β¦8212) Copilot review on merged PR #8198 flagged that setCORSHeaders still defaults Access-Control-Allow-Methods to "GET, OPTIONS" unless callers pass an explicit method list, and that several existing kc-agent handlers serving POST/DELETE (e.g. /serviceaccounts) were still calling setCORSHeaders(w, r) without methods, so their preflight responses advertised only GET/OPTIONS and browsers rejected cross-origin POST/DELETE. This PR audits every setCORSHeaders caller in pkg/agent and updates the non-GET handlers to pass an explicit method list. The default of "GET, OPTIONS" is preserved for back-compat and remains correct for the read-only handlers. Handlers updated to advertise correct Allow-Methods on preflight: server_http.go - handleNamespacesHTTP GET, POST, DELETE, OPTIONS - handleServiceAccountsHTTP GET, POST, DELETE, OPTIONS - handleServiceExportsHTTP POST, DELETE, OPTIONS - handleRoleBindingsHTTP GET, POST, DELETE, OPTIONS - handleScaleHTTP POST, OPTIONS (consolidated from inline) - handleDeployWorkloadHTTP POST, OPTIONS (consolidated from inline) - handleDeleteWorkloadHTTP POST, OPTIONS (consolidated from inline) - handleAutoUpdateConfig GET, POST, OPTIONS (was OPTIONS-only) - handleAutoUpdateTrigger POST, OPTIONS (was OPTIONS-only) - handleAutoUpdateCancel POST, OPTIONS (was OPTIONS-only) - handleKubeconfigRemoveHTTP POST, OPTIONS (consolidated from inline) server_helm.go - handleHelmRollback POST, OPTIONS - handleHelmUninstall POST, OPTIONS - handleHelmUpgrade POST, OPTIONS server_gitops.go - handleDetectDrift POST, OPTIONS - handleGitopsSync POST, OPTIONS server_console_cr.go - handleConsoleCRManagedWorkloads POST, PUT, DELETE, OPTIONS - handleConsoleCRClusterGroups POST, PUT, DELETE, OPTIONS - handleConsoleCRWorkloadDeployments POST, DELETE, OPTIONS - handleConsoleCRWorkloadDeploymentStatus PUT, OPTIONS server_argocd.go - handleArgoCDSync POST, OPTIONS (consolidated from inline) server_gpu_health.go - handleGPUHealthCronJob POST, DELETE, OPTIONS server_operations.go - handleLocalClusters GET, POST, DELETE, OPTIONS - handleLocalClusterLifecycle POST, OPTIONS - handleVClusterCreate POST, OPTIONS - handleVClusterConnect POST, OPTIONS - handleVClusterDisconnect POST, OPTIONS - handleVClusterDelete POST, OPTIONS GET-only handlers (gpu-nodes, nodes, pods, events, deployments, replicasets, statefulsets, daemonsets, cronjobs, ingresses, services, configmaps, secrets, jobs, hpas, pvcs, roles, resourcequotas, limitranges, resolvedeps, clusterhealth, autoupdatestatus, kagenti/*, kagent-crds/*, prometheus query, vCluster list/check, cloudCLIStatus, localClusterTools, rbac/permissions, permissions/summary) keep the default and remain correct. Also updates the setCORSHeaders doc comment with an explicit audit rule so future handlers serving non-GET methods don't silently regress. Adds a regression test (TestHandleServiceAccounts_CORSMethodsHeader) that pins the fix on the specific handler Copilot called out. Fixes #8201 Signed-off-by: Andy Anderson <[email protected]>
Fixes #8188
Addresses three Copilot review comments on merged #8185 (route RBAC introspection through kc-agent, #7993 Phase 6).
Finding 1 β POST preflight CORS
handleCanIHTTPis a POST endpoint butsetCORSHeadersdefaultedAccess-Control-Allow-Methodsto"GET, OPTIONS", so browser preflight for POST would fail.Generalized
setCORSHeaderswith a variadicmethods ...stringparameter:defaultCORSAllowedMethods("GET, OPTIONS") β fully back-compat, all 70+ existing call sites untouched.handleCanIHTTPnow passeshttp.MethodPost, http.MethodOptions.Finding 2 β reuse agentAuthHeaders()
useClusterPermissionsre-implemented the agent auth-header logic and sentAuthorization: ''when no token was stored (the agent rejects empty Bearer tokens). Refactored to reuse the existingagentAuthHeaders()helper, which correctly omits the header when no token is configured. The old fetch was a plain GET with no body, so noContent-Typeis needed.Finding 3 β accurate header comment
The
server_rbac.goheader comment called the pre-#8185 behavior a "privilege-escalation vector". That's wrong β the PR description of #8185 explicitly noted the impact was cosmetic/UX only (no real escalation because mutations already flowed through kc-agent under the user's identity).Rewrote the comment to describe the real problem: misleading RBAC display β
CheckCanIran under the pod SA, so the UI showed system permissions instead of the caller's.Tests
Added
pkg/agent/server_rbac_test.go:TestHandleCanIHTTP_CORSMethodsHeaderβ POST preflight advertises POST.TestSetCORSHeaders_DefaultsToGETβ back-compat: no methods β"GET, OPTIONS".TestSetCORSHeaders_ExplicitMethodsJoinedβ explicit methods are comma-joined.Validation
go build ./...passesgo test ./pkg/agent/... -run 'RBAC|CanI|CORS' -vpasses (9 tests)cd web && npm run buildpasses (post-build safety checks green)cd web && npm run lintonuseUsers.tsonly flags 2 pre-existing errors on lines 378/587 (unrelated)