@@ -13,6 +13,7 @@ import (
13
13
"k8s.io/apiserver/pkg/admission/initializer"
14
14
"k8s.io/client-go/kubernetes"
15
15
"k8s.io/client-go/rest"
16
+ "k8s.io/client-go/tools/cache"
16
17
"k8s.io/klog/v2"
17
18
"k8s.io/kubernetes/pkg/apis/rbac"
18
19
@@ -21,16 +22,53 @@ import (
21
22
userclient "github.com/openshift/client-go/user/clientset/versioned"
22
23
userinformer "github.com/openshift/client-go/user/informers/externalversions"
23
24
"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"
24
27
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers/usercache"
25
28
)
26
29
27
30
func Register (plugins * admission.Plugins ) {
28
31
plugins .Register ("authorization.openshift.io/RestrictSubjectBindings" ,
29
32
func (config io.Reader ) (admission.Interface , error ) {
30
- return NewRestrictUsersAdmission ()
33
+ cfg , err := readConfig (config )
34
+ if err != nil {
35
+ return nil , err
36
+ }
37
+
38
+ return NewRestrictUsersAdmission (cfg )
31
39
})
32
40
}
33
41
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
+
34
72
type GroupCache interface {
35
73
GroupsFor (string ) ([]* userv1.Group , error )
36
74
HasSynced () bool
@@ -46,18 +84,27 @@ type restrictUsersAdmission struct {
46
84
userClient userclient.Interface
47
85
kubeClient kubernetes.Interface
48
86
groupCache GroupCache
87
+ oauthState v1alpha1.OpenShiftOAuthState
49
88
}
50
89
51
- var _ = admissionrestconfig .WantsRESTClientConfig (& restrictUsersAdmission {})
52
- var _ = WantsUserInformer (& restrictUsersAdmission {})
53
- var _ = initializer .WantsExternalKubeClientSet (& restrictUsersAdmission {})
54
- var _ = admission .ValidationInterface (& restrictUsersAdmission {})
90
+ var (
91
+ _ = admissionrestconfig .WantsRESTClientConfig (& restrictUsersAdmission {})
92
+ _ = WantsUserInformer (& restrictUsersAdmission {})
93
+ _ = initializer .WantsExternalKubeClientSet (& restrictUsersAdmission {})
94
+ _ = admission .ValidationInterface (& restrictUsersAdmission {})
95
+ )
55
96
56
97
// NewRestrictUsersAdmission configures an admission plugin that enforces
57
98
// restrictions on adding role bindings in a project.
58
- func NewRestrictUsersAdmission () (admission.Interface , error ) {
99
+ func NewRestrictUsersAdmission (cfg * v1alpha1. RestrictSubjectBindingsAdmissionConfig ) (admission.Interface , error ) {
59
100
return & restrictUsersAdmission {
60
101
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
+ }(),
61
108
}, nil
62
109
}
63
110
@@ -87,6 +134,15 @@ func (q *restrictUsersAdmission) SetRESTClientConfig(restClientConfig rest.Confi
87
134
}
88
135
89
136
func (q * restrictUsersAdmission ) SetUserInformer (userInformers userinformer.SharedInformerFactory ) {
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
145
+ }
90
146
q .groupCache = usercache .NewGroupCache (userInformers .User ().V1 ().Groups ())
91
147
}
92
148
@@ -116,6 +172,10 @@ func subjectsDelta(elementsToIgnore, elements []rbac.Subject) []rbac.Subject {
116
172
// each subject in the binding must be matched by some rolebinding restriction
117
173
// in the namespace.
118
174
func (q * restrictUsersAdmission ) Validate (ctx context.Context , a admission.Attributes , _ admission.ObjectInterfaces ) (err error ) {
175
+ if q .oauthState == v1alpha1 .OpenShiftOAuthStateNotDesired {
176
+ klog .V (2 ).Info ("admission plugin authorization.openshift.io/RestrictSubjectBindings is configured to act as if the OpenShift oauth-apiserver is not present. This admission plugin relies on the OpenShift oauth-apiserver to function as expected and should be disabled when it is not present. Acting as if disabled and not enforcing subject bindings." )
177
+ return nil
178
+ }
119
179
120
180
// We only care about rolebindings
121
181
if a .GetResource ().GroupResource () != rbac .Resource ("rolebindings" ) {
@@ -226,7 +286,7 @@ func (q *restrictUsersAdmission) ValidateInitialization() error {
226
286
if q .userClient == nil {
227
287
return errors .New ("RestrictUsersAdmission plugin requires an OpenShift user client" )
228
288
}
229
- if q .groupCache == nil {
289
+ if q .groupCache == nil && q . oauthState == v1alpha1 . OpenShiftOAuthStateDesired {
230
290
return errors .New ("RestrictUsersAdmission plugin requires a group cache" )
231
291
}
232
292
0 commit comments