From afae2996de1b82815cd06110e795e8e3ddaaf165 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Fri, 7 Mar 2025 14:10:02 -0800 Subject: [PATCH 1/3] Allow TLS for Goldmane API --- pkg/controller/whisker/controller.go | 26 ++++++++++++++++++++- pkg/render/whisker/component.go | 34 ++++++++++++++++++++++++---- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/pkg/controller/whisker/controller.go b/pkg/controller/whisker/controller.go index 49d946023b..dff83ae604 100644 --- a/pkg/controller/whisker/controller.go +++ b/pkg/controller/whisker/controller.go @@ -36,7 +36,9 @@ import ( "github.com/tigera/operator/pkg/controller/utils" "github.com/tigera/operator/pkg/controller/utils/imageset" "github.com/tigera/operator/pkg/ctrlruntime" + "github.com/tigera/operator/pkg/dns" "github.com/tigera/operator/pkg/render" + rcertificatemanagement "github.com/tigera/operator/pkg/render/certificatemanagement" "github.com/tigera/operator/pkg/render/monitor" "github.com/tigera/operator/pkg/render/whisker" "github.com/tigera/operator/pkg/tls/certificatemanagement" @@ -199,6 +201,27 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( return reconcile.Result{}, err } + // Goldmane needs a server certificate for it's gRPC API. + // TODO: Add this to the trusted bundle. This isn't stritctly needed, since the bundle already includes the operator CA that + // signed this certificate. But in order to support custom user-supplied certificates, we will need to do this. + goldmaneCertificateNames := dns.GetServiceDNSNames(whisker.GoldmaneServiceName, whisker.WhiskerNamespace, r.clusterDomain) + goldmaneCertificateNames = append(goldmaneCertificateNames, "localhost", "127.0.0.1") + keyPair, err := certificateManager.GetOrCreateKeyPair(r.cli, whisker.GoldmaneServerSecret, common.OperatorNamespace(), goldmaneCertificateNames) + if err != nil { + r.status.SetDegraded(operatorv1.ResourceCreateError, "Error creating TLS certificate", err, log) + return reconcile.Result{}, err + } + certComponent := rcertificatemanagement.CertificateManagement(&rcertificatemanagement.Config{ + Namespace: whisker.WhiskerNamespace, + TruthNamespace: common.OperatorNamespace(), + ServiceAccounts: []string{whisker.WhiskerServiceAccountName}, + KeyPairOptions: []rcertificatemanagement.KeyPairOption{ + rcertificatemanagement.NewKeyPairOption(keyPair, true, true), + }, + // TrustedBundle is managed by the core controller. + TrustedBundle: nil, + }) + trustedCertBundle, err := certificateManager.LoadTrustedBundle(ctx, r.cli, whisker.WhiskerNamespace) if err != nil { r.status.SetDegraded(operatorv1.ResourceReadError, "Error loading trusted cert bundle", err, reqLogger) @@ -213,9 +236,10 @@ func (r *Reconciler) Reconcile(ctx context.Context, request reconcile.Request) ( TunnelSecret: tunnelSecret, TrustedCertBundle: trustedCertBundle, ManagementClusterConnection: managementClusterConnection, + GoldmaneServerKeyPair: keyPair, } - components := []render.Component{whisker.Whisker(cfg)} + components := []render.Component{certComponent, whisker.Whisker(cfg)} if err = imageset.ApplyImageSet(ctx, r.cli, variant, components...); err != nil { r.status.SetDegraded(operatorv1.ResourceUpdateError, "Error with images from ImageSet", err, reqLogger) return reconcile.Result{}, err diff --git a/pkg/render/whisker/component.go b/pkg/render/whisker/component.go index 8989d8c6fc..7cc5255342 100644 --- a/pkg/render/whisker/component.go +++ b/pkg/render/whisker/component.go @@ -42,6 +42,8 @@ const ( WhiskerServiceAccountName = WhiskerName WhiskerDeploymentName = WhiskerName WhiskerRoleName = WhiskerName + GoldmaneServerSecret = "goldmane-server-secret" + GoldmaneServiceName = "goldmane" GuardianContainerName = "guardian" GoldmaneContainerName = "goldmane" @@ -64,6 +66,7 @@ type Configuration struct { TunnelSecret *corev1.Secret TrustedCertBundle certificatemanagement.TrustedBundleRO ManagementClusterConnection *operatorv1.ManagementClusterConnection + GoldmaneServerKeyPair certificatemanagement.KeyPairInterface } type Component struct { @@ -189,21 +192,38 @@ func (c *Component) whiskerBackendContainer() corev1.Container { } func (c *Component) goldmaneContainer() corev1.Container { + var volumeMounts []corev1.VolumeMount + env := []corev1.EnvVar{ {Name: "LOG_LEVEL", Value: "INFO"}, {Name: "PORT", Value: "7443"}, } - var volumeMounts []corev1.VolumeMount + + if c.cfg.GoldmaneServerKeyPair != nil { + env = append(env, corev1.EnvVar{ + Name: "SERVER_KEY_PATH", + Value: c.cfg.GoldmaneServerKeyPair.VolumeMountKeyFilePath(), + }) + env = append(env, corev1.EnvVar{ + Name: "SERVER_CERT_PATH", + Value: c.cfg.GoldmaneServerKeyPair.VolumeMountCertificateFilePath(), + }) + + volumeMounts = append(volumeMounts, c.cfg.GoldmaneServerKeyPair.VolumeMount(c.SupportedOSType())) + } + if c.cfg.ManagementClusterConnection != nil { env = append(env, corev1.EnvVar{ Name: "PUSH_URL", - Value: "https://localhost:8080/api/v1/flows/bulk"}, + Value: "https://localhost:8080/api/v1/flows/bulk", + }, corev1.EnvVar{ Name: "CA_CERT_PATH", - Value: c.cfg.TrustedCertBundle.MountPath()}, + Value: c.cfg.TrustedCertBundle.MountPath(), + }, ) - volumeMounts = c.cfg.TrustedCertBundle.VolumeMounts(c.SupportedOSType()) + volumeMounts = append(volumeMounts, c.cfg.TrustedCertBundle.VolumeMounts(c.SupportedOSType())...) } return corev1.Container{ @@ -219,7 +239,7 @@ func (c *Component) goldmaneContainer() corev1.Container { func (c *Component) goldmaneService() *corev1.Service { return &corev1.Service{ ObjectMeta: metav1.ObjectMeta{ - Name: "goldmane", + Name: GoldmaneServiceName, Namespace: WhiskerNamespace, }, Spec: corev1.ServiceSpec{ @@ -261,6 +281,10 @@ func (c *Component) deployment() *appsv1.Deployment { ctrs := []corev1.Container{c.whiskerContainer(), c.whiskerBackendContainer(), c.goldmaneContainer()} volumes := []corev1.Volume{c.cfg.TrustedCertBundle.Volume()} + if c.cfg.GoldmaneServerKeyPair != nil { + volumes = append(volumes, c.cfg.GoldmaneServerKeyPair.Volume()) + } + if c.cfg.ManagementClusterConnection != nil { ctrs = append(ctrs, c.guardianContainer()) volumes = append(volumes, secretVolume(c.cfg.TunnelSecret)) From 14dba95a1ba927264a81ee6607b85d3a983cab64 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Fri, 7 Mar 2025 14:15:24 -0800 Subject: [PATCH 2/3] include trusted bundle in volume mounts --- pkg/render/whisker/component.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/render/whisker/component.go b/pkg/render/whisker/component.go index 7cc5255342..13247eca0f 100644 --- a/pkg/render/whisker/component.go +++ b/pkg/render/whisker/component.go @@ -188,6 +188,7 @@ func (c *Component) whiskerBackendContainer() corev1.Container { {Name: "GOLDMANE_HOST", Value: "localhost:7443"}, }, SecurityContext: securitycontext.NewNonRootContext(), + VolumeMounts: c.cfg.TrustedCertBundle.VolumeMounts(rmeta.OSTypeLinux), } } From 39ea34d112dae29863aab4d886b19e9758892899 Mon Sep 17 00:00:00 2001 From: Casey Davenport Date: Fri, 7 Mar 2025 15:35:21 -0800 Subject: [PATCH 3/3] Fix ut --- pkg/render/whisker/component_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pkg/render/whisker/component_test.go b/pkg/render/whisker/component_test.go index e740016348..8738d464a2 100644 --- a/pkg/render/whisker/component_test.go +++ b/pkg/render/whisker/component_test.go @@ -115,6 +115,7 @@ var _ = Describe("ComponentRendering", func() { {Name: "GOLDMANE_HOST", Value: "localhost:7443"}, }, SecurityContext: securitycontext.NewNonRootContext(), + VolumeMounts: certificatemanagement.CreateTrustedBundle(nil).VolumeMounts(rmeta.OSTypeAny), }, { Name: whisker.GoldmaneContainerName, @@ -142,6 +143,7 @@ var _ = Describe("ComponentRendering", func() { }, }, ), + Entry("Should configure guardian", &whisker.Configuration{ Installation: &operatorv1.InstallationSpec{ @@ -196,6 +198,7 @@ var _ = Describe("ComponentRendering", func() { {Name: "GOLDMANE_HOST", Value: "localhost:7443"}, }, SecurityContext: securitycontext.NewNonRootContext(), + VolumeMounts: certificatemanagement.CreateTrustedBundle(nil).VolumeMounts(rmeta.OSTypeAny), }, { Name: whisker.GoldmaneContainerName,