Skip to content

Commit 4b215ac

Browse files
committed
new approach
Signed-off-by: Bryce Palmer <[email protected]>
1 parent 3114152 commit 4b215ac

File tree

9 files changed

+174
-88
lines changed

9 files changed

+174
-88
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
// +k8s:deepcopy-gen=package,register
2+
3+
// Package v1alpha is the v1alpha1 version of the API.
4+
package v1alpha1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package v1alpha1
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/runtime"
5+
"k8s.io/apimachinery/pkg/runtime/schema"
6+
)
7+
8+
var GroupVersion = schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1alpha1"}
9+
10+
var (
11+
localSchemeBuilder = runtime.NewSchemeBuilder(
12+
addKnownTypes,
13+
)
14+
Install = localSchemeBuilder.AddToScheme
15+
)
16+
17+
func addKnownTypes(scheme *runtime.Scheme) error {
18+
scheme.AddKnownTypes(GroupVersion,
19+
&RestrictSubjectBindingsAdmissionConfig{},
20+
)
21+
return nil
22+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package v1alpha1
2+
3+
import (
4+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
5+
)
6+
7+
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
8+
9+
// RestrictSubjectBindingsAdmissionConfig is the type
10+
// used for configuring the authorization.openshift.io/RestrictSubjectBindings
11+
// admission plugin.
12+
type RestrictSubjectBindingsAdmissionConfig struct {
13+
metav1.TypeMeta `json:",inline"`
14+
15+
// openshiftOAuthDesiredState specifies the desired state
16+
// of the OpenShift oauth-apiserver based on observed configuration.
17+
//
18+
// Allowed values are Desired and NotDesired.
19+
//
20+
// When set to Desired, the authorization.openshift.io/RestrictSubjectBindings
21+
// admission plugin will be configured with the expectation that the OpenShift
22+
// oauth-apiserver will eventually be running and serving it's APIs.
23+
//
24+
// When set to NotDesired, the authorization.openshift.io/RestrictSubjectBindings
25+
// admission plugin will be configured with the expectation that the OpenShift
26+
// oauth-apiserver will not be running.
27+
OpenShiftOAuthDesiredState OpenShiftOAuthState `json:"openshiftOAuthDesiredState"`
28+
}
29+
30+
type OpenShiftOAuthState string
31+
32+
const (
33+
OpenShiftOAuthStateDesired = "Desired"
34+
OpenShiftOAuthStateNotDesired = "NotDesired"
35+
)

openshift-kube-apiserver/admission/authorization/apis/restrictusers/v1alpha1/zz_generated.deepcopy.go

+51
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

openshift-kube-apiserver/admission/authorization/restrictusers/authncache/authentication.go

-24
This file was deleted.

openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers.go

+56-22
Original file line numberDiff line numberDiff line change
@@ -22,16 +22,53 @@ import (
2222
userclient "github.com/openshift/client-go/user/clientset/versioned"
2323
userinformer "github.com/openshift/client-go/user/informers/externalversions"
2424
"github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig"
25+
"github.com/openshift/library-go/pkg/config/helpers"
26+
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/apis/restrictusers/v1alpha1"
2527
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers/usercache"
2628
)
2729

2830
func Register(plugins *admission.Plugins) {
2931
plugins.Register("authorization.openshift.io/RestrictSubjectBindings",
3032
func(config io.Reader) (admission.Interface, error) {
31-
return NewRestrictUsersAdmission()
33+
cfg, err := readConfig(config)
34+
if err != nil {
35+
return nil, err
36+
}
37+
38+
return NewRestrictUsersAdmission(cfg)
3239
})
3340
}
3441

42+
func defaultConfig() *v1alpha1.RestrictSubjectBindingsAdmissionConfig {
43+
return &v1alpha1.RestrictSubjectBindingsAdmissionConfig{
44+
OpenShiftOAuthDesiredState: v1alpha1.OpenShiftOAuthStateDesired,
45+
}
46+
}
47+
48+
func readConfig(reader io.Reader) (*v1alpha1.RestrictSubjectBindingsAdmissionConfig, error) {
49+
obj, err := helpers.ReadYAMLToInternal(reader, v1alpha1.Install)
50+
if err != nil {
51+
return nil, err
52+
}
53+
if obj == nil {
54+
return nil, nil
55+
}
56+
config, ok := obj.(*v1alpha1.RestrictSubjectBindingsAdmissionConfig)
57+
if !ok {
58+
return nil, fmt.Errorf("unexpected config object: %#v", obj)
59+
}
60+
61+
// validate config
62+
switch config.OpenShiftOAuthDesiredState {
63+
case v1alpha1.OpenShiftOAuthStateDesired, v1alpha1.OpenShiftOAuthStateNotDesired:
64+
// valid, do nothing
65+
default:
66+
return nil, fmt.Errorf("config is invalid, openshiftOAuthDesiredState must be one of Desired,NotDesired but was %s", config.OpenShiftOAuthDesiredState)
67+
}
68+
69+
return config, nil
70+
}
71+
3572
type GroupCache interface {
3673
GroupsFor(string) ([]*userv1.Group, error)
3774
HasSynced() bool
@@ -46,8 +83,8 @@ type restrictUsersAdmission struct {
4683
roleBindingRestrictionsGetter authorizationtypedclient.RoleBindingRestrictionsGetter
4784
userClient userclient.Interface
4885
kubeClient kubernetes.Interface
49-
groupCacheFunc func() (GroupCache, error)
5086
groupCache GroupCache
87+
oauthState v1alpha1.OpenShiftOAuthState
5188
}
5289

5390
var (
@@ -59,9 +96,15 @@ var (
5996

6097
// NewRestrictUsersAdmission configures an admission plugin that enforces
6198
// restrictions on adding role bindings in a project.
62-
func NewRestrictUsersAdmission() (admission.Interface, error) {
99+
func NewRestrictUsersAdmission(cfg *v1alpha1.RestrictSubjectBindingsAdmissionConfig) (admission.Interface, error) {
63100
return &restrictUsersAdmission{
64101
Handler: admission.NewHandler(admission.Create, admission.Update),
102+
oauthState: func() v1alpha1.OpenShiftOAuthState{
103+
if cfg != nil {
104+
return cfg.OpenShiftOAuthDesiredState
105+
}
106+
return v1alpha1.OpenShiftOAuthStateDesired
107+
}(),
65108
}, nil
66109
}
67110

@@ -91,18 +134,16 @@ func (q *restrictUsersAdmission) SetRESTClientConfig(restClientConfig rest.Confi
91134
}
92135

93136
func (q *restrictUsersAdmission) SetUserInformer(userInformers userinformer.SharedInformerFactory) {
94-
// defer the allocation of the group cache until later in the process so we can
95-
// ensure we aren't creating informers for the Group resources until this admission
96-
// plugin actually runs. If authentication type is OIDC, this plugin should be disabled
97-
// resulting in the Group informer never being configured and started.
98-
q.groupCacheFunc = func() (GroupCache, error) {
99-
if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
100-
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
101-
}); err != nil {
102-
return nil, err
103-
}
104-
return usercache.NewGroupCache(userInformers.User().V1().Groups()), nil
137+
if q.oauthState == v1alpha1.OpenShiftOAuthStateNotDesired {
138+
return
139+
}
140+
141+
if err := userInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
142+
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
143+
}); err != nil {
144+
return
105145
}
146+
q.groupCache = usercache.NewGroupCache(userInformers.User().V1().Groups())
106147
}
107148

108149
// subjectsDelta returns the relative complement of elementsToIgnore in
@@ -201,13 +242,6 @@ func (q *restrictUsersAdmission) Validate(ctx context.Context, a admission.Attri
201242
checkers = append(checkers, checker)
202243
}
203244

204-
if q.groupCache == nil && q.groupCacheFunc != nil {
205-
q.groupCache, err = q.groupCacheFunc()
206-
if err != nil {
207-
return admission.NewForbidden(a, fmt.Errorf("could not create group cache: %v", err))
208-
}
209-
}
210-
211245
roleBindingRestrictionContext, err := newRoleBindingRestrictionContext(ns,
212246
q.kubeClient, q.userClient.UserV1(), q.groupCache)
213247
if err != nil {
@@ -247,7 +281,7 @@ func (q *restrictUsersAdmission) ValidateInitialization() error {
247281
if q.userClient == nil {
248282
return errors.New("RestrictUsersAdmission plugin requires an OpenShift user client")
249283
}
250-
if q.groupCache == nil && q.groupCacheFunc == nil {
284+
if q.groupCache == nil && q.oauthState == v1alpha1.OpenShiftOAuthStateDesired {
251285
return errors.New("RestrictUsersAdmission plugin requires a group cache")
252286
}
253287

openshift-kube-apiserver/admission/authorization/restrictusers/restrictusers_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -359,7 +359,7 @@ func TestAdmission(t *testing.T) {
359359
fakeUserClient := fakeuserclient.NewSimpleClientset(tc.userObjects...)
360360
fakeAuthorizationClient := fakeauthorizationclient.NewSimpleClientset(tc.authorizationObjects...)
361361

362-
plugin, err := NewRestrictUsersAdmission()
362+
plugin, err := NewRestrictUsersAdmission(nil)
363363
if err != nil {
364364
t.Errorf("unexpected error initializing admission plugin: %v", err)
365365
}

openshift-kube-apiserver/openshiftkubeapiserver/patch.go

+1-22
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"os"
55
"time"
66

7-
configv1 "github.com/openshift/api/config/v1"
87
"github.com/openshift/apiserver-library-go/pkg/admission/imagepolicy"
98
"github.com/openshift/apiserver-library-go/pkg/admission/imagepolicy/imagereferencemutators"
109
"github.com/openshift/apiserver-library-go/pkg/admission/quota/clusterresourcequota"
@@ -22,15 +21,13 @@ import (
2221
"github.com/openshift/library-go/pkg/apiserver/admission/admissionrestconfig"
2322
"github.com/openshift/library-go/pkg/apiserver/apiserverconfig"
2423
"github.com/openshift/library-go/pkg/quota/clusterquotamapping"
25-
"k8s.io/apimachinery/pkg/util/wait"
2624
"k8s.io/apiserver/pkg/admission"
2725
"k8s.io/apiserver/pkg/quota/v1/generic"
2826
genericapiserver "k8s.io/apiserver/pkg/server"
2927
clientgoinformers "k8s.io/client-go/informers"
3028
corev1informers "k8s.io/client-go/informers/core/v1"
3129
"k8s.io/client-go/rest"
3230
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers"
33-
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers/authncache"
3431
"k8s.io/kubernetes/openshift-kube-apiserver/admission/autoscaling/managednode"
3532
"k8s.io/kubernetes/openshift-kube-apiserver/admission/autoscaling/managementcpusoverride"
3633
"k8s.io/kubernetes/openshift-kube-apiserver/admission/scheduler/nodeenv"
@@ -110,25 +107,7 @@ func OpenShiftKubeAPIServerConfigPatch(genericConfig *genericapiserver.Config, k
110107
// END HANDLER CHAIN
111108

112109
openshiftAPIServiceReachabilityCheck := newOpenshiftAPIServiceReachabilityCheck(genericConfig.PublicAddress)
113-
114-
oauthAPIServiceTerminationCondition := func() (bool, string) {
115-
authnCache := authncache.NewAuthnCache(openshiftInformers.OpenshiftConfigInformers.Config().V1().Authentications())
116-
err := wait.PollImmediate(1*time.Second, 30*time.Second, func() (bool, error) {
117-
return authnCache.HasSynced(), nil
118-
})
119-
if err == nil {
120-
auth, err := authnCache.Authn()
121-
if err == nil && auth != nil {
122-
if auth.Spec.Type == configv1.AuthenticationTypeOIDC {
123-
// skip the oauthAPIServiceReachabilityCheck if OIDC
124-
// has been configured since the oauth apiserver will be down.
125-
return true, "authentication type is OIDC, meaning no oauth-apiserver is deployed. Skipping oauth-apiserver availability check"
126-
}
127-
}
128-
}
129-
return false, ""
130-
}
131-
oauthAPIServiceReachabilityCheck := newOAuthAPIServiceReachabilityCheck(genericConfig.PublicAddress, oauthAPIServiceTerminationCondition)
110+
oauthAPIServiceReachabilityCheck := newOAuthAPIServiceReachabilityCheck(genericConfig.PublicAddress)
132111

133112
genericConfig.ReadyzChecks = append(genericConfig.ReadyzChecks, openshiftAPIServiceReachabilityCheck, oauthAPIServiceReachabilityCheck)
134113

openshift-kube-apiserver/openshiftkubeapiserver/sdn_readyz_wait.go

+4-19
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,25 @@ import (
1919
)
2020

2121
func newOpenshiftAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP) *aggregatedAPIServiceAvailabilityCheck {
22-
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-apiserver", "api", nil)
22+
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-apiserver", "api")
2323
}
2424

25-
func newOAuthAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP, terminationCondition terminationConditionFunc) *aggregatedAPIServiceAvailabilityCheck {
26-
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-oauth-apiserver", "api", terminationCondition)
25+
func newOAuthAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP) *aggregatedAPIServiceAvailabilityCheck {
26+
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-oauth-apiserver", "api")
2727
}
2828

2929
// if the API service is not found or the termination condition is met, then this check returns quickly.
3030
// if the endpoint is not accessible within 60 seconds, we report ready no matter what
3131
// otherwise, wait for up to 60 seconds to be able to reach the apiserver
32-
func newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP, namespace, service string, terminationCondition terminationConditionFunc) *aggregatedAPIServiceAvailabilityCheck {
32+
func newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.IP, namespace, service string) *aggregatedAPIServiceAvailabilityCheck {
3333
return &aggregatedAPIServiceAvailabilityCheck{
3434
done: make(chan struct{}),
3535
ipForKubernetesDefaultService: ipForKubernetesDefaultService,
3636
namespace: namespace,
3737
serviceName: service,
38-
terminationCondition: terminationCondition,
3938
}
4039
}
4140

42-
type terminationConditionFunc func() (bool, string)
43-
4441
type aggregatedAPIServiceAvailabilityCheck struct {
4542
// done indicates that this check is complete (success or failure) and the check should return true
4643
done chan struct{}
@@ -53,11 +50,6 @@ type aggregatedAPIServiceAvailabilityCheck struct {
5350
namespace string
5451
// serviceName is used to get a list of endpoints to directly dial
5552
serviceName string
56-
57-
// terminationCondition is used to determine if conditions are met
58-
// to terminate the availability check early. If the conditions are met,
59-
// it is expected that true and a message is returned to be logged.
60-
terminationCondition terminationConditionFunc
6153
}
6254

6355
func (c *aggregatedAPIServiceAvailabilityCheck) Name() string {
@@ -84,13 +76,6 @@ func (c *aggregatedAPIServiceAvailabilityCheck) checkForConnection(context gener
8476
close(c.done) // once this method is done, the ready check should return true
8577
}()
8678

87-
if c.terminationCondition != nil {
88-
if ok, msg := c.terminationCondition(); ok {
89-
klog.V(2).Infof("%s early termination condition met: %s", c.Name(), msg)
90-
return
91-
}
92-
}
93-
9479
start := time.Now()
9580

9681
kubeClient, err := kubernetes.NewForConfig(context.LoopbackClientConfig)

0 commit comments

Comments
 (0)