mirror of https://github.com/k3s-io/k3s
switch rbac to external
parent
813021c1b1
commit
092714ea0f
|
@ -21,40 +21,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
)
|
)
|
||||||
|
|
||||||
func RoleRefGroupKind(roleRef RoleRef) schema.GroupKind {
|
|
||||||
return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind}
|
|
||||||
}
|
|
||||||
|
|
||||||
func VerbMatches(rule *PolicyRule, requestedVerb string) bool {
|
|
||||||
for _, ruleVerb := range rule.Verbs {
|
|
||||||
if ruleVerb == VerbAll {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if ruleVerb == requestedVerb {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func APIGroupMatches(rule *PolicyRule, requestedGroup string) bool {
|
|
||||||
for _, ruleGroup := range rule.APIGroups {
|
|
||||||
if ruleGroup == APIGroupAll {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if ruleGroup == requestedGroup {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubresource string) bool {
|
func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubresource string) bool {
|
||||||
for _, ruleResource := range rule.Resources {
|
for _, ruleResource := range rule.Resources {
|
||||||
// if everything is allowed, we match
|
// if everything is allowed, we match
|
||||||
|
@ -83,36 +52,6 @@ func ResourceMatches(rule *PolicyRule, combinedRequestedResource, requestedSubre
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func ResourceNameMatches(rule *PolicyRule, requestedName string) bool {
|
|
||||||
if len(rule.ResourceNames) == 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, ruleName := range rule.ResourceNames {
|
|
||||||
if ruleName == requestedName {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func NonResourceURLMatches(rule *PolicyRule, requestedURL string) bool {
|
|
||||||
for _, ruleURL := range rule.NonResourceURLs {
|
|
||||||
if ruleURL == NonResourceAll {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if ruleURL == requestedURL {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes.
|
// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes.
|
||||||
func SubjectsStrings(subjects []Subject) ([]string, []string, []string, []string) {
|
func SubjectsStrings(subjects []Subject) ([]string, []string, []string, []string) {
|
||||||
users := []string{}
|
users := []string{}
|
||||||
|
|
|
@ -10,9 +10,11 @@ go_library(
|
||||||
srcs = [
|
srcs = [
|
||||||
"defaults.go",
|
"defaults.go",
|
||||||
"doc.go",
|
"doc.go",
|
||||||
|
"evaluation_helpers.go",
|
||||||
"helpers.go",
|
"helpers.go",
|
||||||
"register.go",
|
"register.go",
|
||||||
"zz_generated.conversion.go",
|
"zz_generated.conversion.go",
|
||||||
|
"zz_generated.deepcopy.go",
|
||||||
"zz_generated.defaults.go",
|
"zz_generated.defaults.go",
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/apis/rbac/v1",
|
importpath = "k8s.io/kubernetes/pkg/apis/rbac/v1",
|
||||||
|
|
|
@ -18,6 +18,7 @@ limitations under the License.
|
||||||
// +k8s:conversion-gen-external-types=k8s.io/api/rbac/v1
|
// +k8s:conversion-gen-external-types=k8s.io/api/rbac/v1
|
||||||
// +k8s:defaulter-gen=TypeMeta
|
// +k8s:defaulter-gen=TypeMeta
|
||||||
// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/rbac/v1
|
// +k8s:defaulter-gen-input=../../../../vendor/k8s.io/api/rbac/v1
|
||||||
|
// +k8s:deepcopy-gen=package
|
||||||
|
|
||||||
// +groupName=rbac.authorization.k8s.io
|
// +groupName=rbac.authorization.k8s.io
|
||||||
package v1 // import "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
package v1 // import "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RoleRefGroupKind(roleRef rbacv1.RoleRef) schema.GroupKind {
|
||||||
|
return schema.GroupKind{Group: roleRef.APIGroup, Kind: roleRef.Kind}
|
||||||
|
}
|
||||||
|
|
||||||
|
func VerbMatches(rule *rbacv1.PolicyRule, requestedVerb string) bool {
|
||||||
|
for _, ruleVerb := range rule.Verbs {
|
||||||
|
if ruleVerb == rbacv1.VerbAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ruleVerb == requestedVerb {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func APIGroupMatches(rule *rbacv1.PolicyRule, requestedGroup string) bool {
|
||||||
|
for _, ruleGroup := range rule.APIGroups {
|
||||||
|
if ruleGroup == rbacv1.APIGroupAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ruleGroup == requestedGroup {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResourceMatches(rule *rbacv1.PolicyRule, combinedRequestedResource, requestedSubresource string) bool {
|
||||||
|
for _, ruleResource := range rule.Resources {
|
||||||
|
// if everything is allowed, we match
|
||||||
|
if ruleResource == rbacv1.ResourceAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// if we have an exact match, we match
|
||||||
|
if ruleResource == combinedRequestedResource {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// We can also match a */subresource.
|
||||||
|
// if there isn't a subresource, then continue
|
||||||
|
if len(requestedSubresource) == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
// if the rule isn't in the format */subresource, then we don't match, continue
|
||||||
|
if len(ruleResource) == len(requestedSubresource)+2 &&
|
||||||
|
strings.HasPrefix(ruleResource, "*/") &&
|
||||||
|
strings.HasSuffix(ruleResource, requestedSubresource) {
|
||||||
|
return true
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResourceNameMatches(rule *rbacv1.PolicyRule, requestedName string) bool {
|
||||||
|
if len(rule.ResourceNames) == 0 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, ruleName := range rule.ResourceNames {
|
||||||
|
if ruleName == requestedName {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func NonResourceURLMatches(rule *rbacv1.PolicyRule, requestedURL string) bool {
|
||||||
|
for _, ruleURL := range rule.NonResourceURLs {
|
||||||
|
if ruleURL == rbacv1.NonResourceAll {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if ruleURL == requestedURL {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if strings.HasSuffix(ruleURL, "*") && strings.HasPrefix(requestedURL, strings.TrimRight(ruleURL, "*")) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// subjectsStrings returns users, groups, serviceaccounts, unknown for display purposes.
|
||||||
|
func SubjectsStrings(subjects []rbacv1.Subject) ([]string, []string, []string, []string) {
|
||||||
|
users := []string{}
|
||||||
|
groups := []string{}
|
||||||
|
sas := []string{}
|
||||||
|
others := []string{}
|
||||||
|
|
||||||
|
for _, subject := range subjects {
|
||||||
|
switch subject.Kind {
|
||||||
|
case rbacv1.ServiceAccountKind:
|
||||||
|
sas = append(sas, fmt.Sprintf("%s/%s", subject.Namespace, subject.Name))
|
||||||
|
|
||||||
|
case rbacv1.UserKind:
|
||||||
|
users = append(users, subject.Name)
|
||||||
|
|
||||||
|
case rbacv1.GroupKind:
|
||||||
|
groups = append(groups, subject.Name)
|
||||||
|
|
||||||
|
default:
|
||||||
|
others = append(others, fmt.Sprintf("%s/%s/%s", subject.Kind, subject.Namespace, subject.Name))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return users, groups, sas, others
|
||||||
|
}
|
||||||
|
|
||||||
|
func String(r rbacv1.PolicyRule) string {
|
||||||
|
return "PolicyRule" + CompactString(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CompactString exposes a compact string representation for use in escalation error messages
|
||||||
|
func CompactString(r rbacv1.PolicyRule) string {
|
||||||
|
formatStringParts := []string{}
|
||||||
|
formatArgs := []interface{}{}
|
||||||
|
if len(r.APIGroups) > 0 {
|
||||||
|
formatStringParts = append(formatStringParts, "APIGroups:%q")
|
||||||
|
formatArgs = append(formatArgs, r.APIGroups)
|
||||||
|
}
|
||||||
|
if len(r.Resources) > 0 {
|
||||||
|
formatStringParts = append(formatStringParts, "Resources:%q")
|
||||||
|
formatArgs = append(formatArgs, r.Resources)
|
||||||
|
}
|
||||||
|
if len(r.NonResourceURLs) > 0 {
|
||||||
|
formatStringParts = append(formatStringParts, "NonResourceURLs:%q")
|
||||||
|
formatArgs = append(formatArgs, r.NonResourceURLs)
|
||||||
|
}
|
||||||
|
if len(r.ResourceNames) > 0 {
|
||||||
|
formatStringParts = append(formatStringParts, "ResourceNames:%q")
|
||||||
|
formatArgs = append(formatArgs, r.ResourceNames)
|
||||||
|
}
|
||||||
|
if len(r.Verbs) > 0 {
|
||||||
|
formatStringParts = append(formatStringParts, "Verbs:%q")
|
||||||
|
formatArgs = append(formatArgs, r.Verbs)
|
||||||
|
}
|
||||||
|
formatString := "{" + strings.Join(formatStringParts, ", ") + "}"
|
||||||
|
return fmt.Sprintf(formatString, formatArgs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SortableRuleSlice []rbacv1.PolicyRule
|
||||||
|
|
||||||
|
func (s SortableRuleSlice) Len() int { return len(s) }
|
||||||
|
func (s SortableRuleSlice) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||||
|
func (s SortableRuleSlice) Less(i, j int) bool {
|
||||||
|
return strings.Compare(s[i].String(), s[j].String()) < 0
|
||||||
|
}
|
|
@ -21,9 +21,13 @@ import (
|
||||||
|
|
||||||
rbacv1 "k8s.io/api/rbac/v1"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
|
||||||
|
"sort"
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
|
||||||
// PolicyRuleBuilder let's us attach methods. A no-no for API types.
|
// PolicyRuleBuilder let's us attach methods. A no-no for API types.
|
||||||
// We use it to construct rules in code. It's more compact than trying to write them
|
// We use it to construct rules in code. It's more compact than trying to write them
|
||||||
// out in a literal and allows us to perform some basic checking during construction
|
// out in a literal and allows us to perform some basic checking during construction
|
||||||
|
@ -87,9 +91,16 @@ func (r *PolicyRuleBuilder) Rule() (rbacv1.PolicyRule, error) {
|
||||||
return rbacv1.PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule)
|
return rbacv1.PolicyRule{}, fmt.Errorf("a rule must have either nonResourceURLs or resources: %#v", r.PolicyRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sort.Strings(r.PolicyRule.Resources)
|
||||||
|
sort.Strings(r.PolicyRule.ResourceNames)
|
||||||
|
sort.Strings(r.PolicyRule.APIGroups)
|
||||||
|
sort.Strings(r.PolicyRule.NonResourceURLs)
|
||||||
|
sort.Strings(r.PolicyRule.Verbs)
|
||||||
return r.PolicyRule, nil
|
return r.PolicyRule, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
|
||||||
// ClusterRoleBindingBuilder let's us attach methods. A no-no for API types.
|
// ClusterRoleBindingBuilder let's us attach methods. A no-no for API types.
|
||||||
// We use it to construct bindings in code. It's more compact than trying to write them
|
// We use it to construct bindings in code. It's more compact than trying to write them
|
||||||
// out in a literal.
|
// out in a literal.
|
||||||
|
@ -112,14 +123,14 @@ func NewClusterBinding(clusterRoleName string) *ClusterRoleBindingBuilder {
|
||||||
|
|
||||||
func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder {
|
func (r *ClusterRoleBindingBuilder) Groups(groups ...string) *ClusterRoleBindingBuilder {
|
||||||
for _, group := range groups {
|
for _, group := range groups {
|
||||||
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, Name: group})
|
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.GroupKind, Name: group})
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder {
|
func (r *ClusterRoleBindingBuilder) Users(users ...string) *ClusterRoleBindingBuilder {
|
||||||
for _, user := range users {
|
for _, user := range users {
|
||||||
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, Name: user})
|
r.ClusterRoleBinding.Subjects = append(r.ClusterRoleBinding.Subjects, rbacv1.Subject{APIGroup: rbacv1.GroupName, Kind: rbacv1.UserKind, Name: user})
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -146,3 +157,91 @@ func (r *ClusterRoleBindingBuilder) Binding() (rbacv1.ClusterRoleBinding, error)
|
||||||
|
|
||||||
return r.ClusterRoleBinding, nil
|
return r.ClusterRoleBinding, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// +k8s:deepcopy-gen=false
|
||||||
|
|
||||||
|
// RoleBindingBuilder let's us attach methods. It is similar to
|
||||||
|
// ClusterRoleBindingBuilder above.
|
||||||
|
type RoleBindingBuilder struct {
|
||||||
|
RoleBinding rbacv1.RoleBinding
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewRoleBinding creates a RoleBinding builder that can be used
|
||||||
|
// to define the subjects of a role binding. At least one of
|
||||||
|
// the `Groups`, `Users` or `SAs` method must be called before
|
||||||
|
// calling the `Binding*` methods.
|
||||||
|
func NewRoleBinding(roleName, namespace string) *RoleBindingBuilder {
|
||||||
|
return &RoleBindingBuilder{
|
||||||
|
RoleBinding: rbacv1.RoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: roleName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
RoleRef: rbacv1.RoleRef{
|
||||||
|
APIGroup: GroupName,
|
||||||
|
Kind: "Role",
|
||||||
|
Name: roleName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewRoleBindingForClusterRole(roleName, namespace string) *RoleBindingBuilder {
|
||||||
|
return &RoleBindingBuilder{
|
||||||
|
RoleBinding: rbacv1.RoleBinding{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: roleName,
|
||||||
|
Namespace: namespace,
|
||||||
|
},
|
||||||
|
RoleRef: rbacv1.RoleRef{
|
||||||
|
APIGroup: GroupName,
|
||||||
|
Kind: "ClusterRole",
|
||||||
|
Name: roleName,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Groups adds the specified groups as the subjects of the RoleBinding.
|
||||||
|
func (r *RoleBindingBuilder) Groups(groups ...string) *RoleBindingBuilder {
|
||||||
|
for _, group := range groups {
|
||||||
|
r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.GroupKind, APIGroup: GroupName, Name: group})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Users adds the specified users as the subjects of the RoleBinding.
|
||||||
|
func (r *RoleBindingBuilder) Users(users ...string) *RoleBindingBuilder {
|
||||||
|
for _, user := range users {
|
||||||
|
r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: GroupName, Name: user})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// SAs adds the specified service accounts as the subjects of the
|
||||||
|
// RoleBinding.
|
||||||
|
func (r *RoleBindingBuilder) SAs(namespace string, serviceAccountNames ...string) *RoleBindingBuilder {
|
||||||
|
for _, saName := range serviceAccountNames {
|
||||||
|
r.RoleBinding.Subjects = append(r.RoleBinding.Subjects, rbacv1.Subject{Kind: rbacv1.ServiceAccountKind, Namespace: namespace, Name: saName})
|
||||||
|
}
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// BindingOrDie calls the binding method and panics if there is an error.
|
||||||
|
func (r *RoleBindingBuilder) BindingOrDie() rbacv1.RoleBinding {
|
||||||
|
ret, err := r.Binding()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return ret
|
||||||
|
}
|
||||||
|
|
||||||
|
// Binding builds and returns the RoleBinding API object from the builder
|
||||||
|
// object.
|
||||||
|
func (r *RoleBindingBuilder) Binding() (rbacv1.RoleBinding, error) {
|
||||||
|
if len(r.RoleBinding.Subjects) == 0 {
|
||||||
|
return rbacv1.RoleBinding{}, fmt.Errorf("subjects are required: %#v", r.RoleBinding)
|
||||||
|
}
|
||||||
|
|
||||||
|
return r.RoleBinding, nil
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// +build !ignore_autogenerated
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Code generated by conversion-gen. DO NOT EDIT.
|
||||||
|
|
||||||
|
package v1
|
|
@ -108,10 +108,10 @@ func (config AuthorizationConfig) New() (authorizer.Authorizer, authorizer.RuleR
|
||||||
ruleResolvers = append(ruleResolvers, webhookAuthorizer)
|
ruleResolvers = append(ruleResolvers, webhookAuthorizer)
|
||||||
case modes.ModeRBAC:
|
case modes.ModeRBAC:
|
||||||
rbacAuthorizer := rbac.New(
|
rbacAuthorizer := rbac.New(
|
||||||
&rbac.RoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().Roles().Lister()},
|
&rbac.RoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().Roles().Lister()},
|
||||||
&rbac.RoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().RoleBindings().Lister()},
|
&rbac.RoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().RoleBindings().Lister()},
|
||||||
&rbac.ClusterRoleGetter{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoles().Lister()},
|
&rbac.ClusterRoleGetter{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoles().Lister()},
|
||||||
&rbac.ClusterRoleBindingLister{Lister: config.InformerFactory.Rbac().InternalVersion().ClusterRoleBindings().Lister()},
|
&rbac.ClusterRoleBindingLister{Lister: config.VersionedInformerFactory.Rbac().V1().ClusterRoleBindings().Lister()},
|
||||||
)
|
)
|
||||||
authorizers = append(authorizers, rbacAuthorizer)
|
authorizers = append(authorizers, rbacAuthorizer)
|
||||||
ruleResolvers = append(ruleResolvers, rbacAuthorizer)
|
ruleResolvers = append(ruleResolvers, rbacAuthorizer)
|
||||||
|
|
|
@ -16,12 +16,8 @@ go_library(
|
||||||
"//build/visible_to:pkg_kubectl_cmd_auth_CONSUMERS",
|
"//build/visible_to:pkg_kubectl_cmd_auth_CONSUMERS",
|
||||||
],
|
],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
|
||||||
"//pkg/apis/authorization:go_default_library",
|
"//pkg/apis/authorization:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library",
|
"//pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
|
||||||
"//pkg/kubectl/cmd/templates:go_default_library",
|
"//pkg/kubectl/cmd/templates:go_default_library",
|
||||||
"//pkg/kubectl/cmd/util:go_default_library",
|
"//pkg/kubectl/cmd/util:go_default_library",
|
||||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||||
|
@ -31,8 +27,11 @@ go_library(
|
||||||
"//pkg/registry/rbac/reconciliation:go_default_library",
|
"//pkg/registry/rbac/reconciliation:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,9 @@ import (
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
internalcoreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
internalrbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||||
|
@ -42,8 +41,8 @@ type ReconcileOptions struct {
|
||||||
FilenameOptions *resource.FilenameOptions
|
FilenameOptions *resource.FilenameOptions
|
||||||
|
|
||||||
Visitor resource.Visitor
|
Visitor resource.Visitor
|
||||||
RBACClient internalrbacclient.RbacInterface
|
RBACClient rbacv1client.RbacV1Interface
|
||||||
NamespaceClient internalcoreclient.NamespaceInterface
|
NamespaceClient corev1client.CoreV1Interface
|
||||||
|
|
||||||
PrintObject printers.ResourcePrinterFunc
|
PrintObject printers.ResourcePrinterFunc
|
||||||
|
|
||||||
|
@ -104,7 +103,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args
|
||||||
}
|
}
|
||||||
|
|
||||||
r := f.NewBuilder().
|
r := f.NewBuilder().
|
||||||
WithScheme(legacyscheme.Scheme).
|
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
NamespaceParam(namespace).DefaultNamespace().
|
NamespaceParam(namespace).DefaultNamespace().
|
||||||
FilenameParam(enforceNamespace, o.FilenameOptions).
|
FilenameParam(enforceNamespace, o.FilenameOptions).
|
||||||
|
@ -116,12 +115,18 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args
|
||||||
}
|
}
|
||||||
o.Visitor = r
|
o.Visitor = r
|
||||||
|
|
||||||
client, err := f.ClientSet()
|
clientConfig, err := f.ToRESTConfig()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.RBACClient, err = rbacv1client.NewForConfig(clientConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
o.NamespaceClient, err = corev1client.NewForConfig(clientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.RBACClient = client.Rbac()
|
|
||||||
o.NamespaceClient = client.Core().Namespaces()
|
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -161,13 +166,13 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch t := info.Object.(type) {
|
switch t := info.Object.(type) {
|
||||||
case *rbac.Role:
|
case *rbacv1.Role:
|
||||||
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
||||||
Confirm: true,
|
Confirm: true,
|
||||||
RemoveExtraPermissions: false,
|
RemoveExtraPermissions: false,
|
||||||
Role: reconciliation.RoleRuleOwner{Role: t},
|
Role: reconciliation.RoleRuleOwner{Role: t},
|
||||||
Client: reconciliation.RoleModifier{
|
Client: reconciliation.RoleModifier{
|
||||||
NamespaceClient: o.NamespaceClient,
|
NamespaceClient: o.NamespaceClient.Namespaces(),
|
||||||
Client: o.RBACClient,
|
Client: o.RBACClient,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -177,7 +182,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||||
}
|
}
|
||||||
o.PrintObject(result.Role.GetObject(), o.Out)
|
o.PrintObject(result.Role.GetObject(), o.Out)
|
||||||
|
|
||||||
case *rbac.ClusterRole:
|
case *rbacv1.ClusterRole:
|
||||||
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
||||||
Confirm: true,
|
Confirm: true,
|
||||||
RemoveExtraPermissions: false,
|
RemoveExtraPermissions: false,
|
||||||
|
@ -192,14 +197,14 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||||
}
|
}
|
||||||
o.PrintObject(result.Role.GetObject(), o.Out)
|
o.PrintObject(result.Role.GetObject(), o.Out)
|
||||||
|
|
||||||
case *rbac.RoleBinding:
|
case *rbacv1.RoleBinding:
|
||||||
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
||||||
Confirm: true,
|
Confirm: true,
|
||||||
RemoveExtraSubjects: false,
|
RemoveExtraSubjects: false,
|
||||||
RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: t},
|
RoleBinding: reconciliation.RoleBindingAdapter{RoleBinding: t},
|
||||||
Client: reconciliation.RoleBindingClientAdapter{
|
Client: reconciliation.RoleBindingClientAdapter{
|
||||||
Client: o.RBACClient,
|
Client: o.RBACClient,
|
||||||
NamespaceClient: o.NamespaceClient,
|
NamespaceClient: o.NamespaceClient.Namespaces(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
result, err := reconcileOptions.Run()
|
result, err := reconcileOptions.Run()
|
||||||
|
@ -208,7 +213,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||||
}
|
}
|
||||||
o.PrintObject(result.RoleBinding.GetObject(), o.Out)
|
o.PrintObject(result.RoleBinding.GetObject(), o.Out)
|
||||||
|
|
||||||
case *rbac.ClusterRoleBinding:
|
case *rbacv1.ClusterRoleBinding:
|
||||||
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
||||||
Confirm: true,
|
Confirm: true,
|
||||||
RemoveExtraSubjects: false,
|
RemoveExtraSubjects: false,
|
||||||
|
|
|
@ -70,6 +70,7 @@ go_library(
|
||||||
"//pkg/apis/networking:go_default_library",
|
"//pkg/apis/networking:go_default_library",
|
||||||
"//pkg/apis/policy:go_default_library",
|
"//pkg/apis/policy:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/apis/scheduling:go_default_library",
|
"//pkg/apis/scheduling:go_default_library",
|
||||||
"//pkg/apis/storage:go_default_library",
|
"//pkg/apis/storage:go_default_library",
|
||||||
"//pkg/apis/storage/util:go_default_library",
|
"//pkg/apis/storage/util:go_default_library",
|
||||||
|
@ -90,6 +91,7 @@ go_library(
|
||||||
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
|
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
"//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
|
"//vendor/k8s.io/api/rbac/v1beta1:go_default_library",
|
||||||
"//vendor/k8s.io/api/storage/v1:go_default_library",
|
"//vendor/k8s.io/api/storage/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
|
|
|
@ -35,6 +35,7 @@ import (
|
||||||
"github.com/fatih/camelcase"
|
"github.com/fatih/camelcase"
|
||||||
|
|
||||||
versionedextension "k8s.io/api/extensions/v1beta1"
|
versionedextension "k8s.io/api/extensions/v1beta1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
"k8s.io/apimachinery/pkg/api/resource"
|
||||||
|
@ -63,6 +64,7 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/apis/networking"
|
"k8s.io/kubernetes/pkg/apis/networking"
|
||||||
"k8s.io/kubernetes/pkg/apis/policy"
|
"k8s.io/kubernetes/pkg/apis/policy"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/scheduling"
|
"k8s.io/kubernetes/pkg/apis/scheduling"
|
||||||
"k8s.io/kubernetes/pkg/apis/storage"
|
"k8s.io/kubernetes/pkg/apis/storage"
|
||||||
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
storageutil "k8s.io/kubernetes/pkg/apis/storage/util"
|
||||||
|
@ -166,10 +168,10 @@ func describerMap(clientConfig *rest.Config) (map[schema.GroupKind]printers.Desc
|
||||||
certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c},
|
certificates.Kind("CertificateSigningRequest"): &CertificateSigningRequestDescriber{c},
|
||||||
storage.Kind("StorageClass"): &StorageClassDescriber{c},
|
storage.Kind("StorageClass"): &StorageClassDescriber{c},
|
||||||
policy.Kind("PodDisruptionBudget"): &PodDisruptionBudgetDescriber{c},
|
policy.Kind("PodDisruptionBudget"): &PodDisruptionBudgetDescriber{c},
|
||||||
rbac.Kind("Role"): &RoleDescriber{c},
|
rbac.Kind("Role"): &RoleDescriber{externalclient},
|
||||||
rbac.Kind("ClusterRole"): &ClusterRoleDescriber{c},
|
rbac.Kind("ClusterRole"): &ClusterRoleDescriber{externalclient},
|
||||||
rbac.Kind("RoleBinding"): &RoleBindingDescriber{c},
|
rbac.Kind("RoleBinding"): &RoleBindingDescriber{externalclient},
|
||||||
rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{c},
|
rbac.Kind("ClusterRoleBinding"): &ClusterRoleBindingDescriber{externalclient},
|
||||||
networking.Kind("NetworkPolicy"): &NetworkPolicyDescriber{c},
|
networking.Kind("NetworkPolicy"): &NetworkPolicyDescriber{c},
|
||||||
scheduling.Kind("PriorityClass"): &PriorityClassDescriber{c},
|
scheduling.Kind("PriorityClass"): &PriorityClassDescriber{c},
|
||||||
}
|
}
|
||||||
|
@ -2443,7 +2445,7 @@ func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Sec
|
||||||
|
|
||||||
// RoleDescriber generates information about a node.
|
// RoleDescriber generates information about a node.
|
||||||
type RoleDescriber struct {
|
type RoleDescriber struct {
|
||||||
clientset.Interface
|
externalclient.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
func (d *RoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
||||||
|
@ -2452,7 +2454,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
breakdownRules := []rbac.PolicyRule{}
|
breakdownRules := []rbacv1.PolicyRule{}
|
||||||
for _, rule := range role.Rules {
|
for _, rule := range role.Rules {
|
||||||
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
|
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
|
||||||
}
|
}
|
||||||
|
@ -2461,7 +2463,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
sort.Stable(rbac.SortableRuleSlice(compactRules))
|
sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules))
|
||||||
|
|
||||||
return tabbedString(func(out io.Writer) error {
|
return tabbedString(func(out io.Writer) error {
|
||||||
w := NewPrefixWriter(out)
|
w := NewPrefixWriter(out)
|
||||||
|
@ -2482,7 +2484,7 @@ func (d *RoleDescriber) Describe(namespace, name string, describerSettings print
|
||||||
|
|
||||||
// ClusterRoleDescriber generates information about a node.
|
// ClusterRoleDescriber generates information about a node.
|
||||||
type ClusterRoleDescriber struct {
|
type ClusterRoleDescriber struct {
|
||||||
clientset.Interface
|
externalclient.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
||||||
|
@ -2491,7 +2493,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
breakdownRules := []rbac.PolicyRule{}
|
breakdownRules := []rbacv1.PolicyRule{}
|
||||||
for _, rule := range role.Rules {
|
for _, rule := range role.Rules {
|
||||||
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
|
breakdownRules = append(breakdownRules, validation.BreakdownRule(rule)...)
|
||||||
}
|
}
|
||||||
|
@ -2500,7 +2502,7 @@ func (d *ClusterRoleDescriber) Describe(namespace, name string, describerSetting
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
sort.Stable(rbac.SortableRuleSlice(compactRules))
|
sort.Stable(rbacv1helpers.SortableRuleSlice(compactRules))
|
||||||
|
|
||||||
return tabbedString(func(out io.Writer) error {
|
return tabbedString(func(out io.Writer) error {
|
||||||
w := NewPrefixWriter(out)
|
w := NewPrefixWriter(out)
|
||||||
|
@ -2538,7 +2540,7 @@ func combineResourceGroup(resource, group []string) string {
|
||||||
|
|
||||||
// RoleBindingDescriber generates information about a node.
|
// RoleBindingDescriber generates information about a node.
|
||||||
type RoleBindingDescriber struct {
|
type RoleBindingDescriber struct {
|
||||||
clientset.Interface
|
externalclient.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *RoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
func (d *RoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
||||||
|
@ -2570,7 +2572,7 @@ func (d *RoleBindingDescriber) Describe(namespace, name string, describerSetting
|
||||||
|
|
||||||
// ClusterRoleBindingDescriber generates information about a node.
|
// ClusterRoleBindingDescriber generates information about a node.
|
||||||
type ClusterRoleBindingDescriber struct {
|
type ClusterRoleBindingDescriber struct {
|
||||||
clientset.Interface
|
externalclient.Interface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *ClusterRoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
func (d *ClusterRoleBindingDescriber) Describe(namespace, name string, describerSettings printers.DescriberSettings) (string, error) {
|
||||||
|
|
|
@ -16,12 +16,12 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/apis/rbac/validation:go_default_library",
|
"//pkg/apis/rbac/validation:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
|
|
@ -58,12 +58,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
|
||||||
|
|
||||||
clusterRole := obj.(*rbac.ClusterRole)
|
clusterRole := obj.(*rbac.ClusterRole)
|
||||||
rules := clusterRole.Rules
|
rules := clusterRole.Rules
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil {
|
||||||
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err)
|
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err)
|
||||||
}
|
}
|
||||||
// to set the aggregation rule, since it can gather anything, requires * on *.*
|
// to set the aggregation rule, since it can gather anything, requires * on *.*
|
||||||
if hasAggregationRule(clusterRole) {
|
if hasAggregationRule(clusterRole) {
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil {
|
||||||
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule"))
|
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -86,12 +86,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
rules := clusterRole.Rules
|
rules := clusterRole.Rules
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil {
|
||||||
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err)
|
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, err)
|
||||||
}
|
}
|
||||||
// to change the aggregation rule, since it can gather anything and prevent tightening, requires * on *.*
|
// to change the aggregation rule, since it can gather anything and prevent tightening, requires * on *.*
|
||||||
if hasAggregationRule(clusterRole) || hasAggregationRule(oldClusterRole) {
|
if hasAggregationRule(clusterRole) || hasAggregationRule(oldClusterRole) {
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, fullAuthority); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, fullAuthority); err != nil {
|
||||||
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule"))
|
return nil, apierrors.NewForbidden(groupResource, clusterRole.Name, errors.New("must have cluster-admin privileges to use the aggregationRule"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,22 @@ package clusterrole
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry is an interface for things that know how to store ClusterRoles.
|
// Registry is an interface for things that know how to store ClusterRoles.
|
||||||
type Registry interface {
|
type Registry interface {
|
||||||
ListClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error)
|
GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error)
|
||||||
CreateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error
|
|
||||||
UpdateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error
|
|
||||||
GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error)
|
|
||||||
DeleteClusterRole(ctx context.Context, name string) error
|
|
||||||
WatchClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage puts strong typing around storage calls
|
// storage puts strong typing around storage calls
|
||||||
type storage struct {
|
type storage struct {
|
||||||
rest.StandardStorage
|
rest.Getter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||||
|
@ -48,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry {
|
||||||
return &storage{s}
|
return &storage{s}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) ListClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleList, error) {
|
func (s *storage) GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.ClusterRole, error) {
|
||||||
obj, err := s.List(ctx, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.(*rbac.ClusterRoleList), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) CreateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc) error {
|
|
||||||
_, err := s.Create(ctx, clusterRole, createValidation, false)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) UpdateClusterRole(ctx context.Context, clusterRole *rbac.ClusterRole, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error {
|
|
||||||
_, _, err := s.Update(ctx, clusterRole.Name, rest.DefaultUpdatedObjectInfo(clusterRole), createValidation, updateValidation)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) WatchClusterRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
|
||||||
return s.Watch(ctx, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) GetClusterRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRole, error) {
|
|
||||||
obj, err := s.Get(ctx, name, options)
|
obj, err := s.Get(ctx, name, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj.(*rbac.ClusterRole), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) DeleteClusterRole(ctx context.Context, name string) error {
|
ret := &rbacv1.ClusterRole{}
|
||||||
_, _, err := s.Delete(ctx, name, nil)
|
if err := rbacv1helpers.Convert_rbac_ClusterRole_To_v1_ClusterRole(obj.(*rbac.ClusterRole), ret, nil); err != nil {
|
||||||
return err
|
return nil, err
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||||
|
@ -89,6 +61,6 @@ type AuthorizerAdapter struct {
|
||||||
Registry Registry
|
Registry Registry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthorizerAdapter) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
func (a AuthorizerAdapter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) {
|
||||||
return a.Registry.GetClusterRole(genericapirequest.NewContext(), name, &metav1.GetOptions{})
|
return a.Registry.GetClusterRole(genericapirequest.NewContext(), name, &metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/apis/rbac/validation:go_default_library",
|
"//pkg/apis/rbac/validation:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
|
|
@ -12,8 +12,10 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core/helper:go_default_library",
|
"//pkg/apis/core/helper:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/registry/rbac:go_default_library",
|
"//pkg/registry/rbac:go_default_library",
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
|
|
@ -20,6 +20,7 @@ package policybased
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
@ -27,6 +28,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
|
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
@ -59,7 +61,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
|
||||||
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone)
|
v1RoleRef := rbacv1.RoleRef{}
|
||||||
|
err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -88,7 +95,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, see if we already have all the permissions contained in the referenced clusterrole
|
// Otherwise, see if we already have all the permissions contained in the referenced clusterrole
|
||||||
rules, err := s.ruleResolver.GetRoleReferenceRules(clusterRoleBinding.RoleRef, metav1.NamespaceNone)
|
v1RoleRef := rbacv1.RoleRef{}
|
||||||
|
err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&clusterRoleBinding.RoleRef, &v1RoleRef, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, metav1.NamespaceNone)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,22 @@ package clusterrolebinding
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry is an interface for things that know how to store ClusterRoleBindings.
|
// Registry is an interface for things that know how to store ClusterRoleBindings.
|
||||||
type Registry interface {
|
type Registry interface {
|
||||||
ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error)
|
ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error)
|
||||||
CreateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error
|
|
||||||
UpdateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error
|
|
||||||
GetClusterRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error)
|
|
||||||
DeleteClusterRoleBinding(ctx context.Context, name string) error
|
|
||||||
WatchClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage puts strong typing around storage calls
|
// storage puts strong typing around storage calls
|
||||||
type storage struct {
|
type storage struct {
|
||||||
rest.StandardStorage
|
rest.Lister
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||||
|
@ -48,40 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry {
|
||||||
return &storage{s}
|
return &storage{s}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.ClusterRoleBindingList, error) {
|
func (s *storage) ListClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.ClusterRoleBindingList, error) {
|
||||||
obj, err := s.List(ctx, options)
|
obj, err := s.List(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*rbac.ClusterRoleBindingList), nil
|
ret := &rbacv1.ClusterRoleBindingList{}
|
||||||
}
|
if err := rbacv1helpers.Convert_rbac_ClusterRoleBindingList_To_v1_ClusterRoleBindingList(obj.(*rbac.ClusterRoleBindingList), ret, nil); err != nil {
|
||||||
|
|
||||||
func (s *storage) CreateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc) error {
|
|
||||||
_, err := s.Create(ctx, clusterRoleBinding, createValidation, false)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) UpdateClusterRoleBinding(ctx context.Context, clusterRoleBinding *rbac.ClusterRoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error {
|
|
||||||
_, _, err := s.Update(ctx, clusterRoleBinding.Name, rest.DefaultUpdatedObjectInfo(clusterRoleBinding), createValidation, updateValidation)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) WatchClusterRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
|
||||||
return s.Watch(ctx, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) GetClusterRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.ClusterRoleBinding, error) {
|
|
||||||
obj, err := s.Get(ctx, name, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj.(*rbac.ClusterRoleBinding), nil
|
return ret, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) DeleteClusterRoleBinding(ctx context.Context, name string) error {
|
|
||||||
_, _, err := s.Delete(ctx, name, nil)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||||
|
@ -89,13 +61,13 @@ type AuthorizerAdapter struct {
|
||||||
Registry Registry
|
Registry Registry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
func (a AuthorizerAdapter) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) {
|
||||||
list, err := a.Registry.ListClusterRoleBindings(genericapirequest.NewContext(), &metainternalversion.ListOptions{})
|
list, err := a.Registry.ListClusterRoleBindings(genericapirequest.NewContext(), &metainternalversion.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := []*rbac.ClusterRoleBinding{}
|
ret := []*rbacv1.ClusterRoleBinding{}
|
||||||
for i := range list.Items {
|
for i := range list.Items {
|
||||||
ret = append(ret, &list.Items[i])
|
ret = append(ret, &list.Items[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ go_test(
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core/helper:go_default_library",
|
"//pkg/apis/core/helper:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
],
|
],
|
||||||
|
@ -34,16 +34,16 @@ go_library(
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/pkg/registry/rbac/reconciliation",
|
importpath = "k8s.io/kubernetes/pkg/registry/rbac/reconciliation",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core:go_default_library",
|
|
||||||
"//pkg/apis/rbac:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -17,17 +17,17 @@ limitations under the License.
|
||||||
package reconciliation
|
package reconciliation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner
|
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner
|
||||||
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
||||||
type ClusterRoleRuleOwner struct {
|
type ClusterRoleRuleOwner struct {
|
||||||
ClusterRole *rbac.ClusterRole
|
ClusterRole *rbacv1.ClusterRole
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleRuleOwner) GetObject() runtime.Object {
|
func (o ClusterRoleRuleOwner) GetObject() runtime.Object {
|
||||||
|
@ -58,24 +58,24 @@ func (o ClusterRoleRuleOwner) SetAnnotations(in map[string]string) {
|
||||||
o.ClusterRole.Annotations = in
|
o.ClusterRole.Annotations = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleRuleOwner) GetRules() []rbac.PolicyRule {
|
func (o ClusterRoleRuleOwner) GetRules() []rbacv1.PolicyRule {
|
||||||
return o.ClusterRole.Rules
|
return o.ClusterRole.Rules
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleRuleOwner) SetRules(in []rbac.PolicyRule) {
|
func (o ClusterRoleRuleOwner) SetRules(in []rbacv1.PolicyRule) {
|
||||||
o.ClusterRole.Rules = in
|
o.ClusterRole.Rules = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleRuleOwner) GetAggregationRule() *rbac.AggregationRule {
|
func (o ClusterRoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule {
|
||||||
return o.ClusterRole.AggregationRule
|
return o.ClusterRole.AggregationRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) {
|
func (o ClusterRoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) {
|
||||||
o.ClusterRole.AggregationRule = in
|
o.ClusterRole.AggregationRule = in
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleModifier struct {
|
type ClusterRoleModifier struct {
|
||||||
Client internalversion.ClusterRoleInterface
|
Client rbacv1client.ClusterRoleInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
func (c ClusterRoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||||
|
|
|
@ -17,18 +17,18 @@ limitations under the License.
|
||||||
package reconciliation
|
package reconciliation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding
|
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding
|
||||||
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
||||||
type ClusterRoleBindingAdapter struct {
|
type ClusterRoleBindingAdapter struct {
|
||||||
ClusterRoleBinding *rbac.ClusterRoleBinding
|
ClusterRoleBinding *rbacv1.ClusterRoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleBindingAdapter) GetObject() runtime.Object {
|
func (o ClusterRoleBindingAdapter) GetObject() runtime.Object {
|
||||||
|
@ -63,20 +63,20 @@ func (o ClusterRoleBindingAdapter) SetAnnotations(in map[string]string) {
|
||||||
o.ClusterRoleBinding.Annotations = in
|
o.ClusterRoleBinding.Annotations = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleBindingAdapter) GetRoleRef() rbac.RoleRef {
|
func (o ClusterRoleBindingAdapter) GetRoleRef() rbacv1.RoleRef {
|
||||||
return o.ClusterRoleBinding.RoleRef
|
return o.ClusterRoleBinding.RoleRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleBindingAdapter) GetSubjects() []rbac.Subject {
|
func (o ClusterRoleBindingAdapter) GetSubjects() []rbacv1.Subject {
|
||||||
return o.ClusterRoleBinding.Subjects
|
return o.ClusterRoleBinding.Subjects
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o ClusterRoleBindingAdapter) SetSubjects(in []rbac.Subject) {
|
func (o ClusterRoleBindingAdapter) SetSubjects(in []rbacv1.Subject) {
|
||||||
o.ClusterRoleBinding.Subjects = in
|
o.ClusterRoleBinding.Subjects = in
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleBindingClientAdapter struct {
|
type ClusterRoleBindingClientAdapter struct {
|
||||||
Client internalversion.ClusterRoleBindingInterface
|
Client rbacv1client.ClusterRoleBindingInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c ClusterRoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
func (c ClusterRoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
||||||
|
|
|
@ -20,11 +20,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/equality"
|
"k8s.io/apimachinery/pkg/api/equality"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
"k8s.io/kubernetes/pkg/registry/rbac/validation"
|
"k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -51,10 +51,10 @@ type RuleOwner interface {
|
||||||
SetLabels(map[string]string)
|
SetLabels(map[string]string)
|
||||||
GetAnnotations() map[string]string
|
GetAnnotations() map[string]string
|
||||||
SetAnnotations(map[string]string)
|
SetAnnotations(map[string]string)
|
||||||
GetRules() []rbac.PolicyRule
|
GetRules() []rbacv1.PolicyRule
|
||||||
SetRules([]rbac.PolicyRule)
|
SetRules([]rbacv1.PolicyRule)
|
||||||
GetAggregationRule() *rbac.AggregationRule
|
GetAggregationRule() *rbacv1.AggregationRule
|
||||||
SetAggregationRule(*rbac.AggregationRule)
|
SetAggregationRule(*rbacv1.AggregationRule)
|
||||||
DeepCopyRuleOwner() RuleOwner
|
DeepCopyRuleOwner() RuleOwner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ type ReconcileClusterRoleResult struct {
|
||||||
Role RuleOwner
|
Role RuleOwner
|
||||||
|
|
||||||
// MissingRules contains expected rules that were missing from the currently persisted role
|
// MissingRules contains expected rules that were missing from the currently persisted role
|
||||||
MissingRules []rbac.PolicyRule
|
MissingRules []rbacv1.PolicyRule
|
||||||
// ExtraRules contains extra permissions the currently persisted role had
|
// ExtraRules contains extra permissions the currently persisted role had
|
||||||
ExtraRules []rbac.PolicyRule
|
ExtraRules []rbacv1.PolicyRule
|
||||||
|
|
||||||
// MissingAggregationRuleSelectors contains expected selectors that were missing from the currently persisted role
|
// MissingAggregationRuleSelectors contains expected selectors that were missing from the currently persisted role
|
||||||
MissingAggregationRuleSelectors []metav1.LabelSelector
|
MissingAggregationRuleSelectors []metav1.LabelSelector
|
||||||
|
@ -112,7 +112,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e
|
||||||
case errors.IsNotFound(err):
|
case errors.IsNotFound(err):
|
||||||
aggregationRule := o.Role.GetAggregationRule()
|
aggregationRule := o.Role.GetAggregationRule()
|
||||||
if aggregationRule == nil {
|
if aggregationRule == nil {
|
||||||
aggregationRule = &rbac.AggregationRule{}
|
aggregationRule = &rbacv1.AggregationRule{}
|
||||||
}
|
}
|
||||||
result = &ReconcileClusterRoleResult{
|
result = &ReconcileClusterRoleResult{
|
||||||
Role: o.Role,
|
Role: o.Role,
|
||||||
|
@ -178,7 +178,7 @@ func (o *ReconcileRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, e
|
||||||
func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions bool) (*ReconcileClusterRoleResult, error) {
|
func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions bool) (*ReconcileClusterRoleResult, error) {
|
||||||
result := &ReconcileClusterRoleResult{Operation: ReconcileNone}
|
result := &ReconcileClusterRoleResult{Operation: ReconcileNone}
|
||||||
|
|
||||||
result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false")
|
result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false")
|
||||||
|
|
||||||
// Start with a copy of the existing object
|
// Start with a copy of the existing object
|
||||||
result.Role = existing.DeepCopyRuleOwner()
|
result.Role = existing.DeepCopyRuleOwner()
|
||||||
|
@ -223,7 +223,7 @@ func computeReconciledRole(existing, expected RuleOwner, removeExtraPermissions
|
||||||
// add missing rules in the union case
|
// add missing rules in the union case
|
||||||
aggregationRule := result.Role.GetAggregationRule()
|
aggregationRule := result.Role.GetAggregationRule()
|
||||||
if aggregationRule == nil {
|
if aggregationRule == nil {
|
||||||
aggregationRule = &rbac.AggregationRule{}
|
aggregationRule = &rbacv1.AggregationRule{}
|
||||||
}
|
}
|
||||||
aggregationRule.ClusterRoleSelectors = append(aggregationRule.ClusterRoleSelectors, result.MissingAggregationRuleSelectors...)
|
aggregationRule.ClusterRoleSelectors = append(aggregationRule.ClusterRoleSelectors, result.MissingAggregationRuleSelectors...)
|
||||||
result.Role.SetAggregationRule(aggregationRule)
|
result.Role.SetAggregationRule(aggregationRule)
|
||||||
|
@ -254,7 +254,7 @@ func merge(maps ...map[string]string) map[string]string {
|
||||||
// aggregationRuleCovers determines whether or not the ownerSelectors cover the servantSelectors in terms of semantically
|
// aggregationRuleCovers determines whether or not the ownerSelectors cover the servantSelectors in terms of semantically
|
||||||
// equal label selectors.
|
// equal label selectors.
|
||||||
// It returns whether or not the ownerSelectors cover and a list of the rules that the ownerSelectors do not cover.
|
// It returns whether or not the ownerSelectors cover and a list of the rules that the ownerSelectors do not cover.
|
||||||
func aggregationRuleCovers(ownerRule, servantRule *rbac.AggregationRule) (bool, []metav1.LabelSelector) {
|
func aggregationRuleCovers(ownerRule, servantRule *rbacv1.AggregationRule) (bool, []metav1.LabelSelector) {
|
||||||
switch {
|
switch {
|
||||||
case ownerRule == nil && servantRule == nil:
|
case ownerRule == nil && servantRule == nil:
|
||||||
return true, []metav1.LabelSelector{}
|
return true, []metav1.LabelSelector{}
|
||||||
|
|
|
@ -19,23 +19,23 @@ package reconciliation
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func role(rules []rbac.PolicyRule, labels map[string]string, annotations map[string]string) *rbac.ClusterRole {
|
func role(rules []rbacv1.PolicyRule, labels map[string]string, annotations map[string]string) *rbacv1.ClusterRole {
|
||||||
return &rbac.ClusterRole{
|
return &rbacv1.ClusterRole{
|
||||||
Rules: rules,
|
Rules: rules,
|
||||||
ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: annotations},
|
ObjectMeta: metav1.ObjectMeta{Labels: labels, Annotations: annotations},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rules(resources ...string) []rbac.PolicyRule {
|
func rules(resources ...string) []rbacv1.PolicyRule {
|
||||||
r := []rbac.PolicyRule{}
|
r := []rbacv1.PolicyRule{}
|
||||||
for _, resource := range resources {
|
for _, resource := range resources {
|
||||||
r = append(r, rbac.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}})
|
r = append(r, rbacv1.PolicyRule{APIGroups: []string{""}, Verbs: []string{"get"}, Resources: []string{resource}})
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
@ -44,11 +44,11 @@ type ss map[string]string
|
||||||
|
|
||||||
func TestComputeReconciledRoleRules(t *testing.T) {
|
func TestComputeReconciledRoleRules(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
expectedRole *rbac.ClusterRole
|
expectedRole *rbacv1.ClusterRole
|
||||||
actualRole *rbac.ClusterRole
|
actualRole *rbacv1.ClusterRole
|
||||||
removeExtraPermissions bool
|
removeExtraPermissions bool
|
||||||
|
|
||||||
expectedReconciledRole *rbac.ClusterRole
|
expectedReconciledRole *rbacv1.ClusterRole
|
||||||
expectedReconciliationNeeded bool
|
expectedReconciliationNeeded bool
|
||||||
}{
|
}{
|
||||||
"empty": {
|
"empty": {
|
||||||
|
@ -278,14 +278,14 @@ func TestComputeReconciledRoleRules(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func aggregatedRole(aggregationRule *rbac.AggregationRule) *rbac.ClusterRole {
|
func aggregatedRole(aggregationRule *rbacv1.AggregationRule) *rbacv1.ClusterRole {
|
||||||
return &rbac.ClusterRole{
|
return &rbacv1.ClusterRole{
|
||||||
AggregationRule: aggregationRule,
|
AggregationRule: aggregationRule,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func aggregationrule(selectors []map[string]string) *rbac.AggregationRule {
|
func aggregationrule(selectors []map[string]string) *rbacv1.AggregationRule {
|
||||||
ret := &rbac.AggregationRule{}
|
ret := &rbacv1.AggregationRule{}
|
||||||
for _, selector := range selectors {
|
for _, selector := range selectors {
|
||||||
ret.ClusterRoleSelectors = append(ret.ClusterRoleSelectors,
|
ret.ClusterRoleSelectors = append(ret.ClusterRoleSelectors,
|
||||||
metav1.LabelSelector{MatchLabels: selector})
|
metav1.LabelSelector{MatchLabels: selector})
|
||||||
|
@ -295,15 +295,15 @@ func aggregationrule(selectors []map[string]string) *rbac.AggregationRule {
|
||||||
|
|
||||||
func TestComputeReconciledRoleAggregationRules(t *testing.T) {
|
func TestComputeReconciledRoleAggregationRules(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
expectedRole *rbac.ClusterRole
|
expectedRole *rbacv1.ClusterRole
|
||||||
actualRole *rbac.ClusterRole
|
actualRole *rbacv1.ClusterRole
|
||||||
removeExtraPermissions bool
|
removeExtraPermissions bool
|
||||||
|
|
||||||
expectedReconciledRole *rbac.ClusterRole
|
expectedReconciledRole *rbacv1.ClusterRole
|
||||||
expectedReconciliationNeeded bool
|
expectedReconciliationNeeded bool
|
||||||
}{
|
}{
|
||||||
"empty": {
|
"empty": {
|
||||||
expectedRole: aggregatedRole(&rbac.AggregationRule{}),
|
expectedRole: aggregatedRole(&rbacv1.AggregationRule{}),
|
||||||
actualRole: aggregatedRole(nil),
|
actualRole: aggregatedRole(nil),
|
||||||
removeExtraPermissions: true,
|
removeExtraPermissions: true,
|
||||||
|
|
||||||
|
@ -311,8 +311,8 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) {
|
||||||
expectedReconciliationNeeded: false,
|
expectedReconciliationNeeded: false,
|
||||||
},
|
},
|
||||||
"empty-2": {
|
"empty-2": {
|
||||||
expectedRole: aggregatedRole(&rbac.AggregationRule{}),
|
expectedRole: aggregatedRole(&rbacv1.AggregationRule{}),
|
||||||
actualRole: aggregatedRole(&rbac.AggregationRule{}),
|
actualRole: aggregatedRole(&rbacv1.AggregationRule{}),
|
||||||
removeExtraPermissions: true,
|
removeExtraPermissions: true,
|
||||||
|
|
||||||
expectedReconciledRole: nil,
|
expectedReconciledRole: nil,
|
||||||
|
@ -365,7 +365,7 @@ func TestComputeReconciledRoleAggregationRules(t *testing.T) {
|
||||||
// desired role is not aggregated
|
// desired role is not aggregated
|
||||||
expectedRole: role(rules("pods", "nodes", "secrets"), nil, nil),
|
expectedRole: role(rules("pods", "nodes", "secrets"), nil, nil),
|
||||||
// existing role is aggregated and has other permissions
|
// existing role is aggregated and has other permissions
|
||||||
actualRole: func() *rbac.ClusterRole {
|
actualRole: func() *rbacv1.ClusterRole {
|
||||||
r := aggregatedRole(aggregationrule([]map[string]string{{"alpha": "bravo"}}))
|
r := aggregatedRole(aggregationrule([]map[string]string{{"alpha": "bravo"}}))
|
||||||
r.Rules = rules("deployments")
|
r.Rules = rules("deployments")
|
||||||
return r
|
return r
|
||||||
|
|
|
@ -20,10 +20,10 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoleBindingModifier interface {
|
type RoleBindingModifier interface {
|
||||||
|
@ -42,9 +42,9 @@ type RoleBinding interface {
|
||||||
SetLabels(map[string]string)
|
SetLabels(map[string]string)
|
||||||
GetAnnotations() map[string]string
|
GetAnnotations() map[string]string
|
||||||
SetAnnotations(map[string]string)
|
SetAnnotations(map[string]string)
|
||||||
GetRoleRef() rbac.RoleRef
|
GetRoleRef() rbacv1.RoleRef
|
||||||
GetSubjects() []rbac.Subject
|
GetSubjects() []rbacv1.Subject
|
||||||
SetSubjects([]rbac.Subject)
|
SetSubjects([]rbacv1.Subject)
|
||||||
DeepCopyRoleBinding() RoleBinding
|
DeepCopyRoleBinding() RoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,9 +67,9 @@ type ReconcileClusterRoleBindingResult struct {
|
||||||
RoleBinding RoleBinding
|
RoleBinding RoleBinding
|
||||||
|
|
||||||
// MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding
|
// MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding
|
||||||
MissingSubjects []rbac.Subject
|
MissingSubjects []rbacv1.Subject
|
||||||
// ExtraSubjects contains extra subjects the currently persisted rolebinding had
|
// ExtraSubjects contains extra subjects the currently persisted rolebinding had
|
||||||
ExtraSubjects []rbac.Subject
|
ExtraSubjects []rbacv1.Subject
|
||||||
|
|
||||||
// Operation is the API operation required to reconcile.
|
// Operation is the API operation required to reconcile.
|
||||||
// If no reconciliation was needed, it is set to ReconcileNone.
|
// If no reconciliation was needed, it is set to ReconcileNone.
|
||||||
|
@ -176,7 +176,7 @@ func (o *ReconcileRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBi
|
||||||
func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) {
|
func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) {
|
||||||
result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone}
|
result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone}
|
||||||
|
|
||||||
result.Protected = (existing.GetAnnotations()[rbac.AutoUpdateAnnotationKey] == "false")
|
result.Protected = (existing.GetAnnotations()[rbacv1.AutoUpdateAnnotationKey] == "false")
|
||||||
|
|
||||||
// Reset the binding completely if the roleRef is different
|
// Reset the binding completely if the roleRef is different
|
||||||
if expected.GetRoleRef() != existing.GetRoleRef() {
|
if expected.GetRoleRef() != existing.GetRoleRef() {
|
||||||
|
@ -216,7 +216,7 @@ func computeReconciledRoleBinding(existing, expected RoleBinding, removeExtraSub
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func contains(list []rbac.Subject, item rbac.Subject) bool {
|
func contains(list []rbacv1.Subject, item rbacv1.Subject) bool {
|
||||||
for _, listItem := range list {
|
for _, listItem := range list {
|
||||||
if listItem == item {
|
if listItem == item {
|
||||||
return true
|
return true
|
||||||
|
@ -229,7 +229,7 @@ func contains(list []rbac.Subject, item rbac.Subject) bool {
|
||||||
// list1Only = list1 - list2
|
// list1Only = list1 - list2
|
||||||
// list2Only = list2 - list1
|
// list2Only = list2 - list1
|
||||||
// if both returned lists are empty, the provided lists are equal
|
// if both returned lists are empty, the provided lists are equal
|
||||||
func diffSubjectLists(list1 []rbac.Subject, list2 []rbac.Subject) (list1Only []rbac.Subject, list2Only []rbac.Subject) {
|
func diffSubjectLists(list1 []rbacv1.Subject, list2 []rbacv1.Subject) (list1Only []rbacv1.Subject, list2Only []rbacv1.Subject) {
|
||||||
for _, list1Item := range list1 {
|
for _, list1Item := range list1 {
|
||||||
if !contains(list2, list1Item) {
|
if !contains(list2, list1Item) {
|
||||||
if !contains(list1Only, list1Item) {
|
if !contains(list1Only, list1Item) {
|
||||||
|
|
|
@ -19,24 +19,24 @@ package reconciliation
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/core/helper"
|
"k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func binding(roleRef rbac.RoleRef, subjects []rbac.Subject) *rbac.ClusterRoleBinding {
|
func binding(roleRef rbacv1.RoleRef, subjects []rbacv1.Subject) *rbacv1.ClusterRoleBinding {
|
||||||
return &rbac.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects}
|
return &rbacv1.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ref(name string) rbac.RoleRef {
|
func ref(name string) rbacv1.RoleRef {
|
||||||
return rbac.RoleRef{Name: name}
|
return rbacv1.RoleRef{Name: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func subject(name string) rbac.Subject {
|
func subject(name string) rbacv1.Subject {
|
||||||
return rbac.Subject{Name: name}
|
return rbacv1.Subject{Name: name}
|
||||||
}
|
}
|
||||||
|
|
||||||
func subjects(names ...string) []rbac.Subject {
|
func subjects(names ...string) []rbacv1.Subject {
|
||||||
r := []rbac.Subject{}
|
r := []rbacv1.Subject{}
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
r = append(r, subject(name))
|
r = append(r, subject(name))
|
||||||
}
|
}
|
||||||
|
@ -45,10 +45,10 @@ func subjects(names ...string) []rbac.Subject {
|
||||||
|
|
||||||
func TestDiffObjectReferenceLists(t *testing.T) {
|
func TestDiffObjectReferenceLists(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
A []rbac.Subject
|
A []rbacv1.Subject
|
||||||
B []rbac.Subject
|
B []rbacv1.Subject
|
||||||
ExpectedOnlyA []rbac.Subject
|
ExpectedOnlyA []rbacv1.Subject
|
||||||
ExpectedOnlyB []rbac.Subject
|
ExpectedOnlyB []rbacv1.Subject
|
||||||
}{
|
}{
|
||||||
"empty": {},
|
"empty": {},
|
||||||
|
|
||||||
|
@ -92,11 +92,11 @@ func TestDiffObjectReferenceLists(t *testing.T) {
|
||||||
|
|
||||||
func TestComputeUpdate(t *testing.T) {
|
func TestComputeUpdate(t *testing.T) {
|
||||||
tests := map[string]struct {
|
tests := map[string]struct {
|
||||||
ExpectedBinding *rbac.ClusterRoleBinding
|
ExpectedBinding *rbacv1.ClusterRoleBinding
|
||||||
ActualBinding *rbac.ClusterRoleBinding
|
ActualBinding *rbacv1.ClusterRoleBinding
|
||||||
RemoveExtraSubjects bool
|
RemoveExtraSubjects bool
|
||||||
|
|
||||||
ExpectedUpdatedBinding *rbac.ClusterRoleBinding
|
ExpectedUpdatedBinding *rbacv1.ClusterRoleBinding
|
||||||
ExpectedUpdateNeeded bool
|
ExpectedUpdateNeeded bool
|
||||||
}{
|
}{
|
||||||
"match without union": {
|
"match without union": {
|
||||||
|
|
|
@ -17,20 +17,20 @@ limitations under the License.
|
||||||
package reconciliation
|
package reconciliation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner
|
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RuleOwner
|
||||||
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
||||||
type RoleRuleOwner struct {
|
type RoleRuleOwner struct {
|
||||||
Role *rbac.Role
|
Role *rbacv1.Role
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleRuleOwner) GetObject() runtime.Object {
|
func (o RoleRuleOwner) GetObject() runtime.Object {
|
||||||
|
@ -61,24 +61,24 @@ func (o RoleRuleOwner) SetAnnotations(in map[string]string) {
|
||||||
o.Role.Annotations = in
|
o.Role.Annotations = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleRuleOwner) GetRules() []rbac.PolicyRule {
|
func (o RoleRuleOwner) GetRules() []rbacv1.PolicyRule {
|
||||||
return o.Role.Rules
|
return o.Role.Rules
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleRuleOwner) SetRules(in []rbac.PolicyRule) {
|
func (o RoleRuleOwner) SetRules(in []rbacv1.PolicyRule) {
|
||||||
o.Role.Rules = in
|
o.Role.Rules = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleRuleOwner) GetAggregationRule() *rbac.AggregationRule {
|
func (o RoleRuleOwner) GetAggregationRule() *rbacv1.AggregationRule {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleRuleOwner) SetAggregationRule(in *rbac.AggregationRule) {
|
func (o RoleRuleOwner) SetAggregationRule(in *rbacv1.AggregationRule) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleModifier struct {
|
type RoleModifier struct {
|
||||||
Client internalversion.RolesGetter
|
Client rbacv1client.RolesGetter
|
||||||
NamespaceClient core.NamespaceInterface
|
NamespaceClient corev1client.NamespaceInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||||
|
@ -90,7 +90,7 @@ func (c RoleModifier) Get(namespace, name string) (RuleOwner, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
func (c RoleModifier) Create(in RuleOwner) (RuleOwner, error) {
|
||||||
ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
||||||
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,21 +17,21 @@ limitations under the License.
|
||||||
package reconciliation
|
package reconciliation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
corev1 "k8s.io/api/core/v1"
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
core "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
|
||||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// +k8s:deepcopy-gen=true
|
// +k8s:deepcopy-gen=true
|
||||||
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding
|
// +k8s:deepcopy-gen:interfaces=k8s.io/kubernetes/pkg/registry/rbac/reconciliation.RoleBinding
|
||||||
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
// +k8s:deepcopy-gen:nonpointer-interfaces=true
|
||||||
type RoleBindingAdapter struct {
|
type RoleBindingAdapter struct {
|
||||||
RoleBinding *rbac.RoleBinding
|
RoleBinding *rbacv1.RoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleBindingAdapter) GetObject() runtime.Object {
|
func (o RoleBindingAdapter) GetObject() runtime.Object {
|
||||||
|
@ -66,21 +66,21 @@ func (o RoleBindingAdapter) SetAnnotations(in map[string]string) {
|
||||||
o.RoleBinding.Annotations = in
|
o.RoleBinding.Annotations = in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleBindingAdapter) GetRoleRef() rbac.RoleRef {
|
func (o RoleBindingAdapter) GetRoleRef() rbacv1.RoleRef {
|
||||||
return o.RoleBinding.RoleRef
|
return o.RoleBinding.RoleRef
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleBindingAdapter) GetSubjects() []rbac.Subject {
|
func (o RoleBindingAdapter) GetSubjects() []rbacv1.Subject {
|
||||||
return o.RoleBinding.Subjects
|
return o.RoleBinding.Subjects
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o RoleBindingAdapter) SetSubjects(in []rbac.Subject) {
|
func (o RoleBindingAdapter) SetSubjects(in []rbacv1.Subject) {
|
||||||
o.RoleBinding.Subjects = in
|
o.RoleBinding.Subjects = in
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleBindingClientAdapter struct {
|
type RoleBindingClientAdapter struct {
|
||||||
Client internalversion.RoleBindingsGetter
|
Client rbacv1client.RoleBindingsGetter
|
||||||
NamespaceClient core.NamespaceInterface
|
NamespaceClient corev1client.NamespaceInterface
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, error) {
|
||||||
|
@ -92,7 +92,7 @@ func (c RoleBindingClientAdapter) Get(namespace, name string) (RoleBinding, erro
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) {
|
func (c RoleBindingClientAdapter) Create(in RoleBinding) (RoleBinding, error) {
|
||||||
ns := &api.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
ns := &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: in.GetNamespace()}}
|
||||||
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
if _, err := c.NamespaceClient.Create(ns); err != nil && !apierrors.IsAlreadyExists(err) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ limitations under the License.
|
||||||
package reconciliation
|
package reconciliation
|
||||||
|
|
||||||
import (
|
import (
|
||||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
v1 "k8s.io/api/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
|
@ -32,7 +32,7 @@ func (in *ClusterRoleBindingAdapter) DeepCopyInto(out *ClusterRoleBindingAdapter
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(rbac.ClusterRoleBinding)
|
*out = new(v1.ClusterRoleBinding)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -62,7 +62,7 @@ func (in *ClusterRoleRuleOwner) DeepCopyInto(out *ClusterRoleRuleOwner) {
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(rbac.ClusterRole)
|
*out = new(v1.ClusterRole)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,7 +92,7 @@ func (in *RoleBindingAdapter) DeepCopyInto(out *RoleBindingAdapter) {
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(rbac.RoleBinding)
|
*out = new(v1.RoleBinding)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,7 +122,7 @@ func (in *RoleRuleOwner) DeepCopyInto(out *RoleRuleOwner) {
|
||||||
if *in == nil {
|
if *in == nil {
|
||||||
*out = nil
|
*out = nil
|
||||||
} else {
|
} else {
|
||||||
*out = new(rbac.Role)
|
*out = new(v1.Role)
|
||||||
(*in).DeepCopyInto(*out)
|
(*in).DeepCopyInto(*out)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,6 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
|
|
||||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
|
||||||
"//pkg/registry/rbac/clusterrole:go_default_library",
|
"//pkg/registry/rbac/clusterrole:go_default_library",
|
||||||
"//pkg/registry/rbac/clusterrole/policybased:go_default_library",
|
"//pkg/registry/rbac/clusterrole/policybased:go_default_library",
|
||||||
"//pkg/registry/rbac/clusterrole/storage:go_default_library",
|
"//pkg/registry/rbac/clusterrole/storage:go_default_library",
|
||||||
|
@ -43,6 +41,8 @@ go_library(
|
||||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/server:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/server/storage:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/core/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/kubernetes/typed/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/client-go/util/retry:go_default_library",
|
"//vendor/k8s.io/client-go/util/retry:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -35,11 +35,11 @@ import (
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
genericapiserver "k8s.io/apiserver/pkg/server"
|
genericapiserver "k8s.io/apiserver/pkg/server"
|
||||||
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
serverstorage "k8s.io/apiserver/pkg/server/storage"
|
||||||
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
|
rbacv1client "k8s.io/client-go/kubernetes/typed/rbac/v1"
|
||||||
"k8s.io/client-go/util/retry"
|
"k8s.io/client-go/util/retry"
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
|
|
||||||
rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
|
||||||
"k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
"k8s.io/kubernetes/pkg/registry/rbac/clusterrole"
|
||||||
clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased"
|
clusterrolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/policybased"
|
||||||
clusterrolestore "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage"
|
clusterrolestore "k8s.io/kubernetes/pkg/registry/rbac/clusterrole/storage"
|
||||||
|
@ -124,10 +124,10 @@ func (p RESTStorageProvider) PostStartHook() (string, genericapiserver.PostStart
|
||||||
}
|
}
|
||||||
|
|
||||||
type PolicyData struct {
|
type PolicyData struct {
|
||||||
ClusterRoles []rbac.ClusterRole
|
ClusterRoles []rbacapiv1.ClusterRole
|
||||||
ClusterRoleBindings []rbac.ClusterRoleBinding
|
ClusterRoleBindings []rbacapiv1.ClusterRoleBinding
|
||||||
Roles map[string][]rbac.Role
|
Roles map[string][]rbacapiv1.Role
|
||||||
RoleBindings map[string][]rbac.RoleBinding
|
RoleBindings map[string][]rbacapiv1.RoleBinding
|
||||||
// ClusterRolesToAggregate maps from previous clusterrole name to the new clusterrole name
|
// ClusterRolesToAggregate maps from previous clusterrole name to the new clusterrole name
|
||||||
ClusterRolesToAggregate map[string]string
|
ClusterRolesToAggregate map[string]string
|
||||||
}
|
}
|
||||||
|
@ -138,13 +138,13 @@ func (p *PolicyData) EnsureRBACPolicy() genericapiserver.PostStartHookFunc {
|
||||||
// starts, the roles don't initialize, and nothing works.
|
// starts, the roles don't initialize, and nothing works.
|
||||||
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
|
err := wait.Poll(1*time.Second, 30*time.Second, func() (done bool, err error) {
|
||||||
|
|
||||||
coreclientset, err := coreclient.NewForConfig(hookContext.LoopbackClientConfig)
|
coreclientset, err := corev1client.NewForConfig(hookContext.LoopbackClientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
clientset, err := rbacclient.NewForConfig(hookContext.LoopbackClientConfig)
|
clientset, err := rbacv1client.NewForConfig(hookContext.LoopbackClientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
utilruntime.HandleError(fmt.Errorf("unable to initialize client: %v", err))
|
||||||
return false, nil
|
return false, nil
|
||||||
|
@ -303,7 +303,7 @@ func (p RESTStorageProvider) GroupName() string {
|
||||||
|
|
||||||
// primeAggregatedClusterRoles copies roles that have transitioned to aggregated roles and may need to pick up changes
|
// primeAggregatedClusterRoles copies roles that have transitioned to aggregated roles and may need to pick up changes
|
||||||
// that were done to the legacy roles.
|
// that were done to the legacy roles.
|
||||||
func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacclient.ClusterRolesGetter) error {
|
func primeAggregatedClusterRoles(clusterRolesToAggregate map[string]string, clusterRoleClient rbacv1client.ClusterRolesGetter) error {
|
||||||
for oldName, newName := range clusterRolesToAggregate {
|
for oldName, newName := range clusterRolesToAggregate {
|
||||||
_, err := clusterRoleClient.ClusterRoles().Get(newName, metav1.GetOptions{})
|
_, err := clusterRoleClient.ClusterRoles().Get(newName, metav1.GetOptions{})
|
||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
|
@ -16,12 +16,12 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/apis/rbac/validation:go_default_library",
|
"//pkg/apis/rbac/validation:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
|
|
@ -52,7 +52,7 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
|
||||||
|
|
||||||
role := obj.(*rbac.Role)
|
role := obj.(*rbac.Role)
|
||||||
rules := role.Rules
|
rules := role.Rules
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil {
|
||||||
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
||||||
}
|
}
|
||||||
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
||||||
|
@ -72,7 +72,7 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
rules := role.Rules
|
rules := role.Rules
|
||||||
if err := rbacregistryvalidation.ConfirmNoEscalation(ctx, s.ruleResolver, rules); err != nil {
|
if err := rbacregistryvalidation.ConfirmNoEscalationInternal(ctx, s.ruleResolver, rules); err != nil {
|
||||||
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
return nil, errors.NewForbidden(groupResource, role.Name, err)
|
||||||
}
|
}
|
||||||
return obj, nil
|
return obj, nil
|
||||||
|
|
|
@ -19,27 +19,22 @@ package role
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry is an interface for things that know how to store Roles.
|
// Registry is an interface for things that know how to store Roles.
|
||||||
type Registry interface {
|
type Registry interface {
|
||||||
ListRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error)
|
GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error)
|
||||||
CreateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error
|
|
||||||
UpdateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error
|
|
||||||
GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.Role, error)
|
|
||||||
DeleteRole(ctx context.Context, name string) error
|
|
||||||
WatchRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage puts strong typing around storage calls
|
// storage puts strong typing around storage calls
|
||||||
type storage struct {
|
type storage struct {
|
||||||
rest.StandardStorage
|
rest.Getter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||||
|
@ -48,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry {
|
||||||
return &storage{s}
|
return &storage{s}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) ListRoles(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleList, error) {
|
func (s *storage) GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbacv1.Role, error) {
|
||||||
obj, err := s.List(ctx, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return obj.(*rbac.RoleList), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) CreateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc) error {
|
|
||||||
_, err := s.Create(ctx, role, createValidation, false)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) UpdateRole(ctx context.Context, role *rbac.Role, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error {
|
|
||||||
// TODO: any admission?
|
|
||||||
_, _, err := s.Update(ctx, role.Name, rest.DefaultUpdatedObjectInfo(role), createValidation, updateValidation)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) WatchRoles(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
|
||||||
return s.Watch(ctx, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) GetRole(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.Role, error) {
|
|
||||||
obj, err := s.Get(ctx, name, options)
|
obj, err := s.Get(ctx, name, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj.(*rbac.Role), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) DeleteRole(ctx context.Context, name string) error {
|
ret := &rbacv1.Role{}
|
||||||
_, _, err := s.Delete(ctx, name, nil)
|
if err := rbacv1helpers.Convert_rbac_Role_To_v1_Role(obj.(*rbac.Role), ret, nil); err != nil {
|
||||||
return err
|
return nil, err
|
||||||
|
}
|
||||||
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||||
|
@ -90,6 +61,6 @@ type AuthorizerAdapter struct {
|
||||||
Registry Registry
|
Registry Registry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbac.Role, error) {
|
func (a AuthorizerAdapter) GetRole(namespace, name string) (*rbacv1.Role, error) {
|
||||||
return a.Registry.GetRole(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), name, &metav1.GetOptions{})
|
return a.Registry.GetRole(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), name, &metav1.GetOptions{})
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,12 +16,12 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/apis/rbac/validation:go_default_library",
|
"//pkg/apis/rbac/validation:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/internalversion:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
|
||||||
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/endpoints/request:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/registry/rest:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/storage/names:go_default_library",
|
||||||
|
|
|
@ -12,8 +12,10 @@ go_library(
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/core/helper:go_default_library",
|
"//pkg/apis/core/helper:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/registry/rbac:go_default_library",
|
"//pkg/registry/rbac:go_default_library",
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||||
|
|
|
@ -20,6 +20,7 @@ package policybased
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/errors"
|
"k8s.io/apimachinery/pkg/api/errors"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
|
@ -27,6 +28,7 @@ import (
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
|
kapihelper "k8s.io/kubernetes/pkg/apis/core/helper"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
rbacregistry "k8s.io/kubernetes/pkg/registry/rbac"
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
@ -66,7 +68,12 @@ func (s *Storage) Create(ctx context.Context, obj runtime.Object, createValidati
|
||||||
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
return s.StandardStorage.Create(ctx, obj, createValidation, includeUninitialized)
|
||||||
}
|
}
|
||||||
|
|
||||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
v1RoleRef := rbacv1.RoleRef{}
|
||||||
|
err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -102,7 +109,12 @@ func (s *Storage) Update(ctx context.Context, name string, obj rest.UpdatedObjec
|
||||||
}
|
}
|
||||||
|
|
||||||
// Otherwise, see if we already have all the permissions contained in the referenced role
|
// Otherwise, see if we already have all the permissions contained in the referenced role
|
||||||
rules, err := s.ruleResolver.GetRoleReferenceRules(roleBinding.RoleRef, namespace)
|
v1RoleRef := rbacv1.RoleRef{}
|
||||||
|
err := rbacv1helpers.Convert_rbac_RoleRef_To_v1_RoleRef(&roleBinding.RoleRef, &v1RoleRef, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
rules, err := s.ruleResolver.GetRoleReferenceRules(v1RoleRef, namespace)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,27 +19,22 @@ package rolebinding
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/apiserver/pkg/registry/rest"
|
"k8s.io/apiserver/pkg/registry/rest"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Registry is an interface for things that know how to store RoleBindings.
|
// Registry is an interface for things that know how to store RoleBindings.
|
||||||
type Registry interface {
|
type Registry interface {
|
||||||
ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error)
|
ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error)
|
||||||
CreateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error
|
|
||||||
UpdateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error
|
|
||||||
GetRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error)
|
|
||||||
DeleteRoleBinding(ctx context.Context, name string) error
|
|
||||||
WatchRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// storage puts strong typing around storage calls
|
// storage puts strong typing around storage calls
|
||||||
type storage struct {
|
type storage struct {
|
||||||
rest.StandardStorage
|
rest.Lister
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
// NewRegistry returns a new Registry interface for the given Storage. Any mismatched
|
||||||
|
@ -48,41 +43,17 @@ func NewRegistry(s rest.StandardStorage) Registry {
|
||||||
return &storage{s}
|
return &storage{s}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *storage) ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbac.RoleBindingList, error) {
|
func (s *storage) ListRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (*rbacv1.RoleBindingList, error) {
|
||||||
obj, err := s.List(ctx, options)
|
obj, err := s.List(ctx, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return obj.(*rbac.RoleBindingList), nil
|
ret := &rbacv1.RoleBindingList{}
|
||||||
}
|
if err := rbacv1helpers.Convert_rbac_RoleBindingList_To_v1_RoleBindingList(obj.(*rbac.RoleBindingList), ret, nil); err != nil {
|
||||||
|
|
||||||
func (s *storage) CreateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc) error {
|
|
||||||
// TODO(ericchiang): add additional validation
|
|
||||||
_, err := s.Create(ctx, roleBinding, createValidation, false)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) UpdateRoleBinding(ctx context.Context, roleBinding *rbac.RoleBinding, createValidation rest.ValidateObjectFunc, updateValidation rest.ValidateObjectUpdateFunc) error {
|
|
||||||
_, _, err := s.Update(ctx, roleBinding.Name, rest.DefaultUpdatedObjectInfo(roleBinding), createValidation, updateValidation)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) WatchRoleBindings(ctx context.Context, options *metainternalversion.ListOptions) (watch.Interface, error) {
|
|
||||||
return s.Watch(ctx, options)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) GetRoleBinding(ctx context.Context, name string, options *metav1.GetOptions) (*rbac.RoleBinding, error) {
|
|
||||||
obj, err := s.Get(ctx, name, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return obj.(*rbac.RoleBinding), nil
|
return ret, nil
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storage) DeleteRoleBinding(ctx context.Context, name string) error {
|
|
||||||
_, _, err := s.Delete(ctx, name, nil)
|
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// AuthorizerAdapter adapts the registry to the authorizer interface
|
// AuthorizerAdapter adapts the registry to the authorizer interface
|
||||||
|
@ -90,13 +61,13 @@ type AuthorizerAdapter struct {
|
||||||
Registry Registry
|
Registry Registry
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
func (a AuthorizerAdapter) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) {
|
||||||
list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &metainternalversion.ListOptions{})
|
list, err := a.Registry.ListRoleBindings(genericapirequest.WithNamespace(genericapirequest.NewContext(), namespace), &metainternalversion.ListOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ret := []*rbac.RoleBinding{}
|
ret := []*rbacv1.RoleBinding{}
|
||||||
for i := range list.Items {
|
for i := range list.Items {
|
||||||
ret = append(ret, &list.Items[i])
|
ret = append(ret, &list.Items[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,8 @@ go_test(
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||||
|
@ -25,6 +26,7 @@ go_test(
|
||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"internal_version_adapter.go",
|
||||||
"policy_compact.go",
|
"policy_compact.go",
|
||||||
"policy_comparator.go",
|
"policy_comparator.go",
|
||||||
"rule.go",
|
"rule.go",
|
||||||
|
@ -32,7 +34,9 @@ go_library(
|
||||||
importpath = "k8s.io/kubernetes/pkg/registry/rbac/validation",
|
importpath = "k8s.io/kubernetes/pkg/registry/rbac/validation",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authentication/serviceaccount:go_default_library",
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
Copyright 2018 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package validation
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
"k8s.io/kubernetes/pkg/apis/rbac"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConfirmNoEscalationInternal(ctx context.Context, ruleResolver AuthorizationRuleResolver, inRules []rbac.PolicyRule) error {
|
||||||
|
rules := []rbacv1.PolicyRule{}
|
||||||
|
for i := range inRules {
|
||||||
|
v1Rule := rbacv1.PolicyRule{}
|
||||||
|
err := rbacv1helpers.Convert_rbac_PolicyRule_To_v1_PolicyRule(&inRules[i], &v1Rule, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
rules = append(rules, v1Rule)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConfirmNoEscalation(ctx, ruleResolver, rules)
|
||||||
|
}
|
|
@ -19,7 +19,7 @@ package validation
|
||||||
import (
|
import (
|
||||||
"reflect"
|
"reflect"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type simpleResource struct {
|
type simpleResource struct {
|
||||||
|
@ -31,10 +31,10 @@ type simpleResource struct {
|
||||||
|
|
||||||
// CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes.
|
// CompactRules combines rules that contain a single APIGroup/Resource, differ only by verb, and contain no other attributes.
|
||||||
// this is a fast check, and works well with the decomposed "missing rules" list from a Covers check.
|
// this is a fast check, and works well with the decomposed "missing rules" list from a Covers check.
|
||||||
func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) {
|
func CompactRules(rules []rbacv1.PolicyRule) ([]rbacv1.PolicyRule, error) {
|
||||||
compacted := make([]rbac.PolicyRule, 0, len(rules))
|
compacted := make([]rbacv1.PolicyRule, 0, len(rules))
|
||||||
|
|
||||||
simpleRules := map[simpleResource]*rbac.PolicyRule{}
|
simpleRules := map[simpleResource]*rbacv1.PolicyRule{}
|
||||||
for _, rule := range rules {
|
for _, rule := range rules {
|
||||||
if resource, isSimple := isSimpleResourceRule(&rule); isSimple {
|
if resource, isSimple := isSimpleResourceRule(&rule); isSimple {
|
||||||
if existingRule, ok := simpleRules[resource]; ok {
|
if existingRule, ok := simpleRules[resource]; ok {
|
||||||
|
@ -61,7 +61,7 @@ func CompactRules(rules []rbac.PolicyRule) ([]rbac.PolicyRule, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values
|
// isSimpleResourceRule returns true if the given rule contains verbs, a single resource, a single API group, at most one Resource Name, and no other values
|
||||||
func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) {
|
func isSimpleResourceRule(rule *rbacv1.PolicyRule) (simpleResource, bool) {
|
||||||
resource := simpleResource{}
|
resource := simpleResource{}
|
||||||
|
|
||||||
// If we have "complex" rule attributes, return early without allocations or expensive comparisons
|
// If we have "complex" rule attributes, return early without allocations or expensive comparisons
|
||||||
|
@ -74,7 +74,7 @@ func isSimpleResourceRule(rule *rbac.PolicyRule) (simpleResource, bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames
|
// Test if this rule only contains APIGroups/Resources/Verbs/ResourceNames
|
||||||
simpleRule := &rbac.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames}
|
simpleRule := &rbacv1.PolicyRule{APIGroups: rule.APIGroups, Resources: rule.Resources, Verbs: rule.Verbs, ResourceNames: rule.ResourceNames}
|
||||||
if !reflect.DeepEqual(simpleRule, rule) {
|
if !reflect.DeepEqual(simpleRule, rule) {
|
||||||
return resource, false
|
return resource, false
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,20 +21,21 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestCompactRules(t *testing.T) {
|
func TestCompactRules(t *testing.T) {
|
||||||
testcases := map[string]struct {
|
testcases := map[string]struct {
|
||||||
Rules []rbac.PolicyRule
|
Rules []rbacv1.PolicyRule
|
||||||
Expected []rbac.PolicyRule
|
Expected []rbacv1.PolicyRule
|
||||||
}{
|
}{
|
||||||
"empty": {
|
"empty": {
|
||||||
Rules: []rbac.PolicyRule{},
|
Rules: []rbacv1.PolicyRule{},
|
||||||
Expected: []rbac.PolicyRule{},
|
Expected: []rbacv1.PolicyRule{},
|
||||||
},
|
},
|
||||||
"simple": {
|
"simple": {
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
{Verbs: []string{"update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
{Verbs: []string{"update", "patch"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
|
@ -55,7 +56,7 @@ func TestCompactRules(t *testing.T) {
|
||||||
{Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}},
|
{Verbs: nil, APIGroups: []string{""}, Resources: []string{"pods"}},
|
||||||
{Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
|
{Verbs: []string{"create"}, APIGroups: []string{""}, Resources: []string{"pods"}},
|
||||||
},
|
},
|
||||||
Expected: []rbac.PolicyRule{
|
Expected: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"create", "delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
|
{Verbs: []string{"create", "delete"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}},
|
||||||
{Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}},
|
{Verbs: []string{"patch"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{""}},
|
||||||
{Verbs: []string{"get", "list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
|
{Verbs: []string{"get", "list"}, APIGroups: []string{"extensions"}, Resources: []string{"daemonsets"}, ResourceNames: []string{"foo"}},
|
||||||
|
@ -66,44 +67,44 @@ func TestCompactRules(t *testing.T) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"complex multi-group": {
|
"complex multi-group": {
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
{Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
{Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
||||||
},
|
},
|
||||||
Expected: []rbac.PolicyRule{
|
Expected: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
{Verbs: []string{"get"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
{Verbs: []string{"list"}, APIGroups: []string{"", "builds.openshift.io"}, Resources: []string{"builds"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"complex multi-resource": {
|
"complex multi-resource": {
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
||||||
},
|
},
|
||||||
Expected: []rbac.PolicyRule{
|
Expected: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"complex named-resource": {
|
"complex named-resource": {
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
|
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
|
||||||
},
|
},
|
||||||
Expected: []rbac.PolicyRule{
|
Expected: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild"}},
|
||||||
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
|
{Verbs: []string{"list"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"mybuild2"}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
"complex non-resource": {
|
"complex non-resource": {
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
|
||||||
},
|
},
|
||||||
Expected: []rbac.PolicyRule{
|
Expected: []rbacv1.PolicyRule{
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
||||||
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
|
{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/foo"}},
|
||||||
},
|
},
|
||||||
|
@ -112,7 +113,7 @@ func TestCompactRules(t *testing.T) {
|
||||||
|
|
||||||
for k, tc := range testcases {
|
for k, tc := range testcases {
|
||||||
rules := tc.Rules
|
rules := tc.Rules
|
||||||
originalRules := make([]rbac.PolicyRule, len(tc.Rules))
|
originalRules := make([]rbacv1.PolicyRule, len(tc.Rules))
|
||||||
for i := range tc.Rules {
|
for i := range tc.Rules {
|
||||||
originalRules[i] = *tc.Rules[i].DeepCopy()
|
originalRules[i] = *tc.Rules[i].DeepCopy()
|
||||||
}
|
}
|
||||||
|
@ -134,8 +135,8 @@ func TestCompactRules(t *testing.T) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Stable(rbac.SortableRuleSlice(compacted))
|
sort.Stable(rbacv1helpers.SortableRuleSlice(compacted))
|
||||||
sort.Stable(rbac.SortableRuleSlice(tc.Expected))
|
sort.Stable(rbacv1helpers.SortableRuleSlice(tc.Expected))
|
||||||
if !reflect.DeepEqual(compacted, tc.Expected) {
|
if !reflect.DeepEqual(compacted, tc.Expected) {
|
||||||
t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted)
|
t.Errorf("%s: Expected\n%#v\ngot\n%#v", k, tc.Expected, compacted)
|
||||||
continue
|
continue
|
||||||
|
@ -145,68 +146,68 @@ func TestCompactRules(t *testing.T) {
|
||||||
|
|
||||||
func TestIsSimpleResourceRule(t *testing.T) {
|
func TestIsSimpleResourceRule(t *testing.T) {
|
||||||
testcases := map[string]struct {
|
testcases := map[string]struct {
|
||||||
Rule rbac.PolicyRule
|
Rule rbacv1.PolicyRule
|
||||||
Simple bool
|
Simple bool
|
||||||
Resource simpleResource
|
Resource simpleResource
|
||||||
}{
|
}{
|
||||||
"simple, no verbs": {
|
"simple, no verbs": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
Simple: true,
|
Simple: true,
|
||||||
Resource: simpleResource{Group: "", Resource: "builds"},
|
Resource: simpleResource{Group: "", Resource: "builds"},
|
||||||
},
|
},
|
||||||
"simple, one verb": {
|
"simple, one verb": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
Simple: true,
|
Simple: true,
|
||||||
Resource: simpleResource{Group: "", Resource: "builds"},
|
Resource: simpleResource{Group: "", Resource: "builds"},
|
||||||
},
|
},
|
||||||
"simple, one empty resource name": {
|
"simple, one empty resource name": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{""}},
|
||||||
Simple: true,
|
Simple: true,
|
||||||
Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: ""},
|
Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: ""},
|
||||||
},
|
},
|
||||||
"simple, one resource name": {
|
"simple, one resource name": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo"}},
|
||||||
Simple: true,
|
Simple: true,
|
||||||
Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: "foo"},
|
Resource: simpleResource{Group: "", Resource: "builds", ResourceNameExist: true, ResourceName: "foo"},
|
||||||
},
|
},
|
||||||
"simple, multi verb": {
|
"simple, multi verb": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get", "list"}, APIGroups: []string{""}, Resources: []string{"builds"}},
|
||||||
Simple: true,
|
Simple: true,
|
||||||
Resource: simpleResource{Group: "", Resource: "builds"},
|
Resource: simpleResource{Group: "", Resource: "builds"},
|
||||||
},
|
},
|
||||||
|
|
||||||
"complex, empty": {
|
"complex, empty": {
|
||||||
Rule: rbac.PolicyRule{},
|
Rule: rbacv1.PolicyRule{},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, no group": {
|
"complex, no group": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{}, Resources: []string{"builds"}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, multi group": {
|
"complex, multi group": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{"a", "b"}, Resources: []string{"builds"}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, no resource": {
|
"complex, no resource": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, multi resource": {
|
"complex, multi resource": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds", "images"}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, resource names": {
|
"complex, resource names": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, ResourceNames: []string{"foo", "bar"}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
"complex, non-resource urls": {
|
"complex, non-resource urls": {
|
||||||
Rule: rbac.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
Rule: rbacv1.PolicyRule{Verbs: []string{"get"}, APIGroups: []string{""}, Resources: []string{"builds"}, NonResourceURLs: []string{"/"}},
|
||||||
Simple: false,
|
Simple: false,
|
||||||
Resource: simpleResource{},
|
Resource: simpleResource{},
|
||||||
},
|
},
|
||||||
|
|
|
@ -19,23 +19,23 @@ package validation
|
||||||
import (
|
import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Covers determines whether or not the ownerRules cover the servantRules in terms of allowed actions.
|
// 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.
|
// 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) {
|
func Covers(ownerRules, servantRules []rbacv1.PolicyRule) (bool, []rbacv1.PolicyRule) {
|
||||||
// 1. Break every servantRule into individual rule tuples: group, verb, resource, resourceName
|
// 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
|
// 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.
|
// 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
|
// TODO: it might be nice to collapse the list down into something more human readable
|
||||||
|
|
||||||
subrules := []rbac.PolicyRule{}
|
subrules := []rbacv1.PolicyRule{}
|
||||||
for _, servantRule := range servantRules {
|
for _, servantRule := range servantRules {
|
||||||
subrules = append(subrules, BreakdownRule(servantRule)...)
|
subrules = append(subrules, BreakdownRule(servantRule)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
uncoveredRules := []rbac.PolicyRule{}
|
uncoveredRules := []rbacv1.PolicyRule{}
|
||||||
for _, subrule := range subrules {
|
for _, subrule := range subrules {
|
||||||
covered := false
|
covered := false
|
||||||
for _, ownerRule := range ownerRules {
|
for _, ownerRule := range ownerRules {
|
||||||
|
@ -55,18 +55,18 @@ func Covers(ownerRules, servantRules []rbac.PolicyRule) (bool, []rbac.PolicyRule
|
||||||
|
|
||||||
// BreadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one
|
// BreadownRule takes a rule and builds an equivalent list of rules that each have at most one verb, one
|
||||||
// resource, and one resource name
|
// resource, and one resource name
|
||||||
func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule {
|
func BreakdownRule(rule rbacv1.PolicyRule) []rbacv1.PolicyRule {
|
||||||
subrules := []rbac.PolicyRule{}
|
subrules := []rbacv1.PolicyRule{}
|
||||||
for _, group := range rule.APIGroups {
|
for _, group := range rule.APIGroups {
|
||||||
for _, resource := range rule.Resources {
|
for _, resource := range rule.Resources {
|
||||||
for _, verb := range rule.Verbs {
|
for _, verb := range rule.Verbs {
|
||||||
if len(rule.ResourceNames) > 0 {
|
if len(rule.ResourceNames) > 0 {
|
||||||
for _, resourceName := range rule.ResourceNames {
|
for _, resourceName := range rule.ResourceNames {
|
||||||
subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}})
|
subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}, ResourceNames: []string{resourceName}})
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
subrules = append(subrules, rbac.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}})
|
subrules = append(subrules, rbacv1.PolicyRule{APIGroups: []string{group}, Resources: []string{resource}, Verbs: []string{verb}})
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ func BreakdownRule(rule rbac.PolicyRule) []rbac.PolicyRule {
|
||||||
// Non-resource URLs are unique because they only combine with verbs.
|
// Non-resource URLs are unique because they only combine with verbs.
|
||||||
for _, nonResourceURL := range rule.NonResourceURLs {
|
for _, nonResourceURL := range rule.NonResourceURLs {
|
||||||
for _, verb := range rule.Verbs {
|
for _, verb := range rule.Verbs {
|
||||||
subrules = append(subrules, rbac.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}})
|
subrules = append(subrules, rbacv1.PolicyRule{NonResourceURLs: []string{nonResourceURL}, Verbs: []string{verb}})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ func hasAll(set, contains []string) bool {
|
||||||
|
|
||||||
func resourceCoversAll(setResources, coversResources []string) bool {
|
func resourceCoversAll(setResources, coversResources []string) bool {
|
||||||
// if we have a star or an exact match on all resources, then we match
|
// if we have a star or an exact match on all resources, then we match
|
||||||
if has(setResources, rbac.ResourceAll) || hasAll(setResources, coversResources) {
|
if has(setResources, rbacv1.ResourceAll) || hasAll(setResources, coversResources) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +155,9 @@ func nonResourceURLCovers(ownerPath, subPath string) bool {
|
||||||
|
|
||||||
// ruleCovers determines whether the ownerRule (which may have multiple verbs, resources, and resourceNames) covers
|
// 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)
|
// the subrule (which may only contain at most one verb, resource, and resourceName)
|
||||||
func ruleCovers(ownerRule, subRule rbac.PolicyRule) bool {
|
func ruleCovers(ownerRule, subRule rbacv1.PolicyRule) bool {
|
||||||
verbMatches := has(ownerRule.Verbs, rbac.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs)
|
verbMatches := has(ownerRule.Verbs, rbacv1.VerbAll) || hasAll(ownerRule.Verbs, subRule.Verbs)
|
||||||
groupMatches := has(ownerRule.APIGroups, rbac.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups)
|
groupMatches := has(ownerRule.APIGroups, rbacv1.APIGroupAll) || hasAll(ownerRule.APIGroups, subRule.APIGroups)
|
||||||
resourceMatches := resourceCoversAll(ownerRule.Resources, subRule.Resources)
|
resourceMatches := resourceCoversAll(ownerRule.Resources, subRule.Resources)
|
||||||
nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs)
|
nonResourceURLMatches := nonResourceURLsCoversAll(ownerRule.NonResourceURLs, subRule.NonResourceURLs)
|
||||||
|
|
||||||
|
|
|
@ -20,65 +20,65 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
type escalationTest struct {
|
type escalationTest struct {
|
||||||
ownerRules []rbac.PolicyRule
|
ownerRules []rbacv1.PolicyRule
|
||||||
servantRules []rbac.PolicyRule
|
servantRules []rbacv1.PolicyRule
|
||||||
|
|
||||||
expectedCovered bool
|
expectedCovered bool
|
||||||
expectedUncoveredRules []rbac.PolicyRule
|
expectedUncoveredRules []rbacv1.PolicyRule
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversExactMatch(t *testing.T) {
|
func TestCoversExactMatch(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversSubresourceWildcard(t *testing.T) {
|
func TestCoversSubresourceWildcard(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*/scale"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*/scale"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"foo/scale"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"foo/scale"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) {
|
func TestCoversMultipleRulesCoveringSingleRule(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) {
|
func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||||
|
@ -86,22 +86,22 @@ func TestCoversMultipleAPIGroupsCoveringSingleRule(t *testing.T) {
|
||||||
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"group2"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||||
{APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"group2"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) {
|
func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"deployments"}},
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"delete"}, Resources: []string{"builds"}},
|
||||||
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"group1"}, Verbs: []string{"update"}, Resources: []string{"builds", "deployments"}},
|
||||||
|
@ -111,23 +111,23 @@ func TestCoversSingleAPIGroupsCoveringMultiple(t *testing.T) {
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) {
|
func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments"}},
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"pods"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete"}, Resources: []string{"pods"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments", "pods"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"delete", "update"}, Resources: []string{"builds", "deployments", "pods"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"pods"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"update"}, Resources: []string{"pods"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -135,29 +135,29 @@ func TestCoversMultipleRulesMissingSingleVerbResourceCombination(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversAPIGroupStarCoveringMultiple(t *testing.T) {
|
func TestCoversAPIGroupStarCoveringMultiple(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"group1", "group2"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) {
|
func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"dummy-group"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"dummy-group"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -165,43 +165,43 @@ func TestCoversEnumerationNotCoveringAPIGroupStar(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversAPIGroupStarCoveringStar(t *testing.T) {
|
func TestCoversAPIGroupStarCoveringStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"*"}, Verbs: []string{"get"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversVerbStarCoveringMultiple(t *testing.T) {
|
func TestCoversVerbStarCoveringMultiple(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"watch", "list"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"watch", "list"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) {
|
func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get", "list", "watch", "create", "update", "delete", "exec"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get", "list", "watch", "create", "update", "delete", "exec"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -209,43 +209,43 @@ func TestCoversEnumerationNotCoveringVerbStar(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversVerbStarCoveringStar(t *testing.T) {
|
func TestCoversVerbStarCoveringStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"*"}, Resources: []string{"roles"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversResourceStarCoveringMultiple(t *testing.T) {
|
func TestCoversResourceStarCoveringMultiple(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"resourcegroup:deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"resourcegroup:deployments"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) {
|
func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"roles", "resourcegroup:deployments"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"roles", "resourcegroup:deployments"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -253,43 +253,43 @@ func TestCoversEnumerationNotCoveringResourceStar(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversResourceStarCoveringStar(t *testing.T) {
|
func TestCoversResourceStarCoveringStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"*"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversResourceNameEmptyCoveringMultiple(t *testing.T) {
|
func TestCoversResourceNameEmptyCoveringMultiple(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) {
|
func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{"foo", "bar"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}, ResourceNames: []string{}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"pods"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -297,43 +297,43 @@ func TestCoversEnumerationNotCoveringResourceNameEmpty(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversNonResourceURLs(t *testing.T) {
|
func TestCoversNonResourceURLs(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversNonResourceURLsStar(t *testing.T) {
|
func TestCoversNonResourceURLsStar(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"*"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"*"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis", "/apis/v1", "/"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"/apis", "/apis/v1", "/"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) {
|
func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis", "/apis/v1"}, Verbs: []string{"get"}},
|
{NonResourceURLs: []string{"/apis", "/apis/v1"}, Verbs: []string{"get"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{
|
expectedUncoveredRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}},
|
{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}},
|
||||||
},
|
},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
|
@ -341,43 +341,43 @@ func TestCoversNonResourceURLsStarAfterPrefixDoesntCover(t *testing.T) {
|
||||||
|
|
||||||
func TestCoversNonResourceURLsStarAfterPrefix(t *testing.T) {
|
func TestCoversNonResourceURLsStarAfterPrefix(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
{NonResourceURLs: []string{"/apis/*"}, Verbs: []string{"*"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{NonResourceURLs: []string{"/apis/v1/foo", "/apis/v1"}, Verbs: []string{"get"}},
|
{NonResourceURLs: []string{"/apis/v1/foo", "/apis/v1"}, Verbs: []string{"get"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversNonResourceURLsWithOtherFields(t *testing.T) {
|
func TestCoversNonResourceURLsWithOtherFields(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: true,
|
expectedCovered: true,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{},
|
expectedUncoveredRules: []rbacv1.PolicyRule{},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCoversNonResourceURLsWithOtherFieldsFailure(t *testing.T) {
|
func TestCoversNonResourceURLsWithOtherFieldsFailure(t *testing.T) {
|
||||||
escalationTest{
|
escalationTest{
|
||||||
ownerRules: []rbac.PolicyRule{
|
ownerRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}},
|
||||||
},
|
},
|
||||||
servantRules: []rbac.PolicyRule{
|
servantRules: []rbacv1.PolicyRule{
|
||||||
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
{APIGroups: []string{"v1"}, Verbs: []string{"get"}, Resources: []string{"builds"}, NonResourceURLs: []string{"/apis"}},
|
||||||
},
|
},
|
||||||
|
|
||||||
expectedCovered: false,
|
expectedCovered: false,
|
||||||
expectedUncoveredRules: []rbac.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}},
|
expectedUncoveredRules: []rbacv1.PolicyRule{{NonResourceURLs: []string{"/apis"}, Verbs: []string{"get"}}},
|
||||||
}.test(t)
|
}.test(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -393,7 +393,7 @@ func (test escalationTest) test(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func rulesMatch(expectedRules, actualRules []rbac.PolicyRule) bool {
|
func rulesMatch(expectedRules, actualRules []rbacv1.PolicyRule) bool {
|
||||||
if len(expectedRules) != len(actualRules) {
|
if len(expectedRules) != len(actualRules) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,31 +23,31 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
"k8s.io/apiserver/pkg/authentication/serviceaccount"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type AuthorizationRuleResolver interface {
|
type AuthorizationRuleResolver interface {
|
||||||
// GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namepsace
|
// 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.
|
// of the role binding, the empty string if a cluster role binding.
|
||||||
GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error)
|
GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.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
|
// 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
|
// 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.
|
// can be made on the basis of those rules that are found.
|
||||||
RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error)
|
RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error)
|
||||||
|
|
||||||
// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, and each error encountered resolving those rules.
|
// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace, and each error encountered resolving those rules.
|
||||||
// If visitor() returns false, visiting is short-circuited.
|
// If visitor() returns false, visiting is short-circuited.
|
||||||
VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool)
|
VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role.
|
// ConfirmNoEscalation determines if the roles for a given user in a given namespace encompass the provided role.
|
||||||
func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleResolver, rules []rbac.PolicyRule) error {
|
func ConfirmNoEscalation(ctx context.Context, ruleResolver AuthorizationRuleResolver, rules []rbacv1.PolicyRule) error {
|
||||||
ruleResolutionErrors := []error{}
|
ruleResolutionErrors := []error{}
|
||||||
|
|
||||||
user, ok := genericapirequest.UserFrom(ctx)
|
user, ok := genericapirequest.UserFrom(ctx)
|
||||||
|
@ -82,33 +82,33 @@ func NewDefaultRuleResolver(roleGetter RoleGetter, roleBindingLister RoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleGetter interface {
|
type RoleGetter interface {
|
||||||
GetRole(namespace, name string) (*rbac.Role, error)
|
GetRole(namespace, name string) (*rbacv1.Role, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleBindingLister interface {
|
type RoleBindingLister interface {
|
||||||
ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error)
|
ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleGetter interface {
|
type ClusterRoleGetter interface {
|
||||||
GetClusterRole(name string) (*rbac.ClusterRole, error)
|
GetClusterRole(name string) (*rbacv1.ClusterRole, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ClusterRoleBindingLister interface {
|
type ClusterRoleBindingLister interface {
|
||||||
ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error)
|
ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbac.PolicyRule, error) {
|
func (r *DefaultRuleResolver) RulesFor(user user.Info, namespace string) ([]rbacv1.PolicyRule, error) {
|
||||||
visitor := &ruleAccumulator{}
|
visitor := &ruleAccumulator{}
|
||||||
r.VisitRulesFor(user, namespace, visitor.visit)
|
r.VisitRulesFor(user, namespace, visitor.visit)
|
||||||
return visitor.rules, utilerrors.NewAggregate(visitor.errors)
|
return visitor.rules, utilerrors.NewAggregate(visitor.errors)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ruleAccumulator struct {
|
type ruleAccumulator struct {
|
||||||
rules []rbac.PolicyRule
|
rules []rbacv1.PolicyRule
|
||||||
errors []error
|
errors []error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool {
|
func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool {
|
||||||
if rule != nil {
|
if rule != nil {
|
||||||
r.rules = append(r.rules, *rule)
|
r.rules = append(r.rules, *rule)
|
||||||
}
|
}
|
||||||
|
@ -118,9 +118,9 @@ func (r *ruleAccumulator) visit(source fmt.Stringer, rule *rbac.PolicyRule, err
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func describeSubject(s *rbac.Subject, bindingNamespace string) string {
|
func describeSubject(s *rbacv1.Subject, bindingNamespace string) string {
|
||||||
switch s.Kind {
|
switch s.Kind {
|
||||||
case rbac.ServiceAccountKind:
|
case rbacv1.ServiceAccountKind:
|
||||||
if len(s.Namespace) > 0 {
|
if len(s.Namespace) > 0 {
|
||||||
return fmt.Sprintf("%s %q", s.Kind, s.Name+"/"+s.Namespace)
|
return fmt.Sprintf("%s %q", s.Kind, s.Name+"/"+s.Namespace)
|
||||||
}
|
}
|
||||||
|
@ -131,8 +131,8 @@ func describeSubject(s *rbac.Subject, bindingNamespace string) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type clusterRoleBindingDescriber struct {
|
type clusterRoleBindingDescriber struct {
|
||||||
binding *rbac.ClusterRoleBinding
|
binding *rbacv1.ClusterRoleBinding
|
||||||
subject *rbac.Subject
|
subject *rbacv1.Subject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *clusterRoleBindingDescriber) String() string {
|
func (d *clusterRoleBindingDescriber) String() string {
|
||||||
|
@ -145,8 +145,8 @@ func (d *clusterRoleBindingDescriber) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type roleBindingDescriber struct {
|
type roleBindingDescriber struct {
|
||||||
binding *rbac.RoleBinding
|
binding *rbacv1.RoleBinding
|
||||||
subject *rbac.Subject
|
subject *rbacv1.Subject
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *roleBindingDescriber) String() string {
|
func (d *roleBindingDescriber) String() string {
|
||||||
|
@ -158,7 +158,7 @@ func (d *roleBindingDescriber) String() string {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool) {
|
func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool) {
|
||||||
if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil {
|
if clusterRoleBindings, err := r.clusterRoleBindingLister.ListClusterRoleBindings(); err != nil {
|
||||||
if !visitor(nil, nil, err) {
|
if !visitor(nil, nil, err) {
|
||||||
return
|
return
|
||||||
|
@ -219,16 +219,16 @@ func (r *DefaultRuleResolver) VisitRulesFor(user user.Info, namespace string, vi
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding.
|
// GetRoleReferenceRules attempts to resolve the RoleBinding or ClusterRoleBinding.
|
||||||
func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindingNamespace string) ([]rbac.PolicyRule, error) {
|
func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbacv1.RoleRef, bindingNamespace string) ([]rbacv1.PolicyRule, error) {
|
||||||
switch kind := rbac.RoleRefGroupKind(roleRef); kind {
|
switch roleRef.Kind {
|
||||||
case rbac.Kind("Role"):
|
case "Role":
|
||||||
role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name)
|
role, err := r.roleGetter.GetRole(bindingNamespace, roleRef.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return role.Rules, nil
|
return role.Rules, nil
|
||||||
|
|
||||||
case rbac.Kind("ClusterRole"):
|
case "ClusterRole":
|
||||||
clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name)
|
clusterRole, err := r.clusterRoleGetter.GetClusterRole(roleRef.Name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -236,13 +236,13 @@ func (r *DefaultRuleResolver) GetRoleReferenceRules(roleRef rbac.RoleRef, bindin
|
||||||
return clusterRole.Rules, nil
|
return clusterRole.Rules, nil
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported role reference kind: %q", kind)
|
return nil, fmt.Errorf("unsupported role reference kind: %q", roleRef.Kind)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// appliesTo returns whether any of the bindingSubjects applies to the specified subject,
|
// appliesTo returns whether any of the bindingSubjects applies to the specified subject,
|
||||||
// and if true, the index of the first subject that applies
|
// and if true, the index of the first subject that applies
|
||||||
func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string) (int, bool) {
|
func appliesTo(user user.Info, bindingSubjects []rbacv1.Subject, namespace string) (int, bool) {
|
||||||
for i, bindingSubject := range bindingSubjects {
|
for i, bindingSubject := range bindingSubjects {
|
||||||
if appliesToUser(user, bindingSubject, namespace) {
|
if appliesToUser(user, bindingSubject, namespace) {
|
||||||
return i, true
|
return i, true
|
||||||
|
@ -251,15 +251,15 @@ func appliesTo(user user.Info, bindingSubjects []rbac.Subject, namespace string)
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
|
|
||||||
func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool {
|
func appliesToUser(user user.Info, subject rbacv1.Subject, namespace string) bool {
|
||||||
switch subject.Kind {
|
switch subject.Kind {
|
||||||
case rbac.UserKind:
|
case rbacv1.UserKind:
|
||||||
return user.GetName() == subject.Name
|
return user.GetName() == subject.Name
|
||||||
|
|
||||||
case rbac.GroupKind:
|
case rbacv1.GroupKind:
|
||||||
return has(user.GetGroups(), subject.Name)
|
return has(user.GetGroups(), subject.Name)
|
||||||
|
|
||||||
case rbac.ServiceAccountKind:
|
case rbacv1.ServiceAccountKind:
|
||||||
// default the namespace to namespace we're working in if its available. This allows rolebindings that reference
|
// 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.
|
// SAs in th local namespace to avoid having to qualify them.
|
||||||
saNamespace := namespace
|
saNamespace := namespace
|
||||||
|
@ -276,7 +276,7 @@ func appliesToUser(user user.Info, subject rbac.Subject, namespace string) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTestRuleResolver returns a rule resolver from lists of role objects.
|
// 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) {
|
func NewTestRuleResolver(roles []*rbacv1.Role, roleBindings []*rbacv1.RoleBinding, clusterRoles []*rbacv1.ClusterRole, clusterRoleBindings []*rbacv1.ClusterRoleBinding) (AuthorizationRuleResolver, *StaticRoles) {
|
||||||
r := StaticRoles{
|
r := StaticRoles{
|
||||||
roles: roles,
|
roles: roles,
|
||||||
roleBindings: roleBindings,
|
roleBindings: roleBindings,
|
||||||
|
@ -292,13 +292,13 @@ func newMockRuleResolver(r *StaticRoles) AuthorizationRuleResolver {
|
||||||
|
|
||||||
// StaticRoles is a rule resolver that resolves from lists of role objects.
|
// StaticRoles is a rule resolver that resolves from lists of role objects.
|
||||||
type StaticRoles struct {
|
type StaticRoles struct {
|
||||||
roles []*rbac.Role
|
roles []*rbacv1.Role
|
||||||
roleBindings []*rbac.RoleBinding
|
roleBindings []*rbacv1.RoleBinding
|
||||||
clusterRoles []*rbac.ClusterRole
|
clusterRoles []*rbacv1.ClusterRole
|
||||||
clusterRoleBindings []*rbac.ClusterRoleBinding
|
clusterRoleBindings []*rbacv1.ClusterRoleBinding
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) {
|
func (r *StaticRoles) GetRole(namespace, name string) (*rbacv1.Role, error) {
|
||||||
if len(namespace) == 0 {
|
if len(namespace) == 0 {
|
||||||
return nil, errors.New("must provide namespace when getting role")
|
return nil, errors.New("must provide namespace when getting role")
|
||||||
}
|
}
|
||||||
|
@ -310,7 +310,7 @@ func (r *StaticRoles) GetRole(namespace, name string) (*rbac.Role, error) {
|
||||||
return nil, errors.New("role not found")
|
return nil, errors.New("role not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
func (r *StaticRoles) GetClusterRole(name string) (*rbacv1.ClusterRole, error) {
|
||||||
for _, clusterRole := range r.clusterRoles {
|
for _, clusterRole := range r.clusterRoles {
|
||||||
if clusterRole.Name == name {
|
if clusterRole.Name == name {
|
||||||
return clusterRole, nil
|
return clusterRole, nil
|
||||||
|
@ -319,12 +319,12 @@ func (r *StaticRoles) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
||||||
return nil, errors.New("clusterrole not found")
|
return nil, errors.New("clusterrole not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) {
|
||||||
if len(namespace) == 0 {
|
if len(namespace) == 0 {
|
||||||
return nil, errors.New("must provide namespace when listing role bindings")
|
return nil, errors.New("must provide namespace when listing role bindings")
|
||||||
}
|
}
|
||||||
|
|
||||||
roleBindingList := []*rbac.RoleBinding{}
|
roleBindingList := []*rbacv1.RoleBinding{}
|
||||||
for _, roleBinding := range r.roleBindings {
|
for _, roleBinding := range r.roleBindings {
|
||||||
if roleBinding.Namespace != namespace {
|
if roleBinding.Namespace != namespace {
|
||||||
continue
|
continue
|
||||||
|
@ -335,6 +335,6 @@ func (r *StaticRoles) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, e
|
||||||
return roleBindingList, nil
|
return roleBindingList, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *StaticRoles) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
func (r *StaticRoles) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) {
|
||||||
return r.clusterRoleBindings, nil
|
return r.clusterRoleBindings, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// compute a hash of a policy rule so we can sort in a deterministic order
|
// compute a hash of a policy rule so we can sort in a deterministic order
|
||||||
func hashOf(p rbac.PolicyRule) string {
|
func hashOf(p rbacv1.PolicyRule) string {
|
||||||
hash := fnv.New32()
|
hash := fnv.New32()
|
||||||
writeStrings := func(slis ...[]string) {
|
writeStrings := func(slis ...[]string) {
|
||||||
for _, sli := range slis {
|
for _, sli := range slis {
|
||||||
|
@ -44,68 +44,68 @@ func hashOf(p rbac.PolicyRule) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
// byHash sorts a set of policy rules by a hash of its fields
|
// byHash sorts a set of policy rules by a hash of its fields
|
||||||
type byHash []rbac.PolicyRule
|
type byHash []rbacv1.PolicyRule
|
||||||
|
|
||||||
func (b byHash) Len() int { return len(b) }
|
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) 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 (b byHash) Swap(i, j int) { b[i], b[j] = b[j], b[i] }
|
||||||
|
|
||||||
func TestDefaultRuleResolver(t *testing.T) {
|
func TestDefaultRuleResolver(t *testing.T) {
|
||||||
ruleReadPods := rbac.PolicyRule{
|
ruleReadPods := rbacv1.PolicyRule{
|
||||||
Verbs: []string{"GET", "WATCH"},
|
Verbs: []string{"GET", "WATCH"},
|
||||||
APIGroups: []string{"v1"},
|
APIGroups: []string{"v1"},
|
||||||
Resources: []string{"pods"},
|
Resources: []string{"pods"},
|
||||||
}
|
}
|
||||||
ruleReadServices := rbac.PolicyRule{
|
ruleReadServices := rbacv1.PolicyRule{
|
||||||
Verbs: []string{"GET", "WATCH"},
|
Verbs: []string{"GET", "WATCH"},
|
||||||
APIGroups: []string{"v1"},
|
APIGroups: []string{"v1"},
|
||||||
Resources: []string{"services"},
|
Resources: []string{"services"},
|
||||||
}
|
}
|
||||||
ruleWriteNodes := rbac.PolicyRule{
|
ruleWriteNodes := rbacv1.PolicyRule{
|
||||||
Verbs: []string{"PUT", "CREATE", "UPDATE"},
|
Verbs: []string{"PUT", "CREATE", "UPDATE"},
|
||||||
APIGroups: []string{"v1"},
|
APIGroups: []string{"v1"},
|
||||||
Resources: []string{"nodes"},
|
Resources: []string{"nodes"},
|
||||||
}
|
}
|
||||||
ruleAdmin := rbac.PolicyRule{
|
ruleAdmin := rbacv1.PolicyRule{
|
||||||
Verbs: []string{"*"},
|
Verbs: []string{"*"},
|
||||||
APIGroups: []string{"*"},
|
APIGroups: []string{"*"},
|
||||||
Resources: []string{"*"},
|
Resources: []string{"*"},
|
||||||
}
|
}
|
||||||
|
|
||||||
staticRoles1 := StaticRoles{
|
staticRoles1 := StaticRoles{
|
||||||
roles: []*rbac.Role{
|
roles: []*rbacv1.Role{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1", Name: "readthings"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1", Name: "readthings"},
|
||||||
Rules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
Rules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
|
ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
|
||||||
Rules: []rbac.PolicyRule{ruleAdmin},
|
Rules: []rbacv1.PolicyRule{ruleAdmin},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "write-nodes"},
|
ObjectMeta: metav1.ObjectMeta{Name: "write-nodes"},
|
||||||
Rules: []rbac.PolicyRule{ruleWriteNodes},
|
Rules: []rbacv1.PolicyRule{ruleWriteNodes},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1"},
|
ObjectMeta: metav1.ObjectMeta{Namespace: "namespace1"},
|
||||||
Subjects: []rbac.Subject{
|
Subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "foobar"},
|
{Kind: rbacv1.UserKind, Name: "foobar"},
|
||||||
{Kind: rbac.GroupKind, Name: "group1"},
|
{Kind: rbacv1.GroupKind, Name: "group1"},
|
||||||
},
|
},
|
||||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "readthings"},
|
RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: "readthings"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
clusterRoleBindings: []*rbacv1.ClusterRoleBinding{
|
||||||
{
|
{
|
||||||
Subjects: []rbac.Subject{
|
Subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "admin"},
|
{Kind: rbacv1.UserKind, Name: "admin"},
|
||||||
{Kind: rbac.GroupKind, Name: "admin"},
|
{Kind: rbacv1.GroupKind, Name: "admin"},
|
||||||
},
|
},
|
||||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "cluster-admin"},
|
RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: "cluster-admin"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -116,13 +116,13 @@ func TestDefaultRuleResolver(t *testing.T) {
|
||||||
// For a given context, what are the rules that apply?
|
// For a given context, what are the rules that apply?
|
||||||
user user.Info
|
user user.Info
|
||||||
namespace string
|
namespace string
|
||||||
effectiveRules []rbac.PolicyRule
|
effectiveRules []rbacv1.PolicyRule
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
StaticRoles: staticRoles1,
|
StaticRoles: staticRoles1,
|
||||||
user: &user.DefaultInfo{Name: "foobar"},
|
user: &user.DefaultInfo{Name: "foobar"},
|
||||||
namespace: "namespace1",
|
namespace: "namespace1",
|
||||||
effectiveRules: []rbac.PolicyRule{ruleReadPods, ruleReadServices},
|
effectiveRules: []rbacv1.PolicyRule{ruleReadPods, ruleReadServices},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
StaticRoles: staticRoles1,
|
StaticRoles: staticRoles1,
|
||||||
|
@ -134,7 +134,7 @@ func TestDefaultRuleResolver(t *testing.T) {
|
||||||
StaticRoles: staticRoles1,
|
StaticRoles: staticRoles1,
|
||||||
// Same as above but without a namespace. Only cluster rules should apply.
|
// Same as above but without a namespace. Only cluster rules should apply.
|
||||||
user: &user.DefaultInfo{Name: "foobar", Groups: []string{"admin"}},
|
user: &user.DefaultInfo{Name: "foobar", Groups: []string{"admin"}},
|
||||||
effectiveRules: []rbac.PolicyRule{ruleAdmin},
|
effectiveRules: []rbacv1.PolicyRule{ruleAdmin},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
StaticRoles: staticRoles1,
|
StaticRoles: staticRoles1,
|
||||||
|
@ -164,7 +164,7 @@ func TestDefaultRuleResolver(t *testing.T) {
|
||||||
|
|
||||||
func TestAppliesTo(t *testing.T) {
|
func TestAppliesTo(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
subjects []rbac.Subject
|
subjects []rbacv1.Subject
|
||||||
user user.Info
|
user user.Info
|
||||||
namespace string
|
namespace string
|
||||||
appliesTo bool
|
appliesTo bool
|
||||||
|
@ -172,8 +172,8 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase string
|
testCase string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "foobar"},
|
{Kind: rbacv1.UserKind, Name: "foobar"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "foobar"},
|
user: &user.DefaultInfo{Name: "foobar"},
|
||||||
appliesTo: true,
|
appliesTo: true,
|
||||||
|
@ -181,9 +181,9 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "single subject that matches username",
|
testCase: "single subject that matches username",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
{Kind: rbacv1.UserKind, Name: "barfoo"},
|
||||||
{Kind: rbac.UserKind, Name: "foobar"},
|
{Kind: rbacv1.UserKind, Name: "foobar"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "foobar"},
|
user: &user.DefaultInfo{Name: "foobar"},
|
||||||
appliesTo: true,
|
appliesTo: true,
|
||||||
|
@ -191,18 +191,18 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "multiple subjects, one that matches username",
|
testCase: "multiple subjects, one that matches username",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
{Kind: rbacv1.UserKind, Name: "barfoo"},
|
||||||
{Kind: rbac.UserKind, Name: "foobar"},
|
{Kind: rbacv1.UserKind, Name: "foobar"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "zimzam"},
|
user: &user.DefaultInfo{Name: "zimzam"},
|
||||||
appliesTo: false,
|
appliesTo: false,
|
||||||
testCase: "multiple subjects, none that match username",
|
testCase: "multiple subjects, none that match username",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
{Kind: rbacv1.UserKind, Name: "barfoo"},
|
||||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
{Kind: rbacv1.GroupKind, Name: "foobar"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
||||||
appliesTo: true,
|
appliesTo: true,
|
||||||
|
@ -210,9 +210,9 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "multiple subjects, one that match group",
|
testCase: "multiple subjects, one that match group",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
{Kind: rbacv1.UserKind, Name: "barfoo"},
|
||||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
{Kind: rbacv1.GroupKind, Name: "foobar"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
user: &user.DefaultInfo{Name: "zimzam", Groups: []string{"foobar"}},
|
||||||
namespace: "namespace1",
|
namespace: "namespace1",
|
||||||
|
@ -221,10 +221,10 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "multiple subjects, one that match group, should ignore namespace",
|
testCase: "multiple subjects, one that match group, should ignore namespace",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "barfoo"},
|
{Kind: rbacv1.UserKind, Name: "barfoo"},
|
||||||
{Kind: rbac.GroupKind, Name: "foobar"},
|
{Kind: rbacv1.GroupKind, Name: "foobar"},
|
||||||
{Kind: rbac.ServiceAccountKind, Namespace: "kube-system", Name: "default"},
|
{Kind: rbacv1.ServiceAccountKind, Namespace: "kube-system", Name: "default"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "system:serviceaccount:kube-system:default"},
|
user: &user.DefaultInfo{Name: "system:serviceaccount:kube-system:default"},
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
|
@ -233,8 +233,8 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "multiple subjects with a service account that matches",
|
testCase: "multiple subjects with a service account that matches",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.UserKind, Name: "*"},
|
{Kind: rbacv1.UserKind, Name: "*"},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "foobar"},
|
user: &user.DefaultInfo{Name: "foobar"},
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
|
@ -242,9 +242,9 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "* user subject name doesn't match all users",
|
testCase: "* user subject name doesn't match all users",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, Name: user.AllAuthenticated},
|
{Kind: rbacv1.GroupKind, Name: user.AllAuthenticated},
|
||||||
{Kind: rbac.GroupKind, Name: user.AllUnauthenticated},
|
{Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "foobar", Groups: []string{user.AllAuthenticated}},
|
user: &user.DefaultInfo{Name: "foobar", Groups: []string{user.AllAuthenticated}},
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
|
@ -253,9 +253,9 @@ func TestAppliesTo(t *testing.T) {
|
||||||
testCase: "binding to all authenticated and unauthenticated subjects matches authenticated user",
|
testCase: "binding to all authenticated and unauthenticated subjects matches authenticated user",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
subjects: []rbac.Subject{
|
subjects: []rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, Name: user.AllAuthenticated},
|
{Kind: rbacv1.GroupKind, Name: user.AllAuthenticated},
|
||||||
{Kind: rbac.GroupKind, Name: user.AllUnauthenticated},
|
{Kind: rbacv1.GroupKind, Name: user.AllUnauthenticated},
|
||||||
},
|
},
|
||||||
user: &user.DefaultInfo{Name: "system:anonymous", Groups: []string{user.AllUnauthenticated}},
|
user: &user.DefaultInfo{Name: "system:anonymous", Groups: []string{user.AllUnauthenticated}},
|
||||||
namespace: "default",
|
namespace: "default",
|
||||||
|
|
|
@ -42,7 +42,6 @@ go_library(
|
||||||
"//pkg/api/persistentvolume:go_default_library",
|
"//pkg/api/persistentvolume:go_default_library",
|
||||||
"//pkg/api/pod:go_default_library",
|
"//pkg/api/pod:go_default_library",
|
||||||
"//pkg/apis/core:go_default_library",
|
"//pkg/apis/core:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
|
||||||
"//pkg/apis/storage:go_default_library",
|
"//pkg/apis/storage:go_default_library",
|
||||||
"//pkg/auth/nodeidentifier:go_default_library",
|
"//pkg/auth/nodeidentifier:go_default_library",
|
||||||
"//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library",
|
"//pkg/client/informers/informers_generated/internalversion/core/internalversion:go_default_library",
|
||||||
|
@ -52,6 +51,7 @@ go_library(
|
||||||
"//third_party/forked/gonum/graph/simple:go_default_library",
|
"//third_party/forked/gonum/graph/simple:go_default_library",
|
||||||
"//third_party/forked/gonum/graph/traverse:go_default_library",
|
"//third_party/forked/gonum/graph/traverse:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
"//vendor/k8s.io/api/storage/v1beta1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||||
|
|
|
@ -21,11 +21,11 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
rbacapi "k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
storageapi "k8s.io/kubernetes/pkg/apis/storage"
|
||||||
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
"k8s.io/kubernetes/pkg/auth/nodeidentifier"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
|
@ -49,14 +49,14 @@ import (
|
||||||
type NodeAuthorizer struct {
|
type NodeAuthorizer struct {
|
||||||
graph *Graph
|
graph *Graph
|
||||||
identifier nodeidentifier.NodeIdentifier
|
identifier nodeidentifier.NodeIdentifier
|
||||||
nodeRules []rbacapi.PolicyRule
|
nodeRules []rbacv1.PolicyRule
|
||||||
|
|
||||||
// allows overriding for testing
|
// allows overriding for testing
|
||||||
features utilfeature.FeatureGate
|
features utilfeature.FeatureGate
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAuthorizer returns a new node authorizer
|
// NewAuthorizer returns a new node authorizer
|
||||||
func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacapi.PolicyRule) authorizer.Authorizer {
|
func NewAuthorizer(graph *Graph, identifier nodeidentifier.NodeIdentifier, rules []rbacv1.PolicyRule) authorizer.Authorizer {
|
||||||
return &NodeAuthorizer{
|
return &NodeAuthorizer{
|
||||||
graph: graph,
|
graph: graph,
|
||||||
identifier: identifier,
|
identifier: identifier,
|
||||||
|
|
|
@ -14,14 +14,15 @@ go_library(
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac",
|
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/client/listers/rbac/internalversion:go_default_library",
|
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||||
|
"//vendor/k8s.io/client-go/listers/rbac/v1:go_default_library",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -33,9 +34,10 @@ go_test(
|
||||||
],
|
],
|
||||||
embed = [":go_default_library"],
|
embed = [":go_default_library"],
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
|
"//plugin/pkg/auth/authorizer/rbac/bootstrappolicy:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authentication/user:go_default_library",
|
||||||
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
"//vendor/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
|
||||||
|
|
|
@ -15,9 +15,10 @@ go_library(
|
||||||
],
|
],
|
||||||
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy",
|
importpath = "k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy",
|
||||||
deps = [
|
deps = [
|
||||||
"//pkg/apis/rbac:go_default_library",
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/features:go_default_library",
|
"//pkg/features:go_default_library",
|
||||||
"//vendor/github.com/golang/glog:go_default_library",
|
"//vendor/github.com/golang/glog:go_default_library",
|
||||||
|
"//vendor/k8s.io/api/rbac/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||||
|
@ -37,8 +38,8 @@ go_test(
|
||||||
"//pkg/api/legacyscheme:go_default_library",
|
"//pkg/api/legacyscheme:go_default_library",
|
||||||
"//pkg/apis/core:go_default_library",
|
"//pkg/apis/core:go_default_library",
|
||||||
"//pkg/apis/core/install:go_default_library",
|
"//pkg/apis/core/install:go_default_library",
|
||||||
"//pkg/apis/rbac:go_default_library",
|
|
||||||
"//pkg/apis/rbac/install:go_default_library",
|
"//pkg/apis/rbac/install:go_default_library",
|
||||||
|
"//pkg/apis/rbac/v1:go_default_library",
|
||||||
"//pkg/registry/rbac/validation:go_default_library",
|
"//pkg/registry/rbac/validation:go_default_library",
|
||||||
"//vendor/github.com/ghodss/yaml:go_default_library",
|
"//vendor/github.com/ghodss/yaml:go_default_library",
|
||||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||||
|
|
|
@ -21,15 +21,16 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
const saRolePrefix = "system:controller:"
|
const saRolePrefix = "system:controller:"
|
||||||
|
|
||||||
func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindings *[]rbac.ClusterRoleBinding, role rbac.ClusterRole) {
|
func addControllerRole(controllerRoles *[]rbacv1.ClusterRole, controllerRoleBindings *[]rbacv1.ClusterRoleBinding, role rbacv1.ClusterRole) {
|
||||||
if !strings.HasPrefix(role.Name, saRolePrefix) {
|
if !strings.HasPrefix(role.Name, saRolePrefix) {
|
||||||
glog.Fatalf(`role %q must start with %q`, role.Name, saRolePrefix)
|
glog.Fatalf(`role %q must start with %q`, role.Name, saRolePrefix)
|
||||||
}
|
}
|
||||||
|
@ -44,298 +45,298 @@ func addControllerRole(controllerRoles *[]rbac.ClusterRole, controllerRoleBindin
|
||||||
addClusterRoleLabel(*controllerRoles)
|
addClusterRoleLabel(*controllerRoles)
|
||||||
|
|
||||||
*controllerRoleBindings = append(*controllerRoleBindings,
|
*controllerRoleBindings = append(*controllerRoleBindings,
|
||||||
rbac.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie())
|
rbacv1helpers.NewClusterBinding(role.Name).SAs("kube-system", role.Name[len(saRolePrefix):]).BindingOrDie())
|
||||||
addClusterRoleBindingLabel(*controllerRoleBindings)
|
addClusterRoleBindingLabel(*controllerRoleBindings)
|
||||||
}
|
}
|
||||||
|
|
||||||
func eventsRule() rbac.PolicyRule {
|
func eventsRule() rbacv1.PolicyRule {
|
||||||
return rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie()
|
return rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie()
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) {
|
func buildControllerRoles() ([]rbacv1.ClusterRole, []rbacv1.ClusterRoleBinding) {
|
||||||
// controllerRoles is a slice of roles used for controllers
|
// controllerRoles is a slice of roles used for controllers
|
||||||
controllerRoles := []rbac.ClusterRole{}
|
controllerRoles := []rbacv1.ClusterRole{}
|
||||||
// controllerRoleBindings is a slice of roles used for controllers
|
// controllerRoleBindings is a slice of roles used for controllers
|
||||||
controllerRoleBindings := []rbac.ClusterRoleBinding{}
|
controllerRoleBindings := []rbacv1.ClusterRoleBinding{}
|
||||||
|
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbac.ClusterRole {
|
addControllerRole(&controllerRoles, &controllerRoleBindings, func() rbacv1.ClusterRole {
|
||||||
role := rbac.ClusterRole{
|
role := rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "attachdetach-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "attachdetach-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("persistentvolumes", "persistentvolumeclaims").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
||||||
role.Rules = append(role.Rules, rbac.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie())
|
role.Rules = append(role.Rules, rbacv1helpers.NewRule("get", "create", "delete", "list", "watch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie())
|
||||||
}
|
}
|
||||||
|
|
||||||
return role
|
return role
|
||||||
}())
|
}())
|
||||||
|
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "clusterrole-aggregation-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "clusterrole-aggregation-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// this controller must have full permissions to allow it to mutate any role in any way
|
// this controller must have full permissions to allow it to mutate any role in any way
|
||||||
rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
|
||||||
rbac.NewRule("*").URLs("*").RuleOrDie(),
|
rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cronjob-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cronjob-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("cronjobs").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "delete", "patch").Groups(batchGroup).Resources("jobs").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("cronjobs/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "daemon-set-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "daemon-set-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("daemonsets").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("daemonsets/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "delete", "update", "patch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "deployment-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "deployment-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(extensionsGroup, appsGroup).Resources("deployments/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch", "delete").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
||||||
// TODO: remove "update" once
|
// TODO: remove "update" once
|
||||||
// https://github.com/kubernetes/kubernetes/issues/36897 is resolved.
|
// https://github.com/kubernetes/kubernetes/issues/36897 is resolved.
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "disruption-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "disruption-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(extensionsGroup, appsGroup).Resources("deployments").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(policyGroup).Resources("poddisruptionbudgets/status").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpoint-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "endpoint-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services", "pods").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "create", "update", "delete").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints/restricted").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "expand-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "expand-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
// glusterfs
|
// glusterfs
|
||||||
rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "generic-garbage-collector"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// the GC controller needs to run list/watches, selective gets, and updates against any resource
|
// the GC controller needs to run list/watches, selective gets, and updates against any resource
|
||||||
rbac.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "patch", "update", "delete").Groups("*").Resources("*").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "horizontal-pod-autoscaler"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "horizontal-pod-autoscaler"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(autoscalingGroup).Resources("horizontalpodautoscalers/status").RuleOrDie(),
|
||||||
rbac.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "update").Groups("*").Resources("*/scale").RuleOrDie(),
|
||||||
rbac.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
// TODO: restrict this to the appropriate namespace
|
// TODO: restrict this to the appropriate namespace
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("services/proxy").Names("https:heapster:", "http:heapster:").RuleOrDie(),
|
||||||
// allow listing resource metrics and custom metrics
|
// allow listing resource metrics and custom metrics
|
||||||
rbac.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list").Groups(resMetricsGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list").Groups(customMetricsGroup).Resources("*").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "job-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "job-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(batchGroup).Resources("jobs").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(batchGroup).Resources("jobs/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "create", "delete", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "namespace-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "namespace-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("namespaces/finalize", "namespaces/status").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "delete", "deletecollection").Groups("*").Resources("*").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "node-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "node-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "update", "delete", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
||||||
// used for pod eviction
|
// used for pod eviction
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
||||||
rbac.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "persistent-volume-binder"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "persistent-volume-binder"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumes/status").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "get", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
|
|
||||||
// glusterfs
|
// glusterfs
|
||||||
rbac.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||||
rbac.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "create", "delete").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
||||||
// openstack
|
// openstack
|
||||||
rbac.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
|
|
||||||
// recyclerClient.WatchPod
|
// recyclerClient.WatchPod
|
||||||
rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
||||||
|
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pod-garbage-collector"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pod-garbage-collector"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("list").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replicaset-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replicaset-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(appsGroup, extensionsGroup).Resources("replicasets/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replication-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "replication-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// 1.0 controllers needed get, update, so without these old controllers break on new servers
|
// 1.0 controllers needed get, update, so without these old controllers break on new servers
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("replicationcontrollers").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("replicationcontrollers/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "patch", "create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resourcequota-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "resourcequota-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// quota can count quota on anything for reconciliation, so it needs full viewing powers
|
// quota can count quota on anything for reconciliation, so it needs full viewing powers
|
||||||
rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("resourcequotas/status").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "route-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "route-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-account-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-account-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "service-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("services").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("services/status").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "statefulset-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "statefulset-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/status").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(appsGroup).Resources("statefulsets/finalizers").RuleOrDie(),
|
||||||
rbac.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "create", "delete", "update", "patch").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "create", "delete", "update", "patch", "list", "watch").Groups(appsGroup).Resources("controllerrevisions").RuleOrDie(),
|
||||||
rbac.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "create").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "ttl-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("update", "patch", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "certificate-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "certificate-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(certificatesGroup).Resources("certificatesigningrequests/status", "certificatesigningrequests/approval").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pvc-protection-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pvc-protection-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch", "get").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addControllerRole(&controllerRoles, &controllerRoleBindings, rbac.ClusterRole{
|
addControllerRole(&controllerRoles, &controllerRoleBindings, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pv-protection-controller"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "pv-protection-controller"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -344,13 +345,13 @@ func buildControllerRoles() ([]rbac.ClusterRole, []rbac.ClusterRoleBinding) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerRoles returns the cluster roles used by controllers
|
// ControllerRoles returns the cluster roles used by controllers
|
||||||
func ControllerRoles() []rbac.ClusterRole {
|
func ControllerRoles() []rbacv1.ClusterRole {
|
||||||
controllerRoles, _ := buildControllerRoles()
|
controllerRoles, _ := buildControllerRoles()
|
||||||
return controllerRoles
|
return controllerRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerRoleBindings returns the role bindings used by controllers
|
// ControllerRoleBindings returns the role bindings used by controllers
|
||||||
func ControllerRoleBindings() []rbac.ClusterRoleBinding {
|
func ControllerRoleBindings() []rbacv1.ClusterRoleBinding {
|
||||||
_, controllerRoleBindings := buildControllerRoles()
|
_, controllerRoleBindings := buildControllerRoles()
|
||||||
return controllerRoleBindings
|
return controllerRoleBindings
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,19 +21,20 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// namespaceRoles is a map of namespace to slice of roles to create
|
// namespaceRoles is a map of namespace to slice of roles to create
|
||||||
namespaceRoles = map[string][]rbac.Role{}
|
namespaceRoles = map[string][]rbacv1.Role{}
|
||||||
|
|
||||||
// namespaceRoleBindings is a map of namespace to slice of roleBindings to create
|
// namespaceRoleBindings is a map of namespace to slice of roleBindings to create
|
||||||
namespaceRoleBindings = map[string][]rbac.RoleBinding{}
|
namespaceRoleBindings = map[string][]rbacv1.RoleBinding{}
|
||||||
)
|
)
|
||||||
|
|
||||||
func addNamespaceRole(namespace string, role rbac.Role) {
|
func addNamespaceRole(namespace string, role rbacv1.Role) {
|
||||||
if !strings.HasPrefix(namespace, "kube-") {
|
if !strings.HasPrefix(namespace, "kube-") {
|
||||||
glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace)
|
glog.Fatalf(`roles can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace)
|
||||||
}
|
}
|
||||||
|
@ -51,7 +52,7 @@ func addNamespaceRole(namespace string, role rbac.Role) {
|
||||||
namespaceRoles[namespace] = existingRoles
|
namespaceRoles[namespace] = existingRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) {
|
func addNamespaceRoleBinding(namespace string, roleBinding rbacv1.RoleBinding) {
|
||||||
if !strings.HasPrefix(namespace, "kube-") {
|
if !strings.HasPrefix(namespace, "kube-") {
|
||||||
glog.Fatalf(`rolebindings can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace)
|
glog.Fatalf(`rolebindings can only be bootstrapped into reserved namespaces starting with "kube-", not %q`, namespace)
|
||||||
}
|
}
|
||||||
|
@ -70,86 +71,86 @@ func addNamespaceRoleBinding(namespace string, roleBinding rbac.RoleBinding) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for finding authentication config info for starting a server
|
// role for finding authentication config info for starting a server
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "extension-apiserver-authentication-reader"},
|
ObjectMeta: metav1.ObjectMeta{Name: "extension-apiserver-authentication-reader"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// this particular config map is exposed and contains authentication configuration information
|
// this particular config map is exposed and contains authentication configuration information
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("configmaps").Names("extension-apiserver-authentication").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for the bootstrap signer to be able to inspect kube-system secrets
|
// role for the bootstrap signer to be able to inspect kube-system secrets
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for the cloud providers to access/create kube-system configmaps
|
// role for the cloud providers to access/create kube-system configmaps
|
||||||
// Deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy.
|
// Deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cloud-provider"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "cloud-provider"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for the token-cleaner to be able to remove secrets, but only in kube-system
|
// role for the token-cleaner to be able to remove secrets, but only in kube-system
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "token-cleaner"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "token-cleaner"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
// TODO: Create util on Role+Binding for leader locking if more cases evolve.
|
// TODO: Create util on Role+Binding for leader locking if more cases evolve.
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for the leader locking on supplied configmap
|
// role for the leader locking on supplied configmap
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-controller-manager"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-controller-manager"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
||||||
rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-controller-manager").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRole(metav1.NamespaceSystem, rbac.Role{
|
addNamespaceRole(metav1.NamespaceSystem, rbacv1.Role{
|
||||||
// role for the leader locking on supplied configmap
|
// role for the leader locking on supplied configmap
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-scheduler"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system::leader-locking-kube-scheduler"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
||||||
rbac.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "update").Groups(legacyGroup).Resources("configmaps").Names("kube-scheduler").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
||||||
rbac.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie())
|
rbacv1helpers.NewRoleBinding("system::leader-locking-kube-controller-manager", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-controller-manager").BindingOrDie())
|
||||||
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
||||||
rbac.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie())
|
rbacv1helpers.NewRoleBinding("system::leader-locking-kube-scheduler", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "kube-scheduler").BindingOrDie())
|
||||||
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
||||||
rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
|
rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
|
||||||
// cloud-provider is deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy.
|
// cloud-provider is deprecated starting Kubernetes 1.10 and will be deleted according to GA deprecation policy.
|
||||||
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
||||||
rbac.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie())
|
rbacv1helpers.NewRoleBinding(saRolePrefix+"cloud-provider", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "cloud-provider").BindingOrDie())
|
||||||
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
addNamespaceRoleBinding(metav1.NamespaceSystem,
|
||||||
rbac.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie())
|
rbacv1helpers.NewRoleBinding(saRolePrefix+"token-cleaner", metav1.NamespaceSystem).SAs(metav1.NamespaceSystem, "token-cleaner").BindingOrDie())
|
||||||
|
|
||||||
addNamespaceRole(metav1.NamespacePublic, rbac.Role{
|
addNamespaceRole(metav1.NamespacePublic, rbacv1.Role{
|
||||||
// role for the bootstrap signer to be able to write its configmap
|
// role for the bootstrap signer to be able to write its configmap
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
|
ObjectMeta: metav1.ObjectMeta{Name: saRolePrefix + "bootstrap-signer"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("configmaps").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("configmaps").Names("cluster-info").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
addNamespaceRoleBinding(metav1.NamespacePublic,
|
addNamespaceRoleBinding(metav1.NamespacePublic,
|
||||||
rbac.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
|
rbacv1helpers.NewRoleBinding(saRolePrefix+"bootstrap-signer", metav1.NamespacePublic).SAs(metav1.NamespaceSystem, "bootstrap-signer").BindingOrDie())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespaceRoles returns a map of namespace to slice of roles to create
|
// NamespaceRoles returns a map of namespace to slice of roles to create
|
||||||
func NamespaceRoles() map[string][]rbac.Role {
|
func NamespaceRoles() map[string][]rbacv1.Role {
|
||||||
return namespaceRoles
|
return namespaceRoles
|
||||||
}
|
}
|
||||||
|
|
||||||
// NamespaceRoleBindings returns a map of namespace to slice of roles to create
|
// NamespaceRoleBindings returns a map of namespace to slice of roles to create
|
||||||
func NamespaceRoleBindings() map[string][]rbac.RoleBinding {
|
func NamespaceRoleBindings() map[string][]rbacv1.RoleBinding {
|
||||||
return namespaceRoleBindings
|
return namespaceRoleBindings
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,12 +17,13 @@ limitations under the License.
|
||||||
package bootstrappolicy
|
package bootstrappolicy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"k8s.io/apimachinery/pkg/api/meta"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||||
rbac "k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
"k8s.io/kubernetes/pkg/features"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,7 +33,7 @@ var (
|
||||||
ReadUpdate = []string{"get", "list", "watch", "update", "patch"}
|
ReadUpdate = []string{"get", "list", "watch", "update", "patch"}
|
||||||
|
|
||||||
Label = map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}
|
Label = map[string]string{"kubernetes.io/bootstrapping": "rbac-defaults"}
|
||||||
Annotation = map[string]string{rbac.AutoUpdateAnnotationKey: "true"}
|
Annotation = map[string]string{rbacv1.AutoUpdateAnnotationKey: "true"}
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -78,105 +79,105 @@ func addDefaultMetadata(obj runtime.Object) {
|
||||||
metadata.SetAnnotations(annotations)
|
metadata.SetAnnotations(annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
func addClusterRoleLabel(roles []rbac.ClusterRole) {
|
func addClusterRoleLabel(roles []rbacv1.ClusterRole) {
|
||||||
for i := range roles {
|
for i := range roles {
|
||||||
addDefaultMetadata(&roles[i])
|
addDefaultMetadata(&roles[i])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func addClusterRoleBindingLabel(rolebindings []rbac.ClusterRoleBinding) {
|
func addClusterRoleBindingLabel(rolebindings []rbacv1.ClusterRoleBinding) {
|
||||||
for i := range rolebindings {
|
for i := range rolebindings {
|
||||||
addDefaultMetadata(&rolebindings[i])
|
addDefaultMetadata(&rolebindings[i])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func NodeRules() []rbac.PolicyRule {
|
func NodeRules() []rbacv1.PolicyRule {
|
||||||
nodePolicyRules := []rbac.PolicyRule{
|
nodePolicyRules := []rbacv1.PolicyRule{
|
||||||
// Needed to check API access. These creates are non-mutating
|
// Needed to check API access. These creates are non-mutating
|
||||||
rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews", "localsubjectaccessreviews").RuleOrDie(),
|
||||||
|
|
||||||
// Needed to build serviceLister, to populate env vars for services
|
// Needed to build serviceLister, to populate env vars for services
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services").RuleOrDie(),
|
||||||
|
|
||||||
// Nodes can register Node API objects and report status.
|
// Nodes can register Node API objects and report status.
|
||||||
// Use the NodeRestriction admission plugin to limit a node to creating/updating its own API object.
|
// Use the NodeRestriction admission plugin to limit a node to creating/updating its own API object.
|
||||||
rbac.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update", "patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
||||||
rbac.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("update", "patch", "delete").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
|
|
||||||
// TODO: restrict to the bound node as creator in the NodeRestrictions admission plugin
|
// TODO: restrict to the bound node as creator in the NodeRestrictions admission plugin
|
||||||
rbac.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
||||||
|
|
||||||
// TODO: restrict to pods scheduled on the bound node once field selectors are supported by list/watch authorization
|
// TODO: restrict to pods scheduled on the bound node once field selectors are supported by list/watch authorization
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
|
|
||||||
// Needed for the node to create/delete mirror pods.
|
// Needed for the node to create/delete mirror pods.
|
||||||
// Use the NodeRestriction admission plugin to limit a node to creating/deleting mirror pods bound to itself.
|
// Use the NodeRestriction admission plugin to limit a node to creating/deleting mirror pods bound to itself.
|
||||||
rbac.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
// Needed for the node to report status of pods it is running.
|
// Needed for the node to report status of pods it is running.
|
||||||
// Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself.
|
// Use the NodeRestriction admission plugin to limit a node to updating status of pods bound to itself.
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
||||||
// Needed for the node to create pod evictions.
|
// Needed for the node to create pod evictions.
|
||||||
// Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself.
|
// Use the NodeRestriction admission plugin to limit a node to creating evictions for pods bound to itself.
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/eviction").RuleOrDie(),
|
||||||
|
|
||||||
// Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs
|
// Needed for imagepullsecrets, rbd/ceph and secret volumes, and secrets in envs
|
||||||
// Needed for configmap volume and envs
|
// Needed for configmap volume and envs
|
||||||
// Use the Node authorization mode to limit a node to get secrets/configmaps referenced by pods bound to itself.
|
// Use the Node authorization mode to limit a node to get secrets/configmaps referenced by pods bound to itself.
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("secrets", "configmaps").RuleOrDie(),
|
||||||
// Needed for persistent volumes
|
// Needed for persistent volumes
|
||||||
// Use the Node authorization mode to limit a node to get pv/pvc objects referenced by pods bound to itself.
|
// Use the Node authorization mode to limit a node to get pv/pvc objects referenced by pods bound to itself.
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(),
|
||||||
|
|
||||||
// TODO: add to the Node authorizer and restrict to endpoints referenced by pods or PVs bound to the node
|
// TODO: add to the Node authorizer and restrict to endpoints referenced by pods or PVs bound to the node
|
||||||
// Needed for glusterfs volumes
|
// Needed for glusterfs volumes
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
||||||
// Used to create a certificatesigningrequest for a node-specific client certificate, and watch
|
// Used to create a certificatesigningrequest for a node-specific client certificate, and watch
|
||||||
// for it to be signed. This allows the kubelet to rotate it's own certificate.
|
// for it to be signed. This allows the kubelet to rotate it's own certificate.
|
||||||
rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.ExpandPersistentVolumes) {
|
||||||
// Use the Node authorization mode to limit a node to update status of pvc objects referenced by pods bound to itself.
|
// Use the Node authorization mode to limit a node to update status of pvc objects referenced by pods bound to itself.
|
||||||
// Use the NodeRestriction admission plugin to limit a node to just update the status stanza.
|
// Use the NodeRestriction admission plugin to limit a node to just update the status stanza.
|
||||||
pvcStatusPolicyRule := rbac.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie()
|
pvcStatusPolicyRule := rbacv1helpers.NewRule("get", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims/status").RuleOrDie()
|
||||||
nodePolicyRules = append(nodePolicyRules, pvcStatusPolicyRule)
|
nodePolicyRules = append(nodePolicyRules, pvcStatusPolicyRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.TokenRequest) {
|
||||||
// Use the Node authorization to limit a node to create tokens for service accounts running on that node
|
// Use the Node authorization to limit a node to create tokens for service accounts running on that node
|
||||||
// Use the NodeRestriction admission plugin to limit a node to create tokens bound to pods on that node
|
// Use the NodeRestriction admission plugin to limit a node to create tokens bound to pods on that node
|
||||||
tokenRequestRule := rbac.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie()
|
tokenRequestRule := rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("serviceaccounts/token").RuleOrDie()
|
||||||
nodePolicyRules = append(nodePolicyRules, tokenRequestRule)
|
nodePolicyRules = append(nodePolicyRules, tokenRequestRule)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CSI
|
// CSI
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.CSIPersistentVolume) {
|
||||||
volAttachRule := rbac.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()
|
volAttachRule := rbacv1helpers.NewRule("get").Groups(storageGroup).Resources("volumeattachments").RuleOrDie()
|
||||||
nodePolicyRules = append(nodePolicyRules, volAttachRule)
|
nodePolicyRules = append(nodePolicyRules, volAttachRule)
|
||||||
}
|
}
|
||||||
return nodePolicyRules
|
return nodePolicyRules
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClusterRoles returns the cluster roles to bootstrap an API server with
|
// ClusterRoles returns the cluster roles to bootstrap an API server with
|
||||||
func ClusterRoles() []rbac.ClusterRole {
|
func ClusterRoles() []rbacv1.ClusterRole {
|
||||||
roles := []rbac.ClusterRole{
|
roles := []rbacv1.ClusterRole{
|
||||||
{
|
{
|
||||||
// a "root" role which can do absolutely anything
|
// a "root" role which can do absolutely anything
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
|
ObjectMeta: metav1.ObjectMeta{Name: "cluster-admin"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("*").Groups("*").Resources("*").RuleOrDie(),
|
||||||
rbac.NewRule("*").URLs("*").RuleOrDie(),
|
rbacv1helpers.NewRule("*").URLs("*").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role which provides just enough power to determine if the server is ready and discover API versions for negotiation
|
// a role which provides just enough power to determine if the server is ready and discover API versions for negotiation
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:discovery"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get").URLs(
|
rbacv1helpers.NewRule("get").URLs(
|
||||||
"/healthz", "/version", "/version/",
|
"/healthz", "/version", "/version/",
|
||||||
// remove once swagger 1.2 support is removed
|
// remove once swagger 1.2 support is removed
|
||||||
"/swaggerapi", "/swaggerapi/*",
|
"/swaggerapi", "/swaggerapi/*",
|
||||||
|
@ -192,16 +193,16 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
{
|
{
|
||||||
// a role which provides minimal resource access to allow a "normal" user to learn information about themselves
|
// a role which provides minimal resource access to allow a "normal" user to learn information about themselves
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:basic-user"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// TODO add future selfsubjectrulesreview, project request APIs, project listing APIs
|
// TODO add future selfsubjectrulesreview, project request APIs, project listing APIs
|
||||||
rbac.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("selfsubjectaccessreviews", "selfsubjectrulesreviews").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
// a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users.
|
// a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "admin"},
|
ObjectMeta: metav1.ObjectMeta{Name: "admin"},
|
||||||
AggregationRule: &rbac.AggregationRule{
|
AggregationRule: &rbacv1.AggregationRule{
|
||||||
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}},
|
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -210,7 +211,7 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
// It does not grant powers for "privileged" resources which are domain of the system: `/status`
|
// It does not grant powers for "privileged" resources which are domain of the system: `/status`
|
||||||
// subresources or `quota`/`limits` which are used to control namespaces
|
// subresources or `quota`/`limits` which are used to control namespaces
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "edit"},
|
ObjectMeta: metav1.ObjectMeta{Name: "edit"},
|
||||||
AggregationRule: &rbac.AggregationRule{
|
AggregationRule: &rbacv1.AggregationRule{
|
||||||
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}},
|
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -218,46 +219,46 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
// a role for namespace level viewing. It grants Read-only access to non-escalating resources in
|
// a role for namespace level viewing. It grants Read-only access to non-escalating resources in
|
||||||
// a namespace.
|
// a namespace.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "view"},
|
ObjectMeta: metav1.ObjectMeta{Name: "view"},
|
||||||
AggregationRule: &rbac.AggregationRule{
|
AggregationRule: &rbacv1.AggregationRule{
|
||||||
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}},
|
ClusterRoleSelectors: []metav1.LabelSelector{{MatchLabels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}}},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users.
|
// a role for a namespace level admin. It is `edit` plus the power to grant permissions to other users.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-admin", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-admin": "true"}},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
|
||||||
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
||||||
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
|
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
||||||
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
||||||
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
||||||
// indicator of which namespaces you have access to.
|
// indicator of which namespaces you have access to.
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
||||||
rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources(
|
rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources(
|
||||||
"statefulsets", "statefulsets/scale",
|
"statefulsets", "statefulsets/scale",
|
||||||
"daemonsets",
|
"daemonsets",
|
||||||
"deployments", "deployments/scale", "deployments/rollback",
|
"deployments", "deployments/scale", "deployments/rollback",
|
||||||
"replicasets", "replicasets/scale").RuleOrDie(),
|
"replicasets", "replicasets/scale").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets",
|
rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets",
|
||||||
"deployments", "deployments/scale", "deployments/rollback", "ingresses",
|
"deployments", "deployments/scale", "deployments/rollback", "ingresses",
|
||||||
"replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
"replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
||||||
"networkpolicies").RuleOrDie(),
|
"networkpolicies").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
||||||
|
|
||||||
// additional admin powers
|
// additional admin powers
|
||||||
rbac.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("localsubjectaccessreviews").RuleOrDie(),
|
||||||
rbac.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(rbacGroup).Resources("roles", "rolebindings").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -265,75 +266,75 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
// It does not grant powers for "privileged" resources which are domain of the system: `/status`
|
// It does not grant powers for "privileged" resources which are domain of the system: `/status`
|
||||||
// subresources or `quota`/`limits` which are used to control namespaces
|
// subresources or `quota`/`limits` which are used to control namespaces
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-edit", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-edit": "true"}},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("pods", "pods/attach", "pods/proxy", "pods/exec", "pods/portforward").RuleOrDie(),
|
||||||
rbac.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
rbacv1helpers.NewRule(ReadWrite...).Groups(legacyGroup).Resources("replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
||||||
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
|
"services", "services/proxy", "endpoints", "persistentvolumeclaims", "configmaps", "secrets").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
||||||
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
||||||
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
||||||
// indicator of which namespaces you have access to.
|
// indicator of which namespaces you have access to.
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
||||||
rbac.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("impersonate").Groups(legacyGroup).Resources("serviceaccounts").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(appsGroup).Resources(
|
rbacv1helpers.NewRule(ReadWrite...).Groups(appsGroup).Resources(
|
||||||
"statefulsets", "statefulsets/scale",
|
"statefulsets", "statefulsets/scale",
|
||||||
"daemonsets",
|
"daemonsets",
|
||||||
"deployments", "deployments/scale", "deployments/rollback",
|
"deployments", "deployments/scale", "deployments/rollback",
|
||||||
"replicasets", "replicasets/scale").RuleOrDie(),
|
"replicasets", "replicasets/scale").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets",
|
rbacv1helpers.NewRule(ReadWrite...).Groups(extensionsGroup).Resources("daemonsets",
|
||||||
"deployments", "deployments/scale", "deployments/rollback", "ingresses",
|
"deployments", "deployments/scale", "deployments/rollback", "ingresses",
|
||||||
"replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
"replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
||||||
"networkpolicies").RuleOrDie(),
|
"networkpolicies").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadWrite...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role for namespace level viewing. It grants Read-only access to non-escalating resources in
|
// a role for namespace level viewing. It grants Read-only access to non-escalating resources in
|
||||||
// a namespace.
|
// a namespace.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:aggregate-to-view", Labels: map[string]string{"rbac.authorization.k8s.io/aggregate-to-view": "true"}},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("pods", "replicationcontrollers", "replicationcontrollers/scale", "serviceaccounts",
|
||||||
"services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(),
|
"services", "endpoints", "persistentvolumeclaims", "configmaps").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("limitranges", "resourcequotas", "bindings", "events",
|
||||||
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
"pods/status", "resourcequotas/status", "namespaces/status", "replicationcontrollers/status", "pods/log").RuleOrDie(),
|
||||||
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
// read access to namespaces at the namespace scope means you can read *this* namespace. This can be used as an
|
||||||
// indicator of which namespaces you have access to.
|
// indicator of which namespaces you have access to.
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("namespaces").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(appsGroup).Resources(
|
rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources(
|
||||||
"statefulsets", "statefulsets/scale",
|
"statefulsets", "statefulsets/scale",
|
||||||
"daemonsets",
|
"daemonsets",
|
||||||
"deployments", "deployments/scale",
|
"deployments", "deployments/scale",
|
||||||
"replicasets", "replicasets/scale").RuleOrDie(),
|
"replicasets", "replicasets/scale").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(autoscalingGroup).Resources("horizontalpodautoscalers").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(batchGroup).Resources("jobs", "cronjobs").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale",
|
rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("daemonsets", "deployments", "deployments/scale",
|
||||||
"ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
"ingresses", "replicasets", "replicasets/scale", "replicationcontrollers/scale",
|
||||||
"networkpolicies").RuleOrDie(),
|
"networkpolicies").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
||||||
|
|
||||||
rbac.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(networkingGroup).Resources("networkpolicies").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for heapster's connections back to the API server
|
// a role to use for heapster's connections back to the API server
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:heapster"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:heapster"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("events", "pods", "nodes", "namespaces").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(extensionsGroup).Resources("deployments").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -345,19 +346,19 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
// a role to use for node-problem-detector access. It does not get bound to default location since
|
// a role to use for node-problem-detector access. It does not get bound to default location since
|
||||||
// deployment locations can reasonably vary.
|
// deployment locations can reasonably vary.
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:node-problem-detector"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:node-problem-detector"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
rbacv1helpers.NewRule("patch").Groups(legacyGroup).Resources("nodes/status").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for setting up a proxy
|
// a role to use for setting up a proxy
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:node-proxier"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:node-proxier"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// Used to build serviceLister
|
// Used to build serviceLister
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
|
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
|
@ -365,98 +366,98 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
{
|
{
|
||||||
// a role to use for full access to the kubelet API
|
// a role to use for full access to the kubelet API
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:kubelet-api-admin"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:kubelet-api-admin"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// Allow read-only access to the Node API objects
|
// Allow read-only access to the Node API objects
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
// Allow all API calls to the nodes
|
// Allow all API calls to the nodes
|
||||||
rbac.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("proxy").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(),
|
rbacv1helpers.NewRule("*").Groups(legacyGroup).Resources("nodes/proxy", "nodes/metrics", "nodes/spec", "nodes/stats", "nodes/log").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for bootstrapping a node's client certificates
|
// a role to use for bootstrapping a node's client certificates
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:node-bootstrapper"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:node-bootstrapper"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// used to create a certificatesigningrequest for a node-specific client certificate, and watch for it to be signed
|
// used to create a certificatesigningrequest for a node-specific client certificate, and watch for it to be signed
|
||||||
rbac.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "get", "list", "watch").Groups(certificatesGroup).Resources("certificatesigningrequests").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for allowing authentication and authorization delegation
|
// a role to use for allowing authentication and authorization delegation
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:auth-delegator"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:auth-delegator"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// These creates are non-mutating
|
// These creates are non-mutating
|
||||||
rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authorizationGroup).Resources("subjectaccessreviews").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for the API registry, summarization, and proxy handling
|
// a role to use for the API registry, summarization, and proxy handling
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-aggregator"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-aggregator"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
// it needs to see all services so that it knows whether the ones it points to exist or not
|
// it needs to see all services so that it knows whether the ones it points to exist or not
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "endpoints").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for bootstrapping the kube-controller-manager so it can create the shared informers
|
// a role to use for bootstrapping the kube-controller-manager so it can create the shared informers
|
||||||
// service accounts, and secrets that we need to create separate identities for other controllers
|
// service accounts, and secrets that we need to create separate identities for other controllers
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-controller-manager"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-controller-manager"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(),
|
||||||
rbac.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule("delete").Groups(legacyGroup).Resources("secrets").RuleOrDie(),
|
||||||
rbac.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("get").Groups(legacyGroup).Resources("endpoints", "namespaces", "secrets", "serviceaccounts").RuleOrDie(),
|
||||||
rbac.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(),
|
rbacv1helpers.NewRule("update").Groups(legacyGroup).Resources("endpoints", "secrets", "serviceaccounts").RuleOrDie(),
|
||||||
// Needed to check API access. These creates are non-mutating
|
// Needed to check API access. These creates are non-mutating
|
||||||
rbac.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(authenticationGroup).Resources("tokenreviews").RuleOrDie(),
|
||||||
// Needed for all shared informers
|
// Needed for all shared informers
|
||||||
rbac.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups("*").Resources("*").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for the kube-scheduler
|
// a role to use for the kube-scheduler
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-scheduler"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
|
|
||||||
// this is for leaderlease access
|
// this is for leaderlease access
|
||||||
// TODO: scope this to the kube-system namespace
|
// TODO: scope this to the kube-system namespace
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("endpoints").RuleOrDie(),
|
||||||
rbac.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "update", "patch", "delete").Groups(legacyGroup).Resources("endpoints").Names("kube-scheduler").RuleOrDie(),
|
||||||
|
|
||||||
// fundamental resources
|
// fundamental resources
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "delete").Groups(legacyGroup).Resources("pods").RuleOrDie(),
|
||||||
rbac.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(legacyGroup).Resources("pods/binding", "bindings").RuleOrDie(),
|
||||||
rbac.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
rbacv1helpers.NewRule("patch", "update").Groups(legacyGroup).Resources("pods/status").RuleOrDie(),
|
||||||
// things that select pods
|
// things that select pods
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("services", "replicationcontrollers").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(appsGroup, extensionsGroup).Resources("replicasets").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(appsGroup).Resources("statefulsets").RuleOrDie(),
|
||||||
// things that pods use or applies to them
|
// things that pods use or applies to them
|
||||||
rbac.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(policyGroup).Resources("poddisruptionbudgets").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(legacyGroup).Resources("persistentvolumeclaims", "persistentvolumes").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role to use for the kube-dns pod
|
// a role to use for the kube-dns pod
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-dns"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:kube-dns"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(legacyGroup).Resources("endpoints", "services").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role for an external/out-of-tree persistent volume provisioner
|
// a role for an external/out-of-tree persistent volume provisioner
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:persistent-volume-provisioner"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:persistent-volume-provisioner"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "delete").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
// update is needed in addition to read access for setting lock annotations on PVCs
|
// update is needed in addition to read access for setting lock annotations on PVCs
|
||||||
rbac.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||||
|
|
||||||
// Needed for watching provisioning success and failure events
|
// Needed for watching provisioning success and failure events
|
||||||
rbac.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
rbacv1helpers.NewRule("watch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
||||||
|
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
|
@ -464,52 +465,52 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
{
|
{
|
||||||
// a role for the csi external provisioner
|
// a role for the csi external provisioner
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-provisioner"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-provisioner"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create", "delete", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("create", "delete", "list", "watch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumeclaims").RuleOrDie(),
|
||||||
rbac.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
rbacv1helpers.NewRule("list", "watch").Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role for the csi external attacher
|
// a role for the csi external attacher
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-attacher"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:csi-external-attacher"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "update", "patch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "update", "patch").Groups(storageGroup).Resources("volumeattachments").RuleOrDie(),
|
||||||
rbac.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "list", "watch", "create", "update", "patch").Groups(legacyGroup).Resources("events").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:aws-cloud-provider"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:aws-cloud-provider"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
rbacv1helpers.NewRule("get", "patch").Groups(legacyGroup).Resources("nodes").RuleOrDie(),
|
||||||
eventsRule(),
|
eventsRule(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role making the csrapprover controller approve a node client CSR
|
// a role making the csrapprover controller approve a node client CSR
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:nodeclient"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:nodeclient"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/nodeclient").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// a role making the csrapprover controller approve a node client CSR requested by the node itself
|
// a role making the csrapprover controller approve a node client CSR requested by the node itself
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:certificates.k8s.io:certificatesigningrequests:selfnodeclient"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups(certificatesGroup).Resources("certificatesigningrequests/selfnodeclient").RuleOrDie(),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
roles = append(roles, rbac.ClusterRole{
|
roles = append(roles, rbacv1.ClusterRole{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"},
|
ObjectMeta: metav1.ObjectMeta{Name: "system:volume-scheduler"},
|
||||||
Rules: []rbac.PolicyRule{
|
Rules: []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
rbacv1helpers.NewRule(ReadUpdate...).Groups(legacyGroup).Resources("persistentvolumes").RuleOrDie(),
|
||||||
rbac.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
rbacv1helpers.NewRule(Read...).Groups(storageGroup).Resources("storageclasses").RuleOrDie(),
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -521,27 +522,27 @@ func ClusterRoles() []rbac.ClusterRole {
|
||||||
const systemNodeRoleName = "system:node"
|
const systemNodeRoleName = "system:node"
|
||||||
|
|
||||||
// ClusterRoleBindings return default rolebindings to the default roles
|
// ClusterRoleBindings return default rolebindings to the default roles
|
||||||
func ClusterRoleBindings() []rbac.ClusterRoleBinding {
|
func ClusterRoleBindings() []rbacv1.ClusterRoleBinding {
|
||||||
rolebindings := []rbac.ClusterRoleBinding{
|
rolebindings := []rbacv1.ClusterRoleBinding{
|
||||||
rbac.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("cluster-admin").Groups(user.SystemPrivilegedGroup).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:discovery").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:basic-user").Groups(user.AllAuthenticated, user.AllUnauthenticated).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:node-proxier").Users(user.KubeProxy).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:kube-controller-manager").Users(user.KubeControllerManager).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:kube-dns").SAs("kube-system", "kube-dns").BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:kube-scheduler").Users(user.KubeScheduler).BindingOrDie(),
|
||||||
rbac.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(),
|
rbacv1helpers.NewClusterBinding("system:aws-cloud-provider").SAs("kube-system", "aws-cloud-provider").BindingOrDie(),
|
||||||
|
|
||||||
// This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer.
|
// This default binding of the system:node role to the system:nodes group is deprecated in 1.7 with the availability of the Node authorizer.
|
||||||
// This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject.
|
// This leaves the binding, but with an empty set of subjects, so that tightening reconciliation can remove the subject.
|
||||||
{
|
{
|
||||||
ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName},
|
ObjectMeta: metav1.ObjectMeta{Name: systemNodeRoleName},
|
||||||
RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName},
|
RoleRef: rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: systemNodeRoleName},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
if utilfeature.DefaultFeatureGate.Enabled(features.VolumeScheduling) {
|
||||||
rolebindings = append(rolebindings, rbac.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie())
|
rolebindings = append(rolebindings, rbacv1helpers.NewClusterBinding("system:volume-scheduler").Users(user.KubeScheduler).BindingOrDie())
|
||||||
}
|
}
|
||||||
|
|
||||||
addClusterRoleBindingLabel(rolebindings)
|
addClusterRoleBindingLabel(rolebindings)
|
||||||
|
|
|
@ -34,8 +34,8 @@ import (
|
||||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||||
api "k8s.io/kubernetes/pkg/apis/core"
|
api "k8s.io/kubernetes/pkg/apis/core"
|
||||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
_ "k8s.io/kubernetes/pkg/apis/rbac/install"
|
||||||
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
||||||
)
|
)
|
||||||
|
@ -43,12 +43,12 @@ import (
|
||||||
// semanticRoles is a few enumerated roles for which the relationships are well established
|
// semanticRoles is a few enumerated roles for which the relationships are well established
|
||||||
// and we want to maintain symmetric roles
|
// and we want to maintain symmetric roles
|
||||||
type semanticRoles struct {
|
type semanticRoles struct {
|
||||||
admin *rbac.ClusterRole
|
admin *rbacv1.ClusterRole
|
||||||
edit *rbac.ClusterRole
|
edit *rbacv1.ClusterRole
|
||||||
view *rbac.ClusterRole
|
view *rbacv1.ClusterRole
|
||||||
}
|
}
|
||||||
|
|
||||||
func getSemanticRoles(roles []rbac.ClusterRole) semanticRoles {
|
func getSemanticRoles(roles []rbacv1.ClusterRole) semanticRoles {
|
||||||
ret := semanticRoles{}
|
ret := semanticRoles{}
|
||||||
for i := range roles {
|
for i := range roles {
|
||||||
role := roles[i]
|
role := roles[i]
|
||||||
|
@ -81,10 +81,10 @@ func TestCovers(t *testing.T) {
|
||||||
|
|
||||||
// additionalAdminPowers is the list of powers that we expect to be different than the editor role.
|
// additionalAdminPowers is the list of powers that we expect to be different than the editor role.
|
||||||
// one resource per rule to make the "does not already contain" check easy
|
// one resource per rule to make the "does not already contain" check easy
|
||||||
var additionalAdminPowers = []rbac.PolicyRule{
|
var additionalAdminPowers = []rbacv1.PolicyRule{
|
||||||
rbac.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(),
|
rbacv1helpers.NewRule("create").Groups("authorization.k8s.io").Resources("localsubjectaccessreviews").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("rolebindings").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.ReadWrite...).Groups("rbac.authorization.k8s.io").Resources("roles").RuleOrDie(),
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAdminEditRelationship(t *testing.T) {
|
func TestAdminEditRelationship(t *testing.T) {
|
||||||
|
@ -92,7 +92,7 @@ func TestAdminEditRelationship(t *testing.T) {
|
||||||
|
|
||||||
// confirm that the edit role doesn't already have extra powers
|
// confirm that the edit role doesn't already have extra powers
|
||||||
for _, rule := range additionalAdminPowers {
|
for _, rule := range additionalAdminPowers {
|
||||||
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbac.PolicyRule{rule}); covers {
|
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.edit.Rules, []rbacv1.PolicyRule{rule}); covers {
|
||||||
t.Errorf("edit has extra powers: %#v", rule)
|
t.Errorf("edit has extra powers: %#v", rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,19 +109,19 @@ func TestAdminEditRelationship(t *testing.T) {
|
||||||
|
|
||||||
// viewEscalatingNamespaceResources is the list of rules that would allow privilege escalation attacks based on
|
// viewEscalatingNamespaceResources is the list of rules that would allow privilege escalation attacks based on
|
||||||
// ability to view (GET) them
|
// ability to view (GET) them
|
||||||
var viewEscalatingNamespaceResources = []rbac.PolicyRule{
|
var viewEscalatingNamespaceResources = []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/attach").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/proxy").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/exec").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("pods/portforward").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("secrets").RuleOrDie(),
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("").Resources("services/proxy").RuleOrDie(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// ungettableResources is the list of rules that don't allow to view (GET) them
|
// ungettableResources is the list of rules that don't allow to view (GET) them
|
||||||
// this is purposefully separate list to distinguish from escalating privs
|
// this is purposefully separate list to distinguish from escalating privs
|
||||||
var ungettableResources = []rbac.PolicyRule{
|
var ungettableResources = []rbacv1.PolicyRule{
|
||||||
rbac.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(),
|
rbacv1helpers.NewRule(bootstrappolicy.Read...).Groups("apps", "extensions").Resources("deployments/rollback").RuleOrDie(),
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEditViewRelationship(t *testing.T) {
|
func TestEditViewRelationship(t *testing.T) {
|
||||||
|
@ -143,7 +143,7 @@ func TestEditViewRelationship(t *testing.T) {
|
||||||
|
|
||||||
// confirm that the view role doesn't already have extra powers
|
// confirm that the view role doesn't already have extra powers
|
||||||
for _, rule := range viewEscalatingNamespaceResources {
|
for _, rule := range viewEscalatingNamespaceResources {
|
||||||
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers {
|
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers {
|
||||||
t.Errorf("view has extra powers: %#v", rule)
|
t.Errorf("view has extra powers: %#v", rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,7 +151,7 @@ func TestEditViewRelationship(t *testing.T) {
|
||||||
|
|
||||||
// confirm that the view role doesn't have ungettable resources
|
// confirm that the view role doesn't have ungettable resources
|
||||||
for _, rule := range ungettableResources {
|
for _, rule := range ungettableResources {
|
||||||
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbac.PolicyRule{rule}); covers {
|
if covers, _ := rbacregistryvalidation.Covers(semanticRoles.view.Rules, []rbacv1.PolicyRule{rule}); covers {
|
||||||
t.Errorf("view has ungettable resource: %#v", rule)
|
t.Errorf("view has ungettable resource: %#v", rule)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,18 +18,18 @@ limitations under the License.
|
||||||
package rbac
|
package rbac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"bytes"
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/labels"
|
"k8s.io/apimachinery/pkg/labels"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbaclisters "k8s.io/client-go/listers/rbac/v1"
|
||||||
rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion"
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -38,12 +38,12 @@ type RequestToRuleMapper interface {
|
||||||
// Any rule returned is still valid, since rules are deny by default. If you can pass with the rules
|
// Any rule returned is still valid, since rules are deny by default. If you can pass with the rules
|
||||||
// supplied, you do not have to fail the request. If you cannot, you should indicate the error along
|
// supplied, you do not have to fail the request. If you cannot, you should indicate the error along
|
||||||
// with your denial.
|
// with your denial.
|
||||||
RulesFor(subject user.Info, namespace string) ([]rbac.PolicyRule, error)
|
RulesFor(subject user.Info, namespace string) ([]rbacv1.PolicyRule, error)
|
||||||
|
|
||||||
// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace,
|
// VisitRulesFor invokes visitor() with each rule that applies to a given user in a given namespace,
|
||||||
// and each error encountered resolving those rules. Rule may be nil if err is non-nil.
|
// and each error encountered resolving those rules. Rule may be nil if err is non-nil.
|
||||||
// If visitor() returns false, visiting is short-circuited.
|
// If visitor() returns false, visiting is short-circuited.
|
||||||
VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool)
|
VisitRulesFor(user user.Info, namespace string, visitor func(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
type RBACAuthorizer struct {
|
type RBACAuthorizer struct {
|
||||||
|
@ -59,7 +59,7 @@ type authorizingVisitor struct {
|
||||||
errors []error
|
errors []error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbac.PolicyRule, err error) bool {
|
func (v *authorizingVisitor) visit(source fmt.Stringer, rule *rbacv1.PolicyRule, err error) bool {
|
||||||
if rule != nil && RuleAllows(v.requestAttributes, rule) {
|
if rule != nil && RuleAllows(v.requestAttributes, rule) {
|
||||||
v.allowed = true
|
v.allowed = true
|
||||||
v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String())
|
v.reason = fmt.Sprintf("RBAC: allowed by %s", source.String())
|
||||||
|
@ -164,7 +164,7 @@ func New(roles rbacregistryvalidation.RoleGetter, roleBindings rbacregistryvalid
|
||||||
return authorizer
|
return authorizer
|
||||||
}
|
}
|
||||||
|
|
||||||
func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRule) bool {
|
func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbacv1.PolicyRule) bool {
|
||||||
for i := range rules {
|
for i := range rules {
|
||||||
if RuleAllows(requestAttributes, &rules[i]) {
|
if RuleAllows(requestAttributes, &rules[i]) {
|
||||||
return true
|
return true
|
||||||
|
@ -174,28 +174,28 @@ func RulesAllow(requestAttributes authorizer.Attributes, rules ...rbac.PolicyRul
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func RuleAllows(requestAttributes authorizer.Attributes, rule *rbac.PolicyRule) bool {
|
func RuleAllows(requestAttributes authorizer.Attributes, rule *rbacv1.PolicyRule) bool {
|
||||||
if requestAttributes.IsResourceRequest() {
|
if requestAttributes.IsResourceRequest() {
|
||||||
combinedResource := requestAttributes.GetResource()
|
combinedResource := requestAttributes.GetResource()
|
||||||
if len(requestAttributes.GetSubresource()) > 0 {
|
if len(requestAttributes.GetSubresource()) > 0 {
|
||||||
combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource()
|
combinedResource = requestAttributes.GetResource() + "/" + requestAttributes.GetSubresource()
|
||||||
}
|
}
|
||||||
|
|
||||||
return rbac.VerbMatches(rule, requestAttributes.GetVerb()) &&
|
return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) &&
|
||||||
rbac.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) &&
|
rbacv1helpers.APIGroupMatches(rule, requestAttributes.GetAPIGroup()) &&
|
||||||
rbac.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) &&
|
rbacv1helpers.ResourceMatches(rule, combinedResource, requestAttributes.GetSubresource()) &&
|
||||||
rbac.ResourceNameMatches(rule, requestAttributes.GetName())
|
rbacv1helpers.ResourceNameMatches(rule, requestAttributes.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
return rbac.VerbMatches(rule, requestAttributes.GetVerb()) &&
|
return rbacv1helpers.VerbMatches(rule, requestAttributes.GetVerb()) &&
|
||||||
rbac.NonResourceURLMatches(rule, requestAttributes.GetPath())
|
rbacv1helpers.NonResourceURLMatches(rule, requestAttributes.GetPath())
|
||||||
}
|
}
|
||||||
|
|
||||||
type RoleGetter struct {
|
type RoleGetter struct {
|
||||||
Lister rbaclisters.RoleLister
|
Lister rbaclisters.RoleLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *RoleGetter) GetRole(namespace, name string) (*rbac.Role, error) {
|
func (g *RoleGetter) GetRole(namespace, name string) (*rbacv1.Role, error) {
|
||||||
return g.Lister.Roles(namespace).Get(name)
|
return g.Lister.Roles(namespace).Get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -203,7 +203,7 @@ type RoleBindingLister struct {
|
||||||
Lister rbaclisters.RoleBindingLister
|
Lister rbaclisters.RoleBindingLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbac.RoleBinding, error) {
|
func (l *RoleBindingLister) ListRoleBindings(namespace string) ([]*rbacv1.RoleBinding, error) {
|
||||||
return l.Lister.RoleBindings(namespace).List(labels.Everything())
|
return l.Lister.RoleBindings(namespace).List(labels.Everything())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ type ClusterRoleGetter struct {
|
||||||
Lister rbaclisters.ClusterRoleLister
|
Lister rbaclisters.ClusterRoleLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbac.ClusterRole, error) {
|
func (g *ClusterRoleGetter) GetClusterRole(name string) (*rbacv1.ClusterRole, error) {
|
||||||
return g.Lister.Get(name)
|
return g.Lister.Get(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,6 +219,6 @@ type ClusterRoleBindingLister struct {
|
||||||
Lister rbaclisters.ClusterRoleBindingLister
|
Lister rbaclisters.ClusterRoleBindingLister
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbac.ClusterRoleBinding, error) {
|
func (l *ClusterRoleBindingLister) ListClusterRoleBindings() ([]*rbacv1.ClusterRoleBinding, error) {
|
||||||
return l.Lister.List(labels.Everything())
|
return l.Lister.List(labels.Everything())
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,17 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
rbacv1helpers "k8s.io/kubernetes/pkg/apis/rbac/v1"
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
"k8s.io/kubernetes/plugin/pkg/auth/authorizer/rbac/bootstrappolicy"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRule {
|
func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbacv1.PolicyRule {
|
||||||
return rbac.PolicyRule{
|
return rbacv1.PolicyRule{
|
||||||
Verbs: strings.Split(verbs, ","),
|
Verbs: strings.Split(verbs, ","),
|
||||||
APIGroups: strings.Split(apiGroups, ","),
|
APIGroups: strings.Split(apiGroups, ","),
|
||||||
Resources: strings.Split(resources, ","),
|
Resources: strings.Split(resources, ","),
|
||||||
|
@ -38,12 +39,12 @@ func newRule(verbs, apiGroups, resources, nonResourceURLs string) rbac.PolicyRul
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRole(name, namespace string, rules ...rbac.PolicyRule) *rbac.Role {
|
func newRole(name, namespace string, rules ...rbacv1.PolicyRule) *rbacv1.Role {
|
||||||
return &rbac.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules}
|
return &rbacv1.Role{ObjectMeta: metav1.ObjectMeta{Namespace: namespace, Name: name}, Rules: rules}
|
||||||
}
|
}
|
||||||
|
|
||||||
func newClusterRole(name string, rules ...rbac.PolicyRule) *rbac.ClusterRole {
|
func newClusterRole(name string, rules ...rbacv1.PolicyRule) *rbacv1.ClusterRole {
|
||||||
return &rbac.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules}
|
return &rbacv1.ClusterRole{ObjectMeta: metav1.ObjectMeta{Name: name}, Rules: rules}
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -51,26 +52,26 @@ const (
|
||||||
bindToClusterRole uint16 = 0x1
|
bindToClusterRole uint16 = 0x1
|
||||||
)
|
)
|
||||||
|
|
||||||
func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRoleBinding {
|
func newClusterRoleBinding(roleName string, subjects ...string) *rbacv1.ClusterRoleBinding {
|
||||||
r := &rbac.ClusterRoleBinding{
|
r := &rbacv1.ClusterRoleBinding{
|
||||||
ObjectMeta: metav1.ObjectMeta{},
|
ObjectMeta: metav1.ObjectMeta{},
|
||||||
RoleRef: rbac.RoleRef{
|
RoleRef: rbacv1.RoleRef{
|
||||||
APIGroup: rbac.GroupName,
|
APIGroup: rbacv1.GroupName,
|
||||||
Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole
|
Kind: "ClusterRole", // ClusterRoleBindings can only refer to ClusterRole
|
||||||
Name: roleName,
|
Name: roleName,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Subjects = make([]rbac.Subject, len(subjects))
|
r.Subjects = make([]rbacv1.Subject, len(subjects))
|
||||||
for i, subject := range subjects {
|
for i, subject := range subjects {
|
||||||
split := strings.SplitN(subject, ":", 2)
|
split := strings.SplitN(subject, ":", 2)
|
||||||
r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1]
|
r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1]
|
||||||
|
|
||||||
switch r.Subjects[i].Kind {
|
switch r.Subjects[i].Kind {
|
||||||
case rbac.ServiceAccountKind:
|
case rbacv1.ServiceAccountKind:
|
||||||
r.Subjects[i].APIGroup = ""
|
r.Subjects[i].APIGroup = ""
|
||||||
case rbac.UserKind, rbac.GroupKind:
|
case rbacv1.UserKind, rbacv1.GroupKind:
|
||||||
r.Subjects[i].APIGroup = rbac.GroupName
|
r.Subjects[i].APIGroup = rbacv1.GroupName
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind))
|
panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind))
|
||||||
}
|
}
|
||||||
|
@ -78,26 +79,26 @@ func newClusterRoleBinding(roleName string, subjects ...string) *rbac.ClusterRol
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbac.RoleBinding {
|
func newRoleBinding(namespace, roleName string, bindType uint16, subjects ...string) *rbacv1.RoleBinding {
|
||||||
r := &rbac.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}}
|
r := &rbacv1.RoleBinding{ObjectMeta: metav1.ObjectMeta{Namespace: namespace}}
|
||||||
|
|
||||||
switch bindType {
|
switch bindType {
|
||||||
case bindToRole:
|
case bindToRole:
|
||||||
r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: roleName}
|
r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "Role", Name: roleName}
|
||||||
case bindToClusterRole:
|
case bindToClusterRole:
|
||||||
r.RoleRef = rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: roleName}
|
r.RoleRef = rbacv1.RoleRef{APIGroup: rbacv1.GroupName, Kind: "ClusterRole", Name: roleName}
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Subjects = make([]rbac.Subject, len(subjects))
|
r.Subjects = make([]rbacv1.Subject, len(subjects))
|
||||||
for i, subject := range subjects {
|
for i, subject := range subjects {
|
||||||
split := strings.SplitN(subject, ":", 2)
|
split := strings.SplitN(subject, ":", 2)
|
||||||
r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1]
|
r.Subjects[i].Kind, r.Subjects[i].Name = split[0], split[1]
|
||||||
|
|
||||||
switch r.Subjects[i].Kind {
|
switch r.Subjects[i].Kind {
|
||||||
case rbac.ServiceAccountKind:
|
case rbacv1.ServiceAccountKind:
|
||||||
r.Subjects[i].APIGroup = ""
|
r.Subjects[i].APIGroup = ""
|
||||||
case rbac.UserKind, rbac.GroupKind:
|
case rbacv1.UserKind, rbacv1.GroupKind:
|
||||||
r.Subjects[i].APIGroup = rbac.GroupName
|
r.Subjects[i].APIGroup = rbacv1.GroupName
|
||||||
default:
|
default:
|
||||||
panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind))
|
panic(fmt.Errorf("invalid kind %s", r.Subjects[i].Kind))
|
||||||
}
|
}
|
||||||
|
@ -136,19 +137,19 @@ func (d *defaultAttributes) GetPath() string { return "" }
|
||||||
|
|
||||||
func TestAuthorizer(t *testing.T) {
|
func TestAuthorizer(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
roles []*rbac.Role
|
roles []*rbacv1.Role
|
||||||
roleBindings []*rbac.RoleBinding
|
roleBindings []*rbacv1.RoleBinding
|
||||||
clusterRoles []*rbac.ClusterRole
|
clusterRoles []*rbacv1.ClusterRole
|
||||||
clusterRoleBindings []*rbac.ClusterRoleBinding
|
clusterRoleBindings []*rbacv1.ClusterRoleBinding
|
||||||
|
|
||||||
shouldPass []authorizer.Attributes
|
shouldPass []authorizer.Attributes
|
||||||
shouldFail []authorizer.Attributes
|
shouldFail []authorizer.Attributes
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
|
@ -167,12 +168,12 @@ func TestAuthorizer(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Non-resource-url tests
|
// Non-resource-url tests
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")),
|
newClusterRole("non-resource-url-getter", newRule("get", "", "", "/apis")),
|
||||||
newClusterRole("non-resource-url", newRule("*", "", "", "/apis")),
|
newClusterRole("non-resource-url", newRule("*", "", "", "/apis")),
|
||||||
newClusterRole("non-resource-url-prefix", newRule("get", "", "", "/apis/*")),
|
newClusterRole("non-resource-url-prefix", newRule("get", "", "", "/apis/*")),
|
||||||
},
|
},
|
||||||
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
clusterRoleBindings: []*rbacv1.ClusterRoleBinding{
|
||||||
newClusterRoleBinding("non-resource-url-getter", "User:foo", "Group:bar"),
|
newClusterRoleBinding("non-resource-url-getter", "User:foo", "Group:bar"),
|
||||||
newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"),
|
newClusterRoleBinding("non-resource-url", "User:admin", "Group:admin"),
|
||||||
newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"),
|
newClusterRoleBinding("non-resource-url-prefix", "User:prefixed", "Group:prefixed"),
|
||||||
|
@ -208,10 +209,10 @@ func TestAuthorizer(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// test subresource resolution
|
// test subresource resolution
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "pods", "*")),
|
newClusterRole("admin", newRule("*", "*", "pods", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
|
@ -223,13 +224,13 @@ func TestAuthorizer(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// test subresource resolution
|
// test subresource resolution
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("admin",
|
newClusterRole("admin",
|
||||||
newRule("*", "*", "pods/status", "*"),
|
newRule("*", "*", "pods/status", "*"),
|
||||||
newRule("*", "*", "*/scale", "*"),
|
newRule("*", "*", "*/scale", "*"),
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
shouldPass: []authorizer.Attributes{
|
shouldPass: []authorizer.Attributes{
|
||||||
|
@ -263,13 +264,13 @@ func TestAuthorizer(t *testing.T) {
|
||||||
func TestRuleMatches(t *testing.T) {
|
func TestRuleMatches(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
rule rbac.PolicyRule
|
rule rbacv1.PolicyRule
|
||||||
|
|
||||||
requestsToExpected map[authorizer.AttributesRecord]bool
|
requestsToExpected map[authorizer.AttributesRecord]bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "star verb, exact match other",
|
name: "star verb, exact match other",
|
||||||
rule: rbac.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("*").Groups("group1").Resources("resource1").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
||||||
resourceRequest("verb1").Group("group2").Resource("resource1").New(): false,
|
resourceRequest("verb1").Group("group2").Resource("resource1").New(): false,
|
||||||
|
@ -283,7 +284,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "star group, exact match other",
|
name: "star group, exact match other",
|
||||||
rule: rbac.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("verb1").Groups("*").Resources("resource1").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
||||||
resourceRequest("verb1").Group("group2").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group2").Resource("resource1").New(): true,
|
||||||
|
@ -297,7 +298,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "star resource, exact match other",
|
name: "star resource, exact match other",
|
||||||
rule: rbac.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("verb1").Groups("group1").Resources("*").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
||||||
resourceRequest("verb1").Group("group2").Resource("resource1").New(): false,
|
resourceRequest("verb1").Group("group2").Resource("resource1").New(): false,
|
||||||
|
@ -311,7 +312,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "tuple expansion",
|
name: "tuple expansion",
|
||||||
rule: rbac.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("verb1", "verb2").Groups("group1", "group2").Resources("resource1", "resource2").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group1").Resource("resource1").New(): true,
|
||||||
resourceRequest("verb1").Group("group2").Resource("resource1").New(): true,
|
resourceRequest("verb1").Group("group2").Resource("resource1").New(): true,
|
||||||
|
@ -325,7 +326,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "subresource expansion",
|
name: "subresource expansion",
|
||||||
rule: rbac.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("*").Groups("*").Resources("resource1/subresource1").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
resourceRequest("verb1").Group("group1").Resource("resource1").Subresource("subresource1").New(): true,
|
resourceRequest("verb1").Group("group1").Resource("resource1").Subresource("subresource1").New(): true,
|
||||||
resourceRequest("verb1").Group("group2").Resource("resource1").Subresource("subresource2").New(): false,
|
resourceRequest("verb1").Group("group2").Resource("resource1").Subresource("subresource2").New(): false,
|
||||||
|
@ -339,7 +340,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "star nonresource, exact match other",
|
name: "star nonresource, exact match other",
|
||||||
rule: rbac.NewRule("verb1").URLs("*").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("verb1").URLs("*").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
nonresourceRequest("verb1").URL("/foo").New(): true,
|
nonresourceRequest("verb1").URL("/foo").New(): true,
|
||||||
nonresourceRequest("verb1").URL("/foo/bar").New(): true,
|
nonresourceRequest("verb1").URL("/foo/bar").New(): true,
|
||||||
|
@ -355,7 +356,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "star nonresource subpath",
|
name: "star nonresource subpath",
|
||||||
rule: rbac.NewRule("verb1").URLs("/foo/*").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("verb1").URLs("/foo/*").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
nonresourceRequest("verb1").URL("/foo").New(): false,
|
nonresourceRequest("verb1").URL("/foo").New(): false,
|
||||||
nonresourceRequest("verb1").URL("/foo/bar").New(): true,
|
nonresourceRequest("verb1").URL("/foo/bar").New(): true,
|
||||||
|
@ -371,7 +372,7 @@ func TestRuleMatches(t *testing.T) {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "star verb, exact nonresource",
|
name: "star verb, exact nonresource",
|
||||||
rule: rbac.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(),
|
rule: rbacv1helpers.NewRule("*").URLs("/foo", "/foo/bar/one").RuleOrDie(),
|
||||||
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
requestsToExpected: map[authorizer.AttributesRecord]bool{
|
||||||
nonresourceRequest("verb1").URL("/foo").New(): true,
|
nonresourceRequest("verb1").URL("/foo").New(): true,
|
||||||
nonresourceRequest("verb1").URL("/foo/bar").New(): false,
|
nonresourceRequest("verb1").URL("/foo/bar").New(): false,
|
||||||
|
@ -441,19 +442,19 @@ func (r *requestAttributeBuilder) New() authorizer.AttributesRecord {
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAuthorize(b *testing.B) {
|
func BenchmarkAuthorize(b *testing.B) {
|
||||||
bootstrapRoles := []rbac.ClusterRole{}
|
bootstrapRoles := []rbacv1.ClusterRole{}
|
||||||
bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ControllerRoles()...)
|
bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ControllerRoles()...)
|
||||||
bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ClusterRoles()...)
|
bootstrapRoles = append(bootstrapRoles, bootstrappolicy.ClusterRoles()...)
|
||||||
|
|
||||||
bootstrapBindings := []rbac.ClusterRoleBinding{}
|
bootstrapBindings := []rbacv1.ClusterRoleBinding{}
|
||||||
bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ClusterRoleBindings()...)
|
bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ClusterRoleBindings()...)
|
||||||
bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ControllerRoleBindings()...)
|
bootstrapBindings = append(bootstrapBindings, bootstrappolicy.ControllerRoleBindings()...)
|
||||||
|
|
||||||
clusterRoles := []*rbac.ClusterRole{}
|
clusterRoles := []*rbacv1.ClusterRole{}
|
||||||
for i := range bootstrapRoles {
|
for i := range bootstrapRoles {
|
||||||
clusterRoles = append(clusterRoles, &bootstrapRoles[i])
|
clusterRoles = append(clusterRoles, &bootstrapRoles[i])
|
||||||
}
|
}
|
||||||
clusterRoleBindings := []*rbac.ClusterRoleBinding{}
|
clusterRoleBindings := []*rbacv1.ClusterRoleBinding{}
|
||||||
for i := range bootstrapBindings {
|
for i := range bootstrapBindings {
|
||||||
clusterRoleBindings = append(clusterRoleBindings, &bootstrapBindings[i])
|
clusterRoleBindings = append(clusterRoleBindings, &bootstrapBindings[i])
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,21 +18,21 @@ limitations under the License.
|
||||||
package rbac
|
package rbac
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RoleToRuleMapper interface {
|
type RoleToRuleMapper interface {
|
||||||
// GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namespace
|
// GetRoleReferenceRules attempts to resolve the role reference of a RoleBinding or ClusterRoleBinding. The passed namespace should be the namespace
|
||||||
// of the role binding, the empty string if a cluster role binding.
|
// of the role binding, the empty string if a cluster role binding.
|
||||||
GetRoleReferenceRules(roleRef rbac.RoleRef, namespace string) ([]rbac.PolicyRule, error)
|
GetRoleReferenceRules(roleRef rbacv1.RoleRef, namespace string) ([]rbacv1.PolicyRule, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type SubjectLocator interface {
|
type SubjectLocator interface {
|
||||||
AllowedSubjects(attributes authorizer.Attributes) ([]rbac.Subject, error)
|
AllowedSubjects(attributes authorizer.Attributes) ([]rbacv1.Subject, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var _ = SubjectLocator(&SubjectAccessEvaluator{})
|
var _ = SubjectLocator(&SubjectAccessEvaluator{})
|
||||||
|
@ -59,10 +59,10 @@ func NewSubjectAccessEvaluator(roles rbacregistryvalidation.RoleGetter, roleBind
|
||||||
|
|
||||||
// AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list.
|
// AllowedSubjects returns the subjects that can perform an action and any errors encountered while computing the list.
|
||||||
// It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be.
|
// It is possible to have both subjects and errors returned if some rolebindings couldn't be resolved, but others could be.
|
||||||
func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbac.Subject, error) {
|
func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.Attributes) ([]rbacv1.Subject, error) {
|
||||||
subjects := []rbac.Subject{{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup}}
|
subjects := []rbacv1.Subject{{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup}}
|
||||||
if len(r.superUser) > 0 {
|
if len(r.superUser) > 0 {
|
||||||
subjects = append(subjects, rbac.Subject{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: r.superUser})
|
subjects = append(subjects, rbacv1.Subject{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: r.superUser})
|
||||||
}
|
}
|
||||||
errorlist := []error{}
|
errorlist := []error{}
|
||||||
|
|
||||||
|
@ -104,7 +104,7 @@ func (r *SubjectAccessEvaluator) AllowedSubjects(requestAttributes authorizer.At
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dedupedSubjects := []rbac.Subject{}
|
dedupedSubjects := []rbacv1.Subject{}
|
||||||
for _, subject := range subjects {
|
for _, subject := range subjects {
|
||||||
found := false
|
found := false
|
||||||
for _, curr := range dedupedSubjects {
|
for _, curr := range dedupedSubjects {
|
||||||
|
|
|
@ -20,24 +20,24 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
rbacv1 "k8s.io/api/rbac/v1"
|
||||||
"k8s.io/apiserver/pkg/authentication/user"
|
"k8s.io/apiserver/pkg/authentication/user"
|
||||||
"k8s.io/apiserver/pkg/authorization/authorizer"
|
"k8s.io/apiserver/pkg/authorization/authorizer"
|
||||||
"k8s.io/kubernetes/pkg/apis/rbac"
|
|
||||||
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
rbacregistryvalidation "k8s.io/kubernetes/pkg/registry/rbac/validation"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSubjectLocator(t *testing.T) {
|
func TestSubjectLocator(t *testing.T) {
|
||||||
type actionToSubjects struct {
|
type actionToSubjects struct {
|
||||||
action authorizer.Attributes
|
action authorizer.Attributes
|
||||||
subjects []rbac.Subject
|
subjects []rbacv1.Subject
|
||||||
}
|
}
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
roles []*rbac.Role
|
roles []*rbacv1.Role
|
||||||
roleBindings []*rbac.RoleBinding
|
roleBindings []*rbacv1.RoleBinding
|
||||||
clusterRoles []*rbac.ClusterRole
|
clusterRoles []*rbacv1.ClusterRole
|
||||||
clusterRoleBindings []*rbac.ClusterRoleBinding
|
clusterRoleBindings []*rbacv1.ClusterRoleBinding
|
||||||
|
|
||||||
superUser string
|
superUser string
|
||||||
|
|
||||||
|
@ -45,42 +45,42 @@ func TestSubjectLocator(t *testing.T) {
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "no super user, star matches star",
|
name: "no super user, star matches star",
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
||||||
},
|
},
|
||||||
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
clusterRoleBindings: []*rbacv1.ClusterRoleBinding{
|
||||||
newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"),
|
newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"),
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToClusterRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
actionsToSubjects: []actionToSubjects{
|
actionsToSubjects: []actionToSubjects{
|
||||||
{
|
{
|
||||||
&defaultAttributes{"", "", "get", "Pods", "", "ns1", ""},
|
&defaultAttributes{"", "", "get", "Pods", "", "ns1", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// cluster role matches star in namespace
|
// cluster role matches star in namespace
|
||||||
&defaultAttributes{"", "", "*", "Pods", "", "*", ""},
|
&defaultAttributes{"", "", "*", "Pods", "", "*", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// empty ns
|
// empty ns
|
||||||
&defaultAttributes{"", "", "*", "Pods", "", "", ""},
|
&defaultAttributes{"", "", "*", "Pods", "", "", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -88,48 +88,48 @@ func TestSubjectLocator(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "super user, local roles work",
|
name: "super user, local roles work",
|
||||||
superUser: "foo",
|
superUser: "foo",
|
||||||
clusterRoles: []*rbac.ClusterRole{
|
clusterRoles: []*rbacv1.ClusterRole{
|
||||||
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
newClusterRole("admin", newRule("*", "*", "*", "*")),
|
||||||
},
|
},
|
||||||
clusterRoleBindings: []*rbac.ClusterRoleBinding{
|
clusterRoleBindings: []*rbacv1.ClusterRoleBinding{
|
||||||
newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"),
|
newClusterRoleBinding("admin", "User:super-admin", "Group:super-admins"),
|
||||||
},
|
},
|
||||||
roles: []*rbac.Role{
|
roles: []*rbacv1.Role{
|
||||||
newRole("admin", "ns1", newRule("get", "*", "Pods", "*")),
|
newRole("admin", "ns1", newRule("get", "*", "Pods", "*")),
|
||||||
},
|
},
|
||||||
roleBindings: []*rbac.RoleBinding{
|
roleBindings: []*rbacv1.RoleBinding{
|
||||||
newRoleBinding("ns1", "admin", bindToRole, "User:admin", "Group:admins"),
|
newRoleBinding("ns1", "admin", bindToRole, "User:admin", "Group:admins"),
|
||||||
},
|
},
|
||||||
actionsToSubjects: []actionToSubjects{
|
actionsToSubjects: []actionToSubjects{
|
||||||
{
|
{
|
||||||
&defaultAttributes{"", "", "get", "Pods", "", "ns1", ""},
|
&defaultAttributes{"", "", "get", "Pods", "", "ns1", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// verb matchies correctly
|
// verb matchies correctly
|
||||||
&defaultAttributes{"", "", "create", "Pods", "", "ns1", ""},
|
&defaultAttributes{"", "", "create", "Pods", "", "ns1", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// binding only works in correct ns
|
// binding only works in correct ns
|
||||||
&defaultAttributes{"", "", "get", "Pods", "", "ns2", ""},
|
&defaultAttributes{"", "", "get", "Pods", "", "ns2", ""},
|
||||||
[]rbac.Subject{
|
[]rbacv1.Subject{
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: user.SystemPrivilegedGroup},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: user.SystemPrivilegedGroup},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "foo"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "foo"},
|
||||||
{Kind: rbac.UserKind, APIGroup: rbac.GroupName, Name: "super-admin"},
|
{Kind: rbacv1.UserKind, APIGroup: rbacv1.GroupName, Name: "super-admin"},
|
||||||
{Kind: rbac.GroupKind, APIGroup: rbac.GroupName, Name: "super-admins"},
|
{Kind: rbacv1.GroupKind, APIGroup: rbacv1.GroupName, Name: "super-admins"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -199,6 +199,7 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
|
||||||
closeFn()
|
closeFn()
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
var lastHealthContent []byte
|
||||||
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
err = wait.PollImmediate(100*time.Millisecond, 30*time.Second, func() (bool, error) {
|
||||||
result := privilegedClient.Get().AbsPath("/healthz").Do()
|
result := privilegedClient.Get().AbsPath("/healthz").Do()
|
||||||
status := 0
|
status := 0
|
||||||
|
@ -206,10 +207,12 @@ func startMasterOrDie(masterConfig *master.Config, incomingServer *httptest.Serv
|
||||||
if status == 200 {
|
if status == 200 {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
lastHealthContent, _ = result.Raw()
|
||||||
return false, nil
|
return false, nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
closeFn()
|
closeFn()
|
||||||
|
glog.Errorf("last health content: %q", string(lastHealthContent))
|
||||||
glog.Fatal(err)
|
glog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue