Skip to content

OCPBUGS-72526: Impersonating user loads extra pages that user not authorized to view#16088

Open
Leo6Leo wants to merge 1 commit intoopenshift:mainfrom
Leo6Leo:leo/OCPBUGS-72526/impersonation-access-hide-tabs
Open

OCPBUGS-72526: Impersonating user loads extra pages that user not authorized to view#16088
Leo6Leo wants to merge 1 commit intoopenshift:mainfrom
Leo6Leo:leo/OCPBUGS-72526/impersonation-access-hide-tabs

Conversation

@Leo6Leo
Copy link
Contributor

@Leo6Leo Leo6Leo commented Mar 2, 2026

Description

The issue is that when impersonating a user, the SelfSubjectAccessReview checks that determine page visibility are sent via GraphQL but the backend GraphQL HTTP handler wasn't forwarding impersonation headers to the Kubernetes API. So the K8s API always evaluated permissions as kube:admin, not the impersonated user

Steps to QA

  1. kube:admin user impersonate a normal user
  2. wait until the message You are impersonating User testuser-1. You are viewing all resources and roles this User can access. Stop Impersonating appear in masthead, then check the pages
  3. Now you should not be able to see some of the tabs that the testuser-1 doesn't have enough access to view, such as: Home -> Overview, Compute, Administration -> Cluster Settings, Namespaces pages etc.

Summary by CodeRabbit

  • New Features

    • Added HTTP transport override capability for improved connectivity management.
  • Bug Fixes

    • Enhanced impersonation mode with better header handling during feature updates.
    • Improved WebSocket fallback to HTTP when connectivity is unavailable.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 2, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 2, 2026

@Leo6Leo: This pull request references CONSOLE-5070 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Description

The issue is that when impersonating a user, the SelfSubjectAccessReview checks that determine page visibility are sent via GraphQL but the backend GraphQL HTTP handler wasn't forwarding impersonation headers to the Kubernetes API. So the K8s API always evaluated permissions as kube:admin, not the impersonated user

Steps to QA

  1. kube:admin user impersonate a normal user
  2. wait until the message You are impersonating User testuser-1. You are viewing all resources and roles this User can access. Stop Impersonating appear in masthead, then check the pages
  3. Now you should not be able to see some of the tabs that the testuser-1 doesn't have enough access to view, such as: Home -> Overview, Compute, Administration -> Cluster Settings, Namespaces pages etc.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested review from TheRealJon and jhadvig March 2, 2026 15:14
@openshift-ci openshift-ci bot added the component/backend Related to backend label Mar 2, 2026
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 2, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: Leo6Leo
Once this PR has been reviewed and has the lgtm label, please assign jhadvig 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

@openshift-ci openshift-ci bot added the component/core Related to console core functionality label Mar 2, 2026
@Leo6Leo Leo6Leo changed the title CONSOLE-5070: Impersonating user loads extra pages that user not authorized to view OCPBUGS-72526: Impersonating user loads extra pages that user not authorized to view Mar 2, 2026
@openshift-ci-robot openshift-ci-robot added jira/severity-moderate Referenced Jira bug's severity is moderate for the branch this PR is targeting. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Mar 2, 2026
@openshift-ci-robot
Copy link
Contributor

@Leo6Leo: This pull request references Jira Issue OCPBUGS-72526, which is invalid:

  • expected the bug to target the "4.22.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Description

The issue is that when impersonating a user, the SelfSubjectAccessReview checks that determine page visibility are sent via GraphQL but the backend GraphQL HTTP handler wasn't forwarding impersonation headers to the Kubernetes API. So the K8s API always evaluated permissions as kube:admin, not the impersonated user

Steps to QA

  1. kube:admin user impersonate a normal user
  2. wait until the message You are impersonating User testuser-1. You are viewing all resources and roles this User can access. Stop Impersonating appear in masthead, then check the pages
  3. Now you should not be able to see some of the tabs that the testuser-1 doesn't have enough access to view, such as: Home -> Overview, Compute, Administration -> Cluster Settings, Namespaces pages etc.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@Leo6Leo Leo6Leo force-pushed the leo/OCPBUGS-72526/impersonation-access-hide-tabs branch from bf49972 to 0426766 Compare March 2, 2026 15:20
@Leo6Leo
Copy link
Contributor Author

Leo6Leo commented Mar 2, 2026

/jira refresh

@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Mar 2, 2026
@openshift-ci-robot
Copy link
Contributor

@Leo6Leo: This pull request references Jira Issue OCPBUGS-72526, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @yapei

Details

In response to this:

/jira refresh

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci openshift-ci bot requested a review from yapei March 2, 2026 15:21
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 2, 2026

📝 Walkthrough

Walkthrough

This pull request implements impersonation header handling across the GraphQL layer. The frontend introduces a setForceHTTP mechanism to switch transport between WebSocket and HTTP when entering or exiting impersonation mode, with calls placed in the refreshFeaturesAfterImpersonation and stopImpersonate flows. The backend GraphQL HTTP handler was refactored to extract impersonation headers from requests (Impersonate-User and Impersonate-Group variants, with conditional system:authenticated group appending) and propagate them into the resolver context, enabling downstream logic to access impersonation state. A minor error handling adjustment was made in the features action callback.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Title check ✅ Passed The title accurately summarizes the main change—fixing impersonation to properly forward headers so the backend evaluates permissions as the impersonated user rather than kube:admin, preventing unauthorized page visibility.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/server/server.go (1)

390-396: Normalize forwarded impersonation groups before sending downstream.

Line 391 and Line 395 forward raw split values. Trimming whitespace and dropping empty entries prevents malformed Impersonate-Group values from accidental spacing/trailing commas.

♻️ Suggested hardening
 		if consoleGroups := r.Header.Get("X-Console-Impersonate-Groups"); consoleGroups != "" {
-			groups := strings.Split(consoleGroups, ",")
+			rawGroups := strings.Split(consoleGroups, ",")
+			groups := make([]string, 0, len(rawGroups)+1)
+			for _, g := range rawGroups {
+				g = strings.TrimSpace(g)
+				if g != "" {
+					groups = append(groups, g)
+				}
+			}
 			groups = append(groups, "system:authenticated")
 			headers["Impersonate-Group"] = groups
 		} else if impGroups := r.Header.Values("Impersonate-Group"); len(impGroups) > 0 {
+			for i := range impGroups {
+				impGroups[i] = strings.TrimSpace(impGroups[i])
+			}
 			impGroups = append(impGroups, "system:authenticated")
 			headers["Impersonate-Group"] = impGroups
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/server/server.go` around lines 390 - 396, When forwarding impersonation
groups from r.Header.Get("X-Console-Impersonate-Groups") (variable groups) or
r.Header.Values("Impersonate-Group") (variable impGroups) normalize entries by
trimming whitespace and removing empty strings before assigning to
headers["Impersonate-Group"]; keep the existing append of
"system:authenticated". In practice iterate over the split or values, apply
strings.TrimSpace, skip if the trimmed entry == "", collect cleaned entries and
then append "system:authenticated" and set headers["Impersonate-Group"] =
cleanedSlice.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/server/server.go`:
- Around line 398-399: The code creates a new background context and loses
request cancellation/deadline and upstream values; replace
context.WithValue(context.Background(), resolver.HeadersKey, headers) with using
the request's context as the parent (i.e., context.WithValue(r.Context(),
resolver.HeadersKey, headers)) so that graphQLHandler receives
r.WithContext(ctx) that preserves cancellation and other request-scoped values;
update the usage around resolver.HeadersKey and graphQLHandler accordingly.

---

Nitpick comments:
In `@pkg/server/server.go`:
- Around line 390-396: When forwarding impersonation groups from
r.Header.Get("X-Console-Impersonate-Groups") (variable groups) or
r.Header.Values("Impersonate-Group") (variable impGroups) normalize entries by
trimming whitespace and removing empty strings before assigning to
headers["Impersonate-Group"]; keep the existing append of
"system:authenticated". In practice iterate over the split or values, apply
strings.TrimSpace, skip if the trimmed entry == "", collect cleaned entries and
then append "system:authenticated" and set headers["Impersonate-Group"] =
cleanedSlice.

ℹ️ Review info

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between 4a2ba98 and bf49972.

📒 Files selected for processing (4)
  • frontend/public/actions/features.ts
  • frontend/public/actions/ui.ts
  • frontend/public/graphql/client.ts
  • pkg/server/server.go

Comment on lines +398 to 399
ctx := context.WithValue(context.Background(), resolver.HeadersKey, headers)
graphQLHandler(w, r.WithContext(ctx))
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# First, let's examine the actual code at lines 398-399
head -n 410 pkg/server/server.go | tail -n 25

Repository: openshift/console

Length of output: 1281


🏁 Script executed:

#!/bin/bash
# Search for the specific pattern mentioned in the review
rg -nP 'context\.WithValue\(context\.Background\(\),\s*resolver\.HeadersKey' pkg/server/server.go

Repository: openshift/console

Length of output: 143


🏁 Script executed:

#!/bin/bash
# Let's also check the broader context of this handler to understand the function signature
sed -n '380,410p' pkg/server/server.go

Repository: openshift/console

Length of output: 1641


🏁 Script executed:

#!/bin/bash
# Check for other similar patterns of context.Background() in handler contexts
rg -n 'context\.Background\(\)' pkg/server/server.go | head -20

Repository: openshift/console

Length of output: 143


🏁 Script executed:

#!/bin/bash
# Look for how graphQLHandler is defined and uses context
rg -n 'graphQLHandler\|NewHandlerFunc' pkg/server/server.go -B 2 -A 2

Repository: openshift/console

Length of output: 43


🏁 Script executed:

#!/bin/bash
# Check if there are other handlers in the codebase that do this correctly
rg -n 'context\.WithValue\(r\.Context\(\)' pkg/ -t go | head -10

Repository: openshift/console

Length of output: 160


Preserve request context when injecting resolver headers.

Line 398 creates a fresh background context, which drops request cancellation/deadline and upstream context values. The codebase already uses the correct pattern elsewhere (e.g., pkg/middleware/middleware.go). Use r.Context() as the parent instead, particularly important since this handler wraps a GraphQL WebSocket connection that may be long-lived.

🔧 Proposed fix
-		ctx := context.WithValue(context.Background(), resolver.HeadersKey, headers)
+		ctx := context.WithValue(r.Context(), resolver.HeadersKey, headers)
 		graphQLHandler(w, r.WithContext(ctx))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/server/server.go` around lines 398 - 399, The code creates a new
background context and loses request cancellation/deadline and upstream values;
replace context.WithValue(context.Background(), resolver.HeadersKey, headers)
with using the request's context as the parent (i.e.,
context.WithValue(r.Context(), resolver.HeadersKey, headers)) so that
graphQLHandler receives r.WithContext(ctx) that preserves cancellation and other
request-scoped values; update the usage around resolver.HeadersKey and
graphQLHandler accordingly.

@Leo6Leo
Copy link
Contributor Author

Leo6Leo commented Mar 4, 2026

/retest-required

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 4, 2026

@Leo6Leo: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component/backend Related to backend component/core Related to console core functionality jira/severity-moderate Referenced Jira bug's severity is moderate for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants