Skip to content
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

CNTRLPLANE-78: Move Group informer configuration to RestrictSubjectBindings plugin initialization #2157

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

everettraven
Copy link

@everettraven everettraven commented Dec 9, 2024

What type of PR is this?

/kind bug

What this PR does / why we need it:

This PR moves the configuration of the Group informer to the authorization.openshift.io/RestrictSubjectBindings admission plugin initialization process. This is necessary to prevent the startup of an informer for the Group API when the plugin is disabled, which will happen when the OpenShift OAuth stack is intentionally removed from the cluster based on the Authentication configuration.

See openshift/enhancements#1726 for additional information.

@openshift-ci-robot openshift-ci-robot added the backports/unvalidated-commits Indicates that not all commits come to merged upstream PRs. label Dec 9, 2024
@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 9, 2024
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

Copy link

openshift-ci bot commented Dec 9, 2024

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-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from 80e26cb to e933af2 Compare January 24, 2025 19:15
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from e933af2 to edf1675 Compare January 24, 2025 19:18
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from 5e5552d to e25f667 Compare January 28, 2025 15:07
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from e25f667 to b7800b2 Compare January 28, 2025 15:08
@openshift-ci-robot
Copy link

openshift-ci-robot commented Jan 29, 2025

@everettraven: This pull request references CNTRLPLANE-78 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 story to target the "4.19.0" version, but no target version was set.

In response to this:

What type of PR is this?

/kind bug

What this PR does / why we need it:

This PR moves the configuration of the Group informer to the authorization.openshift.io/RestrictSubjectBindings admission plugin initialization process. This is necessary to prevent the startup of an informer for the Group API when the plugin is disabled, which will happen when the OpenShift OAuth stack is intentionally removed from the cluster based on the Authentication configuration.

See openshift/enhancements#1726 for additional information.

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.

@everettraven everettraven changed the title CNTRLPLANE-78: Add configuration for the RestrictSubjectBindings admission plugin CNTRLPLANE-78: Move Group informer configuration to RestrictSubjectBindings plugin initialization Jan 29, 2025
@everettraven everettraven marked this pull request as ready for review January 29, 2025 19:56
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jan 29, 2025
@openshift-ci openshift-ci bot requested review from p0lyn0mial and tkashem January 29, 2025 19:56
@everettraven
Copy link
Author

/retest

@everettraven
Copy link
Author

/retest-required

@everettraven
Copy link
Author

/retest

Comment on lines 93 to 96
if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
}); err != nil {
return
}
Copy link
Member

Choose a reason for hiding this comment

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

Would something like this for error handling be appropriate here?

Suggested change
if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
}); err != nil {
return
}
if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
}); err != nil {
utilruntime.HandleError(err)
return
}

Copy link
Author

Choose a reason for hiding this comment

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

Ah, good idea. I wasn't aware there was a utility for handling runtime errors. I'll update this.

Copy link
Author

Choose a reason for hiding this comment

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

Updated in the latest push

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from 03e0545 to fd11785 Compare February 14, 2025 19:05
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from fd11785 to 5592a48 Compare February 14, 2025 19:06
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@everettraven
Copy link
Author

/retest-required

@liouk
Copy link
Member

liouk commented Feb 28, 2025

/lgtm

@openshift-ci openshift-ci bot added the lgtm Indicates that a PR is ready to be merged. label Feb 28, 2025
Copy link

openshift-ci bot commented Feb 28, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: everettraven, liouk
Once this PR has been reviewed and has the lgtm label, please assign bertinatto for approval. For more information see the Code Review Process.

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 /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

usercache.ByUserIndexName: usercache.ByUserIndexKeys,
}); err != nil {
utilruntime.HandleError(err)
return
Copy link
Member

Choose a reason for hiding this comment

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

This is how we're handling errors in other places in this file, so this seems correct because this is an admission plugin, i.e., it's a non-user-facing error.

usercache.ByUserIndexName: usercache.ByUserIndexKeys,
}); err != nil {
return nil, err
}
Copy link
Member

Choose a reason for hiding this comment

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

In the enhancement, you have this:

- `Group` informer creation and configuration is moved into the `authorization.openshift.io/RestrictSubjectBindings` admission plugin initialization process

From what I understand from your PR, you are not moving the creation of the informer, only the indexer is being added in the admission plugin's informer instead. I assume that's what you meant by "configuration" (i.e., the indexer).

However, in the PR description, you said:

(...)
This is necessary to prevent the startup of an informer for the Group API when the plugin is disabled
(...)

So I'm wondering how this is preventing the startup of the informer. It seems to me that it's still being started as before. Am I missing anything?

Copy link

@benluddy benluddy Mar 11, 2025

Choose a reason for hiding this comment

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

The object passed to the admission plugin initializer is an informer factory, and it's the chained call to Informer() that both creates and registers a new informer if needed (and the informer is later started by SharedInformerFactory's Start). So moving that call to plugin initialization instead of run-always should actually work. This all assumes that the one call being moved is the only place a User Group informer is being requested.

Choose a reason for hiding this comment

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

// InformerFor returns the SharedIndexInformer for obj using an internal
// client.
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
f.lock.Lock()
defer f.lock.Unlock()
informerType := reflect.TypeOf(obj)
informer, exists := f.informers[informerType]
if exists {
return informer
}
resyncPeriod, exists := f.customResync[informerType]
if !exists {
resyncPeriod = f.defaultResync
}
informer = newFunc(f.client, resyncPeriod)
informer.SetTransform(f.transform)
f.informers[informerType] = informer
return informer
}

Copy link
Author

Choose a reason for hiding this comment

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

It was the only place for that particular SharedInformerFactory that it was being called

Copy link
Member

Choose a reason for hiding this comment

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

Hm, I see. Thanks for the explanation. So the factory is created in the run-always path, and the informers that are requested are started there as well. However, the creation of the informer and its configuration need to be done in the plugin.

I'm not familiar with this, and maybe that's how it's typically done, but this "shared responsibility" over the informer sounds error-prone to me. Is there a way to keep where it is, but run it conditionally?

Regardless, if we're going to do this, I'd suggest adding a comment in the plugin initialization stating that. Also, do we have a job proving this is working as intended?

Choose a reason for hiding this comment

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

Is there a way to keep where it is, but run it conditionally?

This is typical. Take a look at all of the implementations of this:

SetExternalKubeInformerFactory(informers.SharedInformerFactory)

The part that is atypical is having only one thing that requires a Group informer, and that it happens to be an admission plugin that is not always enabled. I agree there should be some job demonstrating that this is doing what we expect (are we looking to see that there are group watch 404s from kube-apiserver in an E2E job that enables and disables external OIDC without this, and that those requests disappear with this patch?).

Is there something we could add to CI that would tell us when we have perma-unstarted informers? I know that it's one of the /readyz checks to wait for all the Kube shared informers to start (https://github.com/openshift/kubernetes/blob/master/staging/src/k8s.io/apiserver/pkg/server/config.go#L960-L976). I guess we can't do the same for resources served by the aggregation layer without having a chicken-and-egg problem. Still, we should emit some indication that can be wired to a monitor test.

Copy link
Author

Choose a reason for hiding this comment

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

There is not an existing CI job to test this behavior, but is one that is intended to be created. If this PR is not mergeable until such a job exists I'm happy to place this PR on hold until then.

I have manually tested this based on https://issues.redhat.com/browse/OCPBUGS-45460 and verified that disabling the admission plugin does not result in seeing the same reflector errors being logged. I know manual testing isn't a good substitute for a repeatable CI job, but thought it was worth mentioning that I least stood up a cluster and manually tested this.

Copy link
Author

Choose a reason for hiding this comment

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

This isn't critical, and the BYO OIDC functionality is now slated for TP in 4.19, so this PR can wait until we've got more progress done on the testing front for that feature.

Copy link
Member

Choose a reason for hiding this comment

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

This is typical. Take a look at all of the implementations of this:

Thank you, now I see.

Another question: don't we need to wait for the cache to warm up?

diff --git i/openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers.go w/openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers.go
index 4dea00e61a4..e37ef8c0ff0 100644
--- i/openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers.go
+++ w/openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers.go
@@ -88,13 +88,16 @@ func (q *restrictUsersAdmission) SetRESTClientConfig(restClientConfig rest.Confi
 }
 
 func (q *restrictUsersAdmission) SetUserInformer(userInformers userinformer.SharedInformerFactory) {
-	if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
+	groupInformer := userInformers.User().V1().Groups()
+	if err := groupInformer.Informer().AddIndexers(cache.Indexers{
 		usercache.ByUserIndexName: usercache.ByUserIndexKeys,
 	}); err != nil {
 		utilruntime.HandleError(err)
 		return
 	}
-	q.groupCache = usercache.NewGroupCache(userInformers.User().V1().Groups())
+	q.groupCache = usercache.NewGroupCache(groupInformer)
+
+	q.SetReadyFunc(groupInformer.Informer().HasSynced)
 }
 
 // subjectsDelta returns the relative complement of elementsToIgnore in
@@ -129,6 +132,10 @@ func (q *restrictUsersAdmission) Validate(ctx context.Context, a admission.Attri
 		return nil
 	}
 
+	if !q.WaitForReady() {
+		return admission.NewForbidden(a, fmt.Errorf("not yet ready to handle request"))
+	}
+
 	// Ignore all operations that correspond to subresource actions.
 	if len(a.GetSubresource()) != 0 {
 		return nil

Choose a reason for hiding this comment

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

It's super indirect, but that appears to be already happening via the GroupCache... via newRoleBindingRestrictionContext. I wouldn't expect this PR to affect whether or not that's working as intended.

@@ -22,7 +22,7 @@ func newOpenshiftAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.I
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-apiserver", "api")
}

func newOAuthPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP) *aggregatedAPIServiceAvailabilityCheck {
func newOAuthAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP) *aggregatedAPIServiceAvailabilityCheck {

Choose a reason for hiding this comment

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

I'd like to see the cosmetic changes excluded to reduce the potential for conflicts as we maintain this patch over the years.

Copy link
Author

Choose a reason for hiding this comment

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

This one was my doing, the rest were go fmt related. I'm happy to revert cosmetic changes, would you like both this and the go fmt changes reverted?

Choose a reason for hiding this comment

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

I don't see any output if I run gofmt -d on either of the other files. Is it me? Maybe your editor is set up to run a gofmt-alike? I'd remove all of the cosmetic changes.

Copy link
Author

@everettraven everettraven Mar 11, 2025

Choose a reason for hiding this comment

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

What version of Go are you running? I've got 1.23.4

Choose a reason for hiding this comment

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

I ran GOTOOLCHAIN=go1.23.4 go fmt openshift-kube-apiserver/openshiftkubeapiserver/patch.go on master and it didn't make any changes.

Copy link
Author

Choose a reason for hiding this comment

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

Cosmetic changes reverted

Copy link
Author

Choose a reason for hiding this comment

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

Will rebase to roll up the commit that reverts it in a bit.

@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

@openshift-ci openshift-ci bot removed the lgtm Indicates that a PR is ready to be merged. label Mar 12, 2025
Copy link

openshift-ci bot commented Mar 12, 2025

New changes are detected. LGTM label has been removed.

@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from 3e7fc7b to e998ca8 Compare March 12, 2025 15:30
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

…jectBindings

admission plugin initialization to prevent Group informers being configured when
the plugin is disabled. This is necessary for when the OpenShift OAuth stack
is not present and the plugin is disabled as part of that.

Signed-off-by: Bryce Palmer <[email protected]>
@everettraven everettraven force-pushed the feature/external-oidc-restrictusers branch from e998ca8 to e94a834 Compare March 12, 2025 15:32
@openshift-ci-robot
Copy link

@everettraven: the contents of this pull request could not be automatically validated.

The following commits could not be validated and must be approved by a top-level approver:

Comment /validate-backports to re-evaluate validity of the upstream PRs, for example when they are merged upstream.

Copy link

openshift-ci bot commented Mar 12, 2025

@everettraven: all tests passed!

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backports/unvalidated-commits Indicates that not all commits come to merged upstream PRs. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants