github.com/verrazzano/verrazzano@v1.7.1/platform-operator/controllers/secrets/verrazzano_tls_secret_test.go (about)

     1  // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package secrets
     5  
     6  import (
     7  	"bytes"
     8  	"context"
     9  	"fmt"
    10  	"testing"
    11  
    12  	"github.com/stretchr/testify/assert"
    13  	vzconst "github.com/verrazzano/verrazzano/pkg/constants"
    14  	"github.com/verrazzano/verrazzano/pkg/log/vzlog"
    15  	vzapi "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1alpha1"
    16  	"github.com/verrazzano/verrazzano/platform-operator/constants"
    17  	"github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/healthcheck"
    18  	appsv1 "k8s.io/api/apps/v1"
    19  	corev1 "k8s.io/api/core/v1"
    20  	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    21  	"k8s.io/apimachinery/pkg/runtime"
    22  	"k8s.io/apimachinery/pkg/types"
    23  	controllerruntime "sigs.k8s.io/controller-runtime"
    24  	"sigs.k8s.io/controller-runtime/pkg/client"
    25  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    26  )
    27  
    28  type testUpdater struct{}
    29  
    30  // Update test impl for reconciler unit tests
    31  func (t *testUpdater) Update(_ *healthcheck.UpdateEvent) {}
    32  
    33  // TestReconcileVerrazzanoTLS tests the reconcileVerrazzanoTLS method keeping the VZ CA secret in sync when rotated
    34  // GIVEN a call to reconcileVerrazzanoTLS to reconcile the verrazzano-tls secret update
    35  // WHEN the Verrazzano ingress secret CA bundle exists and has been updated
    36  // THEN the reconcileVerrazzanoTLS can extract the request and call the function to update the copies, unless a VZ reconcile is in progress
    37  func TestReconcileVerrazzanoTLS(t *testing.T) {
    38  
    39  	scheme := newScheme()
    40  	log := vzlog.DefaultLogger()
    41  	updater := &testUpdater{}
    42  
    43  	vzTLSName := types.NamespacedName{Name: vzconst.VerrazzanoIngressTLSSecret, Namespace: vzconst.VerrazzanoSystemNamespace}
    44  	privateCABundleName := types.NamespacedName{Name: vzconst.PrivateCABundle, Namespace: vzconst.VerrazzanoSystemNamespace}
    45  	rancherTLSCATestSecret := types.NamespacedName{Namespace: vzconst.RancherSystemNamespace, Name: vzconst.RancherTLSCA}
    46  	multiclusterCASecret := types.NamespacedName{Namespace: constants.VerrazzanoMultiClusterNamespace, Name: constants.VerrazzanoLocalCABundleSecret}
    47  
    48  	defaultReq := controllerruntime.Request{
    49  		NamespacedName: vzTLSName,
    50  	}
    51  
    52  	defaultWantErr := assert.NoError
    53  
    54  	ingressTLSSecret := &corev1.Secret{
    55  		ObjectMeta: v1.ObjectMeta{Name: vzTLSSecret.Name, Namespace: vzTLSSecret.Namespace},
    56  	}
    57  	privateCASecret := &corev1.Secret{
    58  		ObjectMeta: v1.ObjectMeta{Name: privateCABundleName.Name, Namespace: privateCABundleName.Namespace},
    59  	}
    60  	defaultObjsList := []runtime.Object{
    61  		&corev1.Secret{
    62  			ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
    63  		},
    64  		&corev1.Secret{
    65  			ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
    66  		},
    67  		privateCASecret,
    68  		&corev1.Namespace{
    69  			ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
    70  		},
    71  		&appsv1.Deployment{
    72  			ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
    73  		},
    74  	}
    75  
    76  	vzReady := vzapi.Verrazzano{
    77  		Status: vzapi.VerrazzanoStatus{
    78  			State: vzapi.VzStateReady,
    79  		},
    80  	}
    81  
    82  	type args struct {
    83  		req *controllerruntime.Request
    84  		vz  *vzapi.Verrazzano
    85  	}
    86  	tests := []struct {
    87  		name            string
    88  		cli             client.Client
    89  		args            args
    90  		requeueRequired bool
    91  		wantErr         assert.ErrorAssertionFunc
    92  	}{
    93  		{
    94  			name: "verrazzano-tls-update",
    95  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
    96  				append(defaultObjsList, ingressTLSSecret)...,
    97  			).Build(),
    98  		},
    99  		{
   100  			name: "verrazzano-tls-does-not-exist",
   101  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   102  				defaultObjsList...,
   103  			).Build(),
   104  		},
   105  	}
   106  	for _, tt := range tests {
   107  		t.Run(tt.name, func(t *testing.T) {
   108  			r := &VerrazzanoSecretsReconciler{
   109  				Client:        tt.cli,
   110  				Scheme:        scheme,
   111  				log:           log,
   112  				StatusUpdater: updater,
   113  			}
   114  			wantErr := defaultWantErr
   115  			if tt.wantErr != nil {
   116  				wantErr = tt.wantErr
   117  			}
   118  
   119  			vz := &vzReady
   120  			if tt.args.vz != nil {
   121  				vz = tt.args.vz
   122  			}
   123  
   124  			req := defaultReq
   125  			if tt.args.req != nil {
   126  				req = *tt.args.req
   127  			}
   128  
   129  			ctx := context.TODO()
   130  			got, err := r.reconcileVerrazzanoTLS(ctx, req.NamespacedName, vzconst.CACertKey)
   131  			if !wantErr(t, err, fmt.Sprintf("reconcileVerrazzanoTLS(%v, %v, %v)", ctx, req, vz)) {
   132  				return
   133  			}
   134  			assert.Equal(t, got.Requeue, tt.requeueRequired, "Did not get expected result")
   135  		})
   136  	}
   137  }
   138  
   139  // TestReconcileVerrazzanoCABundleCopies tests the reconcileVerrazzanoCABundleCopies method keeping upstream copies in sync
   140  // GIVEN a call to reconcileVerrazzanoCABundleCopies to reconcile the verrazzano-tls secret
   141  // WHEN the verrazzano-tls secret CA bundle exists and has been updated
   142  // THEN the upstream copies are updated and any required actions are taken
   143  func TestReconcileVerrazzanoCABundleCopies(t *testing.T) {
   144  	scheme := newScheme()
   145  	log := vzlog.DefaultLogger()
   146  	updater := &testUpdater{}
   147  
   148  	updatedBundleData := []byte("bundleupdate")
   149  	originalBundleData := []byte("original bundle data")
   150  	letsEncryptStagingBundleData := []byte("letsencrypt staging bundle data")
   151  
   152  	rancherTLSCATestSecret := types.NamespacedName{Namespace: vzconst.RancherSystemNamespace, Name: vzconst.RancherTLSCA}
   153  	multiclusterCASecret := types.NamespacedName{Namespace: constants.VerrazzanoMultiClusterNamespace, Name: constants.VerrazzanoLocalCABundleSecret}
   154  	rancherDeploymentNSName := types.NamespacedName{Namespace: vzconst.RancherSystemNamespace, Name: rancherDeploymentName}
   155  
   156  	defaultWantErr := assert.NoError
   157  	defaultBundleWantErr := assert.NoError
   158  
   159  	clusterIssuerSecretNotUpdated := &corev1.Secret{
   160  		ObjectMeta: v1.ObjectMeta{Name: vzconst.DefaultVerrazzanoCASecretName, Namespace: vzconst.CertManagerNamespace},
   161  		Data: map[string][]byte{
   162  			"tls.crt": originalBundleData,
   163  		},
   164  	}
   165  
   166  	clusterIssuerSecretUpdated := &corev1.Secret{
   167  		ObjectMeta: v1.ObjectMeta{Name: vzconst.DefaultVerrazzanoCASecretName, Namespace: vzconst.CertManagerNamespace},
   168  		Data: map[string][]byte{
   169  			"tls.crt": updatedBundleData,
   170  		},
   171  	}
   172  
   173  	ingressLeafCertOnly := &corev1.Secret{
   174  		ObjectMeta: v1.ObjectMeta{Name: vzTLSSecret.Name, Namespace: vzTLSSecret.Namespace},
   175  		Data: map[string][]byte{
   176  			"tls.crt": []byte("leaf-cert"),
   177  			"tls.key": []byte("leaf-cert-key"),
   178  		},
   179  	}
   180  
   181  	vzPrivateCASecret := &corev1.Secret{
   182  		ObjectMeta: v1.ObjectMeta{Name: vzPrivateCABundleSecret.Name, Namespace: vzPrivateCABundleSecret.Namespace},
   183  		Data: map[string][]byte{
   184  			vzconst.CABundleKey: originalBundleData,
   185  		},
   186  	}
   187  
   188  	rancherTLSCASecert := &corev1.Secret{
   189  		ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   190  		Data: map[string][]byte{
   191  			vzconst.RancherTLSCAKey: originalBundleData,
   192  		},
   193  	}
   194  
   195  	defaultObjsList := []runtime.Object{
   196  		rancherTLSCASecert,
   197  		&corev1.Secret{
   198  			ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   199  			Data: map[string][]byte{
   200  				mcCABundleKey: originalBundleData,
   201  			},
   202  		},
   203  		vzPrivateCASecret,
   204  		clusterIssuerSecretUpdated,
   205  		// verrazzano-mc namespace exists
   206  		&corev1.Namespace{
   207  			ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   208  		},
   209  		// Rancher deployment to detect when we have/haven't issued a restart
   210  		&appsv1.Deployment{
   211  			ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   212  		},
   213  	}
   214  
   215  	tests := []struct {
   216  		name                         string
   217  		description                  string
   218  		cli                          client.Client
   219  		requeueRequired              bool
   220  		wantErr                      assert.ErrorAssertionFunc
   221  		sourceSecret                 *corev1.Secret
   222  		sourceSecretKey              string
   223  		privateCAExpectedBundleData  []byte
   224  		privateCABundleSecretWantErr assert.ErrorAssertionFunc
   225  		mcExpectedBundleData         []byte
   226  		mcBundleSecretWantErr        assert.ErrorAssertionFunc
   227  		rancherExpectedBundleData    []byte
   228  		rancherBundleSecretWantErr   assert.ErrorAssertionFunc
   229  		rancherRestartRequired       bool
   230  	}{
   231  		{
   232  			name:                        "self-signed-ca",
   233  			description:                 `Basic case where the ClusterIssuer secret has been updated and the MC and Rancher copies exist `,
   234  			cli:                         fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(defaultObjsList...).Build(),
   235  			privateCAExpectedBundleData: updatedBundleData,
   236  			mcExpectedBundleData:        updatedBundleData,
   237  			rancherExpectedBundleData:   updatedBundleData,
   238  			rancherRestartRequired:      true,
   239  		},
   240  		{
   241  			name:        "verrazzano-tls-ca-does-not-exist",
   242  			description: `TLS CA bundle does not exist, the target copies should not be updated; likely a case where the secret was deleted, but should not happen`,
   243  			cli: fake.NewClientBuilder().WithScheme(scheme).WithObjects(
   244  				&corev1.Secret{
   245  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   246  					Data: map[string][]byte{
   247  						mcCABundleKey: originalBundleData,
   248  					},
   249  				},
   250  				ingressLeafCertOnly,
   251  				&corev1.Namespace{
   252  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   253  				},
   254  				// Rancher deployment to detect when we have/haven't issued a restart
   255  				&appsv1.Deployment{
   256  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   257  				},
   258  			).Build(),
   259  			sourceSecret:                 ingressLeafCertOnly,
   260  			privateCABundleSecretWantErr: assert.Error,
   261  			rancherBundleSecretWantErr:   assert.Error,
   262  			mcExpectedBundleData:         []byte(nil),
   263  		},
   264  		{
   265  			name: "lets-encrypt-staging-update-scenario",
   266  			description: "ACME/Let's encrypt staging case, TLS CA bundle-key does not exist in ingress secret but the leaf cert has been rotated.  " +
   267  				"The target copies should not be updated, preserving the staging CA root bundle",
   268  			sourceSecret:    ingressLeafCertOnly,
   269  			sourceSecretKey: vzconst.CACertKey,
   270  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   271  				&corev1.Secret{
   272  					ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   273  					Data: map[string][]byte{
   274  						vzconst.RancherTLSCAKey: letsEncryptStagingBundleData,
   275  					},
   276  				},
   277  				&corev1.Secret{
   278  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   279  					Data: map[string][]byte{
   280  						mcCABundleKey: originalBundleData,
   281  					},
   282  				},
   283  				&corev1.Secret{
   284  					ObjectMeta: v1.ObjectMeta{Name: vzPrivateCABundleSecret.Name, Namespace: vzPrivateCABundleSecret.Namespace},
   285  					Data: map[string][]byte{
   286  						vzconst.CABundleKey: letsEncryptStagingBundleData,
   287  					},
   288  				},
   289  				ingressLeafCertOnly,
   290  				&corev1.Namespace{
   291  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   292  				},
   293  				&appsv1.Deployment{
   294  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   295  				},
   296  			).Build(),
   297  			privateCAExpectedBundleData: letsEncryptStagingBundleData,
   298  			mcExpectedBundleData:        letsEncryptStagingBundleData,
   299  			rancherExpectedBundleData:   letsEncryptStagingBundleData,
   300  		},
   301  		{
   302  			name: "lets-encrypt-staging-to-production",
   303  			description: "ACME/Let's encrypt staging-to-production case; VZ and Rancher TLS CA bundle-key do not exist," +
   304  				"leaf cert has no CA bundle, but the ingress secret but the leaf cert has been rotated.  Only the" +
   305  				"multi-cluster copy should be updated with an empty value, and the other copies should not exist",
   306  			sourceSecret:    ingressLeafCertOnly,
   307  			sourceSecretKey: vzconst.CACertKey,
   308  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   309  				&corev1.Secret{
   310  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   311  					Data: map[string][]byte{
   312  						mcCABundleKey: letsEncryptStagingBundleData,
   313  					},
   314  				},
   315  				ingressLeafCertOnly,
   316  				&corev1.Namespace{
   317  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   318  				},
   319  				&appsv1.Deployment{
   320  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   321  				},
   322  			).Build(),
   323  			privateCABundleSecretWantErr: assert.Error,
   324  			rancherBundleSecretWantErr:   assert.Error,
   325  			mcExpectedBundleData:         []byte(nil),
   326  		},
   327  		{
   328  			name: "lets-encrypt-staging-to-self-signed-rotated",
   329  			description: "System has been updated from LE staging to self-signed; verrazzano-tls-ca and tls-ca are " +
   330  				"using private CA with old data, verrazzano-local-ca-bundle has LE staging data.  verrazzano-tls updated" +
   331  				"with new bundle data.  All secrets should be updated with new bundle data.",
   332  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   333  				&corev1.Secret{
   334  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   335  					Data: map[string][]byte{
   336  						mcCABundleKey: letsEncryptStagingBundleData,
   337  					},
   338  				},
   339  				&corev1.Secret{
   340  					ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   341  					Data: map[string][]byte{
   342  						vzconst.RancherTLSCAKey: originalBundleData,
   343  					},
   344  				},
   345  				vzPrivateCASecret,
   346  				clusterIssuerSecretUpdated,
   347  				&corev1.Namespace{
   348  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   349  				},
   350  				&appsv1.Deployment{
   351  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   352  				},
   353  			).Build(),
   354  			rancherRestartRequired:      true,
   355  			privateCAExpectedBundleData: updatedBundleData,
   356  			rancherExpectedBundleData:   updatedBundleData,
   357  			mcExpectedBundleData:        updatedBundleData,
   358  		},
   359  		{
   360  			name: "lets-encrypt-staging-to-self-signed-not-rotated",
   361  			description: "System has been updated from LE staging to self-signed; verrazzano-tls-ca and tls-ca are " +
   362  				"using up-to-date private CA data, verrazzano-local-ca-bundle has stale LE staging data.  verrazzano-tls updated" +
   363  				"with new bundle data.  All secrets should be updated with new bundle data.",
   364  			sourceSecret: clusterIssuerSecretNotUpdated,
   365  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   366  				&corev1.Secret{
   367  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   368  					Data: map[string][]byte{
   369  						mcCABundleKey: letsEncryptStagingBundleData,
   370  					},
   371  				},
   372  				&corev1.Secret{
   373  					ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   374  					Data: map[string][]byte{
   375  						vzconst.RancherTLSCAKey: originalBundleData,
   376  					},
   377  				},
   378  				vzPrivateCASecret,
   379  				clusterIssuerSecretNotUpdated,
   380  				&corev1.Namespace{
   381  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   382  				},
   383  				&appsv1.Deployment{
   384  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   385  				},
   386  			).Build(),
   387  			privateCAExpectedBundleData: originalBundleData,
   388  			rancherExpectedBundleData:   originalBundleData,
   389  			mcExpectedBundleData:        originalBundleData,
   390  		},
   391  		{
   392  			name:        "mc-namespace-does-not-exist",
   393  			description: `TLS CA bundle updated, but MC namespace does not exist;  Rancher secret should be updated but we should requeue until the verrazzano-mc namespace exists`,
   394  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   395  				&corev1.Secret{
   396  					ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   397  					Data: map[string][]byte{
   398  						vzconst.RancherTLSCAKey: originalBundleData,
   399  					},
   400  				},
   401  				&corev1.Secret{
   402  					ObjectMeta: v1.ObjectMeta{Namespace: multiclusterCASecret.Namespace, Name: multiclusterCASecret.Name},
   403  					Data: map[string][]byte{
   404  						mcCABundleKey: originalBundleData,
   405  					},
   406  				},
   407  				&corev1.Secret{
   408  					ObjectMeta: v1.ObjectMeta{Name: vzPrivateCABundleSecret.Name, Namespace: vzPrivateCABundleSecret.Namespace},
   409  					Data: map[string][]byte{
   410  						vzconst.CABundleKey: updatedBundleData,
   411  					},
   412  				},
   413  				&appsv1.Deployment{
   414  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   415  				},
   416  			).Build(),
   417  			requeueRequired:             true,
   418  			privateCAExpectedBundleData: updatedBundleData,
   419  			mcExpectedBundleData:        originalBundleData,
   420  			rancherExpectedBundleData:   updatedBundleData,
   421  			rancherRestartRequired:      true,
   422  		},
   423  		{
   424  			name:        "mc-bundle-secret-does-not-exist",
   425  			description: `TLS CA bundle updated, but MC bundle secret does not initially exist;  MC bundle secret should be created`,
   426  			cli: fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(
   427  				&corev1.Secret{
   428  					ObjectMeta: v1.ObjectMeta{Namespace: rancherTLSCATestSecret.Namespace, Name: rancherTLSCATestSecret.Name},
   429  					Data: map[string][]byte{
   430  						vzconst.RancherTLSCAKey: originalBundleData,
   431  					},
   432  				},
   433  				&corev1.Secret{
   434  					ObjectMeta: v1.ObjectMeta{Name: vzPrivateCABundleSecret.Name, Namespace: vzPrivateCABundleSecret.Namespace},
   435  					Data: map[string][]byte{
   436  						vzconst.CABundleKey: originalBundleData,
   437  					},
   438  				},
   439  				clusterIssuerSecretUpdated,
   440  				&corev1.Namespace{
   441  					ObjectMeta: v1.ObjectMeta{Name: constants.VerrazzanoMultiClusterNamespace},
   442  				},
   443  				&appsv1.Deployment{
   444  					ObjectMeta: v1.ObjectMeta{Name: rancherDeploymentName, Namespace: vzconst.RancherSystemNamespace},
   445  				},
   446  			).Build(),
   447  			privateCAExpectedBundleData: updatedBundleData,
   448  			mcExpectedBundleData:        updatedBundleData,
   449  			rancherExpectedBundleData:   updatedBundleData,
   450  			rancherRestartRequired:      true,
   451  		},
   452  	}
   453  	for _, tt := range tests {
   454  		t.Run(tt.name, func(t *testing.T) {
   455  			r := &VerrazzanoSecretsReconciler{
   456  				Client:        tt.cli,
   457  				Scheme:        scheme,
   458  				log:           log,
   459  				StatusUpdater: updater,
   460  			}
   461  			wantErr := defaultWantErr
   462  			if tt.wantErr != nil {
   463  				wantErr = tt.wantErr
   464  			}
   465  
   466  			privateCABundleSecretWantErr := defaultBundleWantErr
   467  			if tt.privateCABundleSecretWantErr != nil {
   468  				privateCABundleSecretWantErr = tt.privateCABundleSecretWantErr
   469  			}
   470  
   471  			mcBundleSecretWantErr := defaultBundleWantErr
   472  			if tt.mcBundleSecretWantErr != nil {
   473  				mcBundleSecretWantErr = tt.mcBundleSecretWantErr
   474  			}
   475  
   476  			rancherBundleSecretWantErr := defaultBundleWantErr
   477  			if tt.rancherBundleSecretWantErr != nil {
   478  				rancherBundleSecretWantErr = tt.rancherBundleSecretWantErr
   479  			}
   480  
   481  			sourceSecret := clusterIssuerSecretUpdated
   482  			if tt.sourceSecret != nil {
   483  				sourceSecret = tt.sourceSecret
   484  			}
   485  
   486  			sourceSecretKey := corev1.TLSCertKey
   487  			if len(tt.sourceSecretKey) > 0 {
   488  				sourceSecretKey = tt.sourceSecretKey
   489  			}
   490  
   491  			got, err := r.reconcileVerrazzanoTLS(context.TODO(), types.NamespacedName{Namespace: sourceSecret.Namespace, Name: sourceSecret.Name}, sourceSecretKey)
   492  			assert.NoError(t, err)
   493  			assert.False(t, got.Requeue)
   494  
   495  			got, err = r.reconcileVerrazzanoCABundleCopies()
   496  			if !wantErr(t, err, "reconcileVerrazzanoCABundleCopies did not get expected error result") {
   497  				return
   498  			}
   499  			assert.Equal(t, tt.requeueRequired, got.Requeue, "Did not get expected result")
   500  
   501  			//if tt.rancherRestartRequired {
   502  			deployment := &appsv1.Deployment{}
   503  			assert.NoError(t, tt.cli.Get(context.TODO(), rancherDeploymentNSName, deployment))
   504  			_, foundRestartAnnotation := deployment.Spec.Template.ObjectMeta.Annotations[vzconst.VerrazzanoRestartAnnotation]
   505  			assert.Equal(t, tt.rancherRestartRequired, foundRestartAnnotation, "Rancher restart check failed, expected %v", tt.rancherRestartRequired)
   506  			//}
   507  			// check that the VZ private CA bundle secret was updated if necessary
   508  			assertTargetCopy(t, tt.cli, vzPrivateCABundleSecret, vzconst.CABundleKey, tt.privateCAExpectedBundleData, privateCABundleSecretWantErr)
   509  			assertTargetCopy(t, tt.cli, multiclusterCASecret, mcCABundleKey, tt.mcExpectedBundleData, mcBundleSecretWantErr)
   510  			assertTargetCopy(t, tt.cli, rancherTLSCATestSecret, vzconst.RancherTLSCAKey, tt.rancherExpectedBundleData, rancherBundleSecretWantErr)
   511  		})
   512  	}
   513  }
   514  
   515  func assertTargetCopy(t *testing.T, cli client.Client, targetSecretName types.NamespacedName, key string, expectedBundleData []byte, bundleSecretWantErr assert.ErrorAssertionFunc) {
   516  	bundleSecret := &corev1.Secret{}
   517  	err := cli.Get(context.TODO(), targetSecretName, bundleSecret)
   518  	if !bundleSecretWantErr(t, err, fmt.Sprintf("Bundle secret get err %v", err)) {
   519  		return
   520  	}
   521  	byteSlicesEqualTrimmedWhitespace(t, expectedBundleData, bundleSecret.Data[key], fmt.Sprintf("CA bundle copy for %s did not match", targetSecretName))
   522  }
   523  
   524  func byteSlicesEqualTrimmedWhitespace(t *testing.T, byteSlice1, byteSlice2 []byte, msg string) bool {
   525  	a := bytes.Trim(byteSlice1, " \t\n\r")
   526  	b := bytes.Trim(byteSlice2, " \t\n\r")
   527  	return assert.Equal(t, a, b, msg)
   528  }