Skip to content

Commit dffeb5d

Browse files
hirokuni-kitaharahirokuni.kitahara
andauthored
add finalizer to CR for kubernetes 1.20 update (#283)
Co-authored-by: hirokuni.kitahara <[email protected]@hirokunikitaharanoMacBook-Pro.local>
1 parent 350ffbf commit dffeb5d

File tree

6 files changed

+270
-1
lines changed

6 files changed

+270
-1
lines changed

integrity-shield-operator/api/v1alpha1/integrityshield_types.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ const (
5656
DefaultKeyringFilename = "pubring.gpg"
5757
DefaultIShieldWebhookTimeout = 10
5858
SATokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
59+
60+
CleanupFinalizerName = "cleanup.finalizers.integrityshield.io"
5961
)
6062

6163
// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!

integrity-shield-operator/config/samples/apis_v1alpha1_integrityshield.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ apiVersion: apis.integrityshield.io/v1alpha1
22
kind: IntegrityShield
33
metadata:
44
name: integrity-shield-server
5+
finalizers:
6+
- cleanup.finalizers.integrityshield.io
57
spec:
68
namespace: integrity-shield-operator-system
79
shieldConfig:

integrity-shield-operator/controllers/integrityshield.go

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,32 @@ func (r *IntegrityShieldReconciler) createOrUpdateCRD(instance *apiv1alpha1.Inte
106106

107107
}
108108

109+
func (r *IntegrityShieldReconciler) deleteCRD(instance *apiv1alpha1.IntegrityShield, expected *extv1.CustomResourceDefinition) (ctrl.Result, error) {
110+
ctx := context.Background()
111+
found := &extv1.CustomResourceDefinition{}
112+
113+
reqLogger := r.Log.WithValues(
114+
"Instance.Name", instance.Name,
115+
"CustomResourceDefinition.Name", expected.Name)
116+
117+
err := r.Get(ctx, types.NamespacedName{Name: expected.Name}, found)
118+
119+
if err == nil {
120+
reqLogger.Info(fmt.Sprintf("Deleting the IShield CustomResourceDefinition %s", expected.Name))
121+
err = r.Delete(ctx, found)
122+
if err != nil {
123+
reqLogger.Error(err, fmt.Sprintf("Failed to delete the IShield CustomResourceDefinition %s", expected.Name))
124+
return ctrl.Result{}, err
125+
}
126+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
127+
} else if errors.IsNotFound(err) {
128+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
129+
} else {
130+
return ctrl.Result{}, err
131+
}
132+
133+
}
134+
109135
func (r *IntegrityShieldReconciler) createOrUpdateShieldConfigCRD(
110136
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
111137
expected := res.BuildShieldConfigCRD(instance)
@@ -135,6 +161,35 @@ func (r *IntegrityShieldReconciler) createOrUpdateResourceSigningProfileCRD(
135161
return r.createOrUpdateCRD(instance, expected)
136162
}
137163

164+
func (r *IntegrityShieldReconciler) deleteShieldConfigCRD(
165+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
166+
expected := res.BuildShieldConfigCRD(instance)
167+
return r.deleteCRD(instance, expected)
168+
}
169+
170+
func (r *IntegrityShieldReconciler) deleteSignerConfigCRD(
171+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
172+
expected := res.BuildSignerConfigCRD(instance)
173+
return r.deleteCRD(instance, expected)
174+
}
175+
func (r *IntegrityShieldReconciler) deleteResourceSignatureCRD(
176+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
177+
expected := res.BuildResourceSignatureCRD(instance)
178+
return r.deleteCRD(instance, expected)
179+
}
180+
181+
func (r *IntegrityShieldReconciler) deleteHelmReleaseMetadataCRD(
182+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
183+
expected := res.BuildHelmReleaseMetadataCRD(instance)
184+
return r.deleteCRD(instance, expected)
185+
}
186+
187+
func (r *IntegrityShieldReconciler) deleteResourceSigningProfileCRD(
188+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
189+
expected := res.BuildResourceSigningProfileCRD(instance)
190+
return r.deleteCRD(instance, expected)
191+
}
192+
138193
/**********************************************
139194
140195
CR
@@ -409,6 +464,33 @@ func (r *IntegrityShieldReconciler) createOrUpdateClusterRole(instance *apiv1alp
409464

410465
}
411466

467+
func (r *IntegrityShieldReconciler) deleteClusterRole(instance *apiv1alpha1.IntegrityShield, expected *rbacv1.ClusterRole) (ctrl.Result, error) {
468+
ctx := context.Background()
469+
found := &rbacv1.ClusterRole{}
470+
471+
reqLogger := r.Log.WithValues(
472+
"Instance.Name", instance.Name,
473+
"ClusterRole.Name", expected.Name)
474+
475+
err := r.Get(ctx, types.NamespacedName{Name: expected.Name}, found)
476+
477+
if err == nil {
478+
reqLogger.Info(fmt.Sprintf("Deleting the IShield ClusterRole %s", expected.Name))
479+
err = r.Delete(ctx, found)
480+
if err != nil {
481+
reqLogger.Error(err, fmt.Sprintf("Failed to delete the IShield ClusterRole %s", expected.Name))
482+
return ctrl.Result{}, err
483+
}
484+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
485+
} else if errors.IsNotFound(err) {
486+
487+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
488+
} else {
489+
return ctrl.Result{}, err
490+
}
491+
492+
}
493+
412494
func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleBinding(instance *apiv1alpha1.IntegrityShield, expected *rbacv1.ClusterRoleBinding) (ctrl.Result, error) {
413495
ctx := context.Background()
414496
found := &rbacv1.ClusterRoleBinding{}
@@ -451,6 +533,32 @@ func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleBinding(instance *a
451533

452534
}
453535

536+
func (r *IntegrityShieldReconciler) deleteClusterRoleBinding(instance *apiv1alpha1.IntegrityShield, expected *rbacv1.ClusterRoleBinding) (ctrl.Result, error) {
537+
ctx := context.Background()
538+
found := &rbacv1.ClusterRoleBinding{}
539+
540+
reqLogger := r.Log.WithValues(
541+
"Instance.Name", instance.Name,
542+
"ClusterRoleBinding.Name", expected.Name)
543+
544+
err := r.Get(ctx, types.NamespacedName{Name: expected.Name}, found)
545+
546+
if err == nil {
547+
reqLogger.Info(fmt.Sprintf("Deleting the IShield ClusterRoleBinding %s", expected.Name))
548+
err = r.Delete(ctx, found)
549+
if err != nil {
550+
reqLogger.Error(err, fmt.Sprintf("Failed to delete the IShield ClusterRoleBinding %s", expected.Name))
551+
return ctrl.Result{}, err
552+
}
553+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
554+
} else if errors.IsNotFound(err) {
555+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
556+
} else {
557+
return ctrl.Result{}, err
558+
}
559+
560+
}
561+
454562
func (r *IntegrityShieldReconciler) createOrUpdateRole(instance *apiv1alpha1.IntegrityShield, expected *rbacv1.Role) (ctrl.Result, error) {
455563
ctx := context.Background()
456564
found := &rbacv1.Role{}
@@ -543,6 +651,12 @@ func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleBindingForIShieldAd
543651
return r.createOrUpdateClusterRoleBinding(instance, expected)
544652
}
545653

654+
func (r *IntegrityShieldReconciler) deleteClusterRoleBindingForIShieldAdmin(
655+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
656+
expected := res.BuildClusterRoleBindingForIShieldAdmin(instance)
657+
return r.deleteClusterRoleBinding(instance, expected)
658+
}
659+
546660
func (r *IntegrityShieldReconciler) createOrUpdateRoleBindingForIShieldAdmin(
547661
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
548662
expected := res.BuildRoleBindingForIShieldAdmin(instance)
@@ -561,13 +675,25 @@ func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleForIShieldAdmin(
561675
return r.createOrUpdateClusterRole(instance, expected)
562676
}
563677

678+
func (r *IntegrityShieldReconciler) deleteClusterRoleForIShieldAdmin(
679+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
680+
expected := res.BuildClusterRoleForIShieldAdmin(instance)
681+
return r.deleteClusterRole(instance, expected)
682+
}
683+
564684
// for ie
565685
func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleBindingForIShield(
566686
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
567687
expected := res.BuildClusterRoleBindingForIShield(instance)
568688
return r.createOrUpdateClusterRoleBinding(instance, expected)
569689
}
570690

691+
func (r *IntegrityShieldReconciler) deleteClusterRoleBindingForIShield(
692+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
693+
expected := res.BuildClusterRoleBindingForIShield(instance)
694+
return r.deleteClusterRoleBinding(instance, expected)
695+
}
696+
571697
func (r *IntegrityShieldReconciler) createOrUpdateRoleBindingForIShield(
572698
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
573699
expected := res.BuildRoleBindingForIShield(instance)
@@ -586,6 +712,12 @@ func (r *IntegrityShieldReconciler) createOrUpdateClusterRoleForIShield(
586712
return r.createOrUpdateClusterRole(instance, expected)
587713
}
588714

715+
func (r *IntegrityShieldReconciler) deleteClusterRoleForIShield(
716+
instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
717+
expected := res.BuildClusterRoleForIShield(instance)
718+
return r.deleteClusterRole(instance, expected)
719+
}
720+
589721
func (r *IntegrityShieldReconciler) createOrUpdatePodSecurityPolicy(instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
590722
ctx := context.Background()
591723
expected := res.BuildPodSecurityPolicy(instance)
@@ -629,6 +761,33 @@ func (r *IntegrityShieldReconciler) createOrUpdatePodSecurityPolicy(instance *ap
629761

630762
}
631763

764+
// delete ishield-psp
765+
func (r *IntegrityShieldReconciler) deletePodSecurityPolicy(instance *apiv1alpha1.IntegrityShield) (ctrl.Result, error) {
766+
ctx := context.Background()
767+
expected := res.BuildPodSecurityPolicy(instance)
768+
found := &policyv1.PodSecurityPolicy{}
769+
770+
reqLogger := r.Log.WithValues(
771+
"Instance.Name", instance.Name,
772+
"PodSecurityPolicy.Name", expected.Name)
773+
774+
err := r.Get(ctx, types.NamespacedName{Name: expected.Name}, found)
775+
776+
if err == nil {
777+
reqLogger.Info("Deleting the IShield PodSecurityPolicy")
778+
err = r.Delete(ctx, found)
779+
if err != nil {
780+
reqLogger.Error(err, "Failed to delete the IShield PodSecurityPolicy")
781+
return ctrl.Result{}, err
782+
}
783+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
784+
} else if errors.IsNotFound(err) {
785+
return ctrl.Result{Requeue: true, RequeueAfter: time.Second * 1}, nil
786+
} else {
787+
return ctrl.Result{}, err
788+
}
789+
}
790+
632791
/**********************************************
633792
634793
Secret

integrity-shield-operator/controllers/integrityshield_controller.go

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,32 @@ func (r *IntegrityShieldReconciler) Reconcile(req ctrl.Request) (ctrl.Result, er
7171
var recErr error
7272

7373
// apply default config if not ignored
74+
// this step is necessary to identify default resource names such as ishield-webhook-config, so this should be done even before finalizer
7475
if !instance.Spec.IgnoreDefaultIShieldCR {
7576
instance = resources.MergeDefaultIntegrityShieldCR(instance, "")
7677
}
7778

79+
// Integrity Shield is under deletion - finalizer step
80+
if !instance.ObjectMeta.DeletionTimestamp.IsZero() {
81+
if containsString(instance.ObjectMeta.Finalizers, apisv1alpha1.CleanupFinalizerName) {
82+
if err := r.deleteClusterScopedChildrenResources(instance); err != nil {
83+
// if fail to delete the external dependency here, return with error
84+
// so that it can be retried
85+
reqLogger.Error(err, "Error occured during finalizer process. retrying soon.")
86+
return ctrl.Result{}, err
87+
}
88+
89+
// remove our finalizer from the list and update it.
90+
instance.ObjectMeta.Finalizers = removeString(instance.ObjectMeta.Finalizers, apisv1alpha1.CleanupFinalizerName)
91+
if err := r.Update(context.Background(), instance); err != nil {
92+
return ctrl.Result{}, err
93+
}
94+
}
95+
return ctrl.Result{}, nil
96+
}
97+
98+
// otherwise, normal reconcile
99+
78100
if ok, nonReadyKey := r.isKeyRingReady(instance); !ok {
79101
reqLogger.Info(fmt.Sprintf("KeyRing secret \"%s\" does not exist. Skip reconciling.", nonReadyKey))
80102
return ctrl.Result{Requeue: true}, nil
@@ -237,3 +259,85 @@ func (r *IntegrityShieldReconciler) SetupWithManager(mgr ctrl.Manager) error {
237259
Owns(&apisv1alpha1.IntegrityShield{}).
238260
Complete(r)
239261
}
262+
263+
func (r *IntegrityShieldReconciler) deleteClusterScopedChildrenResources(instance *apisv1alpha1.IntegrityShield) error {
264+
// delete any cluster scope resources owned by the instance
265+
// (In Iubernetes 1.20 and later, a garbage collector ignore cluster scope children even if their owner is deleted)
266+
var err error
267+
_, err = r.deleteWebhook(instance)
268+
if err != nil {
269+
return err
270+
}
271+
_, err = r.deletePodSecurityPolicy(instance)
272+
if err != nil {
273+
return err
274+
}
275+
if !instance.Spec.Security.AutoIShieldAdminCreationDisabled {
276+
_, err = r.deleteClusterRoleBindingForIShieldAdmin(instance)
277+
if err != nil {
278+
return err
279+
}
280+
_, err = r.deleteClusterRoleForIShieldAdmin(instance)
281+
if err != nil {
282+
return err
283+
}
284+
}
285+
_, err = r.deleteClusterRoleBindingForIShield(instance)
286+
if err != nil {
287+
return err
288+
}
289+
_, err = r.deleteClusterRoleForIShield(instance)
290+
if err != nil {
291+
return err
292+
}
293+
294+
enabledPulgins := instance.Spec.ShieldConfig.GetEnabledPlugins()
295+
if enabledPulgins["helm"] {
296+
_, err = r.deleteHelmReleaseMetadataCRD(instance)
297+
if err != nil {
298+
return err
299+
}
300+
}
301+
302+
_, err = r.deleteResourceSigningProfileCRD(instance)
303+
if err != nil {
304+
return err
305+
}
306+
307+
_, err = r.deleteResourceSignatureCRD(instance)
308+
if err != nil {
309+
return err
310+
}
311+
312+
_, err = r.deleteSignerConfigCRD(instance)
313+
if err != nil {
314+
return err
315+
}
316+
317+
_, err = r.deleteShieldConfigCRD(instance)
318+
if err != nil {
319+
return err
320+
}
321+
322+
return nil
323+
}
324+
325+
// Helper functions to check and remove string from a slice of strings.
326+
func containsString(slice []string, s string) bool {
327+
for _, item := range slice {
328+
if item == s {
329+
return true
330+
}
331+
}
332+
return false
333+
}
334+
335+
func removeString(slice []string, s string) (result []string) {
336+
for _, item := range slice {
337+
if item == s {
338+
continue
339+
}
340+
result = append(result, item)
341+
}
342+
return
343+
}

integrity-shield-operator/resources/testdata/integrityShieldCR.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ apiVersion: apis.integrityshield.io/v1alpha1
22
kind: IntegrityShield
33
metadata:
44
creationTimestamp: null
5+
finalizers:
6+
- cleanup.finalizers.integrityshield.io
57
name: integrity-shield-server
68
spec:
79
affinity: {}

shield/pkg/shield/checkFunctions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ func iShieldResourceCheck(reqc *common.ReqContext, config *config.ShieldConfig,
103103
gcReq := checkIfGarbageCollectorRequest(reqc)
104104
spSAReq := checkIfSpecialServiceAccountRequest(reqc)
105105

106-
if (iShieldOperatorResource && (adminReq || gcReq || spSAReq)) || (iShieldServerResource && (operatorReq || serverReq || gcReq || spSAReq)) {
106+
if (iShieldOperatorResource && (adminReq || operatorReq || gcReq || spSAReq)) || (iShieldServerResource && (operatorReq || serverReq || gcReq || spSAReq)) {
107107
ctx.Allow = true
108108
ctx.Verified = true
109109
ctx.ReasonCode = common.REASON_ISHIELD_ADMIN

0 commit comments

Comments
 (0)