Skip to content

Commit 904003a

Browse files
committed
fix(olm): Verify ServiceAccount ownership before installing deployment
Currently, there is a timing during upgrade, the new SA is not yet being created but the deployment is successfully updated and the new pod is coming up using the old SA. As a result, the pod fails to succeed due to permission failure. When CSV is in Pending state, a permission and requirement check list is performed. A check for SA ownership is added to that check list to verify if new SA is in place before moving CSV to Installing state. If new SA is not yet in place, CSV can continue to be Pending which will prevent the deployment to be created/updated. Signed-off-by: Vu Dinh <[email protected]>
1 parent 7062e42 commit 904003a

File tree

2 files changed

+107
-5
lines changed

2 files changed

+107
-5
lines changed

pkg/controller/operators/olm/requirements.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,14 @@ func (a *Operator) permissionStatus(strategyDetailsDeployment *v1alpha1.Strategy
269269
statusesSet[saName] = status
270270
continue
271271
}
272+
// Check SA's ownership
273+
if ownerutil.IsOwnedByKind(sa, v1alpha1.ClusterServiceVersionKind) && !ownerutil.IsOwnedBy(sa, csv) {
274+
met = false
275+
status.Status = v1alpha1.RequirementStatusReasonNotPresent
276+
status.Message = "Service account is stale"
277+
statusesSet[saName] = status
278+
continue
279+
}
272280

273281
// Check if the ServiceAccount is owned by CSV
274282
if len(sa.GetOwnerReferences()) != 0 && !ownerutil.IsOwnedBy(sa, csv) {

pkg/controller/operators/olm/requirements_test.go

Lines changed: 99 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -437,11 +437,11 @@ func TestRequirementAndPermissionStatus(t *testing.T) {
437437
met: false,
438438
expectedRequirementStatuses: map[gvkn]v1alpha1.RequirementStatus{
439439
{"", "v1", "ServiceAccount", "sa"}: {
440-
Group: "",
441-
Version: "v1",
442-
Kind: "ServiceAccount",
443-
Name: "sa",
444-
Status: v1alpha1.RequirementStatusReasonPresentNotSatisfied,
440+
Group: "",
441+
Version: "v1",
442+
Kind: "ServiceAccount",
443+
Name: "sa",
444+
Status: v1alpha1.RequirementStatusReasonPresentNotSatisfied,
445445
Dependents: []v1alpha1.DependentStatus{},
446446
},
447447
{"operators.coreos.com", "v1alpha1", "ClusterServiceVersion", "csv1"}: {
@@ -733,6 +733,100 @@ func TestRequirementAndPermissionStatus(t *testing.T) {
733733
},
734734
expectedError: nil,
735735
},
736+
{
737+
description: "RequirementNotMet/StaleServiceAccount",
738+
csv: csvWithUID(csv("csv1",
739+
namespace,
740+
"0.0.0",
741+
"",
742+
installStrategy(
743+
"csv1-dep",
744+
[]v1alpha1.StrategyDeploymentPermissions{
745+
{
746+
ServiceAccountName: "sa",
747+
Rules: []rbacv1.PolicyRule{
748+
{
749+
APIGroups: []string{""},
750+
Verbs: []string{"*"},
751+
Resources: []string{"donuts"},
752+
},
753+
},
754+
},
755+
},
756+
nil,
757+
),
758+
nil,
759+
nil,
760+
v1alpha1.CSVPhasePending,
761+
), types.UID("csv-uid")),
762+
existingObjs: []runtime.Object{
763+
&corev1.ServiceAccount{
764+
ObjectMeta: metav1.ObjectMeta{
765+
Name: "sa",
766+
Namespace: namespace,
767+
UID: types.UID("sa"),
768+
OwnerReferences: []metav1.OwnerReference{
769+
{
770+
Kind: v1alpha1.ClusterServiceVersionKind,
771+
UID: "csv-wrong",
772+
},
773+
},
774+
},
775+
},
776+
&rbacv1.Role{
777+
ObjectMeta: metav1.ObjectMeta{
778+
Name: "role",
779+
Namespace: namespace,
780+
},
781+
Rules: []rbacv1.PolicyRule{
782+
{
783+
APIGroups: []string{""},
784+
Verbs: []string{"*"},
785+
Resources: []string{"donuts"},
786+
},
787+
},
788+
},
789+
&rbacv1.RoleBinding{
790+
ObjectMeta: metav1.ObjectMeta{
791+
Name: "roleBinding",
792+
Namespace: namespace,
793+
},
794+
Subjects: []rbacv1.Subject{
795+
{
796+
Kind: "ServiceAccount",
797+
APIGroup: "",
798+
Name: "sa",
799+
Namespace: namespace,
800+
},
801+
},
802+
RoleRef: rbacv1.RoleRef{
803+
APIGroup: "rbac.authorization.k8s.io",
804+
Kind: "Role",
805+
Name: "role",
806+
},
807+
},
808+
},
809+
existingExtObjs: nil,
810+
met: false,
811+
expectedRequirementStatuses: map[gvkn]v1alpha1.RequirementStatus{
812+
{"", "v1", "ServiceAccount", "sa"}: {
813+
Group: "",
814+
Version: "v1",
815+
Kind: "ServiceAccount",
816+
Name: "sa",
817+
Status: v1alpha1.RequirementStatusReasonNotPresent,
818+
Dependents: []v1alpha1.DependentStatus{},
819+
},
820+
{"operators.coreos.com", "v1alpha1", "ClusterServiceVersion", "csv1"}: {
821+
Group: "operators.coreos.com",
822+
Version: "v1alpha1",
823+
Kind: "ClusterServiceVersion",
824+
Name: "csv1",
825+
Status: v1alpha1.RequirementStatusReasonPresent,
826+
},
827+
},
828+
expectedError: nil,
829+
},
736830
}
737831

738832
for _, test := range tests {

0 commit comments

Comments
 (0)