Skip to content
This repository was archived by the owner on Sep 9, 2026. It is now read-only.

OSAC-953: Update AuthConfig to use organization groups - #666

Merged
CrystalChun merged 1 commit into
osac-project:mainfrom
CrystalChun:groups-authz
Jul 1, 2026
Merged

CrystalChun merged 1 commit into
osac-project:mainfrom
CrystalChun:groups-authz

Conversation

@CrystalChun

@CrystalChun CrystalChun commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Description

Determine if a user can get/update/delete a project based on the organization group they're part of.

Testing

  • Ran integration test
    • Logged in as admin on CLI and created organization test-org, added user ben, assigned ben tenant-admin role
    • Logged in as ben on CLI and created project, verify able to see project
    • Logged in as charles on CLI and verify not able to see project
    • Deleted project successfully

Assisted-by: Claude Code noreply@anthropic.com

/cc @jhernand

Summary by CodeRabbit

  • New Features

    • Added organization- and group-scoped authorization for Projects (Create, List, Get, Update, Delete) based on tenant-scoped viewer/manager membership.
    • Enhanced JWT processing for organization claims, supporting both array and object formats.
  • Bug Fixes

    • Removed fallback tenant derivation from unrelated claims when JWT organization data is missing.
    • Tightened tenant/group mapping to correctly interpret organization-scoped group memberships.
  • Tests

    • Updated multitenant setup and adjusted/removed specific authorization cases to match the revised tenant resolution behavior.

@openshift-ci-robot

openshift-ci-robot commented Jun 9, 2026

Copy link
Copy Markdown

@CrystalChun: This pull request references OSAC-953 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 sub-task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Description

Determine if a user can get/update/delete a project based on the organization group they're part of.

Testing

  • Ran integration test
    • Logged in as admin on CLI and created organization test-org, added user ben, assigned ben tenant-admin role
    • Logged in as ben on CLI and created project, verify able to see project
    • Logged in as charles on CLI and verify not able to see project
    • Deleted project successfully

Assisted-by: Claude Code noreply@anthropic.com

/cc @jhernand

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.

@coderabbitai

coderabbitai Bot commented Jun 9, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

An error occurred during the review process. Please try again later.

Walkthrough

JWT organization claims now accept array or object shapes, tenant and org-group normalization follows that shape, Projects RPC authorization uses tenant-scoped group membership, and test setup provisions Keycloak organizations and memberships before integration tests run.

Changes

Organization-based authorization

Layer / File(s) Summary
Organization claim parsing
internal/auth/grpc_authz_interceptor.go, internal/auth/grpc_authz_interceptor_test.go
buildInput accepts JWT organization claims as arrays or objects, and the removed tests no longer cover the deleted groups-fallback behavior.
Tenant and org-group normalization
internal/auth/policies/authz.rego, manifests/base/grpc-server/authconfig.yaml
subject_tenants now derives JWT tenants only from organization, and subject_org_groups normalizes object-shaped and array-shaped organization claims.
Project authorization rules
internal/auth/policies/authz.rego, manifests/base/grpc-server/authconfig.yaml
Projects/Create, Projects/List, Projects/Get, Projects/Update, and Projects/Delete rules are added using tenant admin, client permission, and tenant-scoped group checks.
Tenant provisioning and membership sync
it/it_tool.go, it/it_multitenancy_test.go, it/it_tenant_lifecycle_test.go
Tool.Setup now creates referenced organizations, adds users to Keycloak organizations and groups, updates multitenancy setup, and validates organization-claim extraction in integration tests.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant ToolSetup as Tool.Setup
  participant KeycloakAdminAPI as Keycloak admin API
  participant IntegrationTests as integration tests

  ToolSetup->>KeycloakAdminAPI: create tenants, org memberships, and /members groups
  ToolSetup->>IntegrationTests: provide provisioned organizations and claims
Loading

Possibly related PRs

Suggested labels: lgtm

Suggested reviewers: jhernand

🚥 Pre-merge checks | ✅ 5 | ❌ 6

❌ Failed checks (6 inconclusive)

Check name Status Explanation Resolution
No-Hardcoded-Secrets ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Weak-Crypto ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Injection-Vectors ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Container-Privileges ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
No-Sensitive-Data-In-Logs ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
Ai-Attribution ❓ Inconclusive Repository clone failed, so this custom check could not run with code access. Retry the review run. If this persists, inspect pre-merge custom-check logs for infrastructure or agent runtime failures.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately reflects the main change around AuthConfig and organization groups.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Tools execution failed with the following error:

Failed to run tools: 13 INTERNAL: Received RST_STREAM with code 2 (Internal server error)


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/service/templates/grpc-server/authconfig.yaml`:
- Around line 282-295: The current authorization rule inside the allow if block
applies the same group check to Get/Update/Delete and therefore denies read-only
viewers; modify the policy by splitting the rule into two checks: one allow
branch that permits grpc_method == "/osac.public.v1.Projects/Get" when
input.auth.identity.authnMethod == "jwt" and some group in
subject_org_groups[tenant].groups where group == sprintf("/%s/viewers", [name])
or group == sprintf("/%s/managers", [name]); and a second allow branch that
permits grpc_method in
{"/osac.public.v1.Projects/Update","/osac.public.v1.Projects/Delete"} only when
the same jwt check and some group in subject_org_groups[tenant].groups where
group == sprintf("/%s/managers", [name]); retain use of tenant :=
input.context.context_extensions.tenant and name :=
input.context.context_extensions.name in both branches.
- Around line 104-108: The current rule assigns subject_tenants = subject_groups
when input.auth.identity.authnMethod == "jwt" and organization is missing, which
incorrectly treats project group paths as tenants; update the logic so that when
authnMethod is "jwt" and input.auth.identity.organization is absent,
subject_tenants remains empty (do not assign subject_groups). Concretely, remove
or guard the branch that sets subject_tenants from subject_groups for JWTs
without organization, relying solely on input.auth.identity.organization as the
authoritative tenant source and leaving subject_tenants unset in that case.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 99d70ea3-613b-4bd1-95d3-1a70fbb81c66

📥 Commits

Reviewing files that changed from the base of the PR and between 8e8f231 and 20ea641.

📒 Files selected for processing (1)
  • charts/service/templates/grpc-server/authconfig.yaml

Comment thread charts/service/templates/grpc-server/authconfig.yaml Outdated
Comment thread charts/service/templates/grpc-server/authconfig.yaml Outdated
@CrystalChun
CrystalChun force-pushed the groups-authz branch 2 times, most recently from 5b0c673 to 41f59c9 Compare June 10, 2026 00:35

@jhernand jhernand left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

You need to update the authconfig.yaml file in the manifests directory as well.

@CrystalChun
CrystalChun force-pushed the groups-authz branch 2 times, most recently from 61f8677 to 0b765cb Compare June 10, 2026 15:05
@CrystalChun

Copy link
Copy Markdown
Contributor Author

You need to update the authconfig.yaml file in the manifests directory as well.

Thank you! Updated that one as well

@CrystalChun
CrystalChun force-pushed the groups-authz branch 2 times, most recently from 3b6cd8b to 930964d Compare June 10, 2026 18:15

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@charts/service/templates/grpc-server/authconfig.yaml`:
- Around line 271-301: Add an allow rule for the Projects/List gRPC method:
create a new allow-if block checking grpc_method ==
"/osac.public.v1.Projects/List", extract tenant :=
input.context.context_extensions.tenant, require input.auth.identity.authnMethod
== "jwt", and verify some group in subject_org_groups[tenant].groups (or narrow
to viewers/managers if you prefer filtering at the app layer); this mirrors the
Get/Update rules and ensures JWT-authenticated tenant members can call
Projects/List while the server can perform any result-level filtering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 3f312678-7c68-4944-b608-71f503969b9d

📥 Commits

Reviewing files that changed from the base of the PR and between 20ea641 and 930964d.

📒 Files selected for processing (2)
  • charts/service/templates/grpc-server/authconfig.yaml
  • manifests/base/grpc-server/authconfig.yaml

Comment thread charts/service/templates/grpc-server/authconfig.yaml Outdated
@CrystalChun
CrystalChun force-pushed the groups-authz branch 5 times, most recently from ad5b834 to 14bff45 Compare June 10, 2026 21:07

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@it/charts/keycloak/files/realm.json`:
- Around line 836-846: The realm config sets protocolMapper
"oidc-organization-group-membership-mapper" (id "org-group-membership-001") but
the chart defaults images.keycloak to 26.3 and realm.json declares
keycloakVersion 26.3.5, which is <26.6.0 where that mapper is guaranteed; update
the deployment to a compatible Keycloak version (bump values.images.keycloak
default and chart/appVersion to >=26.6.0 and align realm.json keycloakVersion)
or alternatively gate/remove the protocolMapper
"oidc-organization-group-membership-mapper" (org-group-membership-001) for older
versions and provide a fallback mapper implementation so org-scoped JWT
membership continues to be emitted.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: 3a58f4ce-ff1b-4fd9-a490-e39d1ef78a29

📥 Commits

Reviewing files that changed from the base of the PR and between 930964d and 14bff45.

📒 Files selected for processing (3)
  • charts/service/templates/grpc-server/authconfig.yaml
  • it/charts/keycloak/files/realm.json
  • manifests/base/grpc-server/authconfig.yaml

Comment thread it/charts/keycloak/files/realm.json Outdated
@CrystalChun
CrystalChun force-pushed the groups-authz branch 9 times, most recently from bd603a9 to 2312cef Compare June 11, 2026 16:31
@omer-vishlitzky

Copy link
Copy Markdown
Contributor

🔴 CI Triage: pr_issue | Category: TEST

Root cause: PR #666 removes the Rego policy fallback that derived tenant membership from the JWT groups claim when the organization claim is absent, but the E2E test's Keycloak realm (in the CI snapshot) does not emit an organization claim in JWT tokens — the PR only updated the integration test Keycloak config (it/charts/keycloak/files/realm.json), not the E2E snapshot's Keycloak.

Causal chain:

  • PR OSAC-953: Update AuthConfig to use organization groups #666 modifies authz.rego to remove the subject_tenants = subject_groups fallback rule that allowed JWT users without an organization claim to use their groups as tenants.
  • The E2E test fixture jwt_grpc_tenant1 obtains a JWT token from the snapshot's Keycloak, which only includes groups: ["tenant1"] and no organization claim.
  • With the PR's new Rego policy, subject_tenants evaluates to an empty list for JWT users without the organization claim.
  • When test_jwt_virtual_network_lifecycle calls VirtualNetworks/Create, DetermineAssignableTenants finds subject.Tenants is empty and returns an error.
  • The gRPC server returns Internal: failed to determine assignable tenants, causing all 3 JWT-based create tests to fail.
  • Non-JWT tests (service account-based) pass because the subject_tenants = subject_groups rule for service accounts is unchanged.

Evidence:

step:e2e-vmaas-osac-project-cluster-tool-test:

ERROR:\n  Code: Internal\n  Message: failed to determine assignable tenants

JWT token payload (decoded from build log):

"groups": ["tenant1"], "username": "tenant1_user" — no 'organization' claim present in the JWT token

PR #666 diff: internal/auth/policies/authz.rego:

Removed: subject_tenants = subject_groups if { input.auth.identity.authnMethod == "jwt" ; not input.auth.identity.organization ; not input.auth.identity.organizations }

[PR #666 diff: internal/auth/policies/authz.rego](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/pr-logs/pull/osac-project_fulfillment-service/666/pull-ci-osac-project-fulfillment-service-main-e2e-vmaas/2070556338554933248/artifacts/e2e-vmaas/osac-project-gather/artifacts/osac-logs/PR #666 diff: internal/auth/policies/authz.rego):

Added comment: # JWT users without an organization claim will have an empty tenant list.

[PR #666 diff: it/charts/keycloak/files/realm.json](https://gcsweb-ci.apps.ci.l2s4.p1.openshiftapps.com/gcs/test-platform-results/pr-logs/pull/osac-project_fulfillment-service/666/pull-ci-osac-project-fulfillment-service-main-e2e-vmaas/2070556338554933248/artifacts/e2e-vmaas/osac-project-gather/artifacts/osac-logs/PR #666 diff: it/charts/keycloak/files/realm.json):

Added oidc-organization-group-membership-mapper — but this only affects integration tests, not the E2E snapshot's Keycloak

fulfillment-service/internal/auth/default_tenancy_logic.go:65-72:

if result.Empty() { err = fmt.Errorf("subject must belong to at least one tenant to create objects") }

step:e2e-vmaas-osac-project-cluster-tool-test:

tests/vmaas/test_virtual_network_lifecycle.py::test_virtual_network_lifecycle PASSED [100%] — non-JWT (service account) version of the same test passes

Suggestion: The E2E snapshot's Keycloak realm needs to be updated to include the oidc-organization-membership-mapper (or equivalent) and users must be added to Keycloak organizations so the organization claim appears in JWT tokens. Either: (1) update the E2E test setup script (cluster-tool-test) to configure Keycloak organizations before running tests, similar to what it/it_tool.go:addUsersToKeycloakOrganizations does for integration tests, or (2) re-snapshot with the updated Keycloak realm configuration.


Prow job | Build 2070556338554933248 | 🤖 triagent | Cost: $1.7341

For deeper investigation, use the /osac-debug-e2e skill with this build ID.

@CrystalChun
CrystalChun force-pushed the groups-authz branch 2 times, most recently from 9881ce4 to 48b9bfe Compare June 26, 2026 20:44

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/auth/grpc_authz_interceptor.go`:
- Around line 481-498: The authz interceptor is logging sensitive JWT
organization data and usernames in the organization-claim handling path. Update
the logging in grpc_authz_interceptor.go around the organization claim parsing
logic to remove raw orgValue/orgArray/orgObj and username fields from
InfoContext/WarnContext calls, and replace them with safe metadata like claim
type, presence, and count only. Keep the behavior in the same org claim branch,
but ensure any logs in the claimAsAnySlice, orgValue map handling, and “No
organization claim in JWT” paths are fully redacted.

In `@internal/auth/policies/authz.rego`:
- Around line 325-332: The project authorization rules currently assign tenant
and name together before they are both needed, but Regal wants name deferred
until right before it is used in the group checks. Update the relevant project
rule blocks in authz.rego so tenant is bound first, then move the name
assignment closer to the sprintf-based group comparison while keeping the logic
in the same rule structure and preserving the existing authnMethod and
subject_org_groups behavior.

In `@it/it_tool.go`:
- Around line 1914-1915: The Keycloak organization log in the it_tool.go flow is
exposing potentially sensitive identifiers via the slog fields in the
InfoContext call. Update the logging in the code path around the "Added user to
Keycloak organization" message so the keys for username and orgName are prefixed
with !, ensuring the repository’s redaction handler masks those values. Keep the
same log location and context, and only adjust the field keys used in the
InfoContext call.

In `@manifests/base/grpc-server/authconfig.yaml`:
- Around line 309-316: The embedded Rego in the AuthConfig policy is still using
the old eager name binding and needs to match the Regal cleanup in
internal/auth/policies/authz.rego. Update the rule that uses tenant and name so
the name value is assigned later via the same deferred pattern, and keep the
group membership check unchanged while preserving the existing identifiers in
the policy block.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Enterprise

Run ID: fdbf861c-289f-4ff1-93ec-241ae05a2cdc

📥 Commits

Reviewing files that changed from the base of the PR and between e508a5a and 60c878a.

📒 Files selected for processing (6)
  • internal/auth/grpc_authz_interceptor.go
  • internal/auth/grpc_authz_interceptor_test.go
  • internal/auth/policies/authz.rego
  • it/it_multitenancy_test.go
  • it/it_tool.go
  • manifests/base/grpc-server/authconfig.yaml
💤 Files with no reviewable changes (1)
  • internal/auth/grpc_authz_interceptor_test.go

Comment thread internal/auth/grpc_authz_interceptor.go Outdated
Comment thread internal/auth/policies/authz.rego
Comment thread it/it_tool.go Outdated
Comment thread manifests/base/grpc-server/authconfig.yaml
@CrystalChun
CrystalChun marked this pull request as draft June 26, 2026 21:17
@CrystalChun
CrystalChun force-pushed the groups-authz branch 8 times, most recently from 5e53989 to b70a51c Compare June 26, 2026 22:51
@CrystalChun
CrystalChun marked this pull request as ready for review June 26, 2026 22:52
@CrystalChun
CrystalChun marked this pull request as draft June 26, 2026 22:57
Determine if a user can get/update/delete a project based
on the organization group they're part of.

Assisted-by: Claude Code <noreply@anthropic.com>
@CrystalChun

Copy link
Copy Markdown
Contributor Author

/test e2e-vmaas

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown

Triggered: E2E VMaaS Full Install

@openshift-ci

openshift-ci Bot commented Jul 1, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: CrystalChun, jhernand, oourfali

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

The pull request process is described 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

@oourfali

oourfali commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

/lgtm

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants