Bumping k8s dependencies to 1.13

This commit is contained in:
Cheng Xing
2018-11-16 14:08:25 -08:00
parent 305407125c
commit b4c0b68ec7
8002 changed files with 884099 additions and 276228 deletions

View File

@@ -15,13 +15,14 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/registry/rbac",
deps = [
"//pkg/apis/rbac:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/conversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
],
)
@@ -54,7 +55,7 @@ go_test(
deps = [
"//pkg/apis/core:go_default_library",
"//pkg/apis/core/helper:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)

View File

@@ -18,13 +18,13 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/apis/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)

View File

@@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
@@ -14,9 +15,11 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/registry/rbac:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)
@@ -32,3 +35,22 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["storage_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/install:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)

View File

@@ -22,7 +22,9 @@ import (
"errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/registry/rest"
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
"k8s.io/kubernetes/pkg/apis/rbac"
@@ -35,11 +37,13 @@ var groupResource = rbac.Resource("clusterroles")
type Storage struct {
rest.StandardStorage
authorizer authorizer.Authorizer
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
}
func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
return &Storage{s, ruleResolver}
func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
return &Storage{s, authorizer, ruleResolver}
}
func (r *Storage) NamespaceScoped() bool {
@@ -51,9 +55,9 @@ var fullAuthority = []rbac.PolicyRule{
rbac.NewRule("*").URLs("*").RuleOrDie(),
}
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, includeUninitialized)
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidatingAdmission rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) {
return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, options)
}
clusterRole := obj.(*rbac.ClusterRole)
@@ -68,12 +72,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
}
}
return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidatingAdmission, options)
}
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation)
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options)
}
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
@@ -99,7 +103,7 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
return obj, nil
})
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
}
func hasAggregationRule(clusterRole *rbac.ClusterRole) bool {

View File

@@ -0,0 +1,195 @@
/*
Copyright 2018 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 policybased
import (
"context"
"testing"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/kubernetes/pkg/apis/rbac"
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
"k8s.io/kubernetes/pkg/registry/rbac/validation"
)
func TestEscalation(t *testing.T) {
createContext := request.WithRequestInfo(request.WithNamespace(context.TODO(), ""), &request.RequestInfo{
IsResourceRequest: true,
Verb: "create",
APIGroup: "rbac.authorization.k8s.io",
APIVersion: "v1",
Resource: "clusterroles",
Name: "",
})
updateContext := request.WithRequestInfo(request.WithNamespace(context.TODO(), ""), &request.RequestInfo{
IsResourceRequest: true,
Verb: "update",
APIGroup: "rbac.authorization.k8s.io",
APIVersion: "v1",
Resource: "clusterroles",
Name: "myrole",
})
superuser := &user.DefaultInfo{Name: "superuser", Groups: []string{"system:masters"}}
bob := &user.DefaultInfo{Name: "bob"}
steve := &user.DefaultInfo{Name: "steve"}
alice := &user.DefaultInfo{Name: "alice"}
authzCalled := 0
fakeStorage := &fakeStorage{}
fakeAuthorizer := authorizer.AuthorizerFunc(func(attr authorizer.Attributes) (authorizer.Decision, string, error) {
authzCalled++
if attr.GetUser().GetName() == "steve" {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionNoOpinion, "", nil
})
fakeRuleResolver, _ := validation.NewTestRuleResolver(
nil,
nil,
[]*rbacv1.ClusterRole{{ObjectMeta: metav1.ObjectMeta{Name: "alice-role"}, Rules: []rbacv1.PolicyRule{{APIGroups: []string{"*"}, Resources: []string{"*"}, Verbs: []string{"*"}}}}},
[]*rbacv1.ClusterRoleBinding{{RoleRef: rbacv1.RoleRef{Name: "alice-role", APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole"}, Subjects: []rbacv1.Subject{{Name: "alice", Kind: "User", APIGroup: "rbac.authorization.k8s.io"}}}},
)
role := &rbac.ClusterRole{
ObjectMeta: metav1.ObjectMeta{Name: "myrole", Namespace: ""},
Rules: []rbac.PolicyRule{{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{"pods"}}},
}
s := NewStorage(fakeStorage, fakeAuthorizer, fakeRuleResolver)
testcases := []struct {
name string
user user.Info
expectAllowed bool
expectAuthz bool
}{
// superuser doesn't even trigger an authz check, and is allowed
{
name: "superuser",
user: superuser,
expectAuthz: false,
expectAllowed: true,
},
// bob triggers an authz check, is disallowed by the authorizer, and has no RBAC permissions, so is not allowed
{
name: "bob",
user: bob,
expectAuthz: true,
expectAllowed: false,
},
// steve triggers an authz check, is allowed by the authorizer, and has no RBAC permissions, but is still allowed
{
name: "steve",
user: steve,
expectAuthz: true,
expectAllowed: true,
},
// alice triggers an authz check, is denied by the authorizer, but has RBAC permissions in the fakeRuleResolver, so is allowed
{
name: "alice",
user: alice,
expectAuthz: true,
expectAllowed: true,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
authzCalled, fakeStorage.created, fakeStorage.updated = 0, 0, 0
_, err := s.Create(request.WithUser(createContext, tc.user), role, nil, nil)
if tc.expectAllowed {
if err != nil {
t.Error(err)
return
}
if fakeStorage.created != 1 {
t.Errorf("unexpected calls to underlying storage.Create: %d", fakeStorage.created)
return
}
} else {
if !errors.IsForbidden(err) {
t.Errorf("expected forbidden, got %v", err)
return
}
if fakeStorage.created != 0 {
t.Errorf("unexpected calls to underlying storage.Create: %d", fakeStorage.created)
return
}
}
if tc.expectAuthz != (authzCalled > 0) {
t.Fatalf("expected authz=%v, saw %d calls", tc.expectAuthz, authzCalled)
}
authzCalled, fakeStorage.created, fakeStorage.updated = 0, 0, 0
_, _, err = s.Update(request.WithUser(updateContext, tc.user), role.Name, rest.DefaultUpdatedObjectInfo(role), nil, nil, false, nil)
if tc.expectAllowed {
if err != nil {
t.Error(err)
return
}
if fakeStorage.updated != 1 {
t.Errorf("unexpected calls to underlying storage.Update: %d", fakeStorage.updated)
return
}
} else {
if !errors.IsForbidden(err) {
t.Errorf("expected forbidden, got %v", err)
return
}
if fakeStorage.updated != 0 {
t.Errorf("unexpected calls to underlying storage.Update: %d", fakeStorage.updated)
return
}
}
if tc.expectAuthz != (authzCalled > 0) {
t.Fatalf("expected authz=%v, saw %d calls", tc.expectAuthz, authzCalled)
}
})
}
}
type fakeStorage struct {
updated int
created int
rest.StandardStorage
}
func (f *fakeStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
f.created++
return nil, nil
}
func (f *fakeStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
obj, err := objInfo.UpdatedObject(ctx, &rbac.ClusterRole{})
if err != nil {
return obj, false, err
}
f.updated++
return nil, false, nil
}

View File

@@ -12,9 +12,9 @@ go_library(
deps = [
"//pkg/apis/rbac:go_default_library",
"//pkg/registry/rbac/clusterrole:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)

View File

@@ -18,13 +18,13 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/apis/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)

View File

@@ -15,12 +15,12 @@ go_library(
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/registry/rbac:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)

View File

@@ -51,14 +51,14 @@ func (r *Storage) NamespaceScoped() bool {
return false
}
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) {
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, metav1.NamespaceNone, s.authorizer) {
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
v1RoleRef := rbacv1.RoleRef{}
@@ -73,12 +73,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
}
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) {
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options)
}
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
@@ -110,5 +110,5 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
return obj, nil
})
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
}

View File

@@ -15,9 +15,9 @@ go_library(
"//pkg/printers/internalversion:go_default_library",
"//pkg/printers/storage:go_default_library",
"//pkg/registry/rbac/clusterrolebinding:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)

View File

@@ -20,6 +20,7 @@ import (
"context"
"fmt"
"k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
@@ -27,6 +28,7 @@ import (
"k8s.io/kubernetes/pkg/apis/rbac"
)
// EscalationAllowed checks if the user associated with the context is a superuser
func EscalationAllowed(ctx context.Context) bool {
u, ok := genericapirequest.UserFrom(ctx)
if !ok {
@@ -44,6 +46,56 @@ func EscalationAllowed(ctx context.Context) bool {
return false
}
var roleResources = map[schema.GroupResource]bool{
rbac.SchemeGroupVersion.WithResource("clusterroles").GroupResource(): true,
rbac.SchemeGroupVersion.WithResource("roles").GroupResource(): true,
}
// RoleEscalationAuthorized checks if the user associated with the context is explicitly authorized to escalate the role resource associated with the context
func RoleEscalationAuthorized(ctx context.Context, a authorizer.Authorizer) bool {
if a == nil {
return false
}
user, ok := genericapirequest.UserFrom(ctx)
if !ok {
return false
}
requestInfo, ok := genericapirequest.RequestInfoFrom(ctx)
if !ok {
return false
}
if !requestInfo.IsResourceRequest {
return false
}
requestResource := schema.GroupResource{Group: requestInfo.APIGroup, Resource: requestInfo.Resource}
if !roleResources[requestResource] {
return false
}
attrs := authorizer.AttributesRecord{
User: user,
Verb: "escalate",
APIGroup: requestInfo.APIGroup,
Resource: requestInfo.Resource,
Name: requestInfo.Name,
Namespace: requestInfo.Namespace,
ResourceRequest: true,
}
decision, _, err := a.Authorize(attrs)
if err != nil {
utilruntime.HandleError(fmt.Errorf(
"error authorizing user %#v to escalate %#v named %q in namespace %q: %v",
user, requestResource, requestInfo.Name, requestInfo.Namespace, err,
))
}
return decision == authorizer.DecisionAllow
}
// BindingAuthorized returns true if the user associated with the context is explicitly authorized to bind the specified roleRef
func BindingAuthorized(ctx context.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool {
if a == nil {

View File

@@ -15,9 +15,9 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/core/helper:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
],
)
@@ -35,15 +35,15 @@ go_library(
importpath = "k8s.io/kubernetes/pkg/registry/rbac/reconciliation",
deps = [
"//pkg/registry/rbac/validation:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//staging/src/k8s.io/api/core/v1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/types:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
],
)

View File

@@ -29,12 +29,8 @@ func (in *ClusterRoleBindingAdapter) DeepCopyInto(out *ClusterRoleBindingAdapter
*out = *in
if in.ClusterRoleBinding != nil {
in, out := &in.ClusterRoleBinding, &out.ClusterRoleBinding
if *in == nil {
*out = nil
} else {
*out = new(v1.ClusterRoleBinding)
(*in).DeepCopyInto(*out)
}
*out = new(v1.ClusterRoleBinding)
(*in).DeepCopyInto(*out)
}
return
}
@@ -59,12 +55,8 @@ func (in *ClusterRoleRuleOwner) DeepCopyInto(out *ClusterRoleRuleOwner) {
*out = *in
if in.ClusterRole != nil {
in, out := &in.ClusterRole, &out.ClusterRole
if *in == nil {
*out = nil
} else {
*out = new(v1.ClusterRole)
(*in).DeepCopyInto(*out)
}
*out = new(v1.ClusterRole)
(*in).DeepCopyInto(*out)
}
return
}
@@ -89,12 +81,8 @@ func (in *RoleBindingAdapter) DeepCopyInto(out *RoleBindingAdapter) {
*out = *in
if in.RoleBinding != nil {
in, out := &in.RoleBinding, &out.RoleBinding
if *in == nil {
*out = nil
} else {
*out = new(v1.RoleBinding)
(*in).DeepCopyInto(*out)
}
*out = new(v1.RoleBinding)
(*in).DeepCopyInto(*out)
}
return
}
@@ -119,12 +107,8 @@ func (in *RoleRuleOwner) DeepCopyInto(out *RoleRuleOwner) {
*out = *in
if in.Role != nil {
in, out := &in.Role, &out.Role
if *in == nil {
*out = nil
} else {
*out = new(v1.Role)
(*in).DeepCopyInto(*out)
}
*out = new(v1.Role)
(*in).DeepCopyInto(*out)
}
return
}

View File

@@ -27,23 +27,23 @@ go_library(
"//pkg/registry/rbac/rolebinding/storage:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1alpha1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1beta1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//staging/src/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//staging/src/k8s.io/client-go/util/retry:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/api/rbac/v1alpha1:go_default_library",
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
"//vendor/k8s.io/client-go/util/retry:go_default_library",
],
)

View File

@@ -98,13 +98,13 @@ func (p RESTStorageProvider) storage(version schema.GroupVersion, apiResourceCon
)
// roles
storage["roles"] = rolepolicybased.NewStorage(rolesStorage, authorizationRuleResolver)
storage["roles"] = rolepolicybased.NewStorage(rolesStorage, p.Authorizer, authorizationRuleResolver)
// rolebindings
storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, p.Authorizer, authorizationRuleResolver)
// clusterroles
storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, authorizationRuleResolver)
storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, p.Authorizer, authorizationRuleResolver)
// clusterrolebindings
storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, p.Authorizer, authorizationRuleResolver)

View File

@@ -18,13 +18,13 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/apis/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)

View File

@@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_library(
@@ -14,9 +15,11 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/registry/rbac:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)
@@ -32,3 +35,22 @@ filegroup(
srcs = [":package-srcs"],
tags = ["automanaged"],
)
go_test(
name = "go_default_test",
srcs = ["storage_test.go"],
embed = [":go_default_library"],
deps = [
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/install:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)

View File

@@ -21,7 +21,9 @@ import (
"context"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/registry/rest"
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
"k8s.io/kubernetes/pkg/apis/rbac"
@@ -34,20 +36,22 @@ var groupResource = rbac.Resource("roles")
type Storage struct {
rest.StandardStorage
authorizer authorizer.Authorizer
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
}
func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
return &Storage{s, ruleResolver}
func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
return &Storage{s, authorizer, ruleResolver}
}
func (r *Storage) NamespaceScoped() bool {
return true
}
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) {
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
role := obj.(*rbac.Role)
@@ -55,12 +59,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, role.Name, err)
}
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation)
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) || rbacregistry.RoleEscalationAuthorized(ctx, s.authorizer) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options)
}
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
@@ -78,5 +82,5 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
return obj, nil
})
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
}

View File

@@ -0,0 +1,197 @@
/*
Copyright 2018 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 policybased
import (
"context"
"testing"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/apiserver/pkg/authorization/authorizer"
"k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
"k8s.io/kubernetes/pkg/apis/rbac"
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
"k8s.io/kubernetes/pkg/registry/rbac/validation"
)
func TestEscalation(t *testing.T) {
createContext := request.WithRequestInfo(request.WithNamespace(context.TODO(), "myns"), &request.RequestInfo{
IsResourceRequest: true,
Verb: "create",
APIGroup: "rbac.authorization.k8s.io",
APIVersion: "v1",
Namespace: "myns",
Resource: "roles",
Name: "",
})
updateContext := request.WithRequestInfo(request.WithNamespace(context.TODO(), "myns"), &request.RequestInfo{
IsResourceRequest: true,
Verb: "update",
APIGroup: "rbac.authorization.k8s.io",
APIVersion: "v1",
Namespace: "myns",
Resource: "roles",
Name: "myrole",
})
superuser := &user.DefaultInfo{Name: "superuser", Groups: []string{"system:masters"}}
bob := &user.DefaultInfo{Name: "bob"}
steve := &user.DefaultInfo{Name: "steve"}
alice := &user.DefaultInfo{Name: "alice"}
authzCalled := 0
fakeStorage := &fakeStorage{}
fakeAuthorizer := authorizer.AuthorizerFunc(func(attr authorizer.Attributes) (authorizer.Decision, string, error) {
authzCalled++
if attr.GetUser().GetName() == "steve" {
return authorizer.DecisionAllow, "", nil
}
return authorizer.DecisionNoOpinion, "", nil
})
fakeRuleResolver, _ := validation.NewTestRuleResolver(
nil,
nil,
[]*rbacv1.ClusterRole{{ObjectMeta: metav1.ObjectMeta{Name: "alice-role"}, Rules: []rbacv1.PolicyRule{{APIGroups: []string{"*"}, Resources: []string{"*"}, Verbs: []string{"*"}}}}},
[]*rbacv1.ClusterRoleBinding{{RoleRef: rbacv1.RoleRef{Name: "alice-role", APIGroup: "rbac.authorization.k8s.io", Kind: "ClusterRole"}, Subjects: []rbacv1.Subject{{Name: "alice", Kind: "User", APIGroup: "rbac.authorization.k8s.io"}}}},
)
role := &rbac.Role{
ObjectMeta: metav1.ObjectMeta{Name: "myrole", Namespace: "myns"},
Rules: []rbac.PolicyRule{{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{"pods"}}},
}
s := NewStorage(fakeStorage, fakeAuthorizer, fakeRuleResolver)
testcases := []struct {
name string
user user.Info
expectAllowed bool
expectAuthz bool
}{
// superuser doesn't even trigger an authz check, and is allowed
{
name: "superuser",
user: superuser,
expectAuthz: false,
expectAllowed: true,
},
// bob triggers an authz check, is disallowed by the authorizer, and has no RBAC permissions, so is not allowed
{
name: "bob",
user: bob,
expectAuthz: true,
expectAllowed: false,
},
// steve triggers an authz check, is allowed by the authorizer, and has no RBAC permissions, but is still allowed
{
name: "steve",
user: steve,
expectAuthz: true,
expectAllowed: true,
},
// alice triggers an authz check, is denied by the authorizer, but has RBAC permissions in the fakeRuleResolver, so is allowed
{
name: "alice",
user: alice,
expectAuthz: true,
expectAllowed: true,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
authzCalled, fakeStorage.created, fakeStorage.updated = 0, 0, 0
_, err := s.Create(request.WithUser(createContext, tc.user), role, nil, nil)
if tc.expectAllowed {
if err != nil {
t.Error(err)
return
}
if fakeStorage.created != 1 {
t.Errorf("unexpected calls to underlying storage.Create: %d", fakeStorage.created)
return
}
} else {
if !errors.IsForbidden(err) {
t.Errorf("expected forbidden, got %v", err)
return
}
if fakeStorage.created != 0 {
t.Errorf("unexpected calls to underlying storage.Create: %d", fakeStorage.created)
return
}
}
if tc.expectAuthz != (authzCalled > 0) {
t.Fatalf("expected authz=%v, saw %d calls", tc.expectAuthz, authzCalled)
}
authzCalled, fakeStorage.created, fakeStorage.updated = 0, 0, 0
_, _, err = s.Update(request.WithUser(updateContext, tc.user), role.Name, rest.DefaultUpdatedObjectInfo(role), nil, nil, false, nil)
if tc.expectAllowed {
if err != nil {
t.Error(err)
return
}
if fakeStorage.updated != 1 {
t.Errorf("unexpected calls to underlying storage.Update: %d", fakeStorage.updated)
return
}
} else {
if !errors.IsForbidden(err) {
t.Errorf("expected forbidden, got %v", err)
return
}
if fakeStorage.updated != 0 {
t.Errorf("unexpected calls to underlying storage.Update: %d", fakeStorage.updated)
return
}
}
if tc.expectAuthz != (authzCalled > 0) {
t.Fatalf("expected authz=%v, saw %d calls", tc.expectAuthz, authzCalled)
}
})
}
}
type fakeStorage struct {
updated int
created int
rest.StandardStorage
}
func (f *fakeStorage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
f.created++
return nil, nil
}
func (f *fakeStorage) Update(ctx context.Context, name string, objInfo rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
obj, err := objInfo.UpdatedObject(ctx, &rbac.Role{})
if err != nil {
return obj, false, err
}
f.updated++
return nil, false, nil
}

View File

@@ -12,9 +12,9 @@ go_library(
deps = [
"//pkg/apis/rbac:go_default_library",
"//pkg/registry/rbac/role:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)

View File

@@ -18,13 +18,13 @@ go_library(
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/apis/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/storage/names:go_default_library",
],
)

View File

@@ -15,12 +15,13 @@ go_library(
"//pkg/apis/rbac/v1:go_default_library",
"//pkg/registry/rbac:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/rest:go_default_library",
],
)

View File

@@ -22,6 +22,7 @@ import (
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apiserver/pkg/authorization/authorizer"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
@@ -51,9 +52,9 @@ func (r *Storage) NamespaceScoped() bool {
return true
}
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, includeUninitialized bool) (runtime.Object, error) {
func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidation rest.ValidateObjectFunc, options *metav1.CreateOptions) (runtime.Object, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
// Get the namespace from the context (populated from the URL).
@@ -65,7 +66,7 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
roleBinding := obj.(*rbac.RoleBinding)
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, namespace, s.authorizer) {
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
v1RoleRef := rbacv1.RoleRef{}
@@ -80,12 +81,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
return nil, errors.NewForbidden(groupResource, roleBinding.Name, err)
}
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
return s.StandardStorage.Create(ctx, obj, createValidation, options)
}
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) (runtime.Object, bool, error) {
func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjectInfo, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc, forceAllowCreate bool, options *metav1.UpdateOptions) (runtime.Object, bool, error) {
if rbacregistry.EscalationAllowed(ctx) {
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, obj, createValidation, updateValidation, forceAllowCreate, options)
}
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx context.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
@@ -124,5 +125,5 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
return obj, nil
})
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation)
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo, createValidation, updateValidation, forceAllowCreate, options)
}

View File

@@ -15,9 +15,9 @@ go_library(
"//pkg/printers/internalversion:go_default_library",
"//pkg/printers/storage:go_default_library",
"//pkg/registry/rbac/rolebinding:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//vendor/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/registry/generic/registry:go_default_library",
],
)

View File

@@ -16,10 +16,10 @@ go_test(
embed = [":go_default_library"],
deps = [
"//pkg/apis/rbac/v1:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
],
)
@@ -35,13 +35,13 @@ go_library(
deps = [
"//pkg/apis/rbac:go_default_library",
"//pkg/apis/rbac/v1:go_default_library",
"//staging/src/k8s.io/api/rbac/v1:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//staging/src/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/api/rbac/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
],
)

View File

@@ -20,15 +20,17 @@ import (
"context"
"errors"
"fmt"
"strings"
"github.com/golang/glog"
rbacv1 "k8s.io/api/rbac/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/apiserver/pkg/authentication/serviceaccount"
"k8s.io/apiserver/pkg/authentication/user"
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
)
type AuthorizationRuleResolver interface {
@@ -65,7 +67,22 @@ func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleReso
ownerRightsCover, missingRights := Covers(ownerRules, rules)
if !ownerRightsCover {
return apierrors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v ruleResolutionErrors=%v", missingRights, user, ownerRules, ruleResolutionErrors))
compactMissingRights := missingRights
if compact, err := CompactRules(missingRights); err == nil {
compactMissingRights = compact
}
missingDescriptions := sets.NewString()
for _, missing := range compactMissingRights {
missingDescriptions.Insert(rbacv1helpers.CompactString(missing))
}
msg := fmt.Sprintf("user %q (groups=%q) is attempting to grant RBAC permissions not currently held:\n%s", user.GetName(), user.GetGroups(), strings.Join(missingDescriptions.List(), "\n"))
if len(ruleResolutionErrors) > 0 {
msg = msg + fmt.Sprintf("; resolution errors: %v", ruleResolutionErrors)
}
return errors.New(msg)
}
return nil
}