Skip to content

WIP: AUTH-543: OIDC/OAuth resource configuration #740

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
2be467c
common: add helper to determine whether OIDC is enabled on KAS pods
liouk Nov 13, 2024
6892957
controllers: add helper that deletes controller conditions from opera…
liouk Jul 3, 2025
564611d
operator: configure static resources that should be removed for OIDC
liouk Jun 18, 2025
d673191
operator: enable or disable API services depending on whether OIDC is…
liouk Jun 18, 2025
8d249b2
deployment: bypass precondition checks if OIDC is available
liouk Nov 20, 2024
726e408
endpointaccessible: disable controller checks upon specific conditions
liouk Nov 13, 2024
a645adb
proxyconfig: disable proxy checks when external OIDC config is available
liouk Nov 14, 2024
fa2a646
ingressnodesavailable: disable checks when external OIDC config is av…
liouk Nov 14, 2024
9dd17d8
ingressstate: disable checks when external OIDC config is available
liouk Nov 14, 2024
a399cba
readiness: disable checks when external OIDC config is available
liouk Nov 14, 2024
a3fbe42
metadata: remove operands if external OIDC config is available
liouk Nov 14, 2024
98a2d89
routercerts: remove operands if external OIDC config is available
liouk Nov 15, 2024
c621dd4
serviceca: remove operands if external OIDC config is available
liouk Nov 15, 2024
e6acb56
payload: remove operands if external OIDC config is available
liouk Nov 15, 2024
c1c28bc
customroute: remove operands and clear custom route ingress status if…
liouk Nov 18, 2024
2cdda07
controllers: add switchable informer controller
liouk Nov 22, 2024
aeeaa03
oauthclientscontroller: remove operands when external OIDC config is …
liouk Nov 14, 2024
4933044
trustdistribution: remove operands if external OIDC config is available
liouk Jun 16, 2025
3b7fb52
webhookauthenticator: remove operands if external OIDC config is avai…
liouk Jun 16, 2025
5783e47
test/e2e-oidc: validate oauth resources missing when OIDC gets rolled…
liouk Jun 16, 2025
dc6ad1e
drop! pull in lib-go workload changes
liouk Jul 3, 2025
e72ead9
drop! use new lib-go to delete workloads
liouk Jun 30, 2025
1a9d90f
drop! add helper envs in e2e test
liouk Jul 3, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,5 @@ require (
sigs.k8s.io/structured-merge-diff/v4 v4.4.2 // indirect
sigs.k8s.io/yaml v1.4.0 // indirect
)

replace github.com/openshift/library-go => github.com/liouk/library-go v0.0.0-20250620094701-b03ce0ac0d58
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/ledongthuc/pdf v0.0.0-20220302134840-0c2507a12d80/go.mod h1:imJHygn/1yfhB7XSJJKlFZKl/J+dCPAknuiaGOshXAs=
github.com/liouk/library-go v0.0.0-20250620094701-b03ce0ac0d58 h1:N/KdLelLRiQdsnJTTcivQvkwgXiAPEB6DlwRyrcEcbI=
github.com/liouk/library-go v0.0.0-20250620094701-b03ce0ac0d58/go.mod h1:DAa3BGl0CFtkfJn/g5rU8kDDTErfMVA/QlFm4cvU+MI=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
Expand All @@ -155,8 +157,6 @@ github.com/openshift/build-machinery-go v0.0.0-20250102153059-e85a1a7ecb5c h1:6X
github.com/openshift/build-machinery-go v0.0.0-20250102153059-e85a1a7ecb5c/go.mod h1:8jcm8UPtg2mCAsxfqKil1xrmRMI3a+XU2TZ9fF8A7TE=
github.com/openshift/client-go v0.0.0-20250125113824-8e1f0b8fa9a7 h1:4iliLcvr1P9EUMZgIaSNEKNQQzBn+L6PSequlFOuB6Q=
github.com/openshift/client-go v0.0.0-20250125113824-8e1f0b8fa9a7/go.mod h1:2tcufBE4Cu6RNgDCxcUJepa530kGo5GFVfR9BSnndhI=
github.com/openshift/library-go v0.0.0-20250319141325-07c53d93ad06 h1:vM1BbOl3adyX0LgzNYYndZ+nkerEo7bKEQxxc6zLgNA=
github.com/openshift/library-go v0.0.0-20250319141325-07c53d93ad06/go.mod h1:GHwvopE5KXXCz4ULHp871sTPLLW+FB+hu/RIzlNwxx8=
github.com/openshift/multi-operator-manager v0.0.0-20241205181422-20aa3906b99d h1:Rzx23P63JFNNz5D23ubhC0FCN5rK8CeJhKcq5QKcdyU=
github.com/openshift/multi-operator-manager v0.0.0-20241205181422-20aa3906b99d/go.mod h1:iVi9Bopa5cLhjG5ie9DoZVVqkH8BGb1FQVTtecOLn4I=
github.com/orisano/pixelmatch v0.0.0-20220722002657-fb0b55479cde/go.mod h1:nZgzbfBr3hhjoZnS66nKrHmduYNpc34ny7RK4z5/HM0=
Expand Down
46 changes: 46 additions & 0 deletions pkg/controllers/common/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ package common

import (
"context"
"fmt"
"strings"
"time"

"k8s.io/apimachinery/pkg/util/sets"

operatorv1 "github.com/openshift/api/operator/v1"
applyoperatorv1 "github.com/openshift/client-go/operator/applyconfigurations/operator/v1"
"github.com/openshift/library-go/pkg/apiserver/jsonpatch"
"github.com/openshift/library-go/pkg/operator/v1helpers"
)

Expand Down Expand Up @@ -108,3 +110,47 @@ func ApplyControllerConditions(ctx context.Context, operatorClient v1helpers.Ope

return operatorClient.ApplyOperatorStatus(ctx, fieldManager, status)
}

func DeleteControllerConditions(ctx context.Context, operatorClient v1helpers.OperatorClient, conditionTypes ...string) error {
if len(conditionTypes) == 0 {
return nil
}

_, operatorStatus, _, err := operatorClient.GetOperatorState()
if err != nil {
return err
}

// TODO replace with the one from library-go/pkg/operator/v1helpers when this PR gets merged: https://github.com/openshift/library-go/pull/1902
patch := removeConditionsJSONPatch(operatorStatus, conditionTypes)
if patch == nil || patch.IsEmpty() {
return nil
}

return operatorClient.PatchOperatorStatus(ctx, patch)
}

func removeConditionsJSONPatch(operatorStatus *operatorv1.OperatorStatus, conditionTypesToRemove []string) *jsonpatch.PatchSet {
if operatorStatus == nil || len(conditionTypesToRemove) == 0 {
return nil
}

jsonPatch := jsonpatch.New()
var removedCount int
for i, cond := range operatorStatus.Conditions {
for _, conditionTypeToRemove := range conditionTypesToRemove {
if cond.Type != conditionTypeToRemove {
continue
}

removeAtIndex := i - removedCount
jsonPatch.WithRemove(
fmt.Sprintf("/status/conditions/%d", removeAtIndex),
jsonpatch.NewTestCondition(fmt.Sprintf("/status/conditions/%d/type", removeAtIndex), conditionTypeToRemove),
)
removedCount++
}
}

return jsonPatch
}
105 changes: 105 additions & 0 deletions pkg/controllers/common/external_oidc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package common

import (
"fmt"
"strings"

configv1 "github.com/openshift/api/config/v1"
configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1"
configv1listers "github.com/openshift/client-go/config/listers/config/v1"
operatorv1informers "github.com/openshift/client-go/operator/informers/externalversions/operator/v1"
operatorv1listers "github.com/openshift/client-go/operator/listers/operator/v1"
corev1informers "k8s.io/client-go/informers/core/v1"

"k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/util/sets"
corelistersv1 "k8s.io/client-go/listers/core/v1"
)

type AuthConfigChecker struct {
authentications configv1informers.AuthenticationInformer
authLister configv1listers.AuthenticationLister
kubeAPIServers operatorv1informers.KubeAPIServerInformer
kasLister operatorv1listers.KubeAPIServerLister
Comment on lines +20 to +23
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do we actually need to keep a hold of the *Informer types here?

I don't see anywhere they are used within the AuthConfigChecker or being accessed through the accessor methods on the AuthConfigChecker. Did I miss something?

Copy link
Member Author

Choose a reason for hiding this comment

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

The AuthenticationInformer and KubeAPIServerInformer are accessed via the accessor methods in controllers that need to use them to trigger syncs. But indeed, the ConfigMapInformer one isn't used anywhere, this was probably a left over during development; I'll drop that one.

kasNamespaceConfigMaps corev1informers.ConfigMapInformer
kasConfigMapLister corelistersv1.ConfigMapLister
}

func NewAuthConfigChecker(authentications configv1informers.AuthenticationInformer, kubeapiservers operatorv1informers.KubeAPIServerInformer, configmaps corev1informers.ConfigMapInformer) AuthConfigChecker {
return AuthConfigChecker{
authentications: authentications,
kubeAPIServers: kubeapiservers,
kasNamespaceConfigMaps: configmaps,
authLister: authentications.Lister(),
kasLister: kubeapiservers.Lister(),
kasConfigMapLister: configmaps.Lister(),
}
}

func (c *AuthConfigChecker) AuthConfig() (*configv1.Authentication, error) {
return c.authLister.Get("cluster")
}

func (c *AuthConfigChecker) Authentications() configv1informers.AuthenticationInformer {
return c.authentications
}

func (c *AuthConfigChecker) KubeAPIServers() operatorv1informers.KubeAPIServerInformer {
return c.kubeAPIServers
}

func (c *AuthConfigChecker) KubeAPIServerNamespaceConfigMaps() corev1informers.ConfigMapInformer {
return c.kasNamespaceConfigMaps
}

// OIDCAvailable checks the kubeapiservers/cluster resource for KAS pod
// rollout status; it returns true if auth type is OIDC, all KAS pods are currently on a revision
// that includes the structured auth-config ConfigMap, and the KAS args include the respective
// arg that enables usage of the structured auth-config. It returns false otherwise.
func (c *AuthConfigChecker) OIDCAvailable() (bool, error) {
if auth, err := c.authLister.Get("cluster"); err != nil {
return false, err
} else if auth.Spec.Type != configv1.AuthenticationTypeOIDC {
return false, nil
}

kas, err := c.kasLister.Get("cluster")
if err != nil {
return false, err
}

observedRevisions := sets.New[int32]()
for _, nodeStatus := range kas.Status.NodeStatuses {
observedRevisions.Insert(nodeStatus.CurrentRevision)
}

if observedRevisions.Len() == 0 {
return false, nil
}

for _, revision := range observedRevisions.UnsortedList() {
// ensure every observed revision includes an auth-config revisioned configmap
_, err := c.kasConfigMapLister.ConfigMaps("openshift-kube-apiserver").Get(fmt.Sprintf("auth-config-%d", revision))
if errors.IsNotFound(err) {
return false, nil
} else if err != nil {
return false, err
}

// every observed revision includes a copy of the KAS config configmap
cm, err := c.kasConfigMapLister.ConfigMaps("openshift-kube-apiserver").Get(fmt.Sprintf("config-%d", revision))
if err != nil {
return false, err
}

// ensure the KAS config of every observed revision contains the appropriate CLI arg for OIDC
// but not the respective ones for OAuth
if !strings.Contains(cm.Data["config.yaml"], `"oauthMetadataFile":""`) ||
strings.Contains(cm.Data["config.yaml"], `"authentication-token-webhook-config-file":`) ||
!strings.Contains(cm.Data["config.yaml"], `"authentication-config":["/etc/kubernetes/static-pod-resources/configmaps/auth-config/auth-config.json"]`) {
return false, nil
}
}

return true, nil
}
Loading