-
Notifications
You must be signed in to change notification settings - Fork 161
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
AUTH-541: OIDC structured auth config #1760
base: master
Are you sure you want to change the base?
Conversation
@liouk: This pull request references AUTH-541 which is a valid jira issue. In response to this:
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. |
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: liouk The full list of commands accepted by this bot can be found here.
Needs approval from an approver in each of these files:
Approvers can indicate their approval by writing |
48a956d
to
ef36c41
Compare
@liouk: This pull request references AUTH-541 which is a valid jira issue. In response to this:
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. |
/retest |
3 similar comments
/retest |
/retest |
/retest |
Investigating issue found in https://issues.redhat.com/browse/OCPBUGS-44592, will hold. /hold |
ef36c41
to
5cdfb5e
Compare
/retest |
2 similar comments
/retest |
/retest |
Issue fixed, cancelling hold. /hold cancel |
return fmt.Errorf("value of key 'auth-config.json' is empty") | ||
} | ||
|
||
var authConfig apiserver.AuthenticationConfiguration |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The serialized object should be from one of the external versions of apiserver.config.k8s.io
, not the internal version. You'll want to use one of the functions in https://pkg.go.dev/k8s.io/apiserver/pkg/apis/apiserver/load which handle decoding from all external versions and conversion to the internal version for you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://pkg.go.dev/k8s.io/apiserver/pkg/apis/apiserver/load only contains Load*()
funcs for the AuthorizationConfiguration
configuration type, instead of AuthenticationConfiguration
which we need here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, sorry, missed that. Then you'll need to set up the codec yourself here.
} | ||
|
||
observedConfig := make(map[string]interface{}) | ||
if err := unstructured.SetNestedField(observedConfig, []interface{}{staticAuthConfigPath}, apiServerArgumentsPath, argAuthConfig); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: It's equivalent, but you might consider using SetNestedStringSlice
here.
@@ -38,7 +39,7 @@ type ConfigObserver struct { | |||
factory.Controller | |||
} | |||
|
|||
func NewConfigObserver(operatorClient v1helpers.StaticPodOperatorClient, kubeInformersForNamespaces v1helpers.KubeInformersForNamespaces, configInformer configinformers.SharedInformerFactory, operatorInformer operatorv1informers.SharedInformerFactory, resourceSyncer resourcesynccontroller.ResourceSyncer, featureGateAccessor featuregates.FeatureGateAccess, eventRecorder events.Recorder, groupVersionsByFeatureGate map[configv1.FeatureGateName][]schema.GroupVersion) *ConfigObserver { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this taking a clientset now? I don't see it being referenced anywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, leftover from previous changes I'd presume.
@@ -62,7 +63,7 @@ func ObserveWebhookTokenAuthenticator(genericListers configobserver.Listers, rec | |||
} | |||
|
|||
observedWebhookConfigured := len(webhookSecretName) > 0 | |||
if observedWebhookConfigured { | |||
if observedWebhookConfigured && auth.Spec.Type != configv1.AuthenticationTypeOIDC { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The doc for spec.webhookTokenAuthenticator
says:
Can only be set if "Type" is set to "None".
But this seems to consume it when type is either "IntegratedOAuth" or "None". Is this relying on API validation or something else?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That comment is misleading indeed -- this relies on a validation admission plugin: https://github.com/openshift/kubernetes/blob/8540bd493e8a42ffb61a3f470f71290488332b1c/openshift-kube-apiserver/admission/customresourcevalidation/authentication/validate_authentication.go#L103-L130
if len(sourceName) == 0 { | ||
recorder.Eventf("ObserveExternalOIDC", "deleted configmap %s/%s", operatorclient.TargetNamespace, AuthConfigCMName) | ||
} else { | ||
recorder.Eventf("ObserveExternalOIDC", "synced configmap %s/%s to %s/%s", sourceNamespace, sourceName, operatorclient.TargetNamespace, AuthConfigCMName) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SyncConfigMap appears to do the actual writes asynchronously, so a nil return value doesn't mean that the writes are done (or will ever succeed). Any errors will show up later in the operator status. If these events are important then I would make the message clear that the write has been requested.
listers := genericListers.(configobservation.Listers) | ||
auth, err := listers.AuthConfigLister.Get("cluster") | ||
if errors.IsNotFound(err) { | ||
klog.Warningf("authentications.config.openshift.io/cluster: not found") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Other config observers seem to be recording events for similar conditions, is that reasonable to do here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I followed the example of auth_metadata and webhook_authenticator config observers that don't record events for that case; I'll add events to all three of them, since that's what we usually do.
if _, err := listers.ConfigMapLister().ConfigMaps(operatorclient.TargetNamespace).Get(AuthConfigCMName); errors.IsNotFound(err) { | ||
return nil, nil | ||
|
||
} else if err != nil { | ||
return existingConfig, []error{fmt.Errorf("failed to get configmap %s/%s: %v", operatorclient.TargetNamespace, AuthConfigCMName, err)} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will the following call to syncConfigMap
do effectively the same thing? What's the advantage of short-circuiting here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wanted to avoid another sync when we know we don't have that CM anymore, mainly because the syncer seems to be doing a Get API call.
|
||
sourceAuthConfig, err := listers.ConfigMapLister().ConfigMaps(SourceAuthConfigCMNamespace).Get(AuthConfigCMName) | ||
if errors.IsNotFound(err) { | ||
klog.Warningf("configmap %s/%s not found; skipping configuration of OIDC", SourceAuthConfigCMNamespace, AuthConfigCMName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For my understanding, if the target CM exists and the source CM is missing, the resource syncer will eventually delete the target CM asynchronously, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's correct, This check exists here to guard from the case where type has been set to OIDC but CAO isn't ready yet and the source CM hasn't appeared yet -- no point in trying to configure OIDC until it does.
return existingConfig, []error{err} | ||
} | ||
|
||
if targetAuthConfig == nil || !equality.Semantic.DeepEqual(targetAuthConfig.Data, sourceAuthConfig.Data) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would expect the syncer to be responsible for deciding whether or not it needs to do a write. Why test here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As per my previous comment, I wanted to avoid an extra API call that the syncer does.
if cm == nil { | ||
return fmt.Errorf("configmap is nil") | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: The caller is already handling "not found", so we never expect this to be called with a nil pointer. Would it be fine to let this panic on a nil pointer dereference since that would violate our assumptions about how it is used?
5cdfb5e
to
d98f147
Compare
From test result perspective, based on good pre-merge test results in https://issues.redhat.com/browse/OCPBUGS-44592?focusedId=26134688&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-26134688 , adding below label: |
@liouk: This pull request references AUTH-541 which is a valid jira issue. In response to this:
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. |
/retest |
d98f147
to
cabf5cf
Compare
cabf5cf
to
6b9d211
Compare
@liouk: The following tests failed, say
Full PR test history. Your PR dashboard. 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 kubernetes-sigs/prow repository. I understand the commands that are listed here. |
This PR does the following:
AuthMetadata
config observerOIDC
and the structured auth config CM inopenshift-config-managed
openshift-kube-apiserver
where it will be used as a revisioned configmap and synced to a static file on all KAS nodes--authentication-config
CLI flag of the KAS podsAuthMetadata
andWebhookTokenAuthenticator
config observers to delete their respective resources when auth typeOIDC
is detectedEnhancement: openshift/enhancements#1632