Skip to content

Commit edf1675

Browse files
committed
UPSTREAM: <carry>: Add configuration to RestrictSubjectBindings admission plugin
to allow external components to specify that the oauth stack will/will not be present on the cluster. When the oauth stack is not present, this admission plugin is not effective and should not configure and start informers for APIs served by the oauth-apiserver. Signed-off-by: Bryce Palmer <[email protected]>
1 parent 8ac36bf commit edf1675

File tree

8 files changed

+193
-17
lines changed

8 files changed

+193
-17
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,29 @@
1+
package v1alpha1
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/runtime"
5+
"k8s.io/apimachinery/pkg/runtime/schema"
6+
)
7+
8+
var (
9+
GroupVersion = schema.GroupVersion{Group: "authorization.openshift.io", Version: "v1alpha1"}
10+
internalGroupVersion = schema.GroupVersion{Group: "authorization.openshift.io", Version: runtime.APIVersionInternal}
11+
)
12+
13+
var (
14+
localSchemeBuilder = runtime.NewSchemeBuilder(
15+
addKnownTypes,
16+
)
17+
Install = localSchemeBuilder.AddToScheme
18+
)
19+
20+
func addKnownTypes(scheme *runtime.Scheme) error {
21+
scheme.AddKnownTypes(GroupVersion,
22+
&RestrictSubjectBindingsAdmissionConfig{},
23+
)
24+
25+
scheme.AddKnownTypes(internalGroupVersion,
26+
&RestrictSubjectBindingsAdmissionConfig{},
27+
)
28+
return nil
29+
}
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/restrictusers.go

+67-7
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"k8s.io/apiserver/pkg/admission/initializer"
1414
"k8s.io/client-go/kubernetes"
1515
"k8s.io/client-go/rest"
16+
"k8s.io/client-go/tools/cache"
1617
"k8s.io/klog/v2"
1718
"k8s.io/kubernetes/pkg/apis/rbac"
1819

@@ -21,16 +22,53 @@ import (
2122
userclient "github.com/openshift/client-go/user/clientset/versioned"
2223
userinformer "github.com/openshift/client-go/user/informers/externalversions"
2324
"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"
2427
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers/usercache"
2528
)
2629

2730
func Register(plugins *admission.Plugins) {
2831
plugins.Register("authorization.openshift.io/RestrictSubjectBindings",
2932
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)
3139
})
3240
}
3341

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+
3472
type GroupCache interface {
3573
GroupsFor(string) ([]*userv1.Group, error)
3674
HasSynced() bool
@@ -46,18 +84,27 @@ type restrictUsersAdmission struct {
4684
userClient userclient.Interface
4785
kubeClient kubernetes.Interface
4886
groupCache GroupCache
87+
oauthState v1alpha1.OpenShiftOAuthState
4988
}
5089

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+
)
5596

5697
// NewRestrictUsersAdmission configures an admission plugin that enforces
5798
// restrictions on adding role bindings in a project.
58-
func NewRestrictUsersAdmission() (admission.Interface, error) {
99+
func NewRestrictUsersAdmission(cfg *v1alpha1.RestrictSubjectBindingsAdmissionConfig) (admission.Interface, error) {
59100
return &restrictUsersAdmission{
60101
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+
}(),
61108
}, nil
62109
}
63110

@@ -87,6 +134,15 @@ func (q *restrictUsersAdmission) SetRESTClientConfig(restClientConfig rest.Confi
87134
}
88135

89136
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+
}
90146
q.groupCache = usercache.NewGroupCache(userInformers.User().V1().Groups())
91147
}
92148

@@ -116,6 +172,10 @@ func subjectsDelta(elementsToIgnore, elements []rbac.Subject) []rbac.Subject {
116172
// each subject in the binding must be matched by some rolebinding restriction
117173
// in the namespace.
118174
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+
}
119179

120180
// We only care about rolebindings
121181
if a.GetResource().GroupResource() != rbac.Resource("rolebindings") {
@@ -226,7 +286,7 @@ func (q *restrictUsersAdmission) ValidateInitialization() error {
226286
if q.userClient == nil {
227287
return errors.New("RestrictUsersAdmission plugin requires an OpenShift user client")
228288
}
229-
if q.groupCache == nil {
289+
if q.groupCache == nil && q.oauthState == v1alpha1.OpenShiftOAuthStateDesired {
230290
return errors.New("RestrictUsersAdmission plugin requires a group cache")
231291
}
232292

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

+5-8
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,7 @@ import (
2727
clientgoinformers "k8s.io/client-go/informers"
2828
corev1informers "k8s.io/client-go/informers/core/v1"
2929
"k8s.io/client-go/rest"
30-
"k8s.io/client-go/tools/cache"
3130
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers"
32-
"k8s.io/kubernetes/openshift-kube-apiserver/admission/authorization/restrictusers/usercache"
3331
"k8s.io/kubernetes/openshift-kube-apiserver/admission/autoscaling/managednode"
3432
"k8s.io/kubernetes/openshift-kube-apiserver/admission/autoscaling/managementcpusoverride"
3533
"k8s.io/kubernetes/openshift-kube-apiserver/admission/scheduler/nodeenv"
@@ -109,7 +107,8 @@ func OpenShiftKubeAPIServerConfigPatch(genericConfig *genericapiserver.Config, k
109107
// END HANDLER CHAIN
110108

111109
openshiftAPIServiceReachabilityCheck := newOpenshiftAPIServiceReachabilityCheck(genericConfig.PublicAddress)
112-
oauthAPIServiceReachabilityCheck := newOAuthPIServiceReachabilityCheck(genericConfig.PublicAddress)
110+
oauthAPIServiceReachabilityCheck := newOAuthAPIServiceReachabilityCheck(genericConfig.PublicAddress)
111+
113112
genericConfig.ReadyzChecks = append(genericConfig.ReadyzChecks, openshiftAPIServiceReachabilityCheck, oauthAPIServiceReachabilityCheck)
114113

115114
genericConfig.AddPostStartHookOrDie("openshift.io-startkubeinformers", func(context genericapiserver.PostStartHookContext) error {
@@ -176,11 +175,6 @@ func newInformers(loopbackClientConfig *rest.Config) (*kubeAPIServerInformers, e
176175
OpenshiftUserInformers: userinformer.NewSharedInformerFactory(userClient, defaultInformerResyncPeriod),
177176
OpenshiftConfigInformers: configv1informer.NewSharedInformerFactory(configClient, defaultInformerResyncPeriod),
178177
}
179-
if err := ret.OpenshiftUserInformers.User().V1().Groups().Informer().AddIndexers(cache.Indexers{
180-
usercache.ByUserIndexName: usercache.ByUserIndexKeys,
181-
}); err != nil {
182-
return nil, err
183-
}
184178

185179
return ret, nil
186180
}
@@ -195,12 +189,15 @@ type kubeAPIServerInformers struct {
195189
func (i *kubeAPIServerInformers) getOpenshiftQuotaInformers() quotainformer.SharedInformerFactory {
196190
return i.OpenshiftQuotaInformers
197191
}
192+
198193
func (i *kubeAPIServerInformers) getOpenshiftSecurityInformers() securityv1informer.SharedInformerFactory {
199194
return i.OpenshiftSecurityInformers
200195
}
196+
201197
func (i *kubeAPIServerInformers) getOpenshiftUserInformers() userinformer.SharedInformerFactory {
202198
return i.OpenshiftUserInformers
203199
}
200+
204201
func (i *kubeAPIServerInformers) getOpenshiftInfraInformers() configv1informer.SharedInformerFactory {
205202
return i.OpenshiftConfigInformers
206203
}

openshift-kube-apiserver/openshiftkubeapiserver/sdn_readyz_wait.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func newOpenshiftAPIServiceReachabilityCheck(ipForKubernetesDefaultService net.I
2222
return newAggregatedAPIServiceReachabilityCheck(ipForKubernetesDefaultService, "openshift-apiserver", "api")
2323
}
2424

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

0 commit comments

Comments
 (0)