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

MGMT-22988: Add Keycloak service accounts for admin and controller - #462

Merged
openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
jhernand:add_keycloak_service_accounts_for_controller
Apr 28, 2026
Merged

openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
jhernand:add_keycloak_service_accounts_for_controller

Conversation

@jhernand

@jhernand jhernand commented Apr 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Removes the hardcoded fulfillment-controller client from the base Keycloak realm JSON and
    replaces it with two dynamically created service account clients (osac-admin and
    osac-controller) configured via Helm chart values during integration test setup.
  • Updates the Keycloak realm Helm template to support additional clients through .Values.clients,
    automatically appending them to the clients array and creating the required roles.client
    entries.
  • Restructures the OPA authorization policy to distinguish between emergency Kubernetes service
    accounts (emergency_service_accounts) and regular admin service accounts
    (admin_service_accounts), granting both admin permissions.
  • Adds IT_CLIENT_SECRET environment variable support for setting a known client secret, useful for
    logging in with the CLI after preserving a test cluster.

This is a preparation step for changing the controller to use a Keycloak service account instead of
a Kubernetes service account for authentication.

Test plan

  • Integration tests pass with Helm deployment (94/94)
  • Integration tests pass with Kustomize deployment (94/94)
  • Verified osac-controller and osac-admin clients and their service account users are
    correctly created in the Keycloak realm

Related: https://redhat.atlassian.net/browse/MGMT-22988

Summary by CodeRabbit

  • Documentation

    • Added Keycloak and chart README guidance for service account clients, secrets, and deployment prerequisites; added examples for creating controller credentials and test overrides.
  • New Features

    • Helm values now allow appending Keycloak clients and passing controller OAuth credentials; tests accept an explicit client secret for setup.
  • Improvements

    • Controller deployments switched from token-file to OAuth client-credentials (mounted secret).
    • Authorization policy now distinguishes emergency vs. standard admin service accounts.
  • Removals

    • Removed the fulfillment-controller client definition from the base realm.

@openshift-ci-robot

openshift-ci-robot commented Apr 28, 2026

Copy link
Copy Markdown

@jhernand: This pull request references MGMT-22988 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 task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Removes the hardcoded fulfillment-controller client from the base Keycloak realm JSON and
    replaces it with two dynamically created service account clients (osac-admin and
    osac-controller) configured via Helm chart values during integration test setup.
  • Updates the Keycloak realm Helm template to support additional clients through .Values.clients,
    automatically appending them to the clients array and creating the required roles.client
    entries.
  • Restructures the OPA authorization policy to distinguish between emergency Kubernetes service
    accounts (emergency_service_accounts) and regular admin service accounts
    (admin_service_accounts), granting both admin permissions.
  • Adds IT_CLIENT_SECRET environment variable support for setting a known client secret, useful for
    logging in with the CLI after preserving a test cluster.

This is a preparation step for changing the controller to use a Keycloak service account instead of
a Kubernetes service account for authentication.

Test plan

  • Integration tests pass with Helm deployment (94/94)
  • Integration tests pass with Kustomize deployment (94/94)
  • Verified osac-controller and osac-admin clients and their service account users are
    correctly created in the Keycloak realm

Related: https://redhat.atlassian.net/browse/MGMT-22988

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.

@jhernand
jhernand requested review from CrystalChun and removed request for akshaynadkarni and trewest April 28, 2026 10:51
@coderabbitai

coderabbitai Bot commented Apr 28, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@jhernand has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 27 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: df717d33-e1e5-4b3b-83a5-9e06893110ab

📥 Commits

Reviewing files that changed from the base of the PR and between c928376 and e11b858.

📒 Files selected for processing (16)
  • README.md
  • charts/README.md
  • charts/keycloak/README.md
  • charts/keycloak/files/realm.json
  • charts/keycloak/templates/realm.yaml
  • charts/keycloak/values.yaml
  • charts/service/templates/controller/deployment.yaml
  • charts/service/templates/grpc-server/authconfig.yaml
  • charts/service/values.yaml
  • internal/auth/auth_rules_test.go
  • internal/cmd/service/start/controller/start_controller_cmd.go
  • it/it_suite_test.go
  • it/it_tool.go
  • manifests/README.md
  • manifests/base/controller/deployment.yaml
  • manifests/base/grpc-server/authconfig.yaml

Walkthrough

Updates add configurable OAuth client-secret handling across integration tests, tooling, Helm charts, and manifests: integration tooling accepts and propagates a provided client secret and creates a Kubernetes secret; Keycloak Helm values now allow appending clients/users/groups from a base realm JSON and documentation for service-account clients and values is added; the default fulfillment-controller client is removed from the realm JSON; controller deployment and startup are switched from file-based serviceaccount tokens to OAuth client-credentials (issuer URL, client-id/secret) with corresponding manifest and template changes; OPA Rego policy is adjusted to separate emergency and standard admin service-account allowlists.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • adriengentil
  • trewest
🚥 Pre-merge checks | ✅ 5
✅ 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 accurately summarizes the primary change: adding Keycloak service accounts for admin and controller, which is the core objective evident across the raw summary.
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.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@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: 5

🧹 Nitpick comments (1)
charts/service/templates/grpc-server/authconfig.yaml (1)

83-86: Prefer values-driven admin service-account list in Helm template.

These usernames are hardcoded while clients are now values-driven in this PR scope. Making this list configurable avoids auth drift if client IDs change.

♻️ Suggested Helm-safe refactor
+          {{- $adminServiceAccounts := .Values.auth.adminServiceAccounts | default (list "service-account-osac-admin" "service-account-osac-controller") }}
           # Admin service accounts are service accounts that are allowed to act as administrators.
           admin_service_accounts := {
-            "service-account-osac-admin",
-            "service-account-osac-controller",
+          {{- range $adminServiceAccounts }}
+            "{{ . }}",
+          {{- end }}
           }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@charts/service/templates/grpc-server/authconfig.yaml` around lines 83 - 86,
The hardcoded admin_service_accounts set should be driven from Helm values to
avoid drift; replace the literal assignment for admin_service_accounts with a
Helm-templated construction that reads a values list (e.g.
.Values.auth.adminServiceAccounts or .Values.clients.adminServiceAccounts) and
renders each entry into the set (use a Helm range to emit items or toYaml/indent
to format a list into the expected structure). Update the template where
admin_service_accounts is defined so it iterates over the values list and falls
back to an empty list or a sensible default if the values key is absent,
ensuring the variable name admin_service_accounts remains the same.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@charts/keycloak/templates/realm.yaml`:
- Around line 23-25: The template currently concatenates .Values.clients into
$realm.clients and then blindly resets realm.roles.client[clientId], risking
duplicate client entries and wiping existing role mappings; update the logic
around $realm, .Values.clients, concat and realm.roles.client to detect
collisions: either validate and fail when any .Values.clients has a clientId
already present in $realm.clients or within .Values.clients itself, or build a
merge that skips/filters duplicate clientId values before calling set (so you
never overwrite existing realm.roles.client[clientId]); ensure checks reference
the clientId field and produce an explicit error/guard rather than
unconditionally appending and resetting.

In `@charts/service/templates/grpc-server/authconfig.yaml`:
- Around line 75-76: Fix the typo in the policy comment that currently reads
"situatioos" to "situations"; locate the comment block that starts with
"Emergency service accounts are Kubernetes service accounts that are allowed to
act as administrators in case" and correct the misspelled word "situatioos" to
"situations".

In `@it/it_suite_test.go`:
- Around line 56-58: The test suite currently logs the full config including
ClientSecret (struct field ClientSecret) via logger.Info("Configuration",
slog.Any("values", config)), so create a sanitized copy of the config
immediately before logging: clone the config used in it_suite_test.go, set
copy.ClientSecret to a redacted value (e.g. "" or "REDACTED"), and pass that
sanitized copy to logger.Info instead of the original config to prevent secrets
from being emitted.

In `@manifests/base/grpc-server/authconfig.yaml`:
- Around line 74-76: Fix the typo in the comment above the
emergency_service_accounts block: change "situatioos" to "situations" in the
comment that begins "Emergency service accounts are Kubernetes service accounts
that are allowed to act as administrators..." so the rendered and base manifests
are correct (refer to the emergency_service_accounts block in the
authconfig.yaml).

In `@README.md`:
- Around line 329-338: Add a short prerequisite step before the osac login
example that explains how to obtain or export the CA bundle named bundle.pem (so
the --ca-file argument is valid); e.g., instruct users to extract the cluster CA
into bundle.pem from the Kubernetes service/secret or kubeconfig (mentioning
bundle.pem by name) and where to place it locally, then reference using that
path in the osac login command shown; ensure this note appears immediately
before the osac login block so readers know to create or locate bundle.pem
first.

---

Nitpick comments:
In `@charts/service/templates/grpc-server/authconfig.yaml`:
- Around line 83-86: The hardcoded admin_service_accounts set should be driven
from Helm values to avoid drift; replace the literal assignment for
admin_service_accounts with a Helm-templated construction that reads a values
list (e.g. .Values.auth.adminServiceAccounts or
.Values.clients.adminServiceAccounts) and renders each entry into the set (use a
Helm range to emit items or toYaml/indent to format a list into the expected
structure). Update the template where admin_service_accounts is defined so it
iterates over the values list and falls back to an empty list or a sensible
default if the values key is absent, ensuring the variable name
admin_service_accounts remains the same.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e37c4fb8-6116-45a8-9f87-655e97faed00

📥 Commits

Reviewing files that changed from the base of the PR and between 5890154 and dd18bd1.

📒 Files selected for processing (8)
  • README.md
  • charts/keycloak/files/realm.json
  • charts/keycloak/templates/realm.yaml
  • charts/keycloak/values.yaml
  • charts/service/templates/grpc-server/authconfig.yaml
  • it/it_suite_test.go
  • it/it_tool.go
  • manifests/base/grpc-server/authconfig.yaml
💤 Files with no reviewable changes (1)
  • charts/keycloak/files/realm.json

Comment thread charts/keycloak/templates/realm.yaml
Comment thread charts/service/templates/grpc-server/authconfig.yaml Outdated
Comment thread it/it_suite_test.go
Comment thread manifests/base/grpc-server/authconfig.yaml
Comment thread README.md

@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 the current code and only fix it if needed.

Inline comments:
In `@internal/cmd/service/start/controller/start_controller_cmd.go`:
- Around line 105-111: Add the missing CLI flag that sets the authClientSecret
field so the mutual-exclusion checks work: define a flags.StringVar binding
&runner.args.authClientSecret to the flag "auth-client-secret" (default ""),
with help text matching the existing "--auth-client-secret-file" message (e.g.
"OAuth client secret value. Mutually exclusive with
'--auth-client-secret-file'."). Place this alongside the existing
flags.StringVar for authClientSecretFile so the validation code that checks
runner.args.authClientSecret and runner.args.authClientSecretFile is reachable
and behaves as intended.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: bc63e758-a519-4703-9423-130f60546599

📥 Commits

Reviewing files that changed from the base of the PR and between dd18bd1 and c928376.

📒 Files selected for processing (8)
  • charts/README.md
  • charts/keycloak/README.md
  • charts/service/templates/controller/deployment.yaml
  • charts/service/values.yaml
  • internal/cmd/service/start/controller/start_controller_cmd.go
  • it/it_tool.go
  • manifests/README.md
  • manifests/base/controller/deployment.yaml
✅ Files skipped from review due to trivial changes (2)
  • charts/keycloak/README.md
  • manifests/README.md

Comment thread internal/cmd/service/start/controller/start_controller_cmd.go
This is a preparation step for changing the controller to use a Keycloak
service account instead of a Kubernetes service account for
authentication.

The `fulfillment-controller` client that was previously hardcoded in the
base realm JSON has been removed. Instead, two new service account
clients (`osac-admin` and `osac-controller`) are now created dynamically
via the Helm chart values during integration test setup.

The Keycloak realm Helm template has been updated to support additional
clients passed through `.Values.clients`. It automatically appends them
to the `clients` array and creates the corresponding empty
`roles.client` entries that Keycloak requires.

The OPA authorization policy in the authconfig has been restructured to
distinguish between emergency Kubernetes service accounts (renamed to
`emergency_service_accounts`) and regular admin service accounts
(`admin_service_accounts`), which now includes the two new Keycloak
service accounts.

The integration test tool now supports the `IT_CLIENT_SECRET` environment
variable, allowing developers to set a known client secret for the
service accounts. When not set, a random secret is generated. This is
useful for logging in with the CLI after preserving a test cluster.

Related: https://redhat.atlassian.net/browse/MGMT-22988
Signed-off-by: Juan Hernandez <juan.hernandez@redhat.com>
@jhernand
jhernand force-pushed the add_keycloak_service_accounts_for_controller branch from c928376 to c599c17 Compare April 28, 2026 14:18
Replace the Kubernetes service account token authentication used by the
controller with OAuth client credentials flow. The controller now
authenticates to the fulfillment API using a client identifier and secret
obtained from the same OAuth issuer used for user authentication.

The `start controller` command gains `--auth-issuer-url`,
`--auth-client-id`, and `--auth-client-secret` flags, each with a
`...-file` variant that reads the value from a file (trimming
whitespace). The direct and file-based variants are mutually exclusive.

The Helm chart adds an `auth.controllerCredentials` value that follows
the same projected volume pattern used by `database.connection`: users
map keys from ConfigMaps or Secrets to `client-id` and `client-secret`
parameters, giving flexibility over how credentials are stored. The
issuer URL is taken from the existing `auth.issuerUrl` value. The old
`--token-file` flag referencing the pod service account token is removed
from the deployment template.

The kustomize base controller deployment is updated to mount a
well-known Secret (`fulfillment-controller-credentials`) with `client-id`
and `client-secret` keys, and the issuer URL hardcoded to the same
Keycloak address used by the other components in the base manifests.

The integration tests create a Kubernetes Secret containing the
`osac-controller` Keycloak service account credentials and pass it to
the Helm chart via the new `auth.controllerCredentials` value.

The documentation for the Keycloak chart, the service Helm chart, and
the kustomize manifests is updated to explain the new prerequisites and
configuration.

Related: https://redhat.atlassian.net/browse/MGMT-22988
Signed-off-by: Juan Hernandez <juan.hernandez@redhat.com>
@jhernand
jhernand force-pushed the add_keycloak_service_accounts_for_controller branch from c599c17 to e11b858 Compare April 28, 2026 14:20

@CrystalChun CrystalChun 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.

/lgtm

@openshift-ci

openshift-ci Bot commented Apr 28, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is APPROVED

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

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

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.

3 participants