From de954347726a86790eb7f5db41430de5e6df3abd Mon Sep 17 00:00:00 2001 From: Aayush Chouhan Date: Mon, 14 Oct 2024 17:00:45 +0530 Subject: [PATCH 1/3] Added ARN checks in the diagnostics report Signed-off-by: Aayush Chouhan --- pkg/diagnostics/report.go | 82 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) diff --git a/pkg/diagnostics/report.go b/pkg/diagnostics/report.go index b49e6fb11..fb503cf2b 100644 --- a/pkg/diagnostics/report.go +++ b/pkg/diagnostics/report.go @@ -4,12 +4,15 @@ import ( "fmt" "strings" + nbv1 "github.com/noobaa/noobaa-operator/v5/pkg/apis/noobaa/v1alpha1" "github.com/noobaa/noobaa-operator/v5/pkg/bundle" "github.com/noobaa/noobaa-operator/v5/pkg/options" "github.com/noobaa/noobaa-operator/v5/pkg/util" "github.com/spf13/cobra" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/client" ) const ( @@ -36,6 +39,22 @@ func RunReport(cmd *cobra.Command, args []string) { log.Fatalf(`❌ Could not get endpoint Deployment %q in Namespace %q`, endpointApp.Name, endpointApp.Namespace) } + + // Fetching all Backingstores + bsList := &nbv1.BackingStoreList{ + TypeMeta: metav1.TypeMeta{Kind: "BackingStoreList"}, + } + if !util.KubeList(bsList, &client.ListOptions{Namespace: options.Namespace}) { + log.Fatalf(`❌ Could not get backingstores in Namespace %q`, options.Namespace) + } + + // Fetching all Namespacestores + nsList := &nbv1.NamespaceStoreList{ + TypeMeta: metav1.TypeMeta{Kind: "NamespaceStoreList"}, + } + if !util.KubeList(nsList, &client.ListOptions{Namespace: options.Namespace}) { + log.Fatalf(`❌ Could not get namespacestores in Namespace %q`, options.Namespace) + } fmt.Println("") // retrieving the status of proxy environment variables @@ -44,6 +63,9 @@ func RunReport(cmd *cobra.Command, args []string) { // retrieving the overridden env variables using `CONFIG_JS_` prefix overriddenEnvVar(coreApp, endpointApp) + // validating ARNs for backingstore and namespacestore + arnValidationCheck(bsList, nsList) + // TODO: Add support for additional features } @@ -73,6 +95,61 @@ func overriddenEnvVar(coreApp *appsv1.StatefulSet, endpointApp *appsv1.Deploymen fmt.Println("") } +// arnValidationCheck validates the ARNs for backingstores and namespacestores +func arnValidationCheck(bsList *nbv1.BackingStoreList, nsList *nbv1.NamespaceStoreList) { + log := util.Logger() + + log.Print("⏳ Performing validation check for ARNs...\n") + foundARNString := false + + // Validate ARNs for backingstores + fmt.Print("ARN Validation Check (BACKINGSTORES):\n----------------------------------\n") + for _, bs := range bsList.Items { + if bs.Spec.AWSS3 != nil { + if bs.Spec.AWSS3.AWSSTSRoleARN != nil { + arn := *bs.Spec.AWSS3.AWSSTSRoleARN + if isValidArn(&arn) { + fmt.Printf(" ✅ Backingstore \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", bs.Name, arn) + } else { + fmt.Printf(" ⚠️ Backingstore \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", bs.Name, arn) + } + fmt.Println("") + foundARNString = true + } + } + } + + if !foundARNString { + fmt.Print(" ❌ No aws sts arn string found.\n") + } + fmt.Println("") + + foundARNString = false + // Validate ARNs for namespacestores + fmt.Print("ARN Validation Check (NAMESPACESTORES):\n----------------------------------\n") + for _, ns := range nsList.Items { + if ns.Spec.AWSS3 != nil { + if ns.Spec.AWSS3.AWSSTSRoleARN != nil { + arn := *ns.Spec.AWSS3.AWSSTSRoleARN + if isValidArn(&arn) { + fmt.Printf(" ✅ Namespacestore \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", ns.Name, arn) + } else { + fmt.Printf(" ⚠️ Namespacestore \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", ns.Name, arn) + } + fmt.Println("") + foundARNString = true + } + } + } + + if !foundARNString { + fmt.Print(" ❌ No aws sts arn string found.\n") + } + fmt.Println("") + + fmt.Println("") +} + // printProxyStatus prints the proxy status func printProxyStatus(appName string, envVars []corev1.EnvVar) { fmt.Printf("Proxy Environment Variables Check (%s):\n----------------------------------\n", appName) @@ -102,3 +179,8 @@ func printOverriddenEnvVar(appName string, envVars []corev1.EnvVar) { } fmt.Println("") } + +// isValidArn is a function to validate the ARN format for an s3 buckets +func isValidArn(arn *string) bool { + return strings.HasPrefix(*arn, "arn:aws:s3:::") && len(*arn) > len("arn:aws:s3:::") +} From 8276c474679d4cec2243d892ed06a9065d5e7189 Mon Sep 17 00:00:00 2001 From: Aayush Chouhan Date: Tue, 22 Oct 2024 21:28:52 +0530 Subject: [PATCH 2/3] Removed the redundant code, change arn validation check logic and updated some comments Signed-off-by: Aayush Chouhan --- pkg/diagnostics/report.go | 74 +++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 41 deletions(-) diff --git a/pkg/diagnostics/report.go b/pkg/diagnostics/report.go index fb503cf2b..4feb3fad0 100644 --- a/pkg/diagnostics/report.go +++ b/pkg/diagnostics/report.go @@ -45,7 +45,7 @@ func RunReport(cmd *cobra.Command, args []string) { TypeMeta: metav1.TypeMeta{Kind: "BackingStoreList"}, } if !util.KubeList(bsList, &client.ListOptions{Namespace: options.Namespace}) { - log.Fatalf(`❌ Could not get backingstores in Namespace %q`, options.Namespace) + log.Fatalf(`❌ No backingstores were found in the %q namespace`, options.Namespace) } // Fetching all Namespacestores @@ -53,7 +53,7 @@ func RunReport(cmd *cobra.Command, args []string) { TypeMeta: metav1.TypeMeta{Kind: "NamespaceStoreList"}, } if !util.KubeList(nsList, &client.ListOptions{Namespace: options.Namespace}) { - log.Fatalf(`❌ Could not get namespacestores in Namespace %q`, options.Namespace) + log.Fatalf(`❌ No namespacestores were found in the %q namespace`, options.Namespace) } fmt.Println("") @@ -63,7 +63,7 @@ func RunReport(cmd *cobra.Command, args []string) { // retrieving the overridden env variables using `CONFIG_JS_` prefix overriddenEnvVar(coreApp, endpointApp) - // validating ARNs for backingstore and namespacestore + // validating ARNs for backingstores and namespacestores arnValidationCheck(bsList, nsList) // TODO: Add support for additional features @@ -99,53 +99,25 @@ func overriddenEnvVar(coreApp *appsv1.StatefulSet, endpointApp *appsv1.Deploymen func arnValidationCheck(bsList *nbv1.BackingStoreList, nsList *nbv1.NamespaceStoreList) { log := util.Logger() - log.Print("⏳ Performing validation check for ARNs...\n") - foundARNString := false + log.Print("⏳ Validating store ARNs...\n") // Validate ARNs for backingstores - fmt.Print("ARN Validation Check (BACKINGSTORES):\n----------------------------------\n") + bsArnList := make(map[string]string) for _, bs := range bsList.Items { - if bs.Spec.AWSS3 != nil { - if bs.Spec.AWSS3.AWSSTSRoleARN != nil { - arn := *bs.Spec.AWSS3.AWSSTSRoleARN - if isValidArn(&arn) { - fmt.Printf(" ✅ Backingstore \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", bs.Name, arn) - } else { - fmt.Printf(" ⚠️ Backingstore \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", bs.Name, arn) - } - fmt.Println("") - foundARNString = true - } + if bs.Spec.AWSS3 != nil && bs.Spec.AWSS3.AWSSTSRoleARN != nil { + bsArnList[bs.Name] = *bs.Spec.AWSS3.AWSSTSRoleARN } } + printARNStatus("BACKINGSTORE", bsArnList) - if !foundARNString { - fmt.Print(" ❌ No aws sts arn string found.\n") - } - fmt.Println("") - - foundARNString = false // Validate ARNs for namespacestores - fmt.Print("ARN Validation Check (NAMESPACESTORES):\n----------------------------------\n") + nsArnList := make(map[string]string) for _, ns := range nsList.Items { - if ns.Spec.AWSS3 != nil { - if ns.Spec.AWSS3.AWSSTSRoleARN != nil { - arn := *ns.Spec.AWSS3.AWSSTSRoleARN - if isValidArn(&arn) { - fmt.Printf(" ✅ Namespacestore \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", ns.Name, arn) - } else { - fmt.Printf(" ⚠️ Namespacestore \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", ns.Name, arn) - } - fmt.Println("") - foundARNString = true - } + if ns.Spec.AWSS3 != nil && ns.Spec.AWSS3.AWSSTSRoleARN != nil { + nsArnList[ns.Name] = *ns.Spec.AWSS3.AWSSTSRoleARN } } - - if !foundARNString { - fmt.Print(" ❌ No aws sts arn string found.\n") - } - fmt.Println("") + printARNStatus("NAMESPACESTORE", nsArnList) fmt.Println("") } @@ -182,5 +154,25 @@ func printOverriddenEnvVar(appName string, envVars []corev1.EnvVar) { // isValidArn is a function to validate the ARN format for an s3 buckets func isValidArn(arn *string) bool { - return strings.HasPrefix(*arn, "arn:aws:s3:::") && len(*arn) > len("arn:aws:s3:::") + return strings.HasPrefix(*arn, "arn:aws:s3::") && len(*arn) > len("arn:aws:s3::") +} + +// printARNStatus is a function to print ARN validation status +func printARNStatus(listType string, arnList map[string]string) { + foundARNString := false + fmt.Printf("%s ARNs:\n----------------------------------\n", listType) + for name, arn := range arnList { + if isValidArn(&arn) { + fmt.Printf(" ✅ %s \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", listType, name, arn) + } else { + fmt.Printf(" ⚠️ %s \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", listType, name, arn) + } + fmt.Println("") + foundARNString = true + } + + if !foundARNString { + fmt.Print(" ❌ No AWS STS ARN string found.\n") + } + fmt.Println("") } From 4dc5d8a162b21dd49f2cdac842839e4c85a7b72f Mon Sep 17 00:00:00 2001 From: Aayush Chouhan Date: Wed, 30 Oct 2024 19:02:00 +0530 Subject: [PATCH 3/3] Validating only STS ARN and updated the format Signed-off-by: Aayush Chouhan --- pkg/diagnostics/report.go | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/pkg/diagnostics/report.go b/pkg/diagnostics/report.go index 4feb3fad0..a0fe210a2 100644 --- a/pkg/diagnostics/report.go +++ b/pkg/diagnostics/report.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" + "github.com/aws/aws-sdk-go/aws/arn" nbv1 "github.com/noobaa/noobaa-operator/v5/pkg/apis/noobaa/v1alpha1" "github.com/noobaa/noobaa-operator/v5/pkg/bundle" "github.com/noobaa/noobaa-operator/v5/pkg/options" @@ -152,9 +153,21 @@ func printOverriddenEnvVar(appName string, envVars []corev1.EnvVar) { fmt.Println("") } -// isValidArn is a function to validate the ARN format for an s3 buckets -func isValidArn(arn *string) bool { - return strings.HasPrefix(*arn, "arn:aws:s3::") && len(*arn) > len("arn:aws:s3::") +// isValidSTSArn is a function to validate the STS ARN format +func isValidSTSArn(arnStr *string) bool { + if arnStr == nil { + return false + } + + parsedArn, err := arn.Parse(*arnStr) + if err != nil { + return false + } + + if parsedArn.Service == "sts" { + return true + } + return false } // printARNStatus is a function to print ARN validation status @@ -162,17 +175,19 @@ func printARNStatus(listType string, arnList map[string]string) { foundARNString := false fmt.Printf("%s ARNs:\n----------------------------------\n", listType) for name, arn := range arnList { - if isValidArn(&arn) { - fmt.Printf(" ✅ %s \"%s\":\n\t ARN: %s\n\t Status: ✅ Valid\n", listType, name, arn) + fmt.Printf("\t%s \"%s\":\n\t ARN: %s\n\t", listType, name, arn) + // currently validating only for AWS STS ARN, can be changed accordingly for other formats and validation + if isValidSTSArn(&arn) { + fmt.Printf(" Status: ✅ Valid STS ARN\n") } else { - fmt.Printf(" ⚠️ %s \"%s\":\n\t ARN: %s\n\t Status: ⚠️ Invalid (Not an S3 bucket ARN)\n", listType, name, arn) + fmt.Printf(" Status: ⚠️ Invalid (Not an STS ARN)\n") } - fmt.Println("") foundARNString = true + fmt.Println("") } if !foundARNString { - fmt.Print(" ❌ No AWS STS ARN string found.\n") + fmt.Print(" ❌ No AWS ARN string found.\n") } fmt.Println("") }