Commit ef042450 authored by Kubernetes Submit Queue's avatar Kubernetes Submit Queue Committed by GitHub

Merge pull request #41155 from liggitt/reconcile

Automatic merge from submit-queue (batch tested with PRs 41378, 41413, 40743, 41155, 41385) Reconcile bootstrap clusterroles on server start Currently, on server start, bootstrap roles and bindings are only created if there are no existing roles or rolebindings. Instead, we should look at each bootstrap role and rolebinding, and ensure it exists and has required permissions and subjects at server start. This allows seamless upgrades to new versions that define roles for new controllers, or add permissions to existing roles. ```release-note Default RBAC ClusterRole and ClusterRoleBinding objects are automatically updated at server start to add missing permissions and subjects (extra permissions and subjects are left in place). To prevent autoupdating a particular role or rolebinding, annotate it with `rbac.authorization.kubernetes.io/autoupdate=false`. ```
parents be9b58e9 26b42d35
...@@ -34,6 +34,9 @@ const ( ...@@ -34,6 +34,9 @@ const (
GroupKind = "Group" GroupKind = "Group"
ServiceAccountKind = "ServiceAccount" ServiceAccountKind = "ServiceAccount"
UserKind = "User" UserKind = "User"
// AutoUpdateAnnotationKey is the name of an annotation which prevents reconciliation if set to "false"
AutoUpdateAnnotationKey = "rbac.authorization.kubernetes.io/autoupdate"
) )
// PolicyRule holds information that describes a policy rule, but does not contain information // PolicyRule holds information that describes a policy rule, but does not contain information
......
...@@ -34,6 +34,9 @@ const ( ...@@ -34,6 +34,9 @@ const (
GroupKind = "Group" GroupKind = "Group"
ServiceAccountKind = "ServiceAccount" ServiceAccountKind = "ServiceAccount"
UserKind = "User" UserKind = "User"
// AutoUpdateAnnotationKey is the name of an annotation which prevents reconciliation if set to "false"
AutoUpdateAnnotationKey = "rbac.authorization.kubernetes.io/autoupdate"
) )
// Authorization is calculated against // Authorization is calculated against
......
...@@ -34,6 +34,9 @@ const ( ...@@ -34,6 +34,9 @@ const (
GroupKind = "Group" GroupKind = "Group"
ServiceAccountKind = "ServiceAccount" ServiceAccountKind = "ServiceAccount"
UserKind = "User" UserKind = "User"
// AutoUpdateAnnotationKey is the name of an annotation which prevents reconciliation if set to "false"
AutoUpdateAnnotationKey = "rbac.authorization.kubernetes.io/autoupdate"
) )
// Authorization is calculated against // Authorization is calculated against
......
...@@ -33,6 +33,7 @@ filegroup( ...@@ -33,6 +33,7 @@ filegroup(
":package-srcs", ":package-srcs",
"//pkg/registry/rbac/clusterrole:all-srcs", "//pkg/registry/rbac/clusterrole:all-srcs",
"//pkg/registry/rbac/clusterrolebinding:all-srcs", "//pkg/registry/rbac/clusterrolebinding:all-srcs",
"//pkg/registry/rbac/reconciliation:all-srcs",
"//pkg/registry/rbac/rest:all-srcs", "//pkg/registry/rbac/rest:all-srcs",
"//pkg/registry/rbac/role:all-srcs", "//pkg/registry/rbac/role:all-srcs",
"//pkg/registry/rbac/rolebinding:all-srcs", "//pkg/registry/rbac/rolebinding:all-srcs",
......
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
"go_test",
)
go_test(
name = "go_default_test",
srcs = [
"reconcile_clusterrole_test.go",
"reconcile_clusterrolebindings_test.go",
],
library = ":go_default_library",
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
],
)
go_library(
name = "go_default_library",
srcs = [
"reconcile_clusterrole.go",
"reconcile_clusterrolebindings.go",
],
tags = ["automanaged"],
deps = [
"//pkg/api:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
"//pkg/registry/rbac/validation:go_default_library",
"//vendor:k8s.io/apimachinery/pkg/api/errors",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
)
/*
Copyright 2017 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 reconciliation
import (
"fmt"
"reflect"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
"k8s.io/kubernetes/pkg/registry/rbac/validation"
)
type ReconcileOperation string
var (
ReconcileCreate ReconcileOperation = "create"
ReconcileUpdate ReconcileOperation = "update"
ReconcileRecreate ReconcileOperation = "recreate"
ReconcileNone ReconcileOperation = "none"
)
type ReconcileClusterRoleOptions struct {
// Role is the expected role that will be reconciled
Role *rbac.ClusterRole
// Confirm indicates writes should be performed. When false, results are returned as a dry-run.
Confirm bool
// RemoveExtraPermissions indicates reconciliation should remove extra permissions from an existing role
RemoveExtraPermissions bool
// Client is used to look up existing roles, and create/update the role when Confirm=true
Client internalversion.ClusterRoleInterface
}
type ReconcileClusterRoleResult struct {
// Role is the reconciled role from the reconciliation operation.
// If the reconcile was performed as a dry-run, or the existing role was protected, the reconciled role is not persisted.
Role *rbac.ClusterRole
// MissingRules contains expected rules that were missing from the currently persisted role
MissingRules []rbac.PolicyRule
// ExtraRules contains extra permissions the currently persisted role had
ExtraRules []rbac.PolicyRule
// Operation is the API operation required to reconcile.
// If no reconciliation was needed, it is set to ReconcileNone.
// If options.Confirm == false, the reconcile was in dry-run mode, so the operation was not performed.
// If result.Protected == true, the role opted out of reconciliation, so the operation was not performed.
// Otherwise, the operation was performed.
Operation ReconcileOperation
// Protected indicates an existing role prevented reconciliation
Protected bool
}
func (o *ReconcileClusterRoleOptions) Run() (*ReconcileClusterRoleResult, error) {
return o.run(0)
}
func (o *ReconcileClusterRoleOptions) run(attempts int) (*ReconcileClusterRoleResult, error) {
// This keeps us from retrying forever if a role keeps appearing and disappearing as we reconcile.
// Conflict errors on update are handled at a higher level.
if attempts > 2 {
return nil, fmt.Errorf("exceeded maximum attempts")
}
var result *ReconcileClusterRoleResult
existing, err := o.Client.Get(o.Role.Name, metav1.GetOptions{})
switch {
case errors.IsNotFound(err):
result = &ReconcileClusterRoleResult{
Role: o.Role,
MissingRules: o.Role.Rules,
Operation: ReconcileCreate,
}
case err != nil:
return nil, err
default:
result, err = computeReconciledRole(existing, o.Role, o.RemoveExtraPermissions)
if err != nil {
return nil, err
}
}
// If reconcile-protected, short-circuit
if result.Protected {
return result, nil
}
// If we're in dry-run mode, short-circuit
if !o.Confirm {
return result, nil
}
switch result.Operation {
case ReconcileCreate:
created, err := o.Client.Create(result.Role)
// If created since we started this reconcile, re-run
if errors.IsAlreadyExists(err) {
return o.run(attempts + 1)
}
if err != nil {
return nil, err
}
result.Role = created
case ReconcileUpdate:
updated, err := o.Client.Update(result.Role)
// If deleted since we started this reconcile, re-run
if errors.IsNotFound(err) {
return o.run(attempts + 1)
}
if err != nil {
return nil, err
}
result.Role = updated
case ReconcileNone:
// no-op
default:
return nil, fmt.Errorf("invalid operation: %v", result.Operation)
}
return result, nil
}
// computeReconciledRole returns the role that must be created and/or updated to make the
// existing role's permissions match the expected role's permissions
func computeReconciledRole(existing, expected *rbac.ClusterRole, removeExtraPermissions bool) (*ReconcileClusterRoleResult, error) {
result := &ReconcileClusterRoleResult{Operation: ReconcileNone}
result.Protected = (existing.Annotations[rbac.AutoUpdateAnnotationKey] == "false")
// Start with a copy of the existing object
changedObj, err := api.Scheme.DeepCopy(existing)
if err != nil {
return nil, err
}
result.Role = changedObj.(*rbac.ClusterRole)
// Merge expected annotations and labels
result.Role.Annotations = merge(expected.Annotations, result.Role.Annotations)
if !reflect.DeepEqual(result.Role.Annotations, existing.Annotations) {
result.Operation = ReconcileUpdate
}
result.Role.Labels = merge(expected.Labels, result.Role.Labels)
if !reflect.DeepEqual(result.Role.Labels, existing.Labels) {
result.Operation = ReconcileUpdate
}
// Compute extra and missing rules
_, result.ExtraRules = validation.Covers(expected.Rules, existing.Rules)
_, result.MissingRules = validation.Covers(existing.Rules, expected.Rules)
switch {
case !removeExtraPermissions && len(result.MissingRules) > 0:
// add missing rules in the union case
result.Role.Rules = append(result.Role.Rules, result.MissingRules...)
result.Operation = ReconcileUpdate
case removeExtraPermissions && (len(result.MissingRules) > 0 || len(result.ExtraRules) > 0):
// stomp to expected rules in the non-union case
result.Role.Rules = expected.Rules
result.Operation = ReconcileUpdate
}
return result, nil
}
// merge combines the given maps with the later annotations having higher precedence
func merge(maps ...map[string]string) map[string]string {
var output map[string]string = nil
for _, m := range maps {
if m != nil && output == nil {
output = map[string]string{}
}
for k, v := range m {
output[k] = v
}
}
return output
}
/*
Copyright 2017 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 reconciliation
import (
"fmt"
"reflect"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/rbac"
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
)
// ReconcileClusterRoleBindingOptions holds options for running a role binding reconciliation
type ReconcileClusterRoleBindingOptions struct {
// RoleBinding is the expected rolebinding that will be reconciled
RoleBinding *rbac.ClusterRoleBinding
// Confirm indicates writes should be performed. When false, results are returned as a dry-run.
Confirm bool
// RemoveExtraSubjects indicates reconciliation should remove extra subjects from an existing role binding
RemoveExtraSubjects bool
// Client is used to look up existing rolebindings, and create/update the rolebinding when Confirm=true
Client internalversion.ClusterRoleBindingInterface
}
// ReconcileClusterRoleBindingResult holds the result of a reconciliation operation.
type ReconcileClusterRoleBindingResult struct {
// RoleBinding is the reconciled rolebinding from the reconciliation operation.
// If the reconcile was performed as a dry-run, or the existing rolebinding was protected, the reconciled rolebinding is not persisted.
RoleBinding *rbac.ClusterRoleBinding
// MissingSubjects contains expected subjects that were missing from the currently persisted rolebinding
MissingSubjects []rbac.Subject
// ExtraSubjects contains extra subjects the currently persisted rolebinding had
ExtraSubjects []rbac.Subject
// Operation is the API operation required to reconcile.
// If no reconciliation was needed, it is set to ReconcileNone.
// If options.Confirm == false, the reconcile was in dry-run mode, so the operation was not performed.
// If result.Protected == true, the rolebinding opted out of reconciliation, so the operation was not performed.
// Otherwise, the operation was performed.
Operation ReconcileOperation
// Protected indicates an existing role prevented reconciliation
Protected bool
}
func (o *ReconcileClusterRoleBindingOptions) Run() (*ReconcileClusterRoleBindingResult, error) {
return o.run(0)
}
func (o *ReconcileClusterRoleBindingOptions) run(attempts int) (*ReconcileClusterRoleBindingResult, error) {
// This keeps us from retrying forever if a rolebinding keeps appearing and disappearing as we reconcile.
// Conflict errors on update are handled at a higher level.
if attempts > 3 {
return nil, fmt.Errorf("exceeded maximum attempts")
}
var result *ReconcileClusterRoleBindingResult
existingBinding, err := o.Client.Get(o.RoleBinding.Name, metav1.GetOptions{})
switch {
case errors.IsNotFound(err):
result = &ReconcileClusterRoleBindingResult{
RoleBinding: o.RoleBinding,
MissingSubjects: o.RoleBinding.Subjects,
Operation: ReconcileCreate,
}
case err != nil:
return nil, err
default:
result, err = computeReconciledRoleBinding(existingBinding, o.RoleBinding, o.RemoveExtraSubjects)
if err != nil {
return nil, err
}
}
// If reconcile-protected, short-circuit
if result.Protected {
return result, nil
}
// If we're in dry-run mode, short-circuit
if !o.Confirm {
return result, nil
}
switch result.Operation {
case ReconcileRecreate:
// Try deleting
err := o.Client.Delete(
existingBinding.Name,
&metav1.DeleteOptions{Preconditions: &metav1.Preconditions{UID: &existingBinding.UID}},
)
switch {
case err == nil, errors.IsNotFound(err):
// object no longer exists, as desired
case errors.IsConflict(err):
// delete failed because our UID precondition conflicted
// this could mean another object exists with a different UID, re-run
return o.run(attempts + 1)
default:
// return other errors
return nil, err
}
// continue to create
fallthrough
case ReconcileCreate:
created, err := o.Client.Create(result.RoleBinding)
// If created since we started this reconcile, re-run
if errors.IsAlreadyExists(err) {
return o.run(attempts + 1)
}
if err != nil {
return nil, err
}
result.RoleBinding = created
case ReconcileUpdate:
updated, err := o.Client.Update(result.RoleBinding)
// If deleted since we started this reconcile, re-run
if errors.IsNotFound(err) {
return o.run(attempts + 1)
}
if err != nil {
return nil, err
}
result.RoleBinding = updated
case ReconcileNone:
// no-op
default:
return nil, fmt.Errorf("invalid operation: %v", result.Operation)
}
return result, nil
}
// computeReconciledRoleBinding returns the rolebinding that must be created and/or updated to make the
// existing rolebinding's subjects, roleref, labels, and annotations match the expected rolebinding
func computeReconciledRoleBinding(existing, expected *rbac.ClusterRoleBinding, removeExtraSubjects bool) (*ReconcileClusterRoleBindingResult, error) {
result := &ReconcileClusterRoleBindingResult{Operation: ReconcileNone}
result.Protected = (existing.Annotations[rbac.AutoUpdateAnnotationKey] == "false")
// Reset the binding completely if the roleRef is different
if expected.RoleRef != existing.RoleRef {
result.RoleBinding = expected
result.Operation = ReconcileRecreate
return result, nil
}
// Start with a copy of the existing object
changedObj, err := api.Scheme.DeepCopy(existing)
if err != nil {
return nil, err
}
result.RoleBinding = changedObj.(*rbac.ClusterRoleBinding)
// Merge expected annotations and labels
result.RoleBinding.Annotations = merge(expected.Annotations, result.RoleBinding.Annotations)
if !reflect.DeepEqual(result.RoleBinding.Annotations, existing.Annotations) {
result.Operation = ReconcileUpdate
}
result.RoleBinding.Labels = merge(expected.Labels, result.RoleBinding.Labels)
if !reflect.DeepEqual(result.RoleBinding.Labels, existing.Labels) {
result.Operation = ReconcileUpdate
}
// Compute extra and missing subjects
result.MissingSubjects, result.ExtraSubjects = diffSubjectLists(expected.Subjects, existing.Subjects)
switch {
case !removeExtraSubjects && len(result.MissingSubjects) > 0:
// add missing subjects in the union case
result.RoleBinding.Subjects = append(result.RoleBinding.Subjects, result.MissingSubjects...)
result.Operation = ReconcileUpdate
case removeExtraSubjects && (len(result.MissingSubjects) > 0 || len(result.ExtraSubjects) > 0):
// stomp to expected subjects in the non-union case
result.RoleBinding.Subjects = expected.Subjects
result.Operation = ReconcileUpdate
}
return result, nil
}
func contains(list []rbac.Subject, item rbac.Subject) bool {
for _, listItem := range list {
if listItem == item {
return true
}
}
return false
}
// diffSubjectLists returns lists containing the items unique to each provided list:
// list1Only = list1 - list2
// list2Only = list2 - list1
// 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) {
for _, list1Item := range list1 {
if !contains(list2, list1Item) {
if !contains(list1Only, list1Item) {
list1Only = append(list1Only, list1Item)
}
}
}
for _, list2Item := range list2 {
if !contains(list1, list2Item) {
if !contains(list2Only, list2Item) {
list2Only = append(list2Only, list2Item)
}
}
}
return
}
/*
Copyright 2017 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 reconciliation
import (
"testing"
api "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/rbac"
)
func binding(roleRef rbac.RoleRef, subjects []rbac.Subject) *rbac.ClusterRoleBinding {
return &rbac.ClusterRoleBinding{RoleRef: roleRef, Subjects: subjects}
}
func ref(name string) rbac.RoleRef {
return rbac.RoleRef{Name: name}
}
func subject(name string) rbac.Subject {
return rbac.Subject{Name: name}
}
func subjects(names ...string) []rbac.Subject {
r := []rbac.Subject{}
for _, name := range names {
r = append(r, subject(name))
}
return r
}
func TestDiffObjectReferenceLists(t *testing.T) {
tests := map[string]struct {
A []rbac.Subject
B []rbac.Subject
ExpectedOnlyA []rbac.Subject
ExpectedOnlyB []rbac.Subject
}{
"empty": {},
"matching, order-independent": {
A: subjects("foo", "bar"),
B: subjects("bar", "foo"),
},
"partial match": {
A: subjects("foo", "bar"),
B: subjects("foo", "baz"),
ExpectedOnlyA: subjects("bar"),
ExpectedOnlyB: subjects("baz"),
},
"missing": {
A: subjects("foo"),
B: subjects("bar"),
ExpectedOnlyA: subjects("foo"),
ExpectedOnlyB: subjects("bar"),
},
"remove duplicates": {
A: subjects("foo", "foo"),
B: subjects("bar", "bar"),
ExpectedOnlyA: subjects("foo"),
ExpectedOnlyB: subjects("bar"),
},
}
for k, tc := range tests {
onlyA, onlyB := diffSubjectLists(tc.A, tc.B)
if !api.Semantic.DeepEqual(onlyA, tc.ExpectedOnlyA) {
t.Errorf("%s: Expected %#v, got %#v", k, tc.ExpectedOnlyA, onlyA)
}
if !api.Semantic.DeepEqual(onlyB, tc.ExpectedOnlyB) {
t.Errorf("%s: Expected %#v, got %#v", k, tc.ExpectedOnlyB, onlyB)
}
}
}
func TestComputeUpdate(t *testing.T) {
tests := map[string]struct {
ExpectedBinding *rbac.ClusterRoleBinding
ActualBinding *rbac.ClusterRoleBinding
RemoveExtraSubjects bool
ExpectedUpdatedBinding *rbac.ClusterRoleBinding
ExpectedUpdateNeeded bool
}{
"match without union": {
ExpectedBinding: binding(ref("role"), subjects("a")),
ActualBinding: binding(ref("role"), subjects("a")),
RemoveExtraSubjects: true,
ExpectedUpdatedBinding: nil,
ExpectedUpdateNeeded: false,
},
"match with union": {
ExpectedBinding: binding(ref("role"), subjects("a")),
ActualBinding: binding(ref("role"), subjects("a")),
RemoveExtraSubjects: false,
ExpectedUpdatedBinding: nil,
ExpectedUpdateNeeded: false,
},
"different roleref with identical subjects": {
ExpectedBinding: binding(ref("role"), subjects("a")),
ActualBinding: binding(ref("differentRole"), subjects("a")),
RemoveExtraSubjects: false,
ExpectedUpdatedBinding: binding(ref("role"), subjects("a")),
ExpectedUpdateNeeded: true,
},
"extra subjects without union": {
ExpectedBinding: binding(ref("role"), subjects("a")),
ActualBinding: binding(ref("role"), subjects("a", "b")),
RemoveExtraSubjects: true,
ExpectedUpdatedBinding: binding(ref("role"), subjects("a")),
ExpectedUpdateNeeded: true,
},
"extra subjects with union": {
ExpectedBinding: binding(ref("role"), subjects("a")),
ActualBinding: binding(ref("role"), subjects("a", "b")),
RemoveExtraSubjects: false,
ExpectedUpdatedBinding: nil,
ExpectedUpdateNeeded: false,
},
"missing subjects without union": {
ExpectedBinding: binding(ref("role"), subjects("a", "c")),
ActualBinding: binding(ref("role"), subjects("a", "b")),
RemoveExtraSubjects: true,
ExpectedUpdatedBinding: binding(ref("role"), subjects("a", "c")),
ExpectedUpdateNeeded: true,
},
"missing subjects with union": {
ExpectedBinding: binding(ref("role"), subjects("a", "c")),
ActualBinding: binding(ref("role"), subjects("a", "b")),
RemoveExtraSubjects: false,
ExpectedUpdatedBinding: binding(ref("role"), subjects("a", "b", "c")),
ExpectedUpdateNeeded: true,
},
}
for k, tc := range tests {
result, err := computeReconciledRoleBinding(tc.ActualBinding, tc.ExpectedBinding, tc.RemoveExtraSubjects)
if err != nil {
t.Errorf("%s: %v", k, err)
continue
}
updateNeeded := result.Operation != ReconcileNone
updatedBinding := result.RoleBinding
if updateNeeded != tc.ExpectedUpdateNeeded {
t.Errorf("%s: Expected\n\t%v\ngot\n\t%v (%v)", k, tc.ExpectedUpdateNeeded, updateNeeded, result.Operation)
continue
}
if updateNeeded && !api.Semantic.DeepEqual(updatedBinding, tc.ExpectedUpdatedBinding) {
t.Errorf("%s: Expected\n\t%v %v\ngot\n\t%v %v", k, tc.ExpectedUpdatedBinding.RoleRef, tc.ExpectedUpdatedBinding.Subjects, updatedBinding.RoleRef, updatedBinding.Subjects)
}
}
}
...@@ -17,12 +17,14 @@ go_library( ...@@ -17,12 +17,14 @@ go_library(
"//pkg/apis/rbac/v1alpha1:go_default_library", "//pkg/apis/rbac/v1alpha1:go_default_library",
"//pkg/apis/rbac/v1beta1:go_default_library", "//pkg/apis/rbac/v1beta1:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
"//pkg/client/retry: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",
"//pkg/registry/rbac/clusterrolebinding:go_default_library", "//pkg/registry/rbac/clusterrolebinding:go_default_library",
"//pkg/registry/rbac/clusterrolebinding/policybased:go_default_library", "//pkg/registry/rbac/clusterrolebinding/policybased:go_default_library",
"//pkg/registry/rbac/clusterrolebinding/storage:go_default_library", "//pkg/registry/rbac/clusterrolebinding/storage:go_default_library",
"//pkg/registry/rbac/reconciliation:go_default_library",
"//pkg/registry/rbac/role:go_default_library", "//pkg/registry/rbac/role:go_default_library",
"//pkg/registry/rbac/role/policybased:go_default_library", "//pkg/registry/rbac/role/policybased:go_default_library",
"//pkg/registry/rbac/role/storage:go_default_library", "//pkg/registry/rbac/role/storage:go_default_library",
...@@ -32,7 +34,6 @@ go_library( ...@@ -32,7 +34,6 @@ go_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:github.com/golang/glog", "//vendor:github.com/golang/glog",
"//vendor:k8s.io/apimachinery/pkg/apis/meta/v1",
"//vendor:k8s.io/apimachinery/pkg/runtime/schema", "//vendor:k8s.io/apimachinery/pkg/runtime/schema",
"//vendor:k8s.io/apimachinery/pkg/util/runtime", "//vendor:k8s.io/apimachinery/pkg/util/runtime",
"//vendor:k8s.io/apimachinery/pkg/util/wait", "//vendor:k8s.io/apimachinery/pkg/util/wait",
......
...@@ -23,7 +23,6 @@ import ( ...@@ -23,7 +23,6 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
utilruntime "k8s.io/apimachinery/pkg/util/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
...@@ -36,12 +35,14 @@ import ( ...@@ -36,12 +35,14 @@ import (
rbacapiv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1" rbacapiv1alpha1 "k8s.io/kubernetes/pkg/apis/rbac/v1alpha1"
rbacapiv1beta1 "k8s.io/kubernetes/pkg/apis/rbac/v1beta1" rbacapiv1beta1 "k8s.io/kubernetes/pkg/apis/rbac/v1beta1"
rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion" rbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
"k8s.io/kubernetes/pkg/client/retry"
"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"
"k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding" "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding"
clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased" clusterrolebindingpolicybased "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/policybased"
clusterrolebindingstore "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage" clusterrolebindingstore "k8s.io/kubernetes/pkg/registry/rbac/clusterrolebinding/storage"
"k8s.io/kubernetes/pkg/registry/rbac/reconciliation"
"k8s.io/kubernetes/pkg/registry/rbac/role" "k8s.io/kubernetes/pkg/registry/rbac/role"
rolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/role/policybased" rolepolicybased "k8s.io/kubernetes/pkg/registry/rbac/role/policybased"
rolestore "k8s.io/kubernetes/pkg/registry/rbac/role/storage" rolestore "k8s.io/kubernetes/pkg/registry/rbac/role/storage"
...@@ -133,37 +134,62 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error { ...@@ -133,37 +134,62 @@ func PostStartHook(hookContext genericapiserver.PostStartHookContext) error {
return false, nil return false, nil
} }
existingClusterRoles, err := clientset.ClusterRoles().List(metav1.ListOptions{}) // ensure bootstrap roles are created or reconciled
if err != nil { for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) {
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) opts := reconciliation.ReconcileClusterRoleOptions{
return false, nil Role: &clusterRole,
} Client: clientset.ClusterRoles(),
// only initialized on empty etcd Confirm: true,
if len(existingClusterRoles.Items) == 0 { }
for _, clusterRole := range append(bootstrappolicy.ClusterRoles(), bootstrappolicy.ControllerRoles()...) { err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
if _, err := clientset.ClusterRoles().Create(&clusterRole); err != nil { result, err := opts.Run()
// don't fail on failures, try to create as many as you can if err != nil {
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterroles: %v", err)) return err
continue }
switch {
case result.Protected && result.Operation != reconciliation.ReconcileNone:
glog.Warningf("skipped reconcile-protected clusterrole.%s/%s with missing permissions: %v", rbac.GroupName, clusterRole.Name, result.MissingRules)
case result.Operation == reconciliation.ReconcileUpdate:
glog.Infof("updated clusterrole.%s/%s with additional permissions: %v", rbac.GroupName, clusterRole.Name, result.MissingRules)
case result.Operation == reconciliation.ReconcileCreate:
glog.Infof("created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name)
} }
glog.Infof("Created clusterrole.%s/%s", rbac.GroupName, clusterRole.Name) return nil
})
if err != nil {
// don't fail on failures, try to create as many as you can
utilruntime.HandleError(fmt.Errorf("unable to reconcile clusterrole.%s/%s: %v", rbac.GroupName, clusterRole.Name, err))
} }
} }
existingClusterRoleBindings, err := clientset.ClusterRoleBindings().List(metav1.ListOptions{}) // ensure bootstrap rolebindings are created or reconciled
if err != nil { for _, clusterRoleBinding := range append(bootstrappolicy.ClusterRoleBindings(), bootstrappolicy.ControllerRoleBindings()...) {
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err))
return false, nil opts := reconciliation.ReconcileClusterRoleBindingOptions{
} RoleBinding: &clusterRoleBinding,
// only initialized on empty etcd Client: clientset.ClusterRoleBindings(),
if len(existingClusterRoleBindings.Items) == 0 { Confirm: true,
for _, clusterRoleBinding := range append(bootstrappolicy.ClusterRoleBindings(), bootstrappolicy.ControllerRoleBindings()...) { }
if _, err := clientset.ClusterRoleBindings().Create(&clusterRoleBinding); err != nil { err := retry.RetryOnConflict(retry.DefaultBackoff, func() error {
// don't fail on failures, try to create as many as you can result, err := opts.Run()
utilruntime.HandleError(fmt.Errorf("unable to initialize clusterrolebindings: %v", err)) if err != nil {
continue return err
}
switch {
case result.Protected && result.Operation != reconciliation.ReconcileNone:
glog.Warningf("skipped reconcile-protected clusterrolebinding.%s/%s with missing subjects: %v", rbac.GroupName, clusterRoleBinding.Name, result.MissingSubjects)
case result.Operation == reconciliation.ReconcileUpdate:
glog.Infof("updated clusterrolebinding.%s/%s with additional subjects: %v", rbac.GroupName, clusterRoleBinding.Name, result.MissingSubjects)
case result.Operation == reconciliation.ReconcileCreate:
glog.Infof("created clusterrolebinding.%s/%s", rbac.GroupName, clusterRoleBinding.Name)
case result.Operation == reconciliation.ReconcileRecreate:
glog.Infof("recreated clusterrolebinding.%s/%s", rbac.GroupName, clusterRoleBinding.Name)
} }
glog.Infof("Created clusterrolebinding.%s/%s", rbac.GroupName, clusterRoleBinding.Name) return nil
})
if err != nil {
// don't fail on failures, try to create as many as you can
utilruntime.HandleError(fmt.Errorf("unable to reconcile clusterrolebinding.%s/%s: %v", rbac.GroupName, clusterRoleBinding.Name, err))
} }
} }
......
...@@ -26,7 +26,8 @@ var ( ...@@ -26,7 +26,8 @@ var (
ReadWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"} ReadWrite = []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection"}
Read = []string{"get", "list", "watch"} Read = []string{"get", "list", "watch"}
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"}
) )
const ( const (
...@@ -51,6 +52,13 @@ func addClusterRoleLabel(roles []rbac.ClusterRole) { ...@@ -51,6 +52,13 @@ func addClusterRoleLabel(roles []rbac.ClusterRole) {
for k, v := range Label { for k, v := range Label {
roles[i].ObjectMeta.Labels[k] = v roles[i].ObjectMeta.Labels[k] = v
} }
if roles[i].ObjectMeta.Annotations == nil {
roles[i].ObjectMeta.Annotations = make(map[string]string)
}
for k, v := range Annotation {
roles[i].ObjectMeta.Annotations[k] = v
}
} }
return return
} }
...@@ -63,6 +71,13 @@ func addClusterRoleBindingLabel(rolebindings []rbac.ClusterRoleBinding) { ...@@ -63,6 +71,13 @@ func addClusterRoleBindingLabel(rolebindings []rbac.ClusterRoleBinding) {
for k, v := range Label { for k, v := range Label {
rolebindings[i].ObjectMeta.Labels[k] = v rolebindings[i].ObjectMeta.Labels[k] = v
} }
if rolebindings[i].ObjectMeta.Annotations == nil {
rolebindings[i].ObjectMeta.Annotations = make(map[string]string)
}
for k, v := range Annotation {
rolebindings[i].ObjectMeta.Annotations[k] = v
}
} }
return return
} }
......
...@@ -3,6 +3,8 @@ items: ...@@ -3,6 +3,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -18,6 +20,8 @@ items: ...@@ -18,6 +20,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -36,6 +40,8 @@ items: ...@@ -36,6 +40,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -54,6 +60,8 @@ items: ...@@ -54,6 +60,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -69,6 +77,8 @@ items: ...@@ -69,6 +77,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -84,6 +94,8 @@ items: ...@@ -84,6 +94,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
......
...@@ -3,6 +3,8 @@ items: ...@@ -3,6 +3,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -159,6 +161,8 @@ items: ...@@ -159,6 +161,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -177,6 +181,8 @@ items: ...@@ -177,6 +181,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -313,6 +319,8 @@ items: ...@@ -313,6 +319,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -333,6 +341,8 @@ items: ...@@ -333,6 +341,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -347,6 +357,8 @@ items: ...@@ -347,6 +357,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -365,6 +377,8 @@ items: ...@@ -365,6 +377,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -384,6 +398,8 @@ items: ...@@ -384,6 +398,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -401,6 +417,8 @@ items: ...@@ -401,6 +417,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -506,6 +524,8 @@ items: ...@@ -506,6 +524,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -618,6 +638,8 @@ items: ...@@ -618,6 +638,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -635,6 +657,8 @@ items: ...@@ -635,6 +657,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -663,6 +687,8 @@ items: ...@@ -663,6 +687,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -693,6 +719,8 @@ items: ...@@ -693,6 +719,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -742,6 +770,8 @@ items: ...@@ -742,6 +770,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
......
...@@ -3,6 +3,8 @@ items: ...@@ -3,6 +3,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -18,6 +20,8 @@ items: ...@@ -18,6 +20,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -33,6 +37,8 @@ items: ...@@ -33,6 +37,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -48,6 +54,8 @@ items: ...@@ -48,6 +54,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -63,6 +71,8 @@ items: ...@@ -63,6 +71,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -78,6 +88,8 @@ items: ...@@ -78,6 +88,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -93,6 +105,8 @@ items: ...@@ -93,6 +105,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -108,6 +122,8 @@ items: ...@@ -108,6 +122,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -123,6 +139,8 @@ items: ...@@ -123,6 +139,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -138,6 +156,8 @@ items: ...@@ -138,6 +156,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -153,6 +173,8 @@ items: ...@@ -153,6 +173,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -168,6 +190,8 @@ items: ...@@ -168,6 +190,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -183,6 +207,8 @@ items: ...@@ -183,6 +207,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -198,6 +224,8 @@ items: ...@@ -198,6 +224,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -213,6 +241,8 @@ items: ...@@ -213,6 +241,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -228,6 +258,8 @@ items: ...@@ -228,6 +258,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -243,6 +275,8 @@ items: ...@@ -243,6 +275,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -258,6 +292,8 @@ items: ...@@ -258,6 +292,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -273,6 +309,8 @@ items: ...@@ -273,6 +309,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -288,6 +326,8 @@ items: ...@@ -288,6 +326,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -303,6 +343,8 @@ items: ...@@ -303,6 +343,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -318,6 +360,8 @@ items: ...@@ -318,6 +360,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding kind: ClusterRoleBinding
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
......
...@@ -3,6 +3,8 @@ items: ...@@ -3,6 +3,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -49,6 +51,8 @@ items: ...@@ -49,6 +51,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -80,6 +84,8 @@ items: ...@@ -80,6 +84,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -129,6 +135,8 @@ items: ...@@ -129,6 +135,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -181,6 +189,8 @@ items: ...@@ -181,6 +189,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -233,6 +243,8 @@ items: ...@@ -233,6 +243,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -295,6 +307,8 @@ items: ...@@ -295,6 +307,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -336,6 +350,8 @@ items: ...@@ -336,6 +350,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -363,6 +379,8 @@ items: ...@@ -363,6 +379,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -439,6 +457,8 @@ items: ...@@ -439,6 +457,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -479,6 +499,8 @@ items: ...@@ -479,6 +499,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -512,6 +534,8 @@ items: ...@@ -512,6 +534,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -556,6 +580,8 @@ items: ...@@ -556,6 +580,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -643,6 +669,8 @@ items: ...@@ -643,6 +669,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -665,6 +693,8 @@ items: ...@@ -665,6 +693,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -706,6 +736,8 @@ items: ...@@ -706,6 +736,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -747,6 +779,8 @@ items: ...@@ -747,6 +779,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -776,6 +810,8 @@ items: ...@@ -776,6 +810,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -805,6 +841,8 @@ items: ...@@ -805,6 +841,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -827,6 +865,8 @@ items: ...@@ -827,6 +865,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -864,6 +904,8 @@ items: ...@@ -864,6 +904,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
...@@ -917,6 +959,8 @@ items: ...@@ -917,6 +959,8 @@ items:
- apiVersion: rbac.authorization.k8s.io/v1beta1 - apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole kind: ClusterRole
metadata: metadata:
annotations:
rbac.authorization.kubernetes.io/autoupdate: "true"
creationTimestamp: null creationTimestamp: null
labels: labels:
kubernetes.io/bootstrapping: rbac-defaults kubernetes.io/bootstrapping: rbac-defaults
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment