From f73d1ea90a95dac4704a61fe80c647f8f9d47f6b Mon Sep 17 00:00:00 2001 From: deads2k Date: Tue, 4 Oct 2016 11:07:42 -0400 Subject: [PATCH] make sure that the bootstrap rbac rules are getting created in test-cmd --- hack/make-rules/test-cmd.sh | 4 ++ .../rbac/clusterrole/policybased/storage.go | 22 +++------ .../clusterrolebinding/policybased/storage.go | 22 +++------ pkg/registry/rbac/escalation_check.go | 45 +++++++++++++++++++ pkg/registry/rbac/role/policybased/storage.go | 22 +++------ .../rbac/rolebinding/policybased/storage.go | 22 +++------ 6 files changed, 69 insertions(+), 68 deletions(-) create mode 100644 pkg/registry/rbac/escalation_check.go diff --git a/hack/make-rules/test-cmd.sh b/hack/make-rules/test-cmd.sh index edd3cd4a4b3..6ab1e26edf7 100755 --- a/hack/make-rules/test-cmd.sh +++ b/hack/make-rules/test-cmd.sh @@ -419,6 +419,10 @@ runTests() { kubectl get "${kube_flags[@]}" --raw /version + # make sure the server was properly bootstrapped with clusterroles and bindings + kube::test::get_object_assert clusterroles/cluster-admin "{{.metadata.name}}" 'cluster-admin' + kube::test::get_object_assert clusterrolebindings/cluster-admin "{{.metadata.name}}" 'cluster-admin' + ########################### # POD creation / deletion # ########################### diff --git a/pkg/registry/rbac/clusterrole/policybased/storage.go b/pkg/registry/rbac/clusterrole/policybased/storage.go index a605ce74517..a4909a7da0a 100644 --- a/pkg/registry/rbac/clusterrole/policybased/storage.go +++ b/pkg/registry/rbac/clusterrole/policybased/storage.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" - "k8s.io/kubernetes/pkg/auth/user" + rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" "k8s.io/kubernetes/pkg/runtime" ) @@ -43,18 +43,8 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if u, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && u.GetName() == s.superUser { - return s.StandardStorage.Create(ctx, obj) - } - - // system:masters is special because the API server uses it for privileged loopback connections - // therefore we know that a member of system:masters can always do anything - for _, group := range u.GetGroups() { - if group == user.SystemPrivilegedGroup { - return s.StandardStorage.Create(ctx, obj) - } - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Create(ctx, obj) } clusterRole := obj.(*rbac.ClusterRole) @@ -66,10 +56,8 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { - return s.StandardStorage.Update(ctx, name, obj) - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Update(ctx, name, obj) } nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { diff --git a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go index 539e97d1250..39fdc7d8267 100644 --- a/pkg/registry/rbac/clusterrolebinding/policybased/storage.go +++ b/pkg/registry/rbac/clusterrolebinding/policybased/storage.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" - "k8s.io/kubernetes/pkg/auth/user" + rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" "k8s.io/kubernetes/pkg/runtime" ) @@ -43,18 +43,8 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if u, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && u.GetName() == s.superUser { - return s.StandardStorage.Create(ctx, obj) - } - - // system:masters is special because the API server uses it for privileged loopback connections - // therefore we know that a member of system:masters can always do anything - for _, group := range u.GetGroups() { - if group == user.SystemPrivilegedGroup { - return s.StandardStorage.Create(ctx, obj) - } - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Create(ctx, obj) } clusterRoleBinding := obj.(*rbac.ClusterRoleBinding) @@ -69,10 +59,8 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { - return s.StandardStorage.Update(ctx, name, obj) - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Update(ctx, name, obj) } nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { diff --git a/pkg/registry/rbac/escalation_check.go b/pkg/registry/rbac/escalation_check.go new file mode 100644 index 00000000000..c5ba65a1f4e --- /dev/null +++ b/pkg/registry/rbac/escalation_check.go @@ -0,0 +1,45 @@ +/* +Copyright 2016 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package rbac + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/auth/user" +) + +func EscalationAllowed(ctx api.Context, superUser string) bool { + u, ok := api.UserFrom(ctx) + if !ok { + // the only way to be without a user is to either have no authenticators by explicitly saying that's your preference + // or to be connecting via the insecure port, in which case this logically doesn't apply + return true + } + + // check to see if this subject is allowed to escalate + if len(superUser) != 0 && u.GetName() == superUser { + return true + } + // system:masters is special because the API server uses it for privileged loopback connections + // therefore we know that a member of system:masters can always do anything + for _, group := range u.GetGroups() { + if group == user.SystemPrivilegedGroup { + return true + } + } + + return false +} diff --git a/pkg/registry/rbac/role/policybased/storage.go b/pkg/registry/rbac/role/policybased/storage.go index 38ad81decfd..c7976b9defa 100644 --- a/pkg/registry/rbac/role/policybased/storage.go +++ b/pkg/registry/rbac/role/policybased/storage.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" - "k8s.io/kubernetes/pkg/auth/user" + rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" "k8s.io/kubernetes/pkg/runtime" ) @@ -43,18 +43,8 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if u, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && u.GetName() == s.superUser { - return s.StandardStorage.Create(ctx, obj) - } - - // system:masters is special because the API server uses it for privileged loopback connections - // therefore we know that a member of system:masters can always do anything - for _, group := range u.GetGroups() { - if group == user.SystemPrivilegedGroup { - return s.StandardStorage.Create(ctx, obj) - } - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Create(ctx, obj) } role := obj.(*rbac.Role) @@ -66,10 +56,8 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { - return s.StandardStorage.Update(ctx, name, obj) - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Update(ctx, name, obj) } nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) { diff --git a/pkg/registry/rbac/rolebinding/policybased/storage.go b/pkg/registry/rbac/rolebinding/policybased/storage.go index 49750d457dc..8fb2c435020 100644 --- a/pkg/registry/rbac/rolebinding/policybased/storage.go +++ b/pkg/registry/rbac/rolebinding/policybased/storage.go @@ -23,7 +23,7 @@ import ( "k8s.io/kubernetes/pkg/api/rest" "k8s.io/kubernetes/pkg/apis/rbac" "k8s.io/kubernetes/pkg/apis/rbac/validation" - "k8s.io/kubernetes/pkg/auth/user" + rbacregistry "k8s.io/kubernetes/pkg/registry/rbac" "k8s.io/kubernetes/pkg/runtime" ) @@ -43,18 +43,8 @@ func NewStorage(s rest.StandardStorage, ruleResolver validation.AuthorizationRul } func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, error) { - if u, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && u.GetName() == s.superUser { - return s.StandardStorage.Create(ctx, obj) - } - - // system:masters is special because the API server uses it for privileged loopback connections - // therefore we know that a member of system:masters can always do anything - for _, group := range u.GetGroups() { - if group == user.SystemPrivilegedGroup { - return s.StandardStorage.Create(ctx, obj) - } - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Create(ctx, obj) } roleBinding := obj.(*rbac.RoleBinding) @@ -69,10 +59,8 @@ func (s *Storage) Create(ctx api.Context, obj runtime.Object) (runtime.Object, e } func (s *Storage) Update(ctx api.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) { - if user, ok := api.UserFrom(ctx); ok { - if s.superUser != "" && user.GetName() == s.superUser { - return s.StandardStorage.Update(ctx, name, obj) - } + if rbacregistry.EscalationAllowed(ctx, s.superUser) { + return s.StandardStorage.Update(ctx, name, obj) } nonEscalatingInfo := wrapUpdatedObjectInfo(obj, func(ctx api.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {