Skip to content

Commit 1dcc7cf

Browse files
dtfranzkevinrizza
authored andcommitted
RoleBinding SSA (#3190)
Switch to SSA for RoleBindings during install (as we do now for Services and ClusterRoleBindings) to avoid issues with race conditions and/or failures to retrieve resources due to missing labels. Signed-off-by: Daniel Franz <[email protected]> Upstream-repository: operator-lifecycle-manager Upstream-commit: 6b2b933f7fb5dd1fd6fe7da967f3f22a27c4253c
1 parent 764c6fe commit 1dcc7cf

File tree

9 files changed

+116
-92
lines changed

9 files changed

+116
-92
lines changed

staging/operator-lifecycle-manager/pkg/controller/install/certresources.go

Lines changed: 15 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -463,53 +463,24 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
463463
return nil, nil, err
464464
}
465465

466-
// Create RoleBinding to extension-apiserver-authentication-reader Role in the kube-system namespace.
467-
authReaderRoleBinding := &rbacv1.RoleBinding{
468-
Subjects: []rbacv1.Subject{
469-
{
470-
Kind: "ServiceAccount",
471-
APIGroup: "",
472-
Name: depSpec.Template.Spec.ServiceAccountName,
473-
Namespace: i.owner.GetNamespace(),
474-
},
475-
},
476-
RoleRef: rbacv1.RoleRef{
477-
APIGroup: "rbac.authorization.k8s.io",
478-
Kind: "Role",
479-
Name: "extension-apiserver-authentication-reader",
480-
},
481-
}
482-
authReaderRoleBinding.SetName(AuthReaderRoleBindingName(serviceName))
483-
authReaderRoleBinding.SetNamespace(KubeSystem)
484-
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})
466+
// Apply RoleBinding to extension-apiserver-authentication-reader Role in the kube-system namespace.
467+
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(serviceName), KubeSystem).
468+
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
469+
WithSubjects(rbacv1ac.Subject().
470+
WithKind("ServiceAccount").
471+
WithAPIGroup("").
472+
WithName(depSpec.Template.Spec.ServiceAccountName).
473+
WithNamespace(i.owner.GetNamespace())).
474+
WithRoleRef(rbacv1ac.RoleRef().
475+
WithAPIGroup("rbac.authorization.k8s.io").
476+
WithKind("Role").
477+
WithName("extension-apiserver-authentication-reader"))
485478

486-
existingAuthReaderRoleBinding, err := i.strategyClient.GetOpLister().RbacV1().RoleBindingLister().RoleBindings(KubeSystem).Get(authReaderRoleBinding.GetName())
487-
if err == nil {
488-
// Check if the only owners are this CSV or in this CSV's replacement chain.
489-
if ownerutil.AdoptableLabels(existingAuthReaderRoleBinding.GetLabels(), true, i.owner) {
490-
logger.WithFields(log.Fields{"obj": "existingAuthReaderRB", "labels": existingAuthReaderRoleBinding.GetLabels()}).Debug("adopting")
491-
if err := ownerutil.AddOwnerLabels(authReaderRoleBinding, i.owner); err != nil {
492-
return nil, nil, err
493-
}
494-
}
495-
// Attempt an update.
496-
if _, err := i.strategyClient.GetOpClient().UpdateRoleBinding(authReaderRoleBinding); err != nil {
497-
logger.Warnf("could not update auth reader role binding %s", authReaderRoleBinding.GetName())
498-
return nil, nil, err
499-
}
500-
} else if apierrors.IsNotFound(err) {
501-
// Create the role.
502-
if err := ownerutil.AddOwnerLabels(authReaderRoleBinding, i.owner); err != nil {
503-
return nil, nil, err
504-
}
505-
_, err = i.strategyClient.GetOpClient().CreateRoleBinding(authReaderRoleBinding)
506-
if err != nil {
507-
log.Warnf("could not create auth reader role binding %s", authReaderRoleBinding.GetName())
508-
return nil, nil, err
509-
}
510-
} else {
479+
if _, err = i.strategyClient.GetOpClient().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}); err != nil {
480+
log.Errorf("could not apply auth reader rolebinding %s: %s", *authReaderRoleBindingApplyConfig.Name, err.Error())
511481
return nil, nil, err
512482
}
483+
513484
AddDefaultCertVolumeAndVolumeMounts(&depSpec, secret.GetName())
514485

515486
// Setting the olm hash label forces a rollout and ensures that the new secret

staging/operator-lifecycle-manager/pkg/controller/install/certresources_test.go

Lines changed: 39 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
309309
authReaderRoleBinding.SetNamespace(KubeSystem)
310310
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})
311311

312-
mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
312+
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
313+
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
314+
WithSubjects(rbacv1ac.Subject().
315+
WithKind("ServiceAccount").
316+
WithAPIGroup("").
317+
WithName(args.depSpec.Template.Spec.ServiceAccountName).
318+
WithNamespace(namespace)).
319+
WithRoleRef(rbacv1ac.RoleRef().
320+
WithAPIGroup("rbac.authorization.k8s.io").
321+
WithKind("Role").
322+
WithName("extension-apiserver-authentication-reader"))
323+
324+
mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
313325
},
314326
state: fakeState{
315327
existingService: &corev1.Service{
@@ -569,7 +581,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
569581
authReaderRoleBinding.SetNamespace(KubeSystem)
570582
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})
571583

572-
mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
584+
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
585+
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
586+
WithSubjects(rbacv1ac.Subject().
587+
WithKind("ServiceAccount").
588+
WithAPIGroup("").
589+
WithName(args.depSpec.Template.Spec.ServiceAccountName).
590+
WithNamespace(namespace)).
591+
WithRoleRef(rbacv1ac.RoleRef().
592+
WithAPIGroup("rbac.authorization.k8s.io").
593+
WithKind("Role").
594+
WithName("extension-apiserver-authentication-reader"))
595+
596+
mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
573597
},
574598
state: fakeState{
575599
existingService: &corev1.Service{
@@ -831,7 +855,19 @@ func TestInstallCertRequirementsForDeployment(t *testing.T) {
831855
authReaderRoleBinding.SetNamespace(KubeSystem)
832856
authReaderRoleBinding.SetLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue})
833857

834-
mockOpClient.EXPECT().UpdateRoleBinding(authReaderRoleBinding).Return(authReaderRoleBinding, nil)
858+
authReaderRoleBindingApplyConfig := rbacv1ac.RoleBinding(AuthReaderRoleBindingName(service.GetName()), KubeSystem).
859+
WithLabels(map[string]string{OLMManagedLabelKey: OLMManagedLabelValue}).
860+
WithSubjects(rbacv1ac.Subject().
861+
WithKind("ServiceAccount").
862+
WithAPIGroup("").
863+
WithName(args.depSpec.Template.Spec.ServiceAccountName).
864+
WithNamespace(namespace)).
865+
WithRoleRef(rbacv1ac.RoleRef().
866+
WithAPIGroup("rbac.authorization.k8s.io").
867+
WithKind("Role").
868+
WithName("extension-apiserver-authentication-reader"))
869+
870+
mockOpClient.EXPECT().ApplyRoleBinding(authReaderRoleBindingApplyConfig, metav1.ApplyOptions{Force: true, FieldManager: "olm.install"}).Return(authReaderRoleBinding, nil)
835871
},
836872
state: fakeState{
837873
existingService: nil,

staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1511,6 +1511,7 @@ func TestTransitionCSV(t *testing.T) {
15111511
// Note: Ideally we would not pre-create these objects, but fake client does not support
15121512
// creation through SSA, see issue here: https://github.com/kubernetes/kubernetes/issues/115598
15131513
// Once resolved, these objects and others in this file may be removed.
1514+
roleBinding("a1-service-auth-reader", "kube-system", "extension-apiserver-authentication-reader", "sa", namespace),
15141515
service("a1-service", namespace, "a1", 80),
15151516
clusterRoleBinding("a1-service-system:auth-delegator", "system:auth-delegator", "sa", namespace),
15161517
},
@@ -5985,8 +5986,9 @@ func TestCARotation(t *testing.T) {
59855986
), defaultTemplateAnnotations), apis("a1.v1.a1Kind"), nil),
59865987
},
59875988
clientObjs: []runtime.Object{addAnnotation(defaultOperatorGroup, operatorsv1.OperatorGroupProvidedAPIsAnnotationKey, "c1.v1.g1,a1Kind.v1.a1")},
5988-
// The service and clusterRoleBinding have been added here as a workaround to fake client not supporting SSA
5989+
// The rolebinding, service, and clusterRoleBinding have been added here as a workaround to fake client not supporting SSA
59895990
objs: []runtime.Object{
5991+
roleBinding("a1-service-auth-reader", "kube-system", "extension-apiserver-authentication-reader", "sa", namespace),
59905992
service("a1-service", namespace, "a1", 80, ownerReference),
59915993
clusterRoleBinding("a1-service-system:auth-delegator", "system:auth-delegator", "sa", namespace),
59925994
},

staging/operator-lifecycle-manager/pkg/lib/operatorclient/client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ type RoleClient interface {
9494

9595
// RoleBindingClient contains methods for manipulating RoleBindings.
9696
type RoleBindingClient interface {
97+
ApplyRoleBinding(applyConfig *rbacv1ac.RoleBindingApplyConfiguration, applyOptions metav1.ApplyOptions) (*rbacv1.RoleBinding, error)
9798
CreateRoleBinding(*rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)
9899
GetRoleBinding(namespace, name string) (*rbacv1.RoleBinding, error)
99100
UpdateRoleBinding(modified *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error)

staging/operator-lifecycle-manager/pkg/lib/operatorclient/operatorclientmocks/mock_client.go

Lines changed: 30 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

staging/operator-lifecycle-manager/pkg/lib/operatorclient/rolebinding.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,15 @@ import (
77
rbacv1 "k8s.io/api/rbac/v1"
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
99
"k8s.io/apimachinery/pkg/types"
10+
acv1 "k8s.io/client-go/applyconfigurations/rbac/v1"
1011
"k8s.io/klog"
1112
)
1213

14+
// ApplyRoleBinding applies the roleBinding.
15+
func (c *Client) ApplyRoleBinding(applyConfig *acv1.RoleBindingApplyConfiguration, applyOptions metav1.ApplyOptions) (*rbacv1.RoleBinding, error) {
16+
return c.RbacV1().RoleBindings(*applyConfig.Namespace).Apply(context.TODO(), applyConfig, applyOptions)
17+
}
18+
1319
// CreateRoleBinding creates the roleBinding.
1420
func (c *Client) CreateRoleBinding(ig *rbacv1.RoleBinding) (*rbacv1.RoleBinding, error) {
1521
return c.RbacV1().RoleBindings(ig.GetNamespace()).Create(context.TODO(), ig, metav1.CreateOptions{})

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install/certresources.go

Lines changed: 15 additions & 44 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient/client.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient/rolebinding.go

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)