github.com/verrazzano/verrazzano@v1.7.0/tools/vz/pkg/helpers/vzcapture_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 helpers 5 6 import ( 7 "bytes" 8 "fmt" 9 "github.com/verrazzano/verrazzano/platform-operator/controllers/verrazzano/component/common" 10 "os" 11 "path/filepath" 12 "regexp" 13 "testing" 14 15 v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" 16 "github.com/crossplane/oam-kubernetes-runtime/apis/core" 17 "github.com/stretchr/testify/assert" 18 appv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/app/v1alpha1" 19 appclusterv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/clusters/v1alpha1" 20 appoamv1alpha1 "github.com/verrazzano/verrazzano/application-operator/apis/oam/v1alpha1" 21 clusterv1alpha1 "github.com/verrazzano/verrazzano/cluster-operator/apis/clusters/v1alpha1" 22 "github.com/verrazzano/verrazzano/platform-operator/apis/verrazzano/v1beta1" 23 "github.com/verrazzano/verrazzano/tools/vz/pkg/constants" 24 testhelpers "github.com/verrazzano/verrazzano/tools/vz/test/helpers" 25 corev1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/cli-runtime/pkg/genericclioptions" 28 fakedynamic "k8s.io/client-go/dynamic/fake" 29 k8sfake "k8s.io/client-go/kubernetes/fake" 30 k8scheme "k8s.io/client-go/kubernetes/scheme" 31 "sigs.k8s.io/controller-runtime/pkg/client" 32 "sigs.k8s.io/controller-runtime/pkg/client/fake" 33 ) 34 35 const dummyIP1 = "0.0.0.0" 36 const dummyIP2 = "5.6.x.x" 37 38 // TestCreateReportArchive 39 // GIVEN a directory containing some files 40 // 41 // WHEN I call function CreateReportArchive with a report file 42 // THEN expect it to create the report file 43 func TestCreateReportArchive(t *testing.T) { 44 tmpDir, _ := os.MkdirTemp("", "bug-report") 45 defer cleanupTempDir(t, tmpDir) 46 47 captureDir := tmpDir + string(os.PathSeparator) + "test-report" 48 if err := os.Mkdir(captureDir, os.ModePerm); err != nil { 49 assert.Error(t, err) 50 } 51 52 // Create some files inside bugReport 53 _, err := os.Create(captureDir + string(os.PathSeparator) + "f1.txt") 54 if err != nil { 55 assert.Error(t, err) 56 } 57 58 _, err = os.Create(captureDir + string(os.PathSeparator) + "f2.txt") 59 if err != nil { 60 assert.Error(t, err) 61 } 62 63 _, err = os.Create(captureDir + string(os.PathSeparator) + "f3.txt") 64 if err != nil { 65 assert.Error(t, err) 66 } 67 68 bugReportFile, err := os.Create(tmpDir + string(os.PathSeparator) + "bug.tar.gz") 69 if err != nil { 70 assert.Error(t, err) 71 } 72 err = CreateReportArchive(captureDir, bugReportFile) 73 if err != nil { 74 assert.Error(t, err) 75 } 76 77 // Check file exists 78 assert.FileExists(t, bugReportFile.Name()) 79 } 80 81 // TestRemoveDuplicates 82 // GIVEN a string slice containing duplicates 83 // 84 // WHEN I call function RemoveDuplicate 85 // THEN expect it to remove the duplicate elements 86 func TestRemoveDuplicates(t *testing.T) { 87 testSlice := []string{"abc", "def", "abc"} 88 result := RemoveDuplicate(testSlice) 89 assert.True(t, true, len(result) == 2) 90 } 91 92 // TestGroupVersionResource 93 // 94 // WHEN I call functions to get the config schemes 95 // THEN expect it to return the expected resource 96 func TestGroupVersionResource(t *testing.T) { 97 assert.True(t, true, GetAppConfigScheme().Resource == constants.OAMAppConfigurations) 98 assert.True(t, true, GetComponentConfigScheme().Resource == constants.OAMComponents) 99 assert.True(t, true, GetMetricsTraitConfigScheme().Resource == constants.OAMMetricsTraits) 100 assert.True(t, true, GetIngressTraitConfigScheme().Resource == constants.OAMIngressTraits) 101 assert.True(t, true, GetMCComponentScheme().Resource == constants.OAMMCCompConfigurations) 102 assert.True(t, true, GetMCAppConfigScheme().Resource == constants.OAMMCAppConfigurations) 103 assert.True(t, true, GetVzProjectsConfigScheme().Resource == constants.OAMProjects) 104 assert.True(t, true, GetManagedClusterConfigScheme().Resource == constants.OAMManagedClusters) 105 } 106 107 // TestCaptureK8SResources 108 // 109 // WHEN I call functions to capture k8s resource 110 // THEN expect it to not throw any error 111 func TestCaptureK8SResources(t *testing.T) { 112 schemeForClient := k8scheme.Scheme 113 err := v1.AddToScheme(schemeForClient) 114 assert.NoError(t, err) 115 k8sClient := k8sfake.NewSimpleClientset() 116 scheme := k8scheme.Scheme 117 AddCapiToScheme(scheme) 118 dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme) 119 client := fake.NewClientBuilder().WithScheme(schemeForClient).Build() 120 captureDir, err := os.MkdirTemp("", "testcapture") 121 defer cleanupTempDir(t, captureDir) 122 assert.NoError(t, err) 123 buf := new(bytes.Buffer) 124 errBuf := new(bytes.Buffer) 125 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 126 err = CaptureK8SResources(client, k8sClient, dynamicClient, constants.VerrazzanoInstall, captureDir, rc) 127 assert.NoError(t, err) 128 } 129 130 // TestCaptureMultiClusterResources tests the functionality to capture the multi cluster related resources 131 // 132 // WHEN I call functions to capture Verrazzano multi cluster resources 133 // THEN expect it to not throw any error 134 func TestCaptureMultiClusterResources(t *testing.T) { 135 scheme := k8scheme.Scheme 136 _ = v1beta1.AddToScheme(scheme) 137 _ = clusterv1alpha1.AddToScheme(scheme) 138 _ = appclusterv1alpha1.AddToScheme(scheme) 139 140 dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme) 141 captureDir, err := os.MkdirTemp("", "testcapture") 142 defer cleanupTempDir(t, captureDir) 143 assert.NoError(t, err) 144 buf := new(bytes.Buffer) 145 errBuf := new(bytes.Buffer) 146 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 147 assert.NoError(t, CaptureMultiClusterOAMResources(dynamicClient, []string{constants.VerrazzanoInstall}, captureDir, rc)) 148 } 149 150 // TestCaptureOAMResources tests the functionality to capture the OAM resources in the cluster 151 // 152 // WHEN I call functions to capture Verrazzano OAM resources 153 // THEN expect it to not throw any error 154 func TestCaptureOAMResources(t *testing.T) { 155 scheme := k8scheme.Scheme 156 _ = v1beta1.AddToScheme(scheme) 157 _ = clusterv1alpha1.AddToScheme(scheme) 158 _ = appclusterv1alpha1.AddToScheme(scheme) 159 _ = appv1alpha1.AddToScheme(scheme) 160 _ = appoamv1alpha1.AddToScheme(scheme) 161 _ = core.AddToScheme(scheme) 162 163 dynamicClient := fakedynamic.NewSimpleDynamicClient(scheme) 164 captureDir, err := os.MkdirTemp("", "testcapture") 165 defer cleanupTempDir(t, captureDir) 166 assert.NoError(t, err) 167 buf := new(bytes.Buffer) 168 errBuf := new(bytes.Buffer) 169 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 170 assert.NoError(t, CaptureOAMResources(dynamicClient, []string{constants.VerrazzanoInstall}, captureDir, rc)) 171 } 172 173 // TestCapturePodLog tests the functionality to capture the logs of a given pod. 174 func TestCapturePodLog(t *testing.T) { 175 k8sClient := k8sfake.NewSimpleClientset() 176 captureDir, err := os.MkdirTemp("", "testcapture") 177 defer cleanupTempDir(t, captureDir) 178 assert.NoError(t, err) 179 buf := new(bytes.Buffer) 180 errBuf := new(bytes.Buffer) 181 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 182 err = CapturePodLog(k8sClient, corev1.Pod{}, constants.VerrazzanoInstall, captureDir, rc, 0) 183 assert.NoError(t, err) 184 185 // GIVENT and empty k8s cluster, 186 // WHEN I call functions to capture VPO pod logs, 187 // THEN expect it to not throw any error. 188 err = CapturePodLog(k8sClient, corev1.Pod{ObjectMeta: metav1.ObjectMeta{ 189 Name: constants.VerrazzanoPlatformOperator, 190 Namespace: constants.VerrazzanoInstall, 191 }}, constants.VerrazzanoInstall, captureDir, rc, 0) 192 assert.NoError(t, err) 193 194 // GIVENT a k8s cluster with a VPO pod, 195 // WHEN I call functions to capture VPO pod logs, 196 // THEN expect it to not throw any error. 197 k8sClient = k8sfake.NewSimpleClientset(&corev1.Pod{ObjectMeta: metav1.ObjectMeta{ 198 Name: constants.VerrazzanoPlatformOperator, 199 Namespace: constants.VerrazzanoInstall, 200 }, Spec: corev1.PodSpec{ 201 Containers: []corev1.Container{ 202 { 203 Name: "testcontainer", 204 Image: "dummimage:notag", 205 }, 206 }, 207 }}) 208 err = CapturePodLog(k8sClient, corev1.Pod{ObjectMeta: metav1.ObjectMeta{ 209 Name: constants.VerrazzanoPlatformOperator, 210 Namespace: constants.VerrazzanoInstall, 211 }, Spec: corev1.PodSpec{ 212 Containers: []corev1.Container{ 213 { 214 Name: "testcontainer", 215 Image: "dummimage:notag", 216 }, 217 }, 218 }}, constants.VerrazzanoInstall, captureDir, rc, 300) 219 assert.NoError(t, err) 220 } 221 222 // TestGetPodList tests the functionality to return the list of pods with the given label 223 func TestGetPodList(t *testing.T) { 224 // GIVEN a k8s cluster with no VPO pods, 225 // WHEN I call functions to get the list of pods in the k8s cluster, 226 // THEN expect it to be an empty list. 227 pods, err := GetPodList(fake.NewClientBuilder().Build(), "app", constants.VerrazzanoPlatformOperator, constants.VerrazzanoInstall) 228 assert.NoError(t, err) 229 assert.Empty(t, pods) 230 231 // GIVEN a k8s cluster with a VPO pod, 232 // WHEN I call functions to get the list of pods in the k8s cluster, 233 // THEN expect it to be an empty list. 234 pods, err = GetPodList(fake.NewClientBuilder().WithObjects(&corev1.Pod{ 235 ObjectMeta: metav1.ObjectMeta{ 236 Name: constants.VerrazzanoPlatformOperator, 237 Namespace: constants.VerrazzanoInstall, 238 Labels: map[string]string{"app": constants.VerrazzanoPlatformOperator}, 239 }, 240 }).Build(), "app", constants.VerrazzanoPlatformOperator, constants.VerrazzanoInstall) 241 assert.NoError(t, err) 242 assert.NotEmpty(t, pods) 243 } 244 245 // TestCaptureVZResource tests the functionality to capture the Verrazzano resource. 246 func TestCaptureVZResource(t *testing.T) { 247 captureDir, err := os.MkdirTemp("", "testcapture") 248 defer cleanupTempDir(t, captureDir) 249 assert.NoError(t, err) 250 buf := new(bytes.Buffer) 251 errBuf := new(bytes.Buffer) 252 253 // GIVEN a k8s cluster with a user provided Verrazzano CR, 254 // WHEN I call functions to capture the Verrazzano CR, 255 // THEN expect the file to contain the JSON output of the Verrazzano CR. 256 vz := &v1beta1.Verrazzano{ 257 ObjectMeta: metav1.ObjectMeta{ 258 Namespace: "default", 259 Name: "myverrazzano", 260 }, 261 Spec: v1beta1.VerrazzanoSpec{ 262 Profile: v1beta1.Dev, 263 }, 264 } 265 tempFile, err := os.CreateTemp("", "testfile") 266 defer cleanupFile(t, tempFile) 267 assert.NoError(t, err) 268 SetMultiWriterOut(buf, tempFile) 269 SetMultiWriterErr(errBuf, tempFile) 270 SetVerboseOutput(true) 271 SetIsLiveCluster() 272 err = CaptureVZResource(captureDir, vz) 273 assert.NoError(t, err) 274 assert.NotNil(t, GetMultiWriterOut()) 275 assert.NotNil(t, GetMultiWriterErr()) 276 assert.True(t, GetIsLiveCluster()) 277 } 278 279 // TestDoesNamespaceExist tests the functionality to check if a given namespace exists. 280 func TestDoesNamespaceExist(t *testing.T) { 281 buf := new(bytes.Buffer) 282 errBuf := new(bytes.Buffer) 283 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 284 tempFile, _ := os.CreateTemp("", "testfile") 285 defer cleanupFile(t, tempFile) 286 SetMultiWriterOut(buf, tempFile) 287 SetMultiWriterErr(errBuf, tempFile) 288 SetVerboseOutput(true) 289 290 // GIVEN a k8s cluster with no namespaces, 291 // WHEN I call functions to check if a namespace with empty string exists, 292 // THEN expect it to return false and no error. 293 exists, err := DoesNamespaceExist(k8sfake.NewSimpleClientset(), "", rc) 294 assert.NoError(t, err) 295 assert.False(t, exists) 296 297 // GIVEN a k8s cluster with no namespaces, 298 // WHEN I call functions to check if a namespace verrazzano-install exists, 299 // THEN expect it to return false and an error. 300 exists, err = DoesNamespaceExist(k8sfake.NewSimpleClientset(), constants.VerrazzanoInstall, rc) 301 assert.Error(t, err) 302 assert.False(t, exists) 303 304 // GIVEN a k8s cluster with the required verrazzano-install namespace, 305 // WHEN I call functions to check if a namespace verrazzano-install exists, 306 // THEN expect it to return true and no error. 307 exists, err = DoesNamespaceExist(k8sfake.NewSimpleClientset(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{ 308 Name: constants.VerrazzanoInstall, 309 }}), constants.VerrazzanoInstall, rc) 310 assert.NoError(t, err) 311 assert.True(t, exists) 312 } 313 314 // TestGetVZManagedNamespaces tests the functionality to return all namespaces managed by verrazzano 315 func TestGetVZManagedNamespaces(t *testing.T) { 316 namespaces := GetVZManagedNamespaces(k8sfake.NewSimpleClientset()) 317 assert.Empty(t, namespaces) 318 319 // GIVEN a k8s cluster with the required verrazzano-install namespace with label verrazzano-managed=true, 320 // WHEN I call functions to list the namespaces that are managed by Verrazzano, 321 // THEN expect it to return a single namespace verrazzano-install 322 namespaces = GetVZManagedNamespaces(k8sfake.NewSimpleClientset(&corev1.Namespace{ObjectMeta: metav1.ObjectMeta{ 323 Name: constants.VerrazzanoInstall, 324 Labels: map[string]string{"verrazzano-managed": "true"}, 325 }})) 326 assert.NotEmpty(t, namespaces) 327 assert.Equal(t, 1, len(namespaces)) 328 assert.Equal(t, constants.VerrazzanoInstall, namespaces[0]) 329 } 330 331 // TestIsErrorReported tests the functionality to see if an error had been reported when capturing the k8s resources. 332 func TestIsErrorReported(t *testing.T) { 333 assert.False(t, IsErrorReported()) 334 LogError("dummy error msg") 335 assert.True(t, IsErrorReported()) 336 } 337 338 // TestCreateFile tests the functionality to create a file containing the Verrazzano Resource 339 func TestCreateFile(t *testing.T) { 340 // GIVEN a k8s cluster with a VPO pod, 341 // WHEN I call functions to create a JSON file for the pod, 342 // THEN expect it to write to the provided resource file, the JSON contents of the pod and no error should be returned. 343 captureDir, err := os.MkdirTemp("", "testcapture") 344 defer cleanupTempDir(t, captureDir) 345 assert.NoError(t, err) 346 defer cleanupTempDir(t, captureDir) 347 buf := new(bytes.Buffer) 348 errBuf := new(bytes.Buffer) 349 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 350 err = createFile(corev1.Pod{ObjectMeta: metav1.ObjectMeta{ 351 Name: constants.VerrazzanoPlatformOperator, 352 Namespace: constants.VerrazzanoInstall, 353 }}, constants.VerrazzanoInstall, "test-file", captureDir, rc) 354 assert.NoError(t, err) 355 } 356 357 // cleanupTempDir cleans up the given temp directory after the test run 358 func cleanupTempDir(t *testing.T, dirName string) { 359 if err := os.RemoveAll(dirName); err != nil { 360 t.Fatalf("RemoveAll failed: %v", err) 361 } 362 } 363 364 // cleanupTempDir cleans up the given temp file after the test run 365 func cleanupFile(t *testing.T, file *os.File) { 366 if err := file.Close(); err != nil { 367 t.Fatalf("RemoveAll failed: %v", err) 368 } 369 } 370 371 // TestGetPodListAll tests the functionality to return the list of all pods 372 func TestGetPodListAll(t *testing.T) { 373 nsName := "test" 374 podLength := 5 375 var podList []client.Object 376 for i := 0; i < podLength; i++ { 377 podList = append(podList, &corev1.Pod{ 378 ObjectMeta: metav1.ObjectMeta{ 379 Name: nsName + fmt.Sprint(i), 380 Namespace: nsName, 381 Labels: map[string]string{"name": "myapp"}, 382 }, 383 }) 384 } 385 // GIVEN a k8s cluster with no pods, 386 // WHEN I call functions to get the list of pods in the k8s cluster, 387 // THEN expect it to be an empty list. 388 pods, err := GetPodListAll(fake.NewClientBuilder().Build(), nsName) 389 assert.NoError(t, err) 390 assert.Empty(t, pods) 391 392 // GIVEN a k8s cluster with 5 pods, 393 // WHEN I call functions to get the list of pods in the k8s cluster without label, 394 // THEN expect it to be list all pods. 395 pods, err = GetPodListAll(fake.NewClientBuilder().WithObjects(podList...).Build(), nsName) 396 assert.NoError(t, err) 397 assert.Equal(t, podLength, len(pods)) 398 } 399 400 // TestCreateCertificateFile tests that a certificate file titled certificates.json can be successfully written 401 // GIVEN a k8s cluster with certificates present in a namespace , 402 // WHEN I call functions to create a list of certificates for the namespace, 403 // THEN expect it to write to the provided resource file and no error should be returned. 404 func TestCreateCertificateFile(t *testing.T) { 405 schemeForClient := k8scheme.Scheme 406 err := v1.AddToScheme(schemeForClient) 407 assert.NoError(t, err) 408 sampleCert := v1.Certificate{ 409 ObjectMeta: metav1.ObjectMeta{Name: "testcertificate", Namespace: "cattle-system"}, 410 Spec: v1.CertificateSpec{ 411 DNSNames: []string{"example.com", "www.example.com", "api.example.com"}, 412 IPAddresses: []string{dummyIP1, dummyIP2}, 413 }, 414 } 415 client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(&sampleCert).Build() 416 captureDir, err := os.MkdirTemp("", "testcaptureforcertificates") 417 assert.NoError(t, err) 418 t.Log(captureDir) 419 defer cleanupTempDir(t, captureDir) 420 buf := new(bytes.Buffer) 421 errBuf := new(bytes.Buffer) 422 tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-test") 423 assert.NoError(t, err) 424 SetMultiWriterOut(buf, tempFile) 425 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 426 err = captureCertificates(client, "cattle-system", captureDir, rc) 427 assert.NoError(t, err) 428 } 429 430 // TestCreateCaCrtInfoFile tests that a caCrtInfo file titled caCrtInfo.json can be successfully written 431 // GIVEN a k8s cluster with secrets containing caCrtInfo present in a namespace , 432 // WHEN I call functions to create a list of caCrt for the namespace, 433 // THEN expect it to write to the provided resource file and no error should be returned. 434 func TestCreateCaCrtJsonFile(t *testing.T) { 435 schemeForClient := k8scheme.Scheme 436 err := v1.AddToScheme(schemeForClient) 437 assert.NoError(t, err) 438 certificateListForTest := v1.CertificateList{} 439 sampleCert := v1.Certificate{ 440 ObjectMeta: metav1.ObjectMeta{Name: "test-certificate-caCrt.json", Namespace: "cattle-system"}, 441 Spec: v1.CertificateSpec{ 442 DNSNames: []string{"example.com", "www.example.com", "api.example.com"}, 443 IPAddresses: []string{dummyIP1, dummyIP2}, 444 SecretName: "test-secret-name", 445 }, 446 } 447 certificateListForTest.Items = append(certificateListForTest.Items, sampleCert) 448 sampleSecret := corev1.Secret{ 449 ObjectMeta: metav1.ObjectMeta{Name: "test-secret-name", Namespace: "cattle-system"}, 450 Data: map[string][]byte{ 451 "ca.crt": []byte("-----BEGIN CERTIFICATE-----\nMIIDvTCCAqWgAwIBAgIUJUr+YG3UuQJh6g4MKuRpZPnTVO0wDQYJKoZIhvcNAQEL\nBQAwbTELMAkGA1UEBhMCUEExDTALBgNVBAgMBFRlc3QxDTALBgNVBAcMBFRlc3Qx\nDTALBgNVBAoMBFRlc3QxDTALBgNVBAsMBFRlc3QxDTALBgNVBAMMBFRlc3QxEzAR\nBgkqhkiG9w0BCQEWBFRlc3QwIBcNMjMwODMwMTkxMjE4WhgPMzAyMjEyMzExOTEy\nMThaMG0xCzAJBgNVBAYTAlBBMQ0wCwYDVQQIDARUZXN0MQ0wCwYDVQQHDARUZXN0\nMQ0wCwYDVQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MQ0wCwYDVQQDDARUZXN0MRMw\nEQYJKoZIhvcNAQkBFgRUZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC\nAQEA5R5EAPbPhrfRnpGtC49OX9q4XDVP11C/nHZ13z4QMPQn3eD+S5DODjo95wVD\nbZlmOUdGhas037W/G4rsEr+fg2DF3tNV3bNtDU5NG+PjRDcmFDKup0q7Lh7Yf2FP\naNxi6wlIgmm8Yi4lQmaBSN5LZalIbTO+tk7PRa1FY2LCIKDzzY9ipc0h9nDQWXIz\nEUtjQdQuZsdcv+br2L6b891Pu/fiZgJg1Vzx8N9bBbxMl3usI/CT8qmJy4E9fh4q\n0LQMFcOXeVSR4dhGLpctXP82AH2wgz0mLmgXlYe3koX+TlOxGIG3tUKBndvII8wm\nO03wILuk63XhXg30EFjpj0qZiQIDAQABo1MwUTAdBgNVHQ4EFgQUxkWW0nvivNEy\nLAPMJYgNwpSHQ5IwHwYDVR0jBBgwFoAUxkWW0nvivNEyLAPMJYgNwpSHQ5IwDwYD\nVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAtUjYhkDzJoFNx84Y9KXJ\nVM5BRtiI7YuvrKujwFmct1uCDEDXxZivwDf7khbUlI/GDg13LXsHQbxRaZNotcju\nibG9DNwInlBDpJ/grjlz/KG/LCmYrQE5RAnuqxVe812pc2ndSkTOGvcds7n7Gir/\n1S6zn2d5g2KeYtaMEYV1jArjzsFIdZ4M2R0ZTAsArcJy2ZGZ655j54Df7yzviNpD\nTz6nQQv1DHEpdogys+rOUTXrVhSpnsTacwztp/lvQsZl231THlCJcsySHRgMKmB+\nRKLLMfDfIaGeiZWRvEPEdurMWYkwWdYz9d+iEo3YTpWKy2QeCOEFZKMX5B2MXkdd\nNA==\n-----END CERTIFICATE-----\n"), 452 }, 453 } 454 client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(&sampleCert, &sampleSecret).Build() 455 captureDir, err := os.MkdirTemp("", "testcaptureforcaCrt.json") 456 assert.NoError(t, err) 457 t.Log(captureDir) 458 defer cleanupTempDir(t, captureDir) 459 buf := new(bytes.Buffer) 460 errBuf := new(bytes.Buffer) 461 tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-ca-crt-test") 462 assert.NoError(t, err) 463 SetMultiWriterOut(buf, tempFile) 464 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 465 err = captureCaCrtExpirationInfo(client, certificateListForTest, "cattle-system", captureDir, rc) 466 assert.NoError(t, err) 467 } 468 469 // TestRedactHostNamesForCertificates tests the captureCertificates function 470 // GIVEN when sample cert with DNSNames and IPAddresses which are sensitive information 471 // WHEN captureCertificates is called on certain namespace 472 // THEN it should obfuscate the known hostnames with hashed value 473 // AND the output certificates.json file should NOT contain any of the sensitive information from KnownHostNames 474 func TestRedactHostNamesForCertificates(t *testing.T) { 475 sampleCert := &v1.Certificate{ 476 ObjectMeta: metav1.ObjectMeta{ 477 Name: "test-certificate", 478 Namespace: "cattle-system", 479 }, 480 Spec: v1.CertificateSpec{ 481 DNSNames: []string{"example.com", "www.example.com", "api.example.com"}, 482 IPAddresses: []string{dummyIP1, dummyIP2}, 483 }, 484 } 485 486 schemeForClient := k8scheme.Scheme 487 err := v1.AddToScheme(schemeForClient) 488 assert.NoError(t, err) 489 client := fake.NewClientBuilder().WithScheme(schemeForClient).WithObjects(sampleCert).Build() 490 captureDir, err := os.MkdirTemp("", "testcaptureforcertificates") 491 assert.NoError(t, err) 492 t.Log(captureDir) 493 defer cleanupTempDir(t, captureDir) 494 buf := new(bytes.Buffer) 495 errBuf := new(bytes.Buffer) 496 tempFile, err := os.CreateTemp(captureDir, "temporary-log-file-for-test") 497 assert.NoError(t, err) 498 SetMultiWriterOut(buf, tempFile) 499 rc := testhelpers.NewFakeRootCmdContext(genericclioptions.IOStreams{In: os.Stdin, Out: buf, ErrOut: errBuf}) 500 501 err = captureCertificates(client, common.CattleSystem, captureDir, rc) 502 assert.NoError(t, err) 503 504 // Check if the file is Sanitized as expected 505 certLocation := filepath.Join(captureDir, common.CattleSystem, constants.CertificatesJSON) 506 f, err := os.ReadFile(certLocation) 507 assert.NoError(t, err, "Should not error reading certificates.json file") 508 for k := range KnownHostNames { 509 keyMatch, err := regexp.Match(k, f) 510 assert.NoError(t, err, "Error while regex matching") 511 assert.Falsef(t, keyMatch, "%s should be obfuscated from certificates.json file %s", k, string(f)) 512 } 513 }