Skip to content

Commit 81c8fd9

Browse files
committed
ouathclients: further split oidc and integrated oauth handling
HCP installs directly with OIDC support and as such removes the oauth-apiserver. It then wants to sync its config to the hosted authentication/cluster but it can't because the console-operator needs to set the clients in the status. However, the console-operator short-circuits on an error while querying the oauth APIs. Split the controller to separate the fail modes in integrated oauth and OIDC config.
1 parent c29bbd5 commit 81c8fd9

File tree

4 files changed

+324
-189
lines changed

4 files changed

+324
-189
lines changed

pkg/console/controllers/oauthclients/oauthclients.go

Lines changed: 25 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@ import (
66
"time"
77

88
corev1 "k8s.io/api/core/v1"
9-
apiexensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10-
apiexensionsv1informers "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1"
11-
apiexensionsv1listers "k8s.io/apiextensions-apiserver/pkg/client/listers/apiextensions/v1"
129
apierrors "k8s.io/apimachinery/pkg/api/errors"
1310
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1411
"k8s.io/apimachinery/pkg/util/wait"
@@ -34,17 +31,13 @@ import (
3431
"github.com/openshift/library-go/pkg/operator/events"
3532
"github.com/openshift/library-go/pkg/operator/resource/resourceapply"
3633
"github.com/openshift/library-go/pkg/operator/v1helpers"
37-
appsv1informers "k8s.io/client-go/informers/apps/v1"
38-
appsv1listers "k8s.io/client-go/listers/apps/v1"
3934

4035
"github.com/openshift/console-operator/pkg/api"
4136
"github.com/openshift/console-operator/pkg/console/controllers/util"
4237
"github.com/openshift/console-operator/pkg/console/status"
43-
deploymentsub "github.com/openshift/console-operator/pkg/console/subresource/deployment"
4438
oauthsub "github.com/openshift/console-operator/pkg/console/subresource/oauthclient"
4539
routesub "github.com/openshift/console-operator/pkg/console/subresource/route"
4640
secretsub "github.com/openshift/console-operator/pkg/console/subresource/secret"
47-
utilsub "github.com/openshift/console-operator/pkg/console/subresource/util"
4841
"github.com/openshift/console-operator/pkg/crypto"
4942
)
5043

@@ -58,32 +51,23 @@ type oauthClientsController struct {
5851
authentication configv1client.AuthenticationInterface
5952
authnLister configv1lister.AuthenticationLister
6053
consoleOperatorLister operatorv1listers.ConsoleLister
61-
crdLister apiexensionsv1listers.CustomResourceDefinitionLister
6254
routesLister routev1listers.RouteLister
6355
ingressConfigLister configv1lister.IngressLister
6456
targetNSSecretsLister corev1listers.SecretLister
65-
configNSSecretsLister corev1listers.SecretLister
66-
targetNSDeploymentsLister appsv1listers.DeploymentLister
67-
targetNSConfigLister corev1listers.ConfigMapLister
6857

69-
authStatusHandler status.AuthStatusHandler
58+
authStatusHandler *status.AuthStatusHandler
7059
}
7160

7261
func NewOAuthClientsController(
73-
ctx context.Context,
7462
operatorClient v1helpers.OperatorClient,
7563
oauthClient oauthclient.Interface,
7664
secretsClient corev1client.SecretsGetter,
77-
crdInformer apiexensionsv1informers.CustomResourceDefinitionInformer,
7865
authentication configv1client.AuthenticationInterface,
7966
authnInformer configv1informers.AuthenticationInformer,
8067
consoleOperatorInformer operatorv1informers.ConsoleInformer,
8168
routeInformer routev1informers.RouteInformer,
8269
ingressConfigInformer configv1informers.IngressInformer,
8370
targetNSsecretsInformer corev1informers.SecretInformer,
84-
configNSSecretsInformer corev1informers.SecretInformer,
85-
targetNSConfigInformer corev1informers.ConfigMapInformer,
86-
targetNSDeploymentsInformer appsv1informers.DeploymentInformer,
8771
oauthClientSwitchedInformer *util.InformerWithSwitch,
8872
recorder events.Recorder,
8973
) factory.Controller {
@@ -100,10 +84,6 @@ func NewOAuthClientsController(
10084
routesLister: routeInformer.Lister(),
10185
ingressConfigLister: ingressConfigInformer.Lister(),
10286
targetNSSecretsLister: targetNSsecretsInformer.Lister(),
103-
configNSSecretsLister: configNSSecretsInformer.Lister(),
104-
targetNSConfigLister: targetNSConfigInformer.Lister(),
105-
targetNSDeploymentsLister: targetNSDeploymentsInformer.Lister(),
106-
crdLister: crdInformer.Lister(),
10787

10888
authStatusHandler: status.NewAuthStatusHandler(authentication, api.OpenShiftConsoleName, api.TargetNamespace, api.OpenShiftConsoleOperator),
10989
}
@@ -116,42 +96,45 @@ func NewOAuthClientsController(
11696
routeInformer.Informer(),
11797
ingressConfigInformer.Informer(),
11898
targetNSsecretsInformer.Informer(),
119-
configNSSecretsInformer.Informer(),
120-
targetNSDeploymentsInformer.Informer(),
12199
).
122100
WithFilteredEventsInformers(
123101
factory.NamesFilter(api.OAuthClientName),
124102
oauthClientSwitchedInformer.Informer(),
125103
).
126-
WithFilteredEventsInformers(
127-
factory.NamesFilter("authentications.config.openshift.io"),
128-
crdInformer.Informer(),
129-
).
130104
WithSyncDegradedOnError(operatorClient).
131105
ResyncEvery(wait.Jitter(time.Minute, 1.0)).
132106
ToController("OAuthClientsController", recorder.WithComponentSuffix("oauth-clients-controller"))
133107
}
134108

135109
func (c *oauthClientsController) sync(ctx context.Context, controllerContext factory.SyncContext) error {
136-
statusHandler := status.NewStatusHandler(c.operatorClient)
137-
138110
if shouldSync, err := c.handleManaged(ctx); err != nil {
139111
return err
140112
} else if !shouldSync {
141113
return nil
142114
}
143115

144-
operatorConfig, err := c.consoleOperatorLister.Get(api.ConfigResourceName)
116+
statusHandler := status.NewStatusHandler(c.operatorClient)
117+
118+
authnConfig, err := c.authnLister.Get(api.ConfigResourceName)
145119
if err != nil {
146120
return err
147121
}
148122

149-
ingressConfig, err := c.ingressConfigLister.Get(api.ConfigResourceName)
123+
switch authnConfig.Spec.Type {
124+
case "", configv1.AuthenticationTypeIntegratedOAuth:
125+
default:
126+
// if we're not using integrated oauth, reset all degraded conditions
127+
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSecretSync", "", nil))
128+
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSync", "", nil))
129+
return statusHandler.FlushAndReturn(nil)
130+
}
131+
132+
operatorConfig, err := c.consoleOperatorLister.Get(api.ConfigResourceName)
150133
if err != nil {
151134
return err
152135
}
153136

154-
authnConfig, err := c.authnLister.Get(api.ConfigResourceName)
137+
ingressConfig, err := c.ingressConfigLister.Get(api.ConfigResourceName)
155138
if err != nil {
156139
return err
157140
}
@@ -167,142 +150,25 @@ func (c *oauthClientsController) sync(ctx context.Context, controllerContext fac
167150
return routeErr
168151
}
169152

170-
var syncErr error
171-
switch authnConfig.Spec.Type {
172-
case "", configv1.AuthenticationTypeIntegratedOAuth:
173-
waitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
174-
defer cancel()
175-
if !cache.WaitForCacheSync(waitCtx.Done(), c.oauthClientSwitchedInformer.Informer().HasSynced) {
176-
return statusHandler.FlushAndReturn(fmt.Errorf("timed out waiting for OAuthClients cache sync"))
177-
}
178-
179-
clientSecret, secErr := c.syncSecret(ctx, operatorConfig, controllerContext.Recorder())
180-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSecretSync", "FailedApply", secErr))
181-
if secErr != nil {
182-
return statusHandler.FlushAndReturn(secErr)
183-
}
184-
185-
oauthErrReason, oauthErr := c.syncOAuthClient(ctx, clientSecret, consoleURL.String())
186-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSync", oauthErrReason, oauthErr))
187-
if oauthErr != nil {
188-
return statusHandler.FlushAndReturn(oauthErr)
189-
}
190-
191-
case configv1.AuthenticationTypeOIDC:
192-
syncErr = c.syncAuthTypeOIDC(ctx, controllerContext, statusHandler, operatorConfig, authnConfig)
193-
if syncErr != nil {
194-
return statusHandler.FlushAndReturn(syncErr)
195-
}
153+
waitCtx, cancel := context.WithTimeout(ctx, 10*time.Second)
154+
defer cancel()
155+
if !cache.WaitForCacheSync(waitCtx.Done(), c.oauthClientSwitchedInformer.Informer().HasSynced) {
156+
return statusHandler.FlushAndReturn(fmt.Errorf("timed out waiting for OAuthClients cache sync"))
196157
}
197158

198-
oidcClientsSchema, err := authnConfigHasOIDCFields(c.crdLister)
159+
clientSecret, err := c.syncSecret(ctx, operatorConfig, controllerContext.Recorder())
160+
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSecretSync", "FailedApply", err))
199161
if err != nil {
200162
return statusHandler.FlushAndReturn(err)
201163
}
202164

203-
if oidcClientsSchema {
204-
applyErr := c.authStatusHandler.Apply(ctx, authnConfig)
205-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("AuthStatusHandler", "FailedApply", applyErr))
206-
if applyErr != nil {
207-
return statusHandler.FlushAndReturn(applyErr)
208-
}
209-
}
210-
211-
return statusHandler.FlushAndReturn(nil)
212-
}
213-
214-
func (c *oauthClientsController) syncAuthTypeOIDC(
215-
ctx context.Context,
216-
controllerContext factory.SyncContext,
217-
statusHandler status.StatusHandler,
218-
operatorConfig *operatorv1.Console,
219-
authnConfig *configv1.Authentication,
220-
) error {
221-
222-
clientConfig := utilsub.GetOIDCClientConfig(authnConfig)
223-
if clientConfig == nil {
224-
c.authStatusHandler.WithCurrentOIDCClient("")
225-
c.authStatusHandler.Unavailable("OIDCClientConfig", "no OIDC client found")
226-
return nil
227-
}
228-
229-
if len(clientConfig.ClientID) == 0 {
230-
err := fmt.Errorf("no ID set on OIDC client")
231-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OIDCClientConfig", "MissingID", err))
232-
return statusHandler.FlushAndReturn(err)
233-
}
234-
c.authStatusHandler.WithCurrentOIDCClient(clientConfig.ClientID)
235-
236-
if len(clientConfig.ClientSecret.Name) == 0 {
237-
c.authStatusHandler.Degraded("OIDCClientMissingSecret", "no client secret in the OIDC client config")
238-
return nil
239-
}
240-
241-
clientSecret, err := c.configNSSecretsLister.Secrets(api.OpenShiftConfigNamespace).Get(clientConfig.ClientSecret.Name)
165+
oauthErrReason, err := c.syncOAuthClient(ctx, clientSecret, consoleURL.String())
166+
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OAuthClientSync", oauthErrReason, err))
242167
if err != nil {
243-
c.authStatusHandler.Degraded("OIDCClientSecretGet", err.Error())
244-
return err
245-
}
246-
247-
secret, err := c.targetNSSecretsLister.Secrets(api.TargetNamespace).Get(secretsub.Stub().Name)
248-
expectedClientSecret := secretsub.GetSecretString(clientSecret)
249-
if apierrors.IsNotFound(err) || secretsub.GetSecretString(secret) != expectedClientSecret {
250-
secret, _, err = resourceapply.ApplySecret(ctx, c.secretsClient, controllerContext.Recorder(), secretsub.DefaultSecret(operatorConfig, expectedClientSecret))
251-
if err != nil {
252-
statusHandler.AddConditions(status.HandleProgressingOrDegraded("OIDCClientSecretSync", "FailedApply", err))
253-
return err
254-
}
255-
}
256-
257-
if valid, msg, err := c.checkClientConfigStatus(authnConfig, secret); err != nil {
258-
c.authStatusHandler.Degraded("DeploymentOIDCConfig", err.Error())
259-
return err
260-
261-
} else if !valid {
262-
c.authStatusHandler.Progressing("DeploymentOIDCConfig", msg)
263-
return nil
264-
}
265-
266-
c.authStatusHandler.Available("OIDCConfigAvailable", "")
267-
return nil
268-
}
269-
270-
// checkClientConfigStatus checks whether the current client configuration is being currently in use,
271-
// by looking at the deployment status. It checks whether the deployment is available and updated,
272-
// and also whether the resource versions for the oauth secret and server CA trust configmap match
273-
// the deployment.
274-
func (c *oauthClientsController) checkClientConfigStatus(authnConfig *configv1.Authentication, clientSecret *corev1.Secret) (bool, string, error) {
275-
depl, err := c.targetNSDeploymentsLister.Deployments(api.OpenShiftConsoleNamespace).Get(api.OpenShiftConsoleDeploymentName)
276-
if err != nil {
277-
return false, "", err
278-
}
279-
280-
deplAvailableUpdated := deploymentsub.IsAvailableAndUpdated(depl)
281-
if !deplAvailableUpdated {
282-
return false, "deployment unavailable or outdated", nil
283-
}
284-
285-
if clientSecret.GetResourceVersion() != depl.ObjectMeta.Annotations["console.openshift.io/oauth-secret-version"] {
286-
return false, "client secret version not up to date in current deployment", nil
287-
}
288-
289-
if len(authnConfig.Spec.OIDCProviders) > 0 {
290-
serverCAConfigName := authnConfig.Spec.OIDCProviders[0].Issuer.CertificateAuthority.Name
291-
if len(serverCAConfigName) == 0 {
292-
return deplAvailableUpdated, "", nil
293-
}
294-
295-
serverCAConfig, err := c.targetNSConfigLister.ConfigMaps(api.OpenShiftConsoleNamespace).Get(serverCAConfigName)
296-
if err != nil {
297-
return false, "", err
298-
}
299-
300-
if serverCAConfig.GetResourceVersion() != depl.ObjectMeta.Annotations["console.openshift.io/authn-ca-trust-config-version"] {
301-
return false, "OIDC provider CA version not up to date in current deployment", nil
302-
}
168+
return statusHandler.FlushAndReturn(err)
303169
}
304170

305-
return deplAvailableUpdated, "", nil
171+
return statusHandler.FlushAndReturn(nil)
306172
}
307173

308174
// handleStatus returns whether sync should happen and any error encountering
@@ -375,28 +241,3 @@ func (c *oauthClientsController) deregisterClient(ctx context.Context) error {
375241
return err
376242

377243
}
378-
379-
func authnConfigHasOIDCFields(crdLister apiexensionsv1listers.CustomResourceDefinitionLister) (bool, error) {
380-
authnCRD, err := crdLister.Get("authentications.config.openshift.io")
381-
if err != nil {
382-
return false, err
383-
}
384-
385-
var authnV1Config *apiexensionsv1.CustomResourceDefinitionVersion
386-
for _, version := range authnCRD.Spec.Versions {
387-
if version.Name == "v1" && version.Served && version.Storage {
388-
authnV1Config = &version
389-
break
390-
}
391-
}
392-
393-
if authnV1Config == nil {
394-
return false, fmt.Errorf("authentications.config.openshift.io is not served or stored as v1")
395-
}
396-
397-
schema := authnV1Config.Schema.OpenAPIV3Schema
398-
_, clientsExist := schema.Properties["status"].Properties["oidcClients"]
399-
400-
return clientsExist, nil
401-
402-
}

0 commit comments

Comments
 (0)