From 38b3c8993974145e4770a8b2cc7f0622ad160276 Mon Sep 17 00:00:00 2001 From: Mark Goddard Date: Fri, 29 Nov 2024 16:05:36 +0000 Subject: [PATCH] Check if trust zone is deployed in commands that exec into SPIRE server Some cofidectl commands exec into the SPIRE server to query it using the spire-server CLI. This fails with an error if the SPIRE server has not yet been deployed. This change fixes the issue for the following commands: - federation list (reports Health as Inactive) - workload list (fails with a better error message) - workload discover (continues without querying SPIRE server) Fixes: #52 --- cmd/cofidectl/cmd/federation/federation.go | 22 +++++++++++++++++- cmd/cofidectl/cmd/workload/workload.go | 27 +++++++++++++++++++++- internal/pkg/workload/workload.go | 11 +++++---- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/cmd/cofidectl/cmd/federation/federation.go b/cmd/cofidectl/cmd/federation/federation.go index 76f42a9..645b0f9 100644 --- a/cmd/cofidectl/cmd/federation/federation.go +++ b/cmd/cofidectl/cmd/federation/federation.go @@ -11,8 +11,9 @@ import ( trust_zone_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_zone/v1alpha1" cmdcontext "github.com/cofide/cofidectl/cmd/cofidectl/cmd/context" - kubeutil "github.com/cofide/cofidectl/pkg/kube" + "github.com/cofide/cofidectl/internal/pkg/provider/helm" "github.com/cofide/cofidectl/internal/pkg/spire" + kubeutil "github.com/cofide/cofidectl/pkg/kube" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" ) @@ -118,6 +119,12 @@ func checkFederationStatus(ctx context.Context, kubeConfig string, from *trust_z compare := make(map[*trust_zone_proto.TrustZone]bundles) for _, tz := range []*trust_zone_proto.TrustZone{from, to} { + if deployed, err := isTrustZoneDeployed(ctx, tz); err != nil { + return "", err + } else if !deployed { + return "Inactive", nil + } + client, err := kubeutil.NewKubeClientFromSpecifiedContext(kubeConfig, tz.GetKubernetesContext()) if err != nil { return "", err @@ -148,6 +155,19 @@ func checkFederationStatus(ctx context.Context, kubeConfig string, from *trust_z return "Healthy", nil } +// isTrustZoneDeployed returns whether a trust zone has been deployed, i.e. whether a SPIRE Helm release has been installed. +func isTrustZoneDeployed(ctx context.Context, trustZone *trust_zone_proto.TrustZone) (bool, error) { + prov, err := helm.NewHelmSPIREProvider(ctx, trustZone, nil, nil) + if err != nil { + return false, err + } + if installed, err := prov.CheckIfAlreadyInstalled(); err != nil { + return false, err + } else { + return installed, nil + } +} + var federationAddCmdDesc = ` This command will add a new federation to the Cofide configuration state. ` diff --git a/cmd/cofidectl/cmd/workload/workload.go b/cmd/cofidectl/cmd/workload/workload.go index 647e7cf..e84972d 100644 --- a/cmd/cofidectl/cmd/workload/workload.go +++ b/cmd/cofidectl/cmd/workload/workload.go @@ -10,6 +10,7 @@ import ( trust_zone_proto "github.com/cofide/cofide-api-sdk/gen/go/proto/trust_zone/v1alpha1" cmdcontext "github.com/cofide/cofidectl/cmd/cofidectl/cmd/context" + "github.com/cofide/cofidectl/internal/pkg/provider/helm" "github.com/cofide/cofidectl/internal/pkg/workload" "github.com/olekukonko/tablewriter" "github.com/spf13/cobra" @@ -111,6 +112,12 @@ func renderRegisteredWorkloads(ctx context.Context, kubeConfig string, trustZone data := make([][]string, 0, len(trustZones)) for _, trustZone := range trustZones { + if deployed, err := isTrustZoneDeployed(ctx, trustZone); err != nil { + return err + } else if !deployed { + return fmt.Errorf("trust zone %s has not been deployed", trustZone.Name) + } + registeredWorkloads, err := workload.GetRegisteredWorkloads(ctx, kubeConfig, trustZone.GetKubernetesContext()) if err != nil { return err @@ -205,7 +212,12 @@ func renderUnregisteredWorkloads(ctx context.Context, kubeConfig string, trustZo data := make([][]string, 0, len(trustZones)) for _, trustZone := range trustZones { - registeredWorkloads, err := workload.GetUnregisteredWorkloads(ctx, kubeConfig, trustZone.GetKubernetesContext(), includeSecrets) + deployed, err := isTrustZoneDeployed(ctx, trustZone) + if err != nil { + return err + } + + registeredWorkloads, err := workload.GetUnregisteredWorkloads(ctx, kubeConfig, trustZone.GetKubernetesContext(), includeSecrets, deployed) if err != nil { return err } @@ -237,3 +249,16 @@ func renderUnregisteredWorkloads(ctx context.Context, kubeConfig string, trustZo return nil } + +// isTrustZoneDeployed returns whether a trust zone has been deployed, i.e. whether a SPIRE Helm release has been installed. +func isTrustZoneDeployed(ctx context.Context, trustZone *trust_zone_proto.TrustZone) (bool, error) { + prov, err := helm.NewHelmSPIREProvider(ctx, trustZone, nil, nil) + if err != nil { + return false, err + } + if installed, err := prov.CheckIfAlreadyInstalled(); err != nil { + return false, err + } else { + return installed, nil + } +} diff --git a/internal/pkg/workload/workload.go b/internal/pkg/workload/workload.go index 235ace1..d097425 100644 --- a/internal/pkg/workload/workload.go +++ b/internal/pkg/workload/workload.go @@ -67,7 +67,7 @@ func GetRegisteredWorkloads(ctx context.Context, kubeConfig string, kubeContext } // GetUnregisteredWorkloads will discover workloads in a Kubernetes cluster that are not (yet) registered -func GetUnregisteredWorkloads(ctx context.Context, kubeCfgFile string, kubeContext string, secretDiscovery bool) ([]Workload, error) { +func GetUnregisteredWorkloads(ctx context.Context, kubeCfgFile string, kubeContext string, secretDiscovery bool, checkSpire bool) ([]Workload, error) { // Includes the initial Kubernetes namespaces. ignoredNamespaces := map[string]int{ "kube-node-lease": 1, @@ -82,9 +82,12 @@ func GetUnregisteredWorkloads(ctx context.Context, kubeCfgFile string, kubeConte return nil, err } - registeredEntries, err := spire.GetRegistrationEntries(ctx, client) - if err != nil { - return nil, err + var registeredEntries map[string]*spire.RegisteredEntry + if checkSpire { + registeredEntries, err = spire.GetRegistrationEntries(ctx, client) + if err != nil { + return nil, err + } } pods, err := client.Clientset.CoreV1().Pods("").List(ctx, metav1.ListOptions{})