Switch to github.com/golang/dep for vendoring
Signed-off-by: Mrunal Patel <mrunalp@gmail.com>
This commit is contained in:
parent
d6ab91be27
commit
8e5b17cf13
15431 changed files with 3971413 additions and 8881 deletions
42
vendor/k8s.io/kubernetes/pkg/registry/rbac/BUILD
generated
vendored
Normal file
42
vendor/k8s.io/kubernetes/pkg/registry/rbac/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,42 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["escalation_check.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/registry/rbac/clusterrole:all-srcs",
|
||||
"//pkg/registry/rbac/clusterrolebinding:all-srcs",
|
||||
"//pkg/registry/rbac/rest:all-srcs",
|
||||
"//pkg/registry/rbac/role:all-srcs",
|
||||
"//pkg/registry/rbac/rolebinding:all-srcs",
|
||||
"//pkg/registry/rbac/validation:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
3
vendor/k8s.io/kubernetes/pkg/registry/rbac/OWNERS
generated
vendored
Executable file
3
vendor/k8s.io/kubernetes/pkg/registry/rbac/OWNERS
generated
vendored
Executable file
|
@ -0,0 +1,3 @@
|
|||
reviewers:
|
||||
- deads2k
|
||||
- hongchaodeng
|
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"registry.go",
|
||||
"strategy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/validation:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/registry/rbac/clusterrole/policybased:all-srcs",
|
||||
"//pkg/registry/rbac/clusterrole/storage:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 certificates provides Registry interface and its RESTStorage
|
||||
// implementation for storing ClusterRole objects.
|
||||
package clusterrole // import "k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
36
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
71
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go
generated
vendored
Normal file
71
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 policybased implements a standard storage for ClusterRole that prevents privilege escalation.
|
||||
package policybased
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
)
|
||||
|
||||
var groupResource = rbac.Resource("clusterroles")
|
||||
|
||||
type Storage struct {
|
||||
rest.StandardStorage
|
||||
|
||||
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
|
||||
}
|
||||
|
||||
func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
|
||||
return &Storage{s, ruleResolver}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
clusterRole := obj.(*rbac.ClusterRole)
|
||||
rules := clusterRole.Rules
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, clusterRole.Name, err)
|
||||
}
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Update(ctx, name, obj)
|
||||
}
|
||||
|
||||
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||
clusterRole := obj.(*rbac.ClusterRole)
|
||||
|
||||
rules := clusterRole.Rules
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, clusterRole.Name, err)
|
||||
}
|
||||
return obj, nil
|
||||
})
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo)
|
||||
}
|
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/registry.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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 clusterrole
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
)
|
||||
|
||||
// Registry is an interface for things that know how to store ClusterRoles.
|
||||
type Registry interface {
|
||||
ListClusterRoles(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.ClusterRoleList, error)
|
||||
CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error
|
||||
UpdateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error
|
||||
GetClusterRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error)
|
||||
DeleteClusterRole(ctx genericapirequest.Context, name string) error
|
||||
WatchClusterRoles(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListClusterRoles(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.ClusterRoleList, error) {
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*rbac.ClusterRoleList), nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error {
|
||||
_, err := s.Create(ctx, clusterRole)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) UpdateClusterRole(ctx genericapirequest.Context, clusterRole *rbac.ClusterRole) error {
|
||||
_, _, err := s.Update(ctx, clusterRole.Name, rest.DefaultUpdatedObjectInfo(clusterRole, api.Scheme))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) WatchClusterRoles(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetClusterRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) {
|
||||
obj, err := s.Get(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*rbac.ClusterRole), nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteClusterRole(ctx genericapirequest.Context, name string) error {
|
||||
_, err := s.Delete(ctx, name, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||
type AuthorizerAdapter struct {
|
||||
Registry Registry
|
||||
}
|
||||
|
||||
func (a AuthorizerAdapter) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
||||
return a.Registry.GetClusterRole(genericapirequest.NewContext(), name, &metav1.GetOptions{})
|
||||
}
|
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage/BUILD
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/registry/generic:go_default_library",
|
||||
"//pkg/registry/generic/registry:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrole:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage/storage.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 storage
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
||||
)
|
||||
|
||||
// REST implements a RESTStorage for ClusterRole
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against ClusterRole objects.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &rbac.ClusterRole{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleList{} },
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*rbac.ClusterRole).Name, nil
|
||||
},
|
||||
PredicateFunc: clusterrole.Matcher,
|
||||
QualifiedResource: rbac.Resource("clusterroles"),
|
||||
|
||||
CreateStrategy: clusterrole.Strategy,
|
||||
UpdateStrategy: clusterrole.Strategy,
|
||||
DeleteStrategy: clusterrole.Strategy,
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: clusterrole.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
panic(err) // TODO: Propagate error up
|
||||
}
|
||||
|
||||
return &REST{store}
|
||||
}
|
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrole/strategy.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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 clusterrole
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
apistorage "k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
||||
// strategy implements behavior for ClusterRoles
|
||||
type strategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
}
|
||||
|
||||
// strategy is the default logic that applies when creating and updating
|
||||
// ClusterRole objects.
|
||||
var Strategy = strategy{api.Scheme, names.SimpleNameGenerator}
|
||||
|
||||
// Strategy should implement rest.RESTCreateStrategy
|
||||
var _ rest.RESTCreateStrategy = Strategy
|
||||
|
||||
// Strategy should implement rest.RESTUpdateStrategy
|
||||
var _ rest.RESTUpdateStrategy = Strategy
|
||||
|
||||
// NamespaceScoped is true for ClusterRoles.
|
||||
func (strategy) NamespaceScoped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is true for ClusterRoles.
|
||||
func (strategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users
|
||||
// on creation.
|
||||
func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
|
||||
_ = obj.(*rbac.ClusterRole)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
|
||||
newClusterRole := obj.(*rbac.ClusterRole)
|
||||
oldClusterRole := old.(*rbac.ClusterRole)
|
||||
|
||||
_, _ = newClusterRole, oldClusterRole
|
||||
}
|
||||
|
||||
// Validate validates a new ClusterRole. Validation must check for a correct signature.
|
||||
func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
|
||||
clusterRole := obj.(*rbac.ClusterRole)
|
||||
return validation.ValidateClusterRole(clusterRole)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (strategy) Canonicalize(obj runtime.Object) {
|
||||
_ = obj.(*rbac.ClusterRole)
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
newObj := obj.(*rbac.ClusterRole)
|
||||
errorList := validation.ValidateClusterRole(newObj)
|
||||
return append(errorList, validation.ValidateClusterRoleUpdate(newObj, old.(*rbac.ClusterRole))...)
|
||||
}
|
||||
|
||||
// If AllowUnconditionalUpdate() is true and the object specified by
|
||||
// the user does not have a resource version, then generic Update()
|
||||
// populates it with the latest version. Else, it checks that the
|
||||
// version specified by the user matches the version of latest etcd
|
||||
// object.
|
||||
func (strategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
role, ok := obj.(*rbac.ClusterRole)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a ClusterRole")
|
||||
}
|
||||
return labels.Set(role.Labels), SelectableFields(role), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectableFields returns a field set that can be used for filter selection
|
||||
func SelectableFields(obj *rbac.ClusterRole) fields.Set {
|
||||
return nil
|
||||
}
|
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"registry.go",
|
||||
"strategy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/validation:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/registry/rbac/clusterrolebinding/policybased:all-srcs",
|
||||
"//pkg/registry/rbac/clusterrolebinding/storage:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 certificates provides Registry interface and its RESTStorage
|
||||
// implementation for storing ClusterRoleBinding objects.
|
||||
package clusterrolebinding // import "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding"
|
37
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
90
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go
generated
vendored
Normal file
90
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
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 policybased implements a standard storage for ClusterRoleBinding that prevents privilege escalation.
|
||||
package policybased
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
)
|
||||
|
||||
var groupResource = rbac.Resource("clusterrolebindings")
|
||||
|
||||
type Storage struct {
|
||||
rest.StandardStorage
|
||||
|
||||
authorizer authorizer.Authorizer
|
||||
|
||||
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
|
||||
}
|
||||
|
||||
func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
|
||||
return &Storage{s, authorizer, ruleResolver}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace, s.authorizer) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
|
||||
}
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Update(ctx, name, obj)
|
||||
}
|
||||
|
||||
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
|
||||
// if we're explicitly authorized to bind this clusterrole, return
|
||||
if rbacregistry.BindingAuthorized(ctx, clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace, s.authorizer) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// Otherwise, see if we already have all the permissions contained in the referenced clusterrole
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, clusterRoleBinding.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, clusterRoleBinding.Name, err)
|
||||
}
|
||||
return obj, nil
|
||||
})
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo)
|
||||
}
|
101
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go
generated
vendored
Normal file
101
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/registry.go
generated
vendored
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
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 clusterrolebinding
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
)
|
||||
|
||||
// Registry is an interface for things that know how to store ClusterRoleBindings.
|
||||
type Registry interface {
|
||||
ListClusterRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.ClusterRoleBindingList, error)
|
||||
CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error
|
||||
UpdateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error
|
||||
GetClusterRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error)
|
||||
DeleteClusterRoleBinding(ctx genericapirequest.Context, name string) error
|
||||
WatchClusterRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListClusterRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.ClusterRoleBindingList, error) {
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*rbac.ClusterRoleBindingList), nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error {
|
||||
_, err := s.Create(ctx, clusterRoleBinding)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) UpdateClusterRoleBinding(ctx genericapirequest.Context, clusterRoleBinding *rbac.ClusterRoleBinding) error {
|
||||
_, _, err := s.Update(ctx, clusterRoleBinding.Name, rest.DefaultUpdatedObjectInfo(clusterRoleBinding, api.Scheme))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) WatchClusterRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetClusterRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) {
|
||||
obj, err := s.Get(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*rbac.ClusterRoleBinding), nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteClusterRoleBinding(ctx genericapirequest.Context, name string) error {
|
||||
_, err := s.Delete(ctx, name, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||
type AuthorizerAdapter struct {
|
||||
Registry Registry
|
||||
}
|
||||
|
||||
func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
||||
list, err := a.Registry.ListClusterRoleBindings(genericapirequest.NewContext(), &api.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := []*rbac.ClusterRoleBinding{}
|
||||
for i := range list.Items {
|
||||
ret = append(ret, &list.Items[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage/BUILD
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/registry/generic:go_default_library",
|
||||
"//pkg/registry/generic/registry:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrolebinding:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage/storage.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 storage
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding"
|
||||
)
|
||||
|
||||
// REST implements a RESTStorage for ClusterRoleBinding
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against ClusterRoleBinding objects.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &rbac.ClusterRoleBinding{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.ClusterRoleBindingList{} },
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*rbac.ClusterRoleBinding).Name, nil
|
||||
},
|
||||
PredicateFunc: clusterrolebinding.Matcher,
|
||||
QualifiedResource: rbac.Resource("clusterrolebindings"),
|
||||
|
||||
CreateStrategy: clusterrolebinding.Strategy,
|
||||
UpdateStrategy: clusterrolebinding.Strategy,
|
||||
DeleteStrategy: clusterrolebinding.Strategy,
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: clusterrolebinding.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
panic(err) // TODO: Propagate error up
|
||||
}
|
||||
|
||||
return &REST{store}
|
||||
}
|
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/strategy.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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 clusterrolebinding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
apistorage "k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
||||
// strategy implements behavior for ClusterRoleBindings
|
||||
type strategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
}
|
||||
|
||||
// strategy is the default logic that applies when creating and updating
|
||||
// ClusterRoleBinding objects.
|
||||
var Strategy = strategy{api.Scheme, names.SimpleNameGenerator}
|
||||
|
||||
// Strategy should implement rest.RESTCreateStrategy
|
||||
var _ rest.RESTCreateStrategy = Strategy
|
||||
|
||||
// Strategy should implement rest.RESTUpdateStrategy
|
||||
var _ rest.RESTUpdateStrategy = Strategy
|
||||
|
||||
// NamespaceScoped is true for ClusterRoleBindings.
|
||||
func (strategy) NamespaceScoped() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is true for ClusterRoleBindings.
|
||||
func (strategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users
|
||||
// on creation.
|
||||
func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
|
||||
_ = obj.(*rbac.ClusterRoleBinding)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
|
||||
newClusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
oldClusterRoleBinding := old.(*rbac.ClusterRoleBinding)
|
||||
|
||||
_, _ = newClusterRoleBinding, oldClusterRoleBinding
|
||||
}
|
||||
|
||||
// Validate validates a new ClusterRoleBinding. Validation must check for a correct signature.
|
||||
func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
|
||||
clusterRoleBinding := obj.(*rbac.ClusterRoleBinding)
|
||||
return validation.ValidateClusterRoleBinding(clusterRoleBinding)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (strategy) Canonicalize(obj runtime.Object) {
|
||||
_ = obj.(*rbac.ClusterRoleBinding)
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
newObj := obj.(*rbac.ClusterRoleBinding)
|
||||
errorList := validation.ValidateClusterRoleBinding(newObj)
|
||||
return append(errorList, validation.ValidateClusterRoleBindingUpdate(newObj, old.(*rbac.ClusterRoleBinding))...)
|
||||
}
|
||||
|
||||
// If AllowUnconditionalUpdate() is true and the object specified by
|
||||
// the user does not have a resource version, then generic Update()
|
||||
// populates it with the latest version. Else, it checks that the
|
||||
// version specified by the user matches the version of latest etcd
|
||||
// object.
|
||||
func (strategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
roleBinding, ok := obj.(*rbac.ClusterRoleBinding)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a ClusterRoleBinding")
|
||||
}
|
||||
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectableFields returns a field set that can be used for filter selection
|
||||
func SelectableFields(obj *rbac.ClusterRoleBinding) fields.Set {
|
||||
return nil
|
||||
}
|
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/escalation_check.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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 (
|
||||
"fmt"
|
||||
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
func EscalationAllowed(ctx genericapirequest.Context) bool {
|
||||
u, ok := genericapirequest.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
|
||||
}
|
||||
|
||||
// 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
|
||||
}
|
||||
|
||||
// BindingAuthorized returns true if the user associated with the context is explicitly authorized to bind the specified roleRef
|
||||
func BindingAuthorized(ctx genericapirequest.Context, roleRef rbac.RoleRef, bindingNamespace string, a authorizer.Authorizer) bool {
|
||||
if a == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
user, ok := genericapirequest.UserFrom(ctx)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
attrs := authorizer.AttributesRecord{
|
||||
User: user,
|
||||
Verb: "bind",
|
||||
// check against the namespace where the binding is being created (or the empty namespace for clusterrolebindings).
|
||||
// this allows delegation to bind particular clusterroles in rolebindings within particular namespaces,
|
||||
// and to authorize binding a clusterrole across all namespaces in a clusterrolebinding.
|
||||
Namespace: bindingNamespace,
|
||||
ResourceRequest: true,
|
||||
}
|
||||
|
||||
// This occurs after defaulting and conversion, so values pulled from the roleRef won't change
|
||||
// Invalid APIGroup or Name values will fail validation
|
||||
switch roleRef.Kind {
|
||||
case "ClusterRole":
|
||||
attrs.APIGroup = roleRef.APIGroup
|
||||
attrs.Resource = "clusterroles"
|
||||
attrs.Name = roleRef.Name
|
||||
case "Role":
|
||||
attrs.APIGroup = roleRef.APIGroup
|
||||
attrs.Resource = "roles"
|
||||
attrs.Name = roleRef.Name
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
ok, _, err := a.Authorize(attrs)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf(
|
||||
"error authorizing user %#v to bind %#v in namespace %s: %v",
|
||||
roleRef, bindingNamespace, user, err,
|
||||
))
|
||||
}
|
||||
return ok
|
||||
}
|
54
vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD
generated
vendored
Normal file
54
vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,54 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage_rbac.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/v1alpha1:go_default_library",
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
||||
"//pkg/genericapiserver:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/registry/generic:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrole:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrole/policybased:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrole/storage:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrolebinding:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrolebinding/policybased:go_default_library",
|
||||
"//pkg/registry/rbac/clusterrolebinding/storage:go_default_library",
|
||||
"//pkg/registry/rbac/role:go_default_library",
|
||||
"//pkg/registry/rbac/role/policybased:go_default_library",
|
||||
"//pkg/registry/rbac/role/storage:go_default_library",
|
||||
"//pkg/registry/rbac/rolebinding:go_default_library",
|
||||
"//pkg/registry/rbac/rolebinding/policybased:go_default_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",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/wait",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
177
vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go
generated
vendored
Normal file
177
vendor/k8s.io/kubernetes/pkg/registry/rbac/rest/storage_rbac.go
generated
vendored
Normal file
|
@ -0,0 +1,177 @@
|
|||
/*
|
||||
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 rest
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
rbacapiv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1"
|
||||
rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
||||
clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased"
|
||||
clusterrolestore "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding"
|
||||
clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased"
|
||||
clusterrolebindingstore "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/role"
|
||||
rolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/role/policybased"
|
||||
rolestore "k8s.io/kubernetes/pkg/registry/rbac/role/storage"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/rolebinding"
|
||||
rolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased"
|
||||
rolebindingstore "k8s.io/kubernetes/pkg/registry/rbac/rolebinding/storage"
|
||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
||||
)
|
||||
|
||||
type RESTStorageProvider struct {
|
||||
Authorizer authorizer.Authorizer
|
||||
}
|
||||
|
||||
var _ genericapiserver.PostStartHookProvider = RESTStorageProvider{}
|
||||
|
||||
func (p RESTStorageProvider) NewRESTStorage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) (genericapiserver.APIGroupInfo, bool) {
|
||||
apiGroupInfo := genericapiserver.NewDefaultAPIGroupInfo(rbac.GroupName)
|
||||
|
||||
if apiResourceConfigSource.AnyResourcesForVersionEnabled(rbacapiv1alpha1.SchemeGroupVersion) {
|
||||
apiGroupInfo.VersionedResourcesStorageMap[rbacapiv1alpha1.SchemeGroupVersion.Version] = p.v1alpha1Storage(apiResourceConfigSource, restOptionsGetter)
|
||||
apiGroupInfo.GroupMeta.GroupVersion = rbacapiv1alpha1.SchemeGroupVersion
|
||||
}
|
||||
|
||||
return apiGroupInfo, true
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) v1alpha1Storage(apiResourceConfigSource genericapiserver.APIResourceConfigSource, restOptionsGetter generic.RESTOptionsGetter) map[string]rest.Storage {
|
||||
version := rbacapiv1alpha1.SchemeGroupVersion
|
||||
|
||||
once := new(sync.Once)
|
||||
var (
|
||||
authorizationRuleResolver rbacregistryvalidation.AuthorizationRuleResolver
|
||||
rolesStorage rest.StandardStorage
|
||||
roleBindingsStorage rest.StandardStorage
|
||||
clusterRolesStorage rest.StandardStorage
|
||||
clusterRoleBindingsStorage rest.StandardStorage
|
||||
)
|
||||
|
||||
initializeStorage := func() {
|
||||
once.Do(func() {
|
||||
rolesStorage = rolestore.NewREST(restOptionsGetter)
|
||||
roleBindingsStorage = rolebindingstore.NewREST(restOptionsGetter)
|
||||
clusterRolesStorage = clusterrolestore.NewREST(restOptionsGetter)
|
||||
clusterRoleBindingsStorage = clusterrolebindingstore.NewREST(restOptionsGetter)
|
||||
|
||||
authorizationRuleResolver = rbacregistryvalidation.NewDefaultRuleResolver(
|
||||
role.AuthorizerAdapter{Registry: role.NewRegistry(rolesStorage)},
|
||||
rolebinding.AuthorizerAdapter{Registry: rolebinding.NewRegistry(roleBindingsStorage)},
|
||||
clusterrole.AuthorizerAdapter{Registry: clusterrole.NewRegistry(clusterRolesStorage)},
|
||||
clusterrolebinding.AuthorizerAdapter{Registry: clusterrolebinding.NewRegistry(clusterRoleBindingsStorage)},
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
storage := map[string]rest.Storage{}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("roles")) {
|
||||
initializeStorage()
|
||||
storage["roles"] = rolepolicybased.NewStorage(rolesStorage, authorizationRuleResolver)
|
||||
}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("rolebindings")) {
|
||||
initializeStorage()
|
||||
storage["rolebindings"] = rolebindingpolicybased.NewStorage(roleBindingsStorage, p.Authorizer, authorizationRuleResolver)
|
||||
}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterroles")) {
|
||||
initializeStorage()
|
||||
storage["clusterroles"] = clusterrolepolicybased.NewStorage(clusterRolesStorage, authorizationRuleResolver)
|
||||
}
|
||||
if apiResourceConfigSource.ResourceEnabled(version.WithResource("clusterrolebindings")) {
|
||||
initializeStorage()
|
||||
storage["clusterrolebindings"] = clusterrolebindingpolicybased.NewStorage(clusterRoleBindingsStorage, p.Authorizer, authorizationRuleResolver)
|
||||
}
|
||||
return storage
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStartHookFunc, error) {
|
||||
return "rbac/bootstrap-roles", PostStartHook, nil
|
||||
}
|
||||
|
||||
func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
|
||||
// intializing roles is really important. On some e2e runs, we've seen cases where etcd is down when the server
|
||||
// starts, the roles don't initialize, and nothing works.
|
||||
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
|
||||
clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig)
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err))
|
||||
return false, nil
|
||||
}
|
||||
|
||||
existingClusterRoles, err := clientset.ClusterRoles().List(api.ListOptions{})
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err))
|
||||
return false, nil
|
||||
}
|
||||
// only initialized on empty etcd
|
||||
if len(existingClusterRoles.Items) == 0 {
|
||||
for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) {
|
||||
if _, err := clientset.ClusterRoles().Create(&clusterRole); err != nil {
|
||||
// don't fail on failures, try to create as many as you can
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err))
|
||||
continue
|
||||
}
|
||||
glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name)
|
||||
}
|
||||
}
|
||||
|
||||
existingClusterRoleBindings, err := clientset.ClusterRoleBindings().List(api.ListOptions{})
|
||||
if err != nil {
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err))
|
||||
return false, nil
|
||||
}
|
||||
// only initialized on empty etcd
|
||||
if len(existingClusterRoleBindings.Items) == 0 {
|
||||
for _, clusterRoleBinding := range append(bootstrappolicy.ClusterRoleBindings(), bootstrappolicy.ControllerRoleBindings()...) {
|
||||
if _, err := clientset.ClusterRoleBindings().Create(&clusterRoleBinding); err != nil {
|
||||
// don't fail on failures, try to create as many as you can
|
||||
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err))
|
||||
continue
|
||||
}
|
||||
glog.Infof("Created clusterrolebinding.%s/%s", rbac.GroupName, clusterRoleBinding.Name)
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
// if we're never able to make it through intialization, kill the API server
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to initialize roles: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p RESTStorageProvider) GroupName() string {
|
||||
return rbac.GroupName
|
||||
}
|
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"registry.go",
|
||||
"strategy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/validation:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/registry/rbac/role/policybased:all-srcs",
|
||||
"//pkg/registry/rbac/role/storage:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 certificates provides Registry interface and its RESTStorage
|
||||
// implementation for storing Role objects.
|
||||
package role // import "k8s.io/kubernetes/pkg/registry/rbac/role"
|
36
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD
generated
vendored
Normal file
36
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
71
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go
generated
vendored
Normal file
71
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/policybased/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
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 policybased implements a standard storage for Role that prevents privilege escalation.
|
||||
package policybased
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
)
|
||||
|
||||
var groupResource = rbac.Resource("roles")
|
||||
|
||||
type Storage struct {
|
||||
rest.StandardStorage
|
||||
|
||||
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
|
||||
}
|
||||
|
||||
func NewStorage(s rest.StandardStorage, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
|
||||
return &Storage{s, ruleResolver}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
role := obj.(*rbac.Role)
|
||||
rules := role.Rules
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
||||
}
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Update(ctx, name, obj)
|
||||
}
|
||||
|
||||
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||
role := obj.(*rbac.Role)
|
||||
|
||||
rules := role.Rules
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
||||
}
|
||||
return obj, nil
|
||||
})
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo)
|
||||
}
|
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go
generated
vendored
Normal file
92
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/registry.go
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
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 role
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
)
|
||||
|
||||
// Registry is an interface for things that know how to store Roles.
|
||||
type Registry interface {
|
||||
ListRoles(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.RoleList, error)
|
||||
CreateRole(ctx genericapirequest.Context, role *rbac.Role) error
|
||||
UpdateRole(ctx genericapirequest.Context, role *rbac.Role) error
|
||||
GetRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.Role, error)
|
||||
DeleteRole(ctx genericapirequest.Context, name string) error
|
||||
WatchRoles(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListRoles(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.RoleList, error) {
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*rbac.RoleList), nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateRole(ctx genericapirequest.Context, role *rbac.Role) error {
|
||||
_, err := s.Create(ctx, role)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) UpdateRole(ctx genericapirequest.Context, role *rbac.Role) error {
|
||||
_, _, err := s.Update(ctx, role.Name, rest.DefaultUpdatedObjectInfo(role, api.Scheme))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) WatchRoles(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetRole(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) {
|
||||
obj, err := s.Get(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*rbac.Role), nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteRole(ctx genericapirequest.Context, name string) error {
|
||||
_, err := s.Delete(ctx, name, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||
type AuthorizerAdapter struct {
|
||||
Registry Registry
|
||||
}
|
||||
|
||||
func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbac.Role, error) {
|
||||
return a.Registry.GetRole(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), name, &metav1.GetOptions{})
|
||||
}
|
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/storage/BUILD
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/storage/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/registry/generic:go_default_library",
|
||||
"//pkg/registry/generic/registry:go_default_library",
|
||||
"//pkg/registry/rbac/role:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/storage/storage.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/storage/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 storage
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/role"
|
||||
)
|
||||
|
||||
// REST implements a RESTStorage for Role
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against Role objects.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &rbac.Role{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.RoleList{} },
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*rbac.Role).Name, nil
|
||||
},
|
||||
PredicateFunc: role.Matcher,
|
||||
QualifiedResource: rbac.Resource("roles"),
|
||||
|
||||
CreateStrategy: role.Strategy,
|
||||
UpdateStrategy: role.Strategy,
|
||||
DeleteStrategy: role.Strategy,
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: role.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
panic(err) // TODO: Propagate error up
|
||||
}
|
||||
|
||||
return &REST{store}
|
||||
}
|
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/role/strategy.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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 role
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
apistorage "k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
||||
// strategy implements behavior for Roles
|
||||
type strategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
}
|
||||
|
||||
// strategy is the default logic that applies when creating and updating
|
||||
// Role objects.
|
||||
var Strategy = strategy{api.Scheme, names.SimpleNameGenerator}
|
||||
|
||||
// Strategy should implement rest.RESTCreateStrategy
|
||||
var _ rest.RESTCreateStrategy = Strategy
|
||||
|
||||
// Strategy should implement rest.RESTUpdateStrategy
|
||||
var _ rest.RESTUpdateStrategy = Strategy
|
||||
|
||||
// NamespaceScoped is true for Roles.
|
||||
func (strategy) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is true for Roles.
|
||||
func (strategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users
|
||||
// on creation.
|
||||
func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
|
||||
_ = obj.(*rbac.Role)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
|
||||
newRole := obj.(*rbac.Role)
|
||||
oldRole := old.(*rbac.Role)
|
||||
|
||||
_, _ = newRole, oldRole
|
||||
}
|
||||
|
||||
// Validate validates a new Role. Validation must check for a correct signature.
|
||||
func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
|
||||
role := obj.(*rbac.Role)
|
||||
return validation.ValidateRole(role)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (strategy) Canonicalize(obj runtime.Object) {
|
||||
_ = obj.(*rbac.Role)
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
newObj := obj.(*rbac.Role)
|
||||
errorList := validation.ValidateRole(newObj)
|
||||
return append(errorList, validation.ValidateRoleUpdate(newObj, old.(*rbac.Role))...)
|
||||
}
|
||||
|
||||
// If AllowUnconditionalUpdate() is true and the object specified by
|
||||
// the user does not have a resource version, then generic Update()
|
||||
// populates it with the latest version. Else, it checks that the
|
||||
// version specified by the user matches the version of latest etcd
|
||||
// object.
|
||||
func (strategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
role, ok := obj.(*rbac.Role)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a Role")
|
||||
}
|
||||
return labels.Set(role.Labels), SelectableFields(role), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectableFields returns a field set that can be used for filter selection
|
||||
func SelectableFields(obj *rbac.Role) fields.Set {
|
||||
return nil
|
||||
}
|
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD
generated
vendored
Normal file
50
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,50 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"registry.go",
|
||||
"strategy.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/apis/rbac/validation:go_default_library",
|
||||
"//pkg/fields:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/storage:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
|
||||
"//vendor:k8s.io/apimachinery/pkg/labels",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||
"//vendor:k8s.io/apimachinery/pkg/watch",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
"//vendor:k8s.io/apiserver/pkg/storage/names",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/registry/rbac/rolebinding/policybased:all-srcs",
|
||||
"//pkg/registry/rbac/rolebinding/storage:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/doc.go
generated
vendored
Normal file
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
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 certificates provides Registry interface and its RESTStorage
|
||||
// implementation for storing RoleBinding objects.
|
||||
package rolebinding // import "k8s.io/kubernetes/pkg/registry/rbac/rolebinding"
|
37
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD
generated
vendored
Normal file
37
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,37 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/genericapiserver/api/rest:go_default_library",
|
||||
"//pkg/registry/rbac:go_default_library",
|
||||
"//pkg/registry/rbac/validation:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
"//vendor:k8s.io/apiserver/pkg/authorization/authorizer",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
90
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go
generated
vendored
Normal file
90
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/policybased/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
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 policybased implements a standard storage for RoleBinding that prevents privilege escalation.
|
||||
package policybased
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||
)
|
||||
|
||||
var groupResource = rbac.Resource("rolebindings")
|
||||
|
||||
type Storage struct {
|
||||
rest.StandardStorage
|
||||
|
||||
authorizer authorizer.Authorizer
|
||||
|
||||
ruleResolver rbacregistryvalidation.AuthorizationRuleResolver
|
||||
}
|
||||
|
||||
func NewStorage(s rest.StandardStorage, authorizer authorizer.Authorizer, ruleResolver rbacregistryvalidation.AuthorizationRuleResolver) *Storage {
|
||||
return &Storage{s, authorizer, ruleResolver}
|
||||
}
|
||||
|
||||
func (s *Storage) Create(ctx genericapirequest.Context, obj runtime.Object) (runtime.Object, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
roleBinding := obj.(*rbac.RoleBinding)
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, roleBinding.Namespace, s.authorizer) {
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, roleBinding.Name, err)
|
||||
}
|
||||
return s.StandardStorage.Create(ctx, obj)
|
||||
}
|
||||
|
||||
func (s *Storage) Update(ctx genericapirequest.Context, name string, obj rest.UpdatedObjectInfo) (runtime.Object, bool, error) {
|
||||
if rbacregistry.EscalationAllowed(ctx) {
|
||||
return s.StandardStorage.Update(ctx, name, obj)
|
||||
}
|
||||
|
||||
nonEscalatingInfo := rest.WrapUpdatedObjectInfo(obj, func(ctx genericapirequest.Context, obj runtime.Object, oldObj runtime.Object) (runtime.Object, error) {
|
||||
roleBinding := obj.(*rbac.RoleBinding)
|
||||
|
||||
// if we're explicitly authorized to bind this role, return
|
||||
if rbacregistry.BindingAuthorized(ctx, roleBinding.RoleRef, roleBinding.Namespace, s.authorizer) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
// Otherwise, see if we already have all the permissions contained in the referenced role
|
||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, roleBinding.Namespace)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
||||
return nil, errors.NewForbidden(groupResource, roleBinding.Name, err)
|
||||
}
|
||||
return obj, nil
|
||||
})
|
||||
|
||||
return s.StandardStorage.Update(ctx, name, nonEscalatingInfo)
|
||||
}
|
102
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go
generated
vendored
Normal file
102
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/registry.go
generated
vendored
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
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 rolebinding
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
)
|
||||
|
||||
// Registry is an interface for things that know how to store RoleBindings.
|
||||
type Registry interface {
|
||||
ListRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.RoleBindingList, error)
|
||||
CreateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding) error
|
||||
UpdateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding) error
|
||||
GetRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error)
|
||||
DeleteRoleBinding(ctx genericapirequest.Context, name string) error
|
||||
WatchRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error)
|
||||
}
|
||||
|
||||
// storage puts strong typing around storage calls
|
||||
type storage struct {
|
||||
rest.StandardStorage
|
||||
}
|
||||
|
||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||
// types will panic.
|
||||
func NewRegistry(s rest.StandardStorage) Registry {
|
||||
return &storage{s}
|
||||
}
|
||||
|
||||
func (s *storage) ListRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (*rbac.RoleBindingList, error) {
|
||||
obj, err := s.List(ctx, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return obj.(*rbac.RoleBindingList), nil
|
||||
}
|
||||
|
||||
func (s *storage) CreateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding) error {
|
||||
// TODO(ericchiang): add additional validation
|
||||
_, err := s.Create(ctx, roleBinding)
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) UpdateRoleBinding(ctx genericapirequest.Context, roleBinding *rbac.RoleBinding) error {
|
||||
_, _, err := s.Update(ctx, roleBinding.Name, rest.DefaultUpdatedObjectInfo(roleBinding, api.Scheme))
|
||||
return err
|
||||
}
|
||||
|
||||
func (s *storage) WatchRoleBindings(ctx genericapirequest.Context, options *api.ListOptions) (watch.Interface, error) {
|
||||
return s.Watch(ctx, options)
|
||||
}
|
||||
|
||||
func (s *storage) GetRoleBinding(ctx genericapirequest.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) {
|
||||
obj, err := s.Get(ctx, name, options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return obj.(*rbac.RoleBinding), nil
|
||||
}
|
||||
|
||||
func (s *storage) DeleteRoleBinding(ctx genericapirequest.Context, name string) error {
|
||||
_, err := s.Delete(ctx, name, nil)
|
||||
return err
|
||||
}
|
||||
|
||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||
type AuthorizerAdapter struct {
|
||||
Registry Registry
|
||||
}
|
||||
|
||||
func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
||||
list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &api.ListOptions{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := []*rbac.RoleBinding{}
|
||||
for i := range list.Items {
|
||||
ret = append(ret, &list.Items[i])
|
||||
}
|
||||
return ret, nil
|
||||
}
|
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/storage/BUILD
generated
vendored
Normal file
34
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/storage/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["storage.go"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/registry/generic:go_default_library",
|
||||
"//pkg/registry/generic/registry:go_default_library",
|
||||
"//pkg/registry/rbac/rolebinding:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/runtime",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/storage/storage.go
generated
vendored
Normal file
53
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/storage/storage.go
generated
vendored
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
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 storage
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/registry/generic"
|
||||
genericregistry "k8s.io/kubernetes/pkg/registry/generic/registry"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/rolebinding"
|
||||
)
|
||||
|
||||
// REST implements a RESTStorage for RoleBinding
|
||||
type REST struct {
|
||||
*genericregistry.Store
|
||||
}
|
||||
|
||||
// NewREST returns a RESTStorage object that will work against RoleBinding objects.
|
||||
func NewREST(optsGetter generic.RESTOptionsGetter) *REST {
|
||||
store := &genericregistry.Store{
|
||||
NewFunc: func() runtime.Object { return &rbac.RoleBinding{} },
|
||||
NewListFunc: func() runtime.Object { return &rbac.RoleBindingList{} },
|
||||
ObjectNameFunc: func(obj runtime.Object) (string, error) {
|
||||
return obj.(*rbac.RoleBinding).Name, nil
|
||||
},
|
||||
PredicateFunc: rolebinding.Matcher,
|
||||
QualifiedResource: rbac.Resource("rolebindings"),
|
||||
|
||||
CreateStrategy: rolebinding.Strategy,
|
||||
UpdateStrategy: rolebinding.Strategy,
|
||||
DeleteStrategy: rolebinding.Strategy,
|
||||
}
|
||||
options := &generic.StoreOptions{RESTOptions: optsGetter, AttrFunc: rolebinding.GetAttrs}
|
||||
if err := store.CompleteWithOptions(options); err != nil {
|
||||
panic(err) // TODO: Propagate error up
|
||||
}
|
||||
|
||||
return &REST{store}
|
||||
}
|
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go
generated
vendored
Normal file
127
vendor/k8s.io/kubernetes/pkg/registry/rbac/rolebinding/strategy.go
generated
vendored
Normal file
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
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 rolebinding
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/apiserver/pkg/storage/names"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac/validation"
|
||||
"k8s.io/kubernetes/pkg/fields"
|
||||
"k8s.io/kubernetes/pkg/genericapiserver/api/rest"
|
||||
apistorage "k8s.io/kubernetes/pkg/storage"
|
||||
)
|
||||
|
||||
// strategy implements behavior for RoleBindings
|
||||
type strategy struct {
|
||||
runtime.ObjectTyper
|
||||
names.NameGenerator
|
||||
}
|
||||
|
||||
// strategy is the default logic that applies when creating and updating
|
||||
// RoleBinding objects.
|
||||
var Strategy = strategy{api.Scheme, names.SimpleNameGenerator}
|
||||
|
||||
// Strategy should implement rest.RESTCreateStrategy
|
||||
var _ rest.RESTCreateStrategy = Strategy
|
||||
|
||||
// Strategy should implement rest.RESTUpdateStrategy
|
||||
var _ rest.RESTUpdateStrategy = Strategy
|
||||
|
||||
// NamespaceScoped is true for RoleBindings.
|
||||
func (strategy) NamespaceScoped() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// AllowCreateOnUpdate is true for RoleBindings.
|
||||
func (strategy) AllowCreateOnUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// PrepareForCreate clears fields that are not allowed to be set by end users
|
||||
// on creation.
|
||||
func (strategy) PrepareForCreate(ctx genericapirequest.Context, obj runtime.Object) {
|
||||
_ = obj.(*rbac.RoleBinding)
|
||||
}
|
||||
|
||||
// PrepareForUpdate clears fields that are not allowed to be set by end users on update.
|
||||
func (strategy) PrepareForUpdate(ctx genericapirequest.Context, obj, old runtime.Object) {
|
||||
newRoleBinding := obj.(*rbac.RoleBinding)
|
||||
oldRoleBinding := old.(*rbac.RoleBinding)
|
||||
|
||||
_, _ = newRoleBinding, oldRoleBinding
|
||||
}
|
||||
|
||||
// Validate validates a new RoleBinding. Validation must check for a correct signature.
|
||||
func (strategy) Validate(ctx genericapirequest.Context, obj runtime.Object) field.ErrorList {
|
||||
roleBinding := obj.(*rbac.RoleBinding)
|
||||
return validation.ValidateRoleBinding(roleBinding)
|
||||
}
|
||||
|
||||
// Canonicalize normalizes the object after validation.
|
||||
func (strategy) Canonicalize(obj runtime.Object) {
|
||||
_ = obj.(*rbac.RoleBinding)
|
||||
}
|
||||
|
||||
// ValidateUpdate is the default update validation for an end user.
|
||||
func (strategy) ValidateUpdate(ctx genericapirequest.Context, obj, old runtime.Object) field.ErrorList {
|
||||
newObj := obj.(*rbac.RoleBinding)
|
||||
errorList := validation.ValidateRoleBinding(newObj)
|
||||
return append(errorList, validation.ValidateRoleBindingUpdate(newObj, old.(*rbac.RoleBinding))...)
|
||||
}
|
||||
|
||||
// If AllowUnconditionalUpdate() is true and the object specified by
|
||||
// the user does not have a resource version, then generic Update()
|
||||
// populates it with the latest version. Else, it checks that the
|
||||
// version specified by the user matches the version of latest etcd
|
||||
// object.
|
||||
func (strategy) AllowUnconditionalUpdate() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (s strategy) Export(ctx genericapirequest.Context, obj runtime.Object, exact bool) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetAttrs returns labels and fields of a given object for filtering purposes.
|
||||
func GetAttrs(obj runtime.Object) (labels.Set, fields.Set, error) {
|
||||
roleBinding, ok := obj.(*rbac.RoleBinding)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("not a RoleBinding")
|
||||
}
|
||||
return labels.Set(roleBinding.Labels), SelectableFields(roleBinding), nil
|
||||
}
|
||||
|
||||
// Matcher returns a generic matcher for a given label and field selector.
|
||||
func Matcher(label labels.Selector, field fields.Selector) apistorage.SelectionPredicate {
|
||||
return apistorage.SelectionPredicate{
|
||||
Label: label,
|
||||
Field: field,
|
||||
GetAttrs: GetAttrs,
|
||||
}
|
||||
}
|
||||
|
||||
// SelectableFields returns a field set that can be used for filter selection
|
||||
func SelectableFields(obj *rbac.RoleBinding) fields.Set {
|
||||
return nil
|
||||
}
|
56
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD
generated
vendored
Normal file
56
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/BUILD
generated
vendored
Normal file
|
@ -0,0 +1,56 @@
|
|||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
licenses(["notice"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"policy_comparator_test.go",
|
||||
"rule_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/api:go_default_library",
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/diff",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"policy_comparator.go",
|
||||
"rule.go",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//pkg/apis/rbac:go_default_library",
|
||||
"//pkg/serviceaccount:go_default_library",
|
||||
"//vendor:github.com/golang/glog",
|
||||
"//vendor:k8s.io/apimachinery/pkg/api/errors",
|
||||
"//vendor:k8s.io/apimachinery/pkg/util/errors",
|
||||
"//vendor:k8s.io/apiserver/pkg/authentication/user",
|
||||
"//vendor:k8s.io/apiserver/pkg/request",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
148
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go
generated
vendored
Normal file
148
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator.go
generated
vendored
Normal file
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
// Covers determines whether or not the ownerRules cover the servantRules in terms of allowed actions.
|
||||
// It returns whether or not the ownerRules cover and a list of the rules that the ownerRules do not cover.
|
||||
func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule) {
|
||||
// 1. Break every servantRule into individual rule tuples: group, verb, resource, resourceName
|
||||
// 2. Compare the mini-rules against each owner rule. Because the breakdown is down to the most atomic level, we're guaranteed that each mini-servant rule will be either fully covered or not covered by a single owner rule
|
||||
// 3. Any left over mini-rules means that we are not covered and we have a nice list of them.
|
||||
// TODO: it might be nice to collapse the list down into something more human readable
|
||||
|
||||
subrules := []rbac.PolicyRule{}
|
||||
for _, servantRule := range servantRules {
|
||||
subrules = append(subrules, breakdownRule(servantRule)...)
|
||||
}
|
||||
|
||||
uncoveredRules := []rbac.PolicyRule{}
|
||||
for _, subrule := range subrules {
|
||||
covered := false
|
||||
for _, ownerRule := range ownerRules {
|
||||
if ruleCovers(ownerRule, subrule) {
|
||||
covered = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !covered {
|
||||
uncoveredRules = append(uncoveredRules, subrule)
|
||||
}
|
||||
}
|
||||
|
||||
return (len(uncoveredRules) == 0), uncoveredRules
|
||||
}
|
||||
|
||||
// breadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one
|
||||
// resource, and one resource name
|
||||
func breakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule {
|
||||
subrules := []rbac.PolicyRule{}
|
||||
for _, group := range rule.APIGroups {
|
||||
for _, resource := range rule.Resources {
|
||||
for _, verb := range rule.Verbs {
|
||||
if len(rule.ResourceNames) > 0 {
|
||||
for _, resourceName := range rule.ResourceNames {
|
||||
subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}})
|
||||
}
|
||||
|
||||
} else {
|
||||
subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}})
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Non-resource URLs are unique because they only combine with verbs.
|
||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||
for _, verb := range rule.Verbs {
|
||||
subrules = append(subrules, rbac.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}})
|
||||
}
|
||||
}
|
||||
|
||||
return subrules
|
||||
}
|
||||
|
||||
func has(set []string, ele string) bool {
|
||||
for _, s := range set {
|
||||
if s == ele {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func hasAll(set, contains []string) bool {
|
||||
owning := make(map[string]struct{}, len(set))
|
||||
for _, ele := range set {
|
||||
owning[ele] = struct{}{}
|
||||
}
|
||||
for _, ele := range contains {
|
||||
if _, ok := owning[ele]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func nonResourceURLsCoversAll(set, covers []string) bool {
|
||||
for _, path := range covers {
|
||||
covered := false
|
||||
for _, owner := range set {
|
||||
if nonResourceURLCovers(owner, path) {
|
||||
covered = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !covered {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func nonResourceURLCovers(ownerPath, subPath string) bool {
|
||||
if ownerPath == subPath {
|
||||
return true
|
||||
}
|
||||
return strings.HasSuffix(ownerPath, "*") && strings.HasPrefix(subPath, strings.TrimRight(ownerPath, "*"))
|
||||
}
|
||||
|
||||
// ruleCovers determines whether the ownerRule (which may have multiple verbs, resources, and resourceNames) covers
|
||||
// the subrule (which may only contain at most one verb, resource, and resourceName)
|
||||
func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool {
|
||||
verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs)
|
||||
groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups)
|
||||
resourceMatches := has(ownerRule.Resources, rbac.ResourceAll) || hasAll(ownerRule.Resources, subRule.Resources)
|
||||
nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs)
|
||||
|
||||
resourceNameMatches := false
|
||||
|
||||
if len(subRule.ResourceNames) == 0 {
|
||||
resourceNameMatches = (len(ownerRule.ResourceNames) == 0)
|
||||
} else {
|
||||
resourceNameMatches = (len(ownerRule.ResourceNames) == 0) || hasAll(ownerRule.ResourceNames, subRule.ResourceNames)
|
||||
}
|
||||
|
||||
return verbMatches && groupMatches && resourceMatches && resourceNameMatches && nonResourceURLMatches
|
||||
}
|
427
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go
generated
vendored
Normal file
427
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/policy_comparator_test.go
generated
vendored
Normal file
|
@ -0,0 +1,427 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
type escalationTest struct {
|
||||
ownerRules []rbac.PolicyRule
|
||||
servantRules []rbac.PolicyRule
|
||||
|
||||
expectedCovered bool
|
||||
expectedUncoveredRules []rbac.PolicyRule
|
||||
}
|
||||
|
||||
func TestCoversExactMatch(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
|
||||
}
|
||||
|
||||
func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
|
||||
}
|
||||
|
||||
func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||
{APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
|
||||
}
|
||||
|
||||
func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"pods"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments", "pods"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"pods"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversAPIGroupStarCoveringMultiple(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"dummy-group"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversAPIGroupStarCoveringStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversVerbStarCoveringMultiple(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"watch", "list"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get", "list", "watch", "create", "update", "delete", "exec"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversVerbStarCoveringStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversResourceStarCoveringMultiple(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"resourcegroup:deployments"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"roles", "resourcegroup:deployments"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversResourceStarCoveringStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversResourceNameEmptyCoveringMultiple(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLs(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLsStar(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"*"}, Verbs: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis", "/apis/v1", "/"}, Verbs: []string{"*"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis", "/apis/v1"}, Verbs: []string{"get"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}},
|
||||
},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLsStarAfterPrefix(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{NonResourceURLs: []string{"/apis/v1/foo", "/apis/v1"}, Verbs: []string{"get"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLsWithOtherFields(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||
},
|
||||
|
||||
expectedCovered: true,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func TestCoversNonResourceURLsWithOtherFieldsFailure(t *testing.T) {
|
||||
escalationTest{
|
||||
ownerRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||
},
|
||||
servantRules: []rbac.PolicyRule{
|
||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||
},
|
||||
|
||||
expectedCovered: false,
|
||||
expectedUncoveredRules: []rbac.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}},
|
||||
}.test(t)
|
||||
}
|
||||
|
||||
func (test escalationTest) test(t *testing.T) {
|
||||
actualCovered, actualUncoveredRules := Covers(test.ownerRules, test.servantRules)
|
||||
|
||||
if actualCovered != test.expectedCovered {
|
||||
t.Errorf("expected %v, but got %v", test.expectedCovered, actualCovered)
|
||||
}
|
||||
|
||||
if !rulesMatch(test.expectedUncoveredRules, actualUncoveredRules) {
|
||||
t.Errorf("expected %v, but got %v", test.expectedUncoveredRules, actualUncoveredRules)
|
||||
}
|
||||
}
|
||||
|
||||
func rulesMatch(expectedRules, actualRules []rbac.PolicyRule) bool {
|
||||
if len(expectedRules) != len(actualRules) {
|
||||
return false
|
||||
}
|
||||
|
||||
for _, expectedRule := range expectedRules {
|
||||
found := false
|
||||
for _, actualRule := range actualRules {
|
||||
if reflect.DeepEqual(expectedRule, actualRule) {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func TestNonResourceURLCovers(t *testing.T) {
|
||||
tests := []struct {
|
||||
owner string
|
||||
requested string
|
||||
want bool
|
||||
}{
|
||||
{"*", "/api", true},
|
||||
{"/api", "/api", true},
|
||||
{"/apis", "/api", false},
|
||||
{"/api/v1", "/api", false},
|
||||
{"/api/v1", "/api/v1", true},
|
||||
{"/api/*", "/api/v1", true},
|
||||
{"/api/*", "/api", false},
|
||||
{"/api/*/*", "/api/v1", false},
|
||||
{"/*/v1/*", "/api/v1", false},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
got := nonResourceURLCovers(tc.owner, tc.requested)
|
||||
if got != tc.want {
|
||||
t.Errorf("nonResourceURLCovers(%q, %q): want=(%t), got=(%t)", tc.owner, tc.requested, tc.want, got)
|
||||
}
|
||||
}
|
||||
}
|
254
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go
generated
vendored
Normal file
254
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule.go
generated
vendored
Normal file
|
@ -0,0 +1,254 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
genericapirequest "k8s.io/apiserver/pkg/request"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||
)
|
||||
|
||||
type AuthorizationRuleResolver interface {
|
||||
// GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace
|
||||
// of the role binding, the empty string if a cluster role binding.
|
||||
GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error)
|
||||
|
||||
// RulesFor returns the list of rules that apply to a given user in a given namespace and error. If an error is returned, the slice of
|
||||
// PolicyRules may not be complete, but it contains all retrievable rules. This is done because policy rules are purely additive and policy determinations
|
||||
// can be made on the basis of those rules that are found.
|
||||
RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error)
|
||||
}
|
||||
|
||||
// ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role.
|
||||
func ConfirmNoEscalation(ctx genericapirequest.Context, ruleResolver AuthorizationRuleResolver, rules []rbac.PolicyRule) error {
|
||||
ruleResolutionErrors := []error{}
|
||||
|
||||
user, ok := genericapirequest.UserFrom(ctx)
|
||||
if !ok {
|
||||
return fmt.Errorf("no user on context")
|
||||
}
|
||||
namespace, _ := genericapirequest.NamespaceFrom(ctx)
|
||||
|
||||
ownerRules, err := ruleResolver.RulesFor(user, namespace)
|
||||
if err != nil {
|
||||
// As per AuthorizationRuleResolver contract, this may return a non fatal error with an incomplete list of policies. Log the error and continue.
|
||||
glog.V(1).Infof("non-fatal error getting local rules for %v: %v", user, err)
|
||||
ruleResolutionErrors = append(ruleResolutionErrors, err)
|
||||
}
|
||||
|
||||
ownerRightsCover, missingRights := Covers(ownerRules, rules)
|
||||
if !ownerRightsCover {
|
||||
user, _ := genericapirequest.UserFrom(ctx)
|
||||
return apierrors.NewUnauthorized(fmt.Sprintf("attempt to grant extra privileges: %v user=%v ownerrules=%v ruleResolutionErrors=%v", missingRights, user, ownerRules, ruleResolutionErrors))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type DefaultRuleResolver struct {
|
||||
roleGetter RoleGetter
|
||||
roleBindingLister RoleBindingLister
|
||||
clusterRoleGetter ClusterRoleGetter
|
||||
clusterRoleBindingLister ClusterRoleBindingLister
|
||||
}
|
||||
|
||||
func NewDefaultRuleResolver(roleGetter RoleGetter, roleBindingLister RoleBindingLister, clusterRoleGetter ClusterRoleGetter, clusterRoleBindingLister ClusterRoleBindingLister) *DefaultRuleResolver {
|
||||
return &DefaultRuleResolver{roleGetter, roleBindingLister, clusterRoleGetter, clusterRoleBindingLister}
|
||||
}
|
||||
|
||||
type RoleGetter interface {
|
||||
GetRole(namespace, name string) (*rbac.Role, error)
|
||||
}
|
||||
|
||||
type RoleBindingLister interface {
|
||||
ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error)
|
||||
}
|
||||
|
||||
type ClusterRoleGetter interface {
|
||||
GetClusterRole(name string) (*rbac.ClusterRole, error)
|
||||
}
|
||||
|
||||
type ClusterRoleBindingLister interface {
|
||||
ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error)
|
||||
}
|
||||
|
||||
func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) {
|
||||
policyRules := []rbac.PolicyRule{}
|
||||
errorlist := []error{}
|
||||
|
||||
if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil {
|
||||
errorlist = append(errorlist, err)
|
||||
|
||||
} else {
|
||||
for _, clusterRoleBinding := range clusterRoleBindings {
|
||||
if !appliesTo(user, clusterRoleBinding.Subjects, "") {
|
||||
continue
|
||||
}
|
||||
rules, err := r.GetRoleReferenceRules(clusterRoleBinding.RoleRef, "")
|
||||
if err != nil {
|
||||
errorlist = append(errorlist, err)
|
||||
continue
|
||||
}
|
||||
policyRules = append(policyRules, rules...)
|
||||
}
|
||||
}
|
||||
|
||||
if len(namespace) > 0 {
|
||||
if roleBindings, err := r.roleBindingLister.ListRoleBindings(namespace); err != nil {
|
||||
errorlist = append(errorlist, err)
|
||||
|
||||
} else {
|
||||
for _, roleBinding := range roleBindings {
|
||||
if !appliesTo(user, roleBinding.Subjects, namespace) {
|
||||
continue
|
||||
}
|
||||
rules, err := r.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
||||
if err != nil {
|
||||
errorlist = append(errorlist, err)
|
||||
continue
|
||||
}
|
||||
policyRules = append(policyRules, rules...)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return policyRules, utilerrors.NewAggregate(errorlist)
|
||||
}
|
||||
|
||||
// GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding.
|
||||
func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) {
|
||||
switch kind := rbac.RoleRefGroupKind(roleRef); kind {
|
||||
case rbac.Kind("Role"):
|
||||
role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return role.Rules, nil
|
||||
|
||||
case rbac.Kind("ClusterRole"):
|
||||
clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return clusterRole.Rules, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported role reference kind: %q", kind)
|
||||
}
|
||||
}
|
||||
func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) bool {
|
||||
for _, bindingSubject := range bindingSubjects {
|
||||
if appliesToUser(user, bindingSubject, namespace) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool {
|
||||
switch subject.Kind {
|
||||
case rbac.UserKind:
|
||||
return user.GetName() == subject.Name
|
||||
|
||||
case rbac.GroupKind:
|
||||
return has(user.GetGroups(), subject.Name)
|
||||
|
||||
case rbac.ServiceAccountKind:
|
||||
// default the namespace to namespace we're working in if its available. This allows rolebindings that reference
|
||||
// SAs in th local namespace to avoid having to qualify them.
|
||||
saNamespace := namespace
|
||||
if len(subject.Namespace) > 0 {
|
||||
saNamespace = subject.Namespace
|
||||
}
|
||||
if len(saNamespace) == 0 {
|
||||
return false
|
||||
}
|
||||
return serviceaccount.MakeUsername(saNamespace, subject.Name) == user.GetName()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// NewTestRuleResolver returns a rule resolver from lists of role objects.
|
||||
func NewTestRuleResolver(roles []*rbac.Role, roleBindings []*rbac.RoleBinding, clusterRoles []*rbac.ClusterRole, clusterRoleBindings []*rbac.ClusterRoleBinding) (AuthorizationRuleResolver, *StaticRoles) {
|
||||
r := StaticRoles{
|
||||
roles: roles,
|
||||
roleBindings: roleBindings,
|
||||
clusterRoles: clusterRoles,
|
||||
clusterRoleBindings: clusterRoleBindings,
|
||||
}
|
||||
return newMockRuleResolver(&r), &r
|
||||
}
|
||||
|
||||
func newMockRuleResolver(r *StaticRoles) AuthorizationRuleResolver {
|
||||
return NewDefaultRuleResolver(r, r, r, r)
|
||||
}
|
||||
|
||||
// StaticRoles is a rule resolver that resolves from lists of role objects.
|
||||
type StaticRoles struct {
|
||||
roles []*rbac.Role
|
||||
roleBindings []*rbac.RoleBinding
|
||||
clusterRoles []*rbac.ClusterRole
|
||||
clusterRoleBindings []*rbac.ClusterRoleBinding
|
||||
}
|
||||
|
||||
func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) {
|
||||
if len(namespace) == 0 {
|
||||
return nil, errors.New("must provide namespace when getting role")
|
||||
}
|
||||
for _, role := range r.roles {
|
||||
if role.Namespace == namespace && role.Name == name {
|
||||
return role, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("role not found")
|
||||
}
|
||||
|
||||
func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
||||
for _, clusterRole := range r.clusterRoles {
|
||||
if clusterRole.Name == name {
|
||||
return clusterRole, nil
|
||||
}
|
||||
}
|
||||
return nil, errors.New("role not found")
|
||||
}
|
||||
|
||||
func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
||||
if len(namespace) == 0 {
|
||||
return nil, errors.New("must provide namespace when listing role bindings")
|
||||
}
|
||||
|
||||
roleBindingList := []*rbac.RoleBinding{}
|
||||
for _, roleBinding := range r.roleBindings {
|
||||
if roleBinding.Namespace != namespace {
|
||||
continue
|
||||
}
|
||||
// TODO(ericchiang): need to implement label selectors?
|
||||
roleBindingList = append(roleBindingList, roleBinding)
|
||||
}
|
||||
return roleBindingList, nil
|
||||
}
|
||||
|
||||
func (r *StaticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
||||
return r.clusterRoleBindings, nil
|
||||
}
|
266
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go
generated
vendored
Normal file
266
vendor/k8s.io/kubernetes/pkg/registry/rbac/validation/rule_test.go
generated
vendored
Normal file
|
@ -0,0 +1,266 @@
|
|||
/*
|
||||
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 validation
|
||||
|
||||
import (
|
||||
"hash/fnv"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/diff"
|
||||
"k8s.io/apiserver/pkg/authentication/user"
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||
)
|
||||
|
||||
// compute a hash of a policy rule so we can sort in a deterministic order
|
||||
func hashOf(p rbac.PolicyRule) string {
|
||||
hash := fnv.New32()
|
||||
writeStrings := func(slis ...[]string) {
|
||||
for _, sli := range slis {
|
||||
for _, s := range sli {
|
||||
io.WriteString(hash, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
writeStrings(p.Verbs, p.APIGroups, p.Resources, p.ResourceNames, p.NonResourceURLs)
|
||||
return string(hash.Sum(nil))
|
||||
}
|
||||
|
||||
// byHash sorts a set of policy rules by a hash of its fields
|
||||
type byHash []rbac.PolicyRule
|
||||
|
||||
func (b byHash) Len() int { return len(b) }
|
||||
func (b byHash) Less(i, j int) bool { return hashOf(b[i]) < hashOf(b[j]) }
|
||||
func (b byHash) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||
|
||||
func TestDefaultRuleResolver(t *testing.T) {
|
||||
ruleReadPods := rbac.PolicyRule{
|
||||
Verbs: []string{"GET", "WATCH"},
|
||||
APIGroups: []string{"v1"},
|
||||
Resources: []string{"pods"},
|
||||
}
|
||||
ruleReadServices := rbac.PolicyRule{
|
||||
Verbs: []string{"GET", "WATCH"},
|
||||
APIGroups: []string{"v1"},
|
||||
Resources: []string{"services"},
|
||||
}
|
||||
ruleWriteNodes := rbac.PolicyRule{
|
||||
Verbs: []string{"PUT", "CREATE", "UPDATE"},
|
||||
APIGroups: []string{"v1"},
|
||||
Resources: []string{"nodes"},
|
||||
}
|
||||
ruleAdmin := rbac.PolicyRule{
|
||||
Verbs: []string{"*"},
|
||||
APIGroups: []string{"*"},
|
||||
Resources: []string{"*"},
|
||||
}
|
||||
|
||||
staticRoles1 := StaticRoles{
|
||||
roles: []*rbac.Role{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Namespace: "namespace1", Name: "readthings"},
|
||||
Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
||||
},
|
||||
},
|
||||
clusterRoles: []*rbac.ClusterRole{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "cluster-admin"},
|
||||
Rules: []rbac.PolicyRule{ruleAdmin},
|
||||
},
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Name: "write-nodes"},
|
||||
Rules: []rbac.PolicyRule{ruleWriteNodes},
|
||||
},
|
||||
},
|
||||
roleBindings: []*rbac.RoleBinding{
|
||||
{
|
||||
ObjectMeta: api.ObjectMeta{Namespace: "namespace1"},
|
||||
Subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "foobar"},
|
||||
{Kind: rbac.GroupKind, Name: "group1"},
|
||||
},
|
||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"},
|
||||
},
|
||||
},
|
||||
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
||||
{
|
||||
Subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "admin"},
|
||||
{Kind: rbac.GroupKind, Name: "admin"},
|
||||
},
|
||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "cluster-admin"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
StaticRoles
|
||||
|
||||
// For a given context, what are the rules that apply?
|
||||
user user.Info
|
||||
namespace string
|
||||
effectiveRules []rbac.PolicyRule
|
||||
}{
|
||||
{
|
||||
StaticRoles: staticRoles1,
|
||||
user: &user.DefaultInfo{Name: "foobar"},
|
||||
namespace: "namespace1",
|
||||
effectiveRules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
||||
},
|
||||
{
|
||||
StaticRoles: staticRoles1,
|
||||
user: &user.DefaultInfo{Name: "foobar"},
|
||||
namespace: "namespace2",
|
||||
effectiveRules: []rbac.PolicyRule{},
|
||||
},
|
||||
{
|
||||
StaticRoles: staticRoles1,
|
||||
// Same as above but without a namespace. Only cluster rules should apply.
|
||||
user: &user.DefaultInfo{Name: "foobar", Groups: []string{"admin"}},
|
||||
effectiveRules: []rbac.PolicyRule{ruleAdmin},
|
||||
},
|
||||
{
|
||||
StaticRoles: staticRoles1,
|
||||
user: &user.DefaultInfo{},
|
||||
effectiveRules: []rbac.PolicyRule{},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tc := range tests {
|
||||
ruleResolver := newMockRuleResolver(&tc.StaticRoles)
|
||||
rules, err := ruleResolver.RulesFor(tc.user, tc.namespace)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: GetEffectivePolicyRules(context)=%v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Sort for deep equals
|
||||
sort.Sort(byHash(rules))
|
||||
sort.Sort(byHash(tc.effectiveRules))
|
||||
|
||||
if !reflect.DeepEqual(rules, tc.effectiveRules) {
|
||||
ruleDiff := diff.ObjectDiff(rules, tc.effectiveRules)
|
||||
t.Errorf("case %d: %s", i, ruleDiff)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAppliesTo(t *testing.T) {
|
||||
tests := []struct {
|
||||
subjects []rbac.Subject
|
||||
user user.Info
|
||||
namespace string
|
||||
appliesTo bool
|
||||
testCase string
|
||||
}{
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "foobar"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "foobar"},
|
||||
appliesTo: true,
|
||||
testCase: "single subject that matches username",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
||||
{Kind: rbac.UserKind, Name: "foobar"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "foobar"},
|
||||
appliesTo: true,
|
||||
testCase: "multiple subjects, one that matches username",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
||||
{Kind: rbac.UserKind, Name: "foobar"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "zimzam"},
|
||||
appliesTo: false,
|
||||
testCase: "multiple subjects, none that match username",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
||||
appliesTo: true,
|
||||
testCase: "multiple subjects, one that match group",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
||||
namespace: "namespace1",
|
||||
appliesTo: true,
|
||||
testCase: "multiple subjects, one that match group, should ignore namespace",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
||||
{Kind: rbac.ServiceAccountKind, Namespace: "kube-system", Name: "default"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "system:serviceaccount:kube-system:default"},
|
||||
namespace: "default",
|
||||
appliesTo: true,
|
||||
testCase: "multiple subjects with a service account that matches",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.UserKind, Name: "*"},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "foobar"},
|
||||
namespace: "default",
|
||||
appliesTo: false,
|
||||
testCase: "* user subject name doesn't match all users",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.GroupKind, Name: user.AllAuthenticated},
|
||||
{Kind: rbac.GroupKind, Name: user.AllUnauthenticated},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "foobar", Groups: []string{user.AllAuthenticated}},
|
||||
namespace: "default",
|
||||
appliesTo: true,
|
||||
testCase: "binding to all authenticated and unauthenticated subjects matches authenticated user",
|
||||
},
|
||||
{
|
||||
subjects: []rbac.Subject{
|
||||
{Kind: rbac.GroupKind, Name: user.AllAuthenticated},
|
||||
{Kind: rbac.GroupKind, Name: user.AllUnauthenticated},
|
||||
},
|
||||
user: &user.DefaultInfo{Name: "system:anonymous", Groups: []string{user.AllUnauthenticated}},
|
||||
namespace: "default",
|
||||
appliesTo: true,
|
||||
testCase: "binding to all authenticated and unauthenticated subjects matches anonymous user",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
got := appliesTo(tc.user, tc.subjects, tc.namespace)
|
||||
if got != tc.appliesTo {
|
||||
t.Errorf("case %q want appliesTo=%t, got appliesTo=%t", tc.testCase, tc.appliesTo, got)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue