github.com/verrazzano/verrazzano@v1.7.0/application-operator/internal/operatorinit/update_webhook_test.go (about) 1 // Copyright (c) 2022, 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 operatorinit 5 6 import ( 7 "bytes" 8 "context" 9 "testing" 10 11 "github.com/stretchr/testify/assert" 12 "github.com/verrazzano/verrazzano/application-operator/internal/certificates" 13 adminv1 "k8s.io/api/admissionregistration/v1" 14 v1 "k8s.io/api/core/v1" 15 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 16 "k8s.io/client-go/kubernetes/fake" 17 ) 18 19 // TestUpdateValidatingnWebhookConfiguration tests that the CA Bundle is updated in the verrazzano-application-operator 20 // validatingWebhookConfiguration resource. 21 // GIVEN a validatingWebhookConfiguration resource with the CA Bundle set 22 // 23 // WHEN I call updateValidatingWebhookConfiguration 24 // THEN the validatingWebhookConfiguration resource set the CA Bundle as expected 25 func TestUpdateValidatingnWebhookConfiguration(t *testing.T) { 26 asserts := assert.New(t) 27 28 kubeClient := fake.NewSimpleClientset() 29 30 _, caCert, err := createExpectedCASecret(kubeClient) 31 asserts.Nilf(err, "Unexpected error creating expected CA secret", err) 32 33 wh, err := createExpectedValidatingWebhook(kubeClient) 34 asserts.Nilf(err, "error should not be returned creating validation webhook configuration: %v", err) 35 asserts.NotEmpty(wh) 36 37 err = updateValidatingWebhookConfiguration(kubeClient, certificates.VerrazzanoProjectValidatingWebhookName) 38 asserts.Nilf(err, "error should not be returned updating validation webhook configuration: %v", err) 39 40 updatedWebhook, _ := kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Get(context.TODO(), certificates.VerrazzanoProjectValidatingWebhookName, metav1.GetOptions{}) 41 asserts.Equal(caCert.Bytes(), updatedWebhook.Webhooks[0].ClientConfig.CABundle, "Expected CA bundle name did not match") 42 } 43 44 // TestUpdateValidatingnWebhookConfigurationFail tests that the CA Bundle is not updated in the 45 // verrazzano-application-operator validatingWebhookConfiguration resource. 46 // GIVEN an invalid validatingWebhookConfiguration resource with the CA Bundle set 47 // 48 // WHEN I call updateValidatingWebhookConfiguration 49 // THEN the validatingWebhookConfiguration resource will fail to be updated 50 func TestUpdateValidatingnWebhookConfigurationFail(t *testing.T) { 51 asserts := assert.New(t) 52 53 kubeClient := fake.NewSimpleClientset() 54 55 _, _, err := createExpectedCASecret(kubeClient) 56 asserts.Nilf(err, "Unexpected error creating expected CA secret", err) 57 58 _, err = createInvalidExpectedValidatingWebhook(kubeClient, certificates.VerrazzanoProjectValidatingWebhookName) 59 asserts.Nil(err, "error should not be returned creating validation webhook configuration") 60 61 err = updateValidatingWebhookConfiguration(kubeClient, certificates.VerrazzanoProjectValidatingWebhookName) 62 asserts.Error(err, "error should be returned updating validation webhook configuration") 63 } 64 65 // TestUpdateMutatingWebhookConfiguration tests that the CA Bundle is updated the specified MutatingWebhook configuration 66 // GIVEN a call to updateMutatingWebhookConfiguration 67 // 68 // WHEN with the webhook CA bundle secret exists 69 // THEN the MutatingWebhook configuration sets the CA bundle on all webhook client configurations 70 func TestUpdateMutatingWebhookConfiguration(t *testing.T) { 71 asserts := assert.New(t) 72 73 kubeClient := fake.NewSimpleClientset() 74 75 _, caCert, err := createExpectedCASecret(kubeClient) 76 asserts.Nilf(err, "Unexpected error creating expected CA secret", err) 77 78 _, err = createExpectedMutatingWebhook(kubeClient) 79 asserts.Nilf(err, "Unexpected error creating expected webhook configuration") 80 81 err = updateMutatingWebhookConfiguration(kubeClient, certificates.IstioMutatingWebhookName) 82 asserts.Nilf(err, "Unexpected error returned from updateMutatingWebhookConfiguration: %v", err) 83 84 updatedWebhook, _ := kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Get(context.TODO(), certificates.IstioMutatingWebhookName, metav1.GetOptions{}) 85 asserts.Equal(caCert.Bytes(), updatedWebhook.Webhooks[0].ClientConfig.CABundle, "Expected CA bundle name did not match") 86 asserts.Equal(caCert.Bytes(), updatedWebhook.Webhooks[1].ClientConfig.CABundle, "Expected CA bundle name did not match") 87 } 88 89 // TestUpdateMutatingWebhookConfigurationNoCASecret tests that 90 // GIVEN a call to updateMutatingWebhookConfiguration 91 // 92 // WHEN with the webhook CA bundle secret does not exist but the webhook does 93 // THEN an error is returned 94 func TestUpdateMutatingWebhookConfigurationNoCASecret(t *testing.T) { 95 asserts := assert.New(t) 96 97 kubeClient := fake.NewSimpleClientset() 98 99 _, err := createExpectedMutatingWebhook(kubeClient) 100 asserts.Nilf(err, "Unexpected error creating expected webhook configuration", err) 101 102 err = updateMutatingWebhookConfiguration(kubeClient, certificates.IstioMutatingWebhookName) 103 asserts.NotNil(err, "No error returned when webhook doesn't exist") 104 } 105 106 // TestUpdateMutatingWebhookConfigurationNoWebhook tests that 107 // GIVEN a call to updateMutatingWebhookConfiguration 108 // 109 // WHEN with the webhook CA bundle secret exists but the webhook does not 110 // THEN an error is returned 111 func TestUpdateMutatingWebhookConfigurationNoWebhook(t *testing.T) { 112 asserts := assert.New(t) 113 114 kubeClient := fake.NewSimpleClientset() 115 116 _, _, err := createExpectedCASecret(kubeClient) 117 asserts.Nilf(err, "Unexpected error creating expected CA secret", err) 118 119 err = updateMutatingWebhookConfiguration(kubeClient, certificates.IstioMutatingWebhookName) 120 asserts.NotNil(err, "No error returned when webhook doesn't exist") 121 } 122 123 func createExpectedCASecret(kubeClient *fake.Clientset) (*v1.Secret, bytes.Buffer, error) { 124 var caCert bytes.Buffer 125 caCert.WriteString("Fake CABundle") 126 127 caSecret := v1.Secret{} 128 caSecret.Name = certificates.OperatorCA 129 caSecret.Type = v1.SecretTypeTLS 130 caSecret.Namespace = certificates.OperatorNamespace 131 caSecret.Data = make(map[string][]byte) 132 caSecret.Data[certificates.CertKey] = caCert.Bytes() 133 caSecret.Data[certificates.PrivKey] = caCert.Bytes() 134 135 newSecret, err := kubeClient.CoreV1().Secrets(certificates.OperatorNamespace).Create(context.TODO(), &caSecret, metav1.CreateOptions{}) 136 return newSecret, caCert, err 137 } 138 139 func createExpectedMutatingWebhook(kubeClient *fake.Clientset) (*adminv1.MutatingWebhookConfiguration, error) { 140 webhook := adminv1.MutatingWebhookConfiguration{ 141 TypeMeta: metav1.TypeMeta{}, 142 ObjectMeta: metav1.ObjectMeta{ 143 Name: certificates.IstioMutatingWebhookName, 144 }, 145 Webhooks: []adminv1.MutatingWebhook{ 146 {Name: "webhook1"}, 147 {Name: "webhook2"}, 148 }, 149 } 150 return kubeClient.AdmissionregistrationV1().MutatingWebhookConfigurations().Create(context.TODO(), &webhook, metav1.CreateOptions{}) 151 } 152 153 func createExpectedValidatingWebhook(kubeClient *fake.Clientset) (*adminv1.ValidatingWebhookConfiguration, error) { 154 path := "/validate-clusters-verrazzano-io-v1alpha1-verrazzanoproject" 155 service := adminv1.ServiceReference{ 156 Name: certificates.VerrazzanoProjectValidatingWebhookName, 157 Namespace: certificates.OperatorNamespace, 158 Path: &path, 159 } 160 webhook := adminv1.ValidatingWebhookConfiguration{ 161 TypeMeta: metav1.TypeMeta{}, 162 ObjectMeta: metav1.ObjectMeta{ 163 Name: certificates.VerrazzanoProjectValidatingWebhookName, 164 }, 165 Webhooks: []adminv1.ValidatingWebhook{ 166 { 167 Name: "verrazzano-clusters-verrazzanoproject-validator.verrazzano.io", 168 ClientConfig: adminv1.WebhookClientConfig{ 169 Service: &service, 170 }, 171 }, 172 }, 173 } 174 return kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(context.TODO(), &webhook, metav1.CreateOptions{}) 175 } 176 177 func createInvalidExpectedValidatingWebhook(kubeClient *fake.Clientset, whName string) (*adminv1.ValidatingWebhookConfiguration, error) { 178 path := "/validate-clusters-verrazzano-io-v1alpha1-verrazzanoproject" 179 service := adminv1.ServiceReference{ 180 Name: certificates.VerrazzanoProjectValidatingWebhookName, 181 Namespace: certificates.OperatorNamespace, 182 Path: &path, 183 } 184 webhook := adminv1.ValidatingWebhookConfiguration{ 185 TypeMeta: metav1.TypeMeta{}, 186 ObjectMeta: metav1.ObjectMeta{ 187 Name: "InvalidName", 188 }, 189 Webhooks: []adminv1.ValidatingWebhook{ 190 { 191 Name: "verrazzano-clusters-verrazzanoproject-validator.verrazzano.io", 192 ClientConfig: adminv1.WebhookClientConfig{ 193 Service: &service, 194 }, 195 }, 196 }, 197 } 198 return kubeClient.AdmissionregistrationV1().ValidatingWebhookConfigurations().Create(context.TODO(), &webhook, metav1.CreateOptions{}) 199 }