Skip to content

Commit 966d037

Browse files
committed
Cleanup orphan certificates when nodes are removed from NodeSet
When a node is removed from a DataPlane NodeSet, the TLS certificates created for that node were not being cleaned up, leaving orphan Certificate resources in the cluster. This adds a cleanupStaleCertificates function that runs at the beginning of EnsureTLSCerts to delete certificates for nodes that no longer exist in the NodeSet. It uses the allHostnames map (which reflects current nodes) to identify stale certificates by comparing against the hostname label on existing Certificate CRs. Jira: OSPRH-26077 Signed-off-by: rabi <ramishra@redhat.com>
1 parent cf82a75 commit 966d037

1 file changed

Lines changed: 65 additions & 0 deletions

File tree

internal/dataplane/cert.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,15 @@ import (
3131
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3232
apimachineryvalidation "k8s.io/apimachinery/pkg/util/validation"
3333
ctrl "sigs.k8s.io/controller-runtime"
34+
"sigs.k8s.io/controller-runtime/pkg/client"
3435
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
3536

3637
certmgrv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
3738
infranetworkv1 "github.com/openstack-k8s-operators/infra-operator/apis/network/v1beta1"
3839
"github.com/openstack-k8s-operators/lib-common/modules/certmanager"
3940
"github.com/openstack-k8s-operators/lib-common/modules/common/helper"
4041
"github.com/openstack-k8s-operators/lib-common/modules/common/secret"
42+
"github.com/openstack-k8s-operators/lib-common/modules/common/util"
4143
dataplanev1 "github.com/openstack-k8s-operators/openstack-operator/api/dataplane/v1beta1"
4244
)
4345

@@ -85,6 +87,12 @@ func EnsureTLSCerts(ctx context.Context, helper *helper.Helper,
8587
service dataplanev1.OpenStackDataPlaneService,
8688
certKey string,
8789
) (*ctrl.Result, error) {
90+
if instance.Status.ConfigHash != instance.Status.DeployedConfigHash {
91+
if err := cleanupStaleCertificates(ctx, helper, instance, allHostnames, service, certKey); err != nil {
92+
return &ctrl.Result{}, err
93+
}
94+
}
95+
8896
certsData := map[string][]byte{}
8997
secretMaxSize := instance.Spec.SecretMaxSize
9098

@@ -293,3 +301,60 @@ func GetServiceCertsSecretName(instance *dataplanev1.OpenStackDataPlaneNodeSet,
293301
}
294302
return name
295303
}
304+
305+
func cleanupStaleCertificates(ctx context.Context, helper *helper.Helper,
306+
instance *dataplanev1.OpenStackDataPlaneNodeSet,
307+
allHostnames map[string]map[infranetworkv1.NetNameStr]string,
308+
service dataplanev1.OpenStackDataPlaneService,
309+
certKey string) error {
310+
311+
labelSelector := map[string]string{
312+
NodeSetLabel: instance.Name,
313+
ServiceLabel: service.Name,
314+
ServiceKeyLabel: certKey,
315+
}
316+
listOpts := []client.ListOption{
317+
client.InNamespace(instance.Namespace),
318+
client.MatchingLabels(labelSelector),
319+
}
320+
321+
certList := &certmgrv1.CertificateList{}
322+
if err := helper.GetClient().List(ctx, certList, listOpts...); err != nil {
323+
return fmt.Errorf("failed to list certificates for cleanup: %w", err)
324+
}
325+
326+
for i := range certList.Items {
327+
cert := &certList.Items[i]
328+
hostname, ok := cert.Labels[HostnameLabel]
329+
if !ok {
330+
continue
331+
}
332+
if _, exists := allHostnames[hostname]; !exists {
333+
util.LogForObject(helper, fmt.Sprintf("Deleting stale certificate %s for removed node %s", cert.Name, hostname), instance)
334+
if err := helper.GetClient().Delete(ctx, cert); client.IgnoreNotFound(err) != nil {
335+
return fmt.Errorf("failed to delete stale certificate %s: %w", cert.Name, err)
336+
}
337+
}
338+
}
339+
340+
secretList := &corev1.SecretList{}
341+
if err := helper.GetClient().List(ctx, secretList, listOpts...); err != nil {
342+
return fmt.Errorf("failed to list certificate secrets for cleanup: %w", err)
343+
}
344+
345+
for i := range secretList.Items {
346+
secret := &secretList.Items[i]
347+
hostname, ok := secret.Labels[HostnameLabel]
348+
if !ok {
349+
continue
350+
}
351+
if _, exists := allHostnames[hostname]; !exists {
352+
util.LogForObject(helper, fmt.Sprintf("Deleting stale certificate secret %s for removed node %s", secret.Name, hostname), instance)
353+
if err := helper.GetClient().Delete(ctx, secret); client.IgnoreNotFound(err) != nil {
354+
return fmt.Errorf("failed to delete stale certificate secret %s: %w", secret.Name, err)
355+
}
356+
}
357+
}
358+
359+
return nil
360+
}

0 commit comments

Comments
 (0)