Skip to content

DO-NOT-MERGE: POC: decouple oauthapiserver auth config generation for shared library use#942

Draft
liouk wants to merge 1 commit into
openshift:masterfrom
liouk:poc-reusable-generator
Draft

DO-NOT-MERGE: POC: decouple oauthapiserver auth config generation for shared library use#942
liouk wants to merge 1 commit into
openshift:masterfrom
liouk:poc-reusable-generator

Conversation

@liouk

@liouk liouk commented Jul 3, 2026

Copy link
Copy Markdown
Member

Note: This is a POC PR and shouldn't be merged.

/hold

Refactor the AuthenticationConfigurationGenerator so it can be extracted into a shared library (oauth-apiserver) usable by both the standalone auth operator and HyperShift. Key changes:

  • Replace featuregates.FeatureGate with With*() methods that set bools, removing the dependency on OpenShift feature gate packages
  • Replace corev1listers with ResolverFunc callbacks, removing the dependency on k8s client-go listers
  • Convert standalone functions to methods, eliminating parameter threading of struct fields
  • Remove hardcoded "openshift-config" namespace; callers bind namespace into their resolver closures

Summary by CodeRabbit

  • New Features

    • External OIDC authentication now supports additional configuration options for upstream parity, extra claim mappings, and external claims sourcing.
    • Authentication settings are now read more directly from the selected configuration, improving how OIDC providers are processed.
  • Bug Fixes

    • Improved handling of missing or empty certificate and client secret values, with clearer errors when required data is unavailable.
    • Updated generation logic to use the expected authentication settings format consistently.

…y use

Refactor the AuthenticationConfigurationGenerator so it can be extracted
into a shared library (oauth-apiserver) usable by both the standalone
auth operator and HyperShift. Key changes:

- Replace featuregates.FeatureGate with With*() methods that set bools,
  removing the dependency on OpenShift feature gate packages
- Replace corev1listers with ResolverFunc callbacks, removing the
  dependency on k8s client-go listers
- Convert standalone functions to methods, eliminating parameter
  threading of struct fields
- Remove hardcoded "openshift-config" namespace; callers bind namespace
  into their resolver closures
@openshift-ci openshift-ci Bot added do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. labels Jul 3, 2026
@openshift-ci

openshift-ci Bot commented Jul 3, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci

openshift-ci Bot commented Jul 3, 2026

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 rh-roman 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

@coderabbitai

coderabbitai Bot commented Jul 3, 2026

Copy link
Copy Markdown

Walkthrough

This PR refactors ExternalOIDC authentication configuration generators to accept *configv1.AuthenticationSpec instead of *configv1.Authentication, and replaces feature-gate-driven ConfigMap/Secret lister access in the oauthapiserver generator with injected resolver functions and fluent boolean toggles for upstream parity, additional claim mappings, and external claims sourcing.

Changes

ExternalOIDC generator refactor

Layer / File(s) Summary
kubeapiserver generator signature change
pkg/controllers/externaloidc/generation/kubeapiserver/generate.go, generate_test.go
GenerateAuthenticationConfiguration now takes *AuthenticationSpec; provider iteration and issuer field sourced from the spec; tests updated to pass &tt.auth.Spec.
oauthapiserver generator: resolver-based construction and toggles
pkg/controllers/externaloidc/generation/oauthapiserver/generate.go
Introduces ResolverFunc, updates the generator struct and constructor to accept CA/secret resolvers, adds WithUpstreamParity, WithAdditionalClaimMappings, WithExternalClaimsSourcing fluent methods, and changes GenerateAuthenticationConfiguration to accept *AuthenticationSpec.
Claim mapping and issuer generation using generator state
same file
Upstream parity/additional-claim-mapping conditionals now read generator booleans; issuer generation and certificate authority lookup converted to generator methods.
External claims sourcing via resolver methods
same file
External claims source, authentication, client-credential, and TLS generation converted to generator methods using injected resolvers; adds getClientSecret method.
oauthapiserver generator tests updated for resolvers
pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go
Replaces feature-gate test configuration with boolean toggles, adds newTestCABundleResolver/newTestClientSecretResolver helpers, and updates the test runner to use the new constructor.
Controller wiring and CA/secret resolver helpers
pkg/controllers/externaloidc/externaloidc_controller.go, externaloidc_controller_test.go
Updates the authConfigGenerator interface and feature-gated generator construction with resolvers, updates sync call to pass &auth.Spec, adds newCABundleResolver/newClientSecretResolver, and updates mock generator in tests.

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

Sequence Diagram(s)

sequenceDiagram
  participant Controller
  participant Generator as AuthenticationConfigurationGenerator
  participant CAResolver
  participant SecretResolver

  Controller->>Generator: NewAuthenticationConfigurationGenerator(caResolver, clientSecretResolver)
  Controller->>Generator: WithUpstreamParity()/WithAdditionalClaimMappings()/WithExternalClaimsSourcing()
  Controller->>Generator: GenerateAuthenticationConfiguration(&auth.Spec)
  Generator->>Generator: generateJWTForProvider(provider)
  Generator->>CAResolver: getCertificateAuthority(name)
  Generator->>SecretResolver: getClientSecret(name)
  Generator-->>Controller: AuthenticationConfiguration
Loading
🚥 Pre-merge checks | ✅ 15
✅ Passed checks (15 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 refactor to decouple oauthapiserver auth config generation for shared library use.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Stable And Deterministic Test Names ✅ Passed All changed test/subtest names are static table entries; no fmt.Sprintf or dynamic values appeared in titles.
Test Structure And Quality ✅ Passed The touched tests are plain table-driven unit tests, not Ginkgo; they use t.Run, explicit error messages, and defer Close for httptest servers.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e specs were added; changed test files are plain Go unit tests with no It/Describe/Context/When or MicroShift-specific behavior.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; changed files are unit tests only and contain no SNO-specific assumptions or Ginkgo constructs.
Topology-Aware Scheduling Compatibility ✅ Passed PR contains only Go source code refactoring with no deployment manifests, scheduling constraints, or topology assumptions introduced.
Ote Binary Stdout Contract ✅ Passed Touched files only refactor generators/tests; no main/init/TestMain/RunSpecs/BeforeSuite hooks or stdout-printing APIs were added.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Changed files are unit tests only; no It/Describe/When/Context markers or IPv4/external-connectivity assumptions were found.
No-Weak-Crypto ✅ Passed The changed files only refactor OIDC generator wiring; searches found no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB, custom crypto, or secret comparisons.
Container-Privileges ✅ Passed The PR only refactors controller/generator code; no changed file adds privileged/hostPID/hostNetwork/hostIPC/SYS_ADMIN or allowPrivilegeEscalation settings.
No-Sensitive-Data-In-Logs ✅ Passed No new log statements were added, and the new error paths only mention resource names/key names, not secret/token values.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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: 1

🧹 Nitpick comments (1)
pkg/controllers/externaloidc/generation/kubeapiserver/generate.go (1)

65-65: 🩺 Stability & Availability | 🔵 Trivial | 💤 Low value

Consider a nil-check on authSpec.

Since this generator is being extracted for reuse as a shared library (per PR objective) consumed by both this operator and HyperShift, a future caller could pass a nil *AuthenticationSpec and cause a panic at authSpec.OIDCProviders (Line 74). Current in-repo call sites are safe since they pass &auth.Spec, but a public/reusable API benefits from guarding against nil input.

🛡️ Optional defensive guard
 func (acg *AuthenticationConfigurationGenerator) GenerateAuthenticationConfiguration(authSpec *configv1.AuthenticationSpec) (runtime.Object, error) {
+	if authSpec == nil {
+		return nil, errors.New("authSpec must not be nil")
+	}
 	authConfig := &apiserverv1beta1.AuthenticationConfiguration{
🤖 Prompt for 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.

In `@pkg/controllers/externaloidc/generation/kubeapiserver/generate.go` at line
65, The GenerateAuthenticationConfiguration method should defensively handle a
nil authSpec before dereferencing it. Add an early guard in
AuthenticationConfigurationGenerator.GenerateAuthenticationConfiguration so a
nil *configv1.AuthenticationSpec returns a clear error instead of panicking when
accessing authSpec.OIDCProviders. Keep the fix localized to this reusable API
and use the existing method name to place the check at the start of the
function.
🤖 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 `@pkg/controllers/externaloidc/externaloidc_controller.go`:
- Around line 60-63: Add the missing openshift-config Secret informer to the
external OIDC controller so auth config regenerates when client secrets rotate.
Update the informer setup around NewAuthenticationConfigurationGenerator in
externaloidc_controller.go to include
kubeInformersForNamespaces.InformersFor(configNamespace).Core().V1().Secrets().Informer()
alongside the existing ConfigMap and Secret listers, ensuring the controller
requeues on secret updates.

---

Nitpick comments:
In `@pkg/controllers/externaloidc/generation/kubeapiserver/generate.go`:
- Line 65: The GenerateAuthenticationConfiguration method should defensively
handle a nil authSpec before dereferencing it. Add an early guard in
AuthenticationConfigurationGenerator.GenerateAuthenticationConfiguration so a
nil *configv1.AuthenticationSpec returns a clear error instead of panicking when
accessing authSpec.OIDCProviders. Keep the fix localized to this reusable API
and use the existing method name to place the check at the start of the
function.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 84771049-e0d5-47cd-bff1-defed4a0519d

📥 Commits

Reviewing files that changed from the base of the PR and between 2fbe1fb and 2aaaa4c.

📒 Files selected for processing (6)
  • pkg/controllers/externaloidc/externaloidc_controller.go
  • pkg/controllers/externaloidc/externaloidc_controller_test.go
  • pkg/controllers/externaloidc/generation/kubeapiserver/generate.go
  • pkg/controllers/externaloidc/generation/kubeapiserver/generate_test.go
  • pkg/controllers/externaloidc/generation/oauthapiserver/generate.go
  • pkg/controllers/externaloidc/generation/oauthapiserver/generate_test.go

Comment on lines +60 to +63
gen := oauthapiserver.NewAuthenticationConfigurationGenerator(
newCABundleResolver(kubeInformersForNamespaces.ConfigMapLister(), configNamespace),
newClientSecretResolver(kubeInformersForNamespaces.SecretLister(), configNamespace),
).WithExternalClaimsSourcing()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the controller and related factory wiring
echo "== externaloidc_controller.go =="
cat -n pkg/controllers/externaloidc/externaloidc_controller.go | sed -n '1,180p'

echo
echo "== search for informer wiring and secret resolver usage =="
rg -n "newClientSecretResolver|WithInformers|Secrets\(\)\.Informer\(\)|SecretLister\(\)" pkg/controllers pkg/operator manifests -S

echo
echo "== search for RBAC references to openshift-config secrets =="
rg -n "openshift-config.*secrets|resources:.*secrets|verbs:.*(get|list|watch)" manifests pkg -S

Repository: openshift/cluster-authentication-operator

Length of output: 15186


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the controller factory and resolver helpers in smaller slices if needed
echo "== externaloidc_controller.go (selected range) =="
sed -n '1,180p' pkg/controllers/externaloidc/externaloidc_controller.go | cat -n

echo
echo "== client secret resolver helper =="
rg -n "func newClientSecretResolver|type .*clientSecretResolver|SecretLister" pkg/controllers/externaloidc -S

Repository: openshift/cluster-authentication-operator

Length of output: 9431


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== externaloidc_controller.go =="
cat -n pkg/controllers/externaloidc/externaloidc_controller.go | sed -n '1,180p'

echo
echo "== search for informer wiring and secret resolver usage =="
rg -n "newClientSecretResolver|WithInformers|Secrets\(\)\.Informer\(\)|SecretLister\(\)" pkg/controllers pkg/operator manifests -S

echo
echo "== search for RBAC references to openshift-config secrets =="
rg -n "openshift-config.*secrets|resources:.*secrets|verbs:.*(get|list|watch)" manifests pkg -S

Repository: openshift/cluster-authentication-operator

Length of output: 15186


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== KubeInformersForNamespaces definition =="
rg -n "type KubeInformersForNamespaces|func .*SecretLister|InformersFor\\(" $(git ls-files '*.go') -S

echo
echo "== starter wiring for openshift-config informers =="
cat -n pkg/operator/starter.go | sed -n '150,260p'

echo
echo "== inspect namespace informer implementation =="
rg -n "openshift-config.*Secrets\\(\\)|Core\\(\\)\\.V1\\(\\)\\.Secrets\\(\\)" pkg/operator pkg/controllers -S

Repository: openshift/cluster-authentication-operator

Length of output: 24801


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Focus on the factory/informer helper implementation that backs SecretLister.
fd -a ".*informers.*\.go$" pkg vendor | sed -n '1,120p'

Repository: openshift/cluster-authentication-operator

Length of output: 372


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== locate KubeInformersForNamespaces implementation in repo/vendor =="
rg -n "type KubeInformersForNamespaces|SecretLister\\(" . -S --glob '!**/.git/**'

echo
echo "== show starter informer factory setup =="
cat -n pkg/operator/starter.go | sed -n '1,260p'

Repository: openshift/cluster-authentication-operator

Length of output: 16992


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== controller registration and informer factories =="
rg -n "NewExternalOIDCController|kubeInformersForNamespaces|newInformerFactories|InformersFor\\(\"openshift-config\"" pkg/operator pkg/controllers -S

echo
echo "== snippet around external OIDC starter registration if present =="
cat -n pkg/operator/starter.go | sed -n '180,240p'

Repository: openshift/cluster-authentication-operator

Length of output: 15180


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== v1helpers informer implementation =="
cat -n vendor/github.com/openshift/library-go/pkg/operator/v1helpers/informers.go | sed -n '1,180p'

echo
echo "== replacement_starter.go informer factory setup =="
cat -n pkg/operator/replacement_starter.go | sed -n '230,330p'

echo
echo "== starter.go around externaloidc registration and openshift-config informers =="
cat -n pkg/operator/starter.go | sed -n '740,880p'

Repository: openshift/cluster-authentication-operator

Length of output: 20211


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== externaloidc resolver helpers =="
cat -n pkg/controllers/externaloidc/externaloidc_controller.go | sed -n '200,280p'

echo
echo "== RBAC for openshift-config secrets =="
rg -n "openshift-config|resources:.*secrets|verbs:.*(get|list|watch)" manifests pkg -S

echo
echo "== secret-related config/observer wiring =="
rg -n "SecretLister\\(|Secrets\\(\\)\\.Informer\\(\\)|newClientSecretResolver|ExternalClaimsSourcing" pkg/controllers/externaloidc pkg/operator -S

Repository: openshift/cluster-authentication-operator

Length of output: 19201


Add the openshift-config Secret informer
pkg/controllers/externaloidc/externaloidc_controller.go:85-94 — the shared SecretLister() cache is already available, but this controller never requeues on openshift-config secret updates. Client-secret rotations can therefore leave the generated auth config stale until some other watched resource changes. Add kubeInformersForNamespaces.InformersFor(configNamespace).Core().V1().Secrets().Informer() here.

🤖 Prompt for 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.

In `@pkg/controllers/externaloidc/externaloidc_controller.go` around lines 60 -
63, Add the missing openshift-config Secret informer to the external OIDC
controller so auth config regenerates when client secrets rotate. Update the
informer setup around NewAuthenticationConfigurationGenerator in
externaloidc_controller.go to include
kubeInformersForNamespaces.InformersFor(configNamespace).Core().V1().Secrets().Informer()
alongside the existing ConfigMap and Secret listers, ensuring the controller
requeues on secret updates.

Source: Coding guidelines

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

Labels

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant