Skip to content

πŸ”’ fix: RBAC follow-ups β€” CORS POST, reuse agentAuthHeaders, accurate header comment#8198

Merged
clubanderson merged 1 commit intomainfrom
fix/rbac-nits-8188
Apr 15, 2026
Merged

πŸ”’ fix: RBAC follow-ups β€” CORS POST, reuse agentAuthHeaders, accurate header comment#8198
clubanderson merged 1 commit intomainfrom
fix/rbac-nits-8188

Conversation

@clubanderson
Copy link
Copy Markdown
Collaborator

Fixes #8188

Addresses three Copilot review comments on merged #8185 (route RBAC introspection through kc-agent, #7993 Phase 6).

Finding 1 β€” POST preflight CORS

handleCanIHTTP is a POST endpoint but setCORSHeaders defaulted Access-Control-Allow-Methods to "GET, OPTIONS", so browser preflight for POST would fail.

Generalized setCORSHeaders with a variadic methods ...string parameter:

  • Callers that pass nothing still get defaultCORSAllowedMethods ("GET, OPTIONS") β€” fully back-compat, all 70+ existing call sites untouched.
  • handleCanIHTTP now passes http.MethodPost, http.MethodOptions.

Finding 2 β€” reuse agentAuthHeaders()

useClusterPermissions re-implemented the agent auth-header logic and sent Authorization: '' when no token was stored (the agent rejects empty Bearer tokens). Refactored to reuse the existing agentAuthHeaders() helper, which correctly omits the header when no token is configured. The old fetch was a plain GET with no body, so no Content-Type is needed.

Finding 3 β€” accurate header comment

The server_rbac.go header 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 β€” CheckCanI ran 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 ./... passes
  • go test ./pkg/agent/... -run 'RBAC|CanI|CORS' -v passes (9 tests)
  • cd web && npm run build passes (post-build safety checks green)
  • cd web && npm run lint on useUsers.ts only flags 2 pre-existing errors on lines 378/587 (unrelated)

…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]>
@clubanderson clubanderson added the ai-generated Pull request generated by AI label Apr 15, 2026
Copilot AI review requested due to automatic review settings April 15, 2026 18:25
@kubestellar-prow kubestellar-prow Bot added the dco-signoff: yes Indicates the PR's author has signed the DCO. label Apr 15, 2026
@netlify
Copy link
Copy Markdown

netlify Bot commented Apr 15, 2026

βœ… Deploy Preview for kubestellarconsole ready!

Name Link
πŸ”¨ Latest commit ec78c31
πŸ” Latest deploy log https://app.netlify.com/projects/kubestellarconsole/deploys/69dfd81f541b04000881b6dd
😎 Deploy Preview https://deploy-preview-8198.console-deploy-preview.kubestellar.io
πŸ“± Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@kubestellar-prow
Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clubanderson for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@kubestellar-prow kubestellar-prow Bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Apr 15, 2026
@github-actions
Copy link
Copy Markdown
Contributor

πŸ‘‹ Hey @clubanderson β€” thanks for opening this PR!

πŸ€– This project is developed exclusively using AI coding assistants.

Please do not attempt to code anything for this project manually.
All contributions should be authored using an AI coding tool such as:

This ensures consistency in code style, architecture patterns, test coverage,
and commit quality across the entire codebase.


This is an automated message.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 setCORSHeaders to accept optional allowed methods and update /rbac/can-i to advertise POST, OPTIONS.
  • Refactor useClusterPermissions to reuse agentAuthHeaders() (avoids sending an empty Authorization header).
  • 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.

Comment thread pkg/agent/server_http.go
Comment on lines +1972 to +1976
allowed := defaultCORSAllowedMethods
if len(methods) > 0 {
allowed = strings.Join(methods, ", ")
}
w.Header().Set("Access-Control-Allow-Methods", allowed)
Copy link

Copilot AI Apr 15, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copilot uses AI. Check for mistakes.
@clubanderson clubanderson merged commit 9169b9a into main Apr 15, 2026
48 of 49 checks passed
@clubanderson clubanderson deleted the fix/rbac-nits-8188 branch April 15, 2026 18:30
@github-actions
Copy link
Copy Markdown
Contributor

Thank you for your contribution! Your PR has been merged.

Check out what's new:

Stay connected: Slack #kubestellar-dev | Multi-Cluster Survey

@github-actions
Copy link
Copy Markdown
Contributor

Post-merge build verification passed βœ…

Both Go and frontend builds compiled successfully against merge commit 9169b9a0aa1df395ac7daddae8b00f664bbba1fa.

@github-actions
Copy link
Copy Markdown
Contributor

βœ… Post-Merge Verification: passed

Commit: 9169b9a0aa1df395ac7daddae8b00f664bbba1fa
Specs run: smoke.spec.ts
Report: https://github.com/kubestellar/console/actions/runs/24471374063

clubanderson added a commit that referenced this pull request Apr 15, 2026
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]>
clubanderson added a commit that referenced this pull request Apr 15, 2026
…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]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ai-generated Pull request generated by AI dco-signoff: yes Indicates the PR's author has signed the DCO. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Copilot Review] 3 comment(s) on merged PR #8185

2 participants