From ac743de11657fa5e3c65e37e500ce39ad1423ef5 Mon Sep 17 00:00:00 2001 From: Jan Bouska Date: Mon, 20 Jan 2025 12:46:31 +0100 Subject: [PATCH 1/2] [SECURESIGN-1393] Migrate trillian --- .../utils/kubernetes/ensure/deployment.go | 59 ++++- .../kubernetes/ensure/deployment_test.go | 74 ++++++ internal/controller/common/utils/set_tls.go | 64 ----- .../controller/trillian/actions/constants.go | 7 + .../trillian/actions/db/deployment.go | 218 +++++++++++++++--- .../trillian/actions/db/handle_secret.go | 21 +- .../controller/trillian/utils/constants.go | 10 - .../trillian/utils/server-deployment.go | 14 +- .../trillian/utils/signer-deployment.go | 14 +- .../controller/trillian/utils/trillian-db.go | 186 --------------- 10 files changed, 343 insertions(+), 324 deletions(-) delete mode 100644 internal/controller/common/utils/set_tls.go delete mode 100644 internal/controller/trillian/utils/constants.go delete mode 100644 internal/controller/trillian/utils/trillian-db.go diff --git a/internal/controller/common/utils/kubernetes/ensure/deployment.go b/internal/controller/common/utils/kubernetes/ensure/deployment.go index ae323a72b..c7f5d58bd 100644 --- a/internal/controller/common/utils/kubernetes/ensure/deployment.go +++ b/internal/controller/common/utils/kubernetes/ensure/deployment.go @@ -8,6 +8,16 @@ import ( corev1 "k8s.io/api/core/v1" ) +const ( + CaTrustVolumeName = "ca-trust" + TLSVolumeName = "tls-cert" + + TLSVolumeMount = "/var/run/secrets/tas" + + TLSKeyPath = TLSVolumeMount + "/tls.key" + TLSCertPath = TLSVolumeMount + "/tls.crt" +) + func Proxy() func(*v1.Deployment) error { return func(dp *v1.Deployment) error { utils.SetProxyEnvs(dp) @@ -15,8 +25,6 @@ func Proxy() func(*v1.Deployment) error { } } -const CaTrustVolumeName = "ca-trust" - // TrustedCA mount config map with trusted CA bundle to all deployment's containers. func TrustedCA(lor *v1alpha1.LocalObjectReference) func(dp *v1.Deployment) error { return func(dp *v1.Deployment) error { @@ -52,3 +60,50 @@ func TrustedCA(lor *v1alpha1.LocalObjectReference) func(dp *v1.Deployment) error return nil } } + +// TLS mount secret with tls cert to all deployment's containers. +func TLS(tls v1alpha1.TLS) func(dp *v1.Deployment) error { + return func(dp *v1.Deployment) error { + template := &dp.Spec.Template + + for i := range template.Spec.Containers { + volumeMount := kubernetes.FindVolumeMountByNameOrCreate(&template.Spec.Containers[i], TLSVolumeName) + volumeMount.MountPath = TLSVolumeMount + volumeMount.ReadOnly = true + } + + volume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, TLSVolumeName) + if volume.Projected == nil { + volume.Projected = &corev1.ProjectedVolumeSource{} + } + volume.Projected.Sources = []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: tls.CertRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: tls.CertRef.Key, + Path: "tls.crt", + }, + }, + }, + }, + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: tls.PrivateKeyRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: tls.PrivateKeyRef.Key, + Path: "tls.key", + }, + }, + }, + }, + } + return nil + } +} diff --git a/internal/controller/common/utils/kubernetes/ensure/deployment_test.go b/internal/controller/common/utils/kubernetes/ensure/deployment_test.go index 3ddd2d36e..37b8a681b 100644 --- a/internal/controller/common/utils/kubernetes/ensure/deployment_test.go +++ b/internal/controller/common/utils/kubernetes/ensure/deployment_test.go @@ -5,6 +5,7 @@ import ( "testing" "github.com/onsi/gomega" + "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/annotations" "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" @@ -63,3 +64,76 @@ func TestEnsureTrustedCAFromAnnotations(t *testing.T) { }) } + +func TestEnsureTLS(t *testing.T) { + gomega.RegisterTestingT(t) + t.Run("update existing object", func(t *testing.T) { + + ctx := context.TODO() + c := testAction.FakeClientBuilder(). + WithObjects(&v1.Deployment{ + ObjectMeta: v2.ObjectMeta{Name: name, Namespace: "default"}, + Spec: v1.DeploymentSpec{ + Template: v3.PodTemplateSpec{ + Spec: v3.PodSpec{ + Containers: []v3.Container{ + {Name: name, Image: "test"}, + }, + }, + }, + }, + }). + Build() + + result, err := kubernetes.CreateOrUpdate(ctx, c, + &v1.Deployment{ObjectMeta: v2.ObjectMeta{Name: name, Namespace: "default"}}, + TLS(v1alpha1.TLS{ + PrivateKeyRef: &v1alpha1.SecretKeySelector{ + LocalObjectReference: v1alpha1.LocalObjectReference{ + Name: "testSecret", + }, + Key: "key", + }, + CertRef: &v1alpha1.SecretKeySelector{ + LocalObjectReference: v1alpha1.LocalObjectReference{ + Name: "testSecret", + }, + Key: "cert", + }, + }), + ) + gomega.Expect(err).ToNot(gomega.HaveOccurred()) + + gomega.Expect(result).To(gomega.Equal(controllerutil.OperationResultUpdated)) + + existing := &v1.Deployment{} + gomega.Expect(c.Get(ctx, client.ObjectKey{Namespace: "default", Name: name}, existing)).To(gomega.Succeed()) + + gomega.Expect(existing.Spec.Template.Spec.Containers[0].VolumeMounts).To(gomega.HaveLen(1)) + gomega.Expect(existing.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name).To(gomega.Equal(TLSVolumeName)) + gomega.Expect(existing.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath).To(gomega.Equal("/var/run/secrets/tas")) + + gomega.Expect(existing.Spec.Template.Spec.Volumes).To(gomega.HaveLen(1)) + gomega.Expect(existing.Spec.Template.Spec.Volumes[0].Name).To(gomega.Equal(TLSVolumeName)) + gomega.Expect(existing.Spec.Template.Spec.Volumes[0].Projected.Sources).To(gomega.HaveLen(2)) + gomega.Expect(existing.Spec.Template.Spec.Volumes[0].Projected.Sources).To(gomega.ContainElements( + gomega.And( + gomega.WithTransform(func(s v3.VolumeProjection) string { + return s.Secret.Name + }, gomega.Equal("testSecret")), + gomega.WithTransform(func(s v3.VolumeProjection) string { + return s.Secret.Items[0].Key + }, gomega.Equal("key")), + ), + gomega.And( + gomega.WithTransform(func(s v3.VolumeProjection) string { + return s.Secret.Name + }, gomega.Equal("testSecret")), + gomega.WithTransform(func(s v3.VolumeProjection) string { + return s.Secret.Items[0].Key + }, gomega.Equal("cert")), + ), + )) + + }) +} diff --git a/internal/controller/common/utils/set_tls.go b/internal/controller/common/utils/set_tls.go deleted file mode 100644 index 16e70b2e8..000000000 --- a/internal/controller/common/utils/set_tls.go +++ /dev/null @@ -1,64 +0,0 @@ -package utils - -import ( - "errors" - - "github.com/securesign/operator/api/v1alpha1" - corev1 "k8s.io/api/core/v1" -) - -func SetTLS(template *corev1.PodTemplateSpec, tls v1alpha1.TLS) error { - if template == nil { - return errors.New("SetTLS: PodTemplateSpec is not set") - } - if tls.CertRef == nil { - return nil - } - - template.Spec.Volumes = append(template.Spec.Volumes, corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: tls.CertRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: tls.CertRef.Key, - Path: "tls.crt", - }, - }, - }, - }, - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: tls.PrivateKeyRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: tls.PrivateKeyRef.Key, - Path: "tls.key", - }, - }, - }, - }, - }, - }, - }, - }) - - for i := range template.Spec.Containers { - template.Spec.Containers[i].VolumeMounts = append(template.Spec.Containers[i].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - } - - return nil -} diff --git a/internal/controller/trillian/actions/constants.go b/internal/controller/trillian/actions/constants.go index 9ef43bcf5..7e47fcd5c 100644 --- a/internal/controller/trillian/actions/constants.go +++ b/internal/controller/trillian/actions/constants.go @@ -22,4 +22,11 @@ const ( ServerPortName = "grpc" MetricsPort = 8090 MetricsPortName = "metrics" + + SecretRootPassword = "mysql-root-password" + SecretPassword = "mysql-password" + SecretDatabaseName = "mysql-database" + SecretUser = "mysql-user" + SecretPort = "mysql-port" + SecretHost = "mysql-host" ) diff --git a/internal/controller/trillian/actions/db/deployment.go b/internal/controller/trillian/actions/db/deployment.go index 685b4fd52..61afbde31 100644 --- a/internal/controller/trillian/actions/db/deployment.go +++ b/internal/controller/trillian/actions/db/deployment.go @@ -2,17 +2,20 @@ package db import ( "context" + "errors" "fmt" - "github.com/securesign/operator/internal/controller/common/utils" - v1 "k8s.io/api/core/v1" - "github.com/securesign/operator/internal/controller/common/action" + "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/labels" "github.com/securesign/operator/internal/controller/trillian/actions" trillianUtils "github.com/securesign/operator/internal/controller/trillian/utils" + "golang.org/x/exp/maps" + v2 "k8s.io/api/apps/v1" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -20,6 +23,11 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" ) +const ( + livenessCommand = "mariadb-admin -u ${MYSQL_USER} -p${MYSQL_PASSWORD} ping" + readinessCommand = "mariadb -u ${MYSQL_USER} -p${MYSQL_PASSWORD} -e \"SELECT 1;\"" +) + func NewDeployAction() action.Action[*rhtasv1alpha1.Trillian] { return &deployAction{} } @@ -39,8 +47,8 @@ func (i deployAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Tri func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trillian) *action.Result { var ( - err error - updated bool + err error + result controllerutil.OperationResult ) labels := labels.For(actions.DbComponentName, actions.DbDeploymentName, instance.Name) @@ -69,45 +77,27 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli i.Logger.V(1).Info("Communication to trillian-db is insecure") } - useTLS := trillianUtils.UseTLS(instance) - db, err := trillianUtils.CreateTrillDb(instance, actions.DbDeploymentName, actions.RBACName, scc, labels, useTLS) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.DbCondition, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian DB: %w", err), instance) - } - - if err = controllerutil.SetControllerReference(instance, db, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for DB Deployment: %w", err)) - } - - if updated, err = i.Ensure(ctx, db); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + if result, err = kubernetes.CreateOrUpdate(ctx, i.Client, + &v2.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: actions.DbDeploymentName, + Namespace: instance.Namespace, + }, + }, + i.ensureDbDeployment(instance, actions.RBACName, scc, labels), + ensure.ControllerReference[*v2.Deployment](instance, i.Client), + ensure.Labels[*v2.Deployment](maps.Keys(labels), labels), + ensure.Optional(trillianUtils.UseTLS(instance), i.ensureTLS(instance)), + ); err != nil { + return i.Error(ctx, fmt.Errorf("could not create Trillian DB: %w", err), instance, metav1.Condition{ Type: actions.DbCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian DB: %w", err), instance) } - if updated { + if result != controllerutil.OperationResultNone { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.DbCondition, Status: metav1.ConditionFalse, @@ -118,5 +108,159 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli } else { return i.Continue() } +} + +func (i *deployAction) ensureDbDeployment(instance *rhtasv1alpha1.Trillian, sa string, secCont *v1.PodSecurityContext, labels map[string]string) func(deployment *v2.Deployment) error { + return func(dp *v2.Deployment) error { + switch { + case instance.Status.Db.DatabaseSecretRef == nil: + { + return errors.New("reference to database secret is not set") + } + case instance.Status.Db.Pvc.Name == "": + { + return errors.New("reference to database pvc is not set") + } + } + + var volumeName = "storage" + + spec := &dp.Spec + spec.Replicas = utils.Pointer[int32](1) + spec.Selector = &metav1.LabelSelector{ + MatchLabels: labels, + } + spec.Strategy = v2.DeploymentStrategy{ + Type: "Recreate", + } + + template := &spec.Template + template.Labels = labels + template.Spec.ServiceAccountName = sa + template.Spec.SecurityContext = secCont + + volume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, volumeName) + if volume.PersistentVolumeClaim == nil { + volume.PersistentVolumeClaim = &v1.PersistentVolumeClaimVolumeSource{} + } + volume.PersistentVolumeClaim.ClaimName = instance.Status.Db.Pvc.Name + + container := kubernetes.FindContainerByNameOrCreate(&template.Spec, actions.DbDeploymentName) + container.Image = constants.TrillianDbImage + container.Command = []string{ + "run-mysqld", + } + + port := kubernetes.FindPortByNameOrCreate(container, "3306-tcp") + port.ContainerPort = 3306 + port.Protocol = v1.ProtocolTCP + + volumeMount := kubernetes.FindVolumeMountByNameOrCreate(container, volumeName) + volumeMount.MountPath = "/var/lib/mysql" + + // Env variables from secret trillian-mysql + userEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_USER") + userEnv.ValueFrom = &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: actions.SecretUser, + LocalObjectReference: v1.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + passwordEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_PASSWORD") + passwordEnv.ValueFrom = &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: actions.SecretPassword, + LocalObjectReference: v1.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + rootPasswordEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_ROOT_PASSWORD") + rootPasswordEnv.ValueFrom = &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: actions.SecretRootPassword, + LocalObjectReference: v1.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + portEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_PORT") + portEnv.ValueFrom = &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: actions.SecretPort, + LocalObjectReference: v1.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + dbEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_DATABASE") + dbEnv.ValueFrom = &v1.EnvVarSource{ + SecretKeyRef: &v1.SecretKeySelector{ + Key: actions.SecretDatabaseName, + LocalObjectReference: v1.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + if container.ReadinessProbe == nil { + container.ReadinessProbe = &v1.Probe{} + } + if container.ReadinessProbe.Exec == nil { + container.ReadinessProbe.Exec = &v1.ExecAction{} + } + + container.ReadinessProbe.Exec.Command = []string{"bash", "-c", readinessCommand} + container.ReadinessProbe.InitialDelaySeconds = 10 + + if container.LivenessProbe == nil { + container.LivenessProbe = &v1.Probe{} + } + if container.LivenessProbe.Exec == nil { + container.LivenessProbe.Exec = &v1.ExecAction{} + } + + container.LivenessProbe.Exec.Command = []string{"bash", "-c", livenessCommand} + container.LivenessProbe.InitialDelaySeconds = 30 + return nil + } +} + +func (i *deployAction) ensureTLS(instance *rhtasv1alpha1.Trillian) func(deployment *v2.Deployment) error { + return func(dp *v2.Deployment) error { + if err := ensure.TLS(instance.Status.Db.TLS)(dp); err != nil { + return err + } + + container := kubernetes.FindContainerByNameOrCreate(&dp.Spec.Template.Spec, actions.DbDeploymentName) + if container.ReadinessProbe == nil { + container.ReadinessProbe = &v1.Probe{} + } + if container.ReadinessProbe.Exec == nil { + container.ReadinessProbe.Exec = &v1.ExecAction{} + } + + container.ReadinessProbe.Exec.Command = []string{"bash", "-c", readinessCommand + " --ssl"} + + if container.LivenessProbe == nil { + container.LivenessProbe = &v1.Probe{} + } + if container.LivenessProbe.Exec == nil { + container.LivenessProbe.Exec = &v1.ExecAction{} + } + + container.LivenessProbe.Exec.Command = []string{"bash", "-c", livenessCommand + " --ssl"} + + container.Args = append(container.Args, "--ssl-cert", ensure.TLSCertPath) + container.Args = append(container.Args, "--ssl-key", ensure.TLSKeyPath) + + return nil + } } diff --git a/internal/controller/trillian/actions/db/handle_secret.go b/internal/controller/trillian/actions/db/handle_secret.go index 032d240a6..5d1b81160 100644 --- a/internal/controller/trillian/actions/db/handle_secret.go +++ b/internal/controller/trillian/actions/db/handle_secret.go @@ -18,7 +18,6 @@ import ( "github.com/securesign/operator/internal/controller/constants" labels2 "github.com/securesign/operator/internal/controller/labels" trillian "github.com/securesign/operator/internal/controller/trillian/actions" - trillianUtils "github.com/securesign/operator/internal/controller/trillian/utils" "k8s.io/apimachinery/pkg/api/meta" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -35,10 +34,10 @@ const ( dbConnectionResource = "trillian-db-connection" dbConnectionSecretName = "trillian-db-connection-" - annotationDatabase = labels2.LabelNamespace + "/" + trillianUtils.SecretDatabaseName - annotationUser = labels2.LabelNamespace + "/" + trillianUtils.SecretUser - annotationPort = labels2.LabelNamespace + "/" + trillianUtils.SecretPort - annotationHost = labels2.LabelNamespace + "/" + trillianUtils.SecretHost + annotationDatabase = labels2.LabelNamespace + "/" + trillian.SecretDatabaseName + annotationUser = labels2.LabelNamespace + "/" + trillian.SecretUser + annotationPort = labels2.LabelNamespace + "/" + trillian.SecretPort + annotationHost = labels2.LabelNamespace + "/" + trillian.SecretHost ) var ErrMissingDBConfiguration = errors.New("expecting external DB configuration") @@ -186,12 +185,12 @@ func (i handleSecretAction) createDbSecret(namespace string, labels map[string]s }, Type: "Opaque", Data: map[string][]byte{ - trillianUtils.SecretRootPassword: rootPass, - trillianUtils.SecretPassword: mysqlPass, - trillianUtils.SecretDatabaseName: []byte(databaseName), - trillianUtils.SecretUser: []byte(user), - trillianUtils.SecretPort: []byte(strconv.Itoa(port)), - trillianUtils.SecretHost: []byte(host), + trillian.SecretRootPassword: rootPass, + trillian.SecretPassword: mysqlPass, + trillian.SecretDatabaseName: []byte(databaseName), + trillian.SecretUser: []byte(user), + trillian.SecretPort: []byte(strconv.Itoa(port)), + trillian.SecretHost: []byte(host), }, } } diff --git a/internal/controller/trillian/utils/constants.go b/internal/controller/trillian/utils/constants.go deleted file mode 100644 index 85e1673ff..000000000 --- a/internal/controller/trillian/utils/constants.go +++ /dev/null @@ -1,10 +0,0 @@ -package trillianUtils - -const ( - SecretRootPassword = "mysql-root-password" - SecretPassword = "mysql-password" - SecretDatabaseName = "mysql-database" - SecretUser = "mysql-user" - SecretPort = "mysql-port" - SecretHost = "mysql-host" -) diff --git a/internal/controller/trillian/utils/server-deployment.go b/internal/controller/trillian/utils/server-deployment.go index 0abfa1ca9..b52c42644 100644 --- a/internal/controller/trillian/utils/server-deployment.go +++ b/internal/controller/trillian/utils/server-deployment.go @@ -60,7 +60,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_HOSTNAME", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretHost, + Key: actions.SecretHost, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -71,7 +71,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PORT", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPort, + Key: actions.SecretPort, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -105,7 +105,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_USER", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretUser, + Key: actions.SecretUser, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -116,7 +116,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PASSWORD", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPassword, + Key: actions.SecretPassword, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -127,7 +127,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_HOSTNAME", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretHost, + Key: actions.SecretHost, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -138,7 +138,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PORT", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPort, + Key: actions.SecretPort, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -149,7 +149,7 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_DATABASE", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretDatabaseName, + Key: actions.SecretDatabaseName, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, diff --git a/internal/controller/trillian/utils/signer-deployment.go b/internal/controller/trillian/utils/signer-deployment.go index 47eb34ba3..ff3ddfd98 100644 --- a/internal/controller/trillian/utils/signer-deployment.go +++ b/internal/controller/trillian/utils/signer-deployment.go @@ -60,7 +60,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_HOSTNAME", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretHost, + Key: actions.SecretHost, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -71,7 +71,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PORT", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPort, + Key: actions.SecretPort, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -105,7 +105,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_USER", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretUser, + Key: actions.SecretUser, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -116,7 +116,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PASSWORD", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPassword, + Key: actions.SecretPassword, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -127,7 +127,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_HOSTNAME", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretHost, + Key: actions.SecretHost, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -138,7 +138,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_PORT", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPort, + Key: actions.SecretPort, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, @@ -149,7 +149,7 @@ func CreateLogSignerDeployment(ctx context.Context, client client.Client, instan Name: "MYSQL_DATABASE", ValueFrom: &core.EnvVarSource{ SecretKeyRef: &core.SecretKeySelector{ - Key: SecretDatabaseName, + Key: actions.SecretDatabaseName, LocalObjectReference: core.LocalObjectReference{ Name: instance.Status.Db.DatabaseSecretRef.Name, }, diff --git a/internal/controller/trillian/utils/trillian-db.go b/internal/controller/trillian/utils/trillian-db.go deleted file mode 100644 index 57406d69a..000000000 --- a/internal/controller/trillian/utils/trillian-db.go +++ /dev/null @@ -1,186 +0,0 @@ -package trillianUtils - -import ( - "errors" - - "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common/utils" - "github.com/securesign/operator/internal/controller/constants" - apps "k8s.io/api/apps/v1" - core "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func CreateTrillDb(instance *v1alpha1.Trillian, dpName string, sa string, secCont *core.PodSecurityContext, labels map[string]string, useTLS bool) (*apps.Deployment, error) { - if instance.Status.Db.DatabaseSecretRef == nil { - return nil, errors.New("reference to database secret is not set") - } - if instance.Status.Db.Pvc.Name == "" { - return nil, errors.New("reference to database pvc is not set") - } - replicas := int32(1) - readinessProbeCommand := "mariadb -u ${MYSQL_USER} -p${MYSQL_PASSWORD} -e \"SELECT 1;\"" - livenessProbeCommand := "mariadb-admin -u ${MYSQL_USER} -p${MYSQL_PASSWORD} ping" - - args := []string{} - if useTLS { - readinessProbeCommand += " --ssl" - livenessProbeCommand += " --ssl" - args = append(args, "--ssl-cert", "/var/run/secrets/tas/tls.crt") - args = append(args, "--ssl-key", "/var/run/secrets/tas/tls.key") - } - - template := core.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: core.PodSpec{ - ServiceAccountName: sa, - SecurityContext: secCont, - Volumes: []core.Volume{ - { - Name: "storage", - VolumeSource: core.VolumeSource{ - PersistentVolumeClaim: &core.PersistentVolumeClaimVolumeSource{ - ClaimName: instance.Status.Db.Pvc.Name, - }, - }, - }, - }, - Containers: []core.Container{ - { - Command: []string{ - "run-mysqld", - }, - Args: args, - Name: dpName, - Image: constants.TrillianDbImage, - ReadinessProbe: &core.Probe{ - ProbeHandler: core.ProbeHandler{ - Exec: &core.ExecAction{ - Command: []string{ - "bash", - "-c", - readinessProbeCommand, - }, - }, - }, - InitialDelaySeconds: 10, - PeriodSeconds: 10, - TimeoutSeconds: 1, - SuccessThreshold: 1, - FailureThreshold: 3, - }, - LivenessProbe: &core.Probe{ - ProbeHandler: core.ProbeHandler{ - Exec: &core.ExecAction{ - Command: []string{ - "bash", - "-c", - livenessProbeCommand, - }, - }, - }, - InitialDelaySeconds: 30, - TimeoutSeconds: 1, - PeriodSeconds: 10, - SuccessThreshold: 1, - FailureThreshold: 3, - }, - Ports: []core.ContainerPort{ - { - Protocol: core.ProtocolTCP, - ContainerPort: 3306, - }, - }, - // Env variables from secret trillian-mysql - Env: []core.EnvVar{ - { - Name: "MYSQL_USER", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: SecretUser, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PASSWORD", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPassword, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_ROOT_PASSWORD", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: SecretRootPassword, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PORT", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: SecretPort, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_DATABASE", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: SecretDatabaseName, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - }, - VolumeMounts: []core.VolumeMount{ - { - Name: "storage", - MountPath: "/var/lib/mysql", - }, - }, - }, - }, - }, - } - - if err := utils.SetTLS(&template, instance.Status.Db.TLS); err != nil { - return nil, errors.New("could not set TLS: " + err.Error()) - } - - return &apps.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: dpName, - Namespace: instance.Namespace, - Labels: labels, - }, - Spec: apps.DeploymentSpec{ - Replicas: &replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, - }, - Template: template, - Strategy: apps.DeploymentStrategy{ - Type: "Recreate", - }, - }, - }, nil -} From e2501555cf2f413f6e420db395023bd37d0a1861 Mon Sep 17 00:00:00 2001 From: Jan Bouska Date: Mon, 20 Jan 2025 15:11:30 +0100 Subject: [PATCH 2/2] [SECURESIGN-1393] Migrate trillian logserver --- .../common/utils/kubernetes/deployment.go | 10 + .../utils/kubernetes/ensure/deployment.go | 19 +- .../kubernetes/ensure/deployment_test.go | 5 +- .../trillian/actions/db/deployment.go | 25 +- .../trillian/actions/logserver/deployment.go | 86 +++--- .../trillian/actions/logsigner/deployment.go | 60 ++-- .../trillian/utils/server-deployment.go | 265 +++++++----------- .../trillian/utils/signer-deployment.go | 185 ------------ internal/controller/trillian/utils/tls.go | 17 +- 9 files changed, 228 insertions(+), 444 deletions(-) delete mode 100644 internal/controller/trillian/utils/signer-deployment.go diff --git a/internal/controller/common/utils/kubernetes/deployment.go b/internal/controller/common/utils/kubernetes/deployment.go index 161c122d1..9e1c26127 100644 --- a/internal/controller/common/utils/kubernetes/deployment.go +++ b/internal/controller/common/utils/kubernetes/deployment.go @@ -128,6 +128,16 @@ func FindContainerByNameOrCreate(podSpec *corev1.PodSpec, containerName string) return &podSpec.Containers[len(podSpec.Containers)-1] } +func FindInitContainerByNameOrCreate(podSpec *corev1.PodSpec, containerName string) *corev1.Container { + for i, c := range podSpec.InitContainers { + if c.Name == containerName { + return &podSpec.InitContainers[i] + } + } + podSpec.InitContainers = append(podSpec.InitContainers, corev1.Container{Name: containerName}) + return &podSpec.InitContainers[len(podSpec.InitContainers)-1] +} + func FindVolumeByNameOrCreate(podSpec *corev1.PodSpec, volumeName string) *corev1.Volume { for i, v := range podSpec.Volumes { if v.Name == volumeName { diff --git a/internal/controller/common/utils/kubernetes/ensure/deployment.go b/internal/controller/common/utils/kubernetes/ensure/deployment.go index c7f5d58bd..4cb19a159 100644 --- a/internal/controller/common/utils/kubernetes/ensure/deployment.go +++ b/internal/controller/common/utils/kubernetes/ensure/deployment.go @@ -1,6 +1,8 @@ package ensure import ( + "slices" + "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" @@ -11,6 +13,7 @@ import ( const ( CaTrustVolumeName = "ca-trust" TLSVolumeName = "tls-cert" + CATRustMountPath = "/var/run/configs/tas/ca-trust" TLSVolumeMount = "/var/run/secrets/tas" @@ -32,10 +35,10 @@ func TrustedCA(lor *v1alpha1.LocalObjectReference) func(dp *v1.Deployment) error template := &dp.Spec.Template for i := range template.Spec.Containers { env := kubernetes.FindEnvByNameOrCreate(&template.Spec.Containers[i], "SSL_CERT_DIR") - env.Value = "/var/run/configs/tas/ca-trust:/var/run/secrets/kubernetes.io/serviceaccount" + env.Value = CATRustMountPath + ":/var/run/secrets/kubernetes.io/serviceaccount" volumeMount := kubernetes.FindVolumeMountByNameOrCreate(&template.Spec.Containers[i], CaTrustVolumeName) - volumeMount.MountPath = "/var/run/configs/tas/ca-trust" + volumeMount.MountPath = CATRustMountPath volumeMount.ReadOnly = true } @@ -62,14 +65,16 @@ func TrustedCA(lor *v1alpha1.LocalObjectReference) func(dp *v1.Deployment) error } // TLS mount secret with tls cert to all deployment's containers. -func TLS(tls v1alpha1.TLS) func(dp *v1.Deployment) error { +func TLS(tls v1alpha1.TLS, containerNames ...string) func(dp *v1.Deployment) error { return func(dp *v1.Deployment) error { template := &dp.Spec.Template - for i := range template.Spec.Containers { - volumeMount := kubernetes.FindVolumeMountByNameOrCreate(&template.Spec.Containers[i], TLSVolumeName) - volumeMount.MountPath = TLSVolumeMount - volumeMount.ReadOnly = true + for i, c := range template.Spec.Containers { + if slices.Contains(containerNames, c.Name) { + volumeMount := kubernetes.FindVolumeMountByNameOrCreate(&template.Spec.Containers[i], TLSVolumeName) + volumeMount.MountPath = TLSVolumeMount + volumeMount.ReadOnly = true + } } volume := kubernetes.FindVolumeByNameOrCreate(&template.Spec, TLSVolumeName) diff --git a/internal/controller/common/utils/kubernetes/ensure/deployment_test.go b/internal/controller/common/utils/kubernetes/ensure/deployment_test.go index 37b8a681b..b1ff02f64 100644 --- a/internal/controller/common/utils/kubernetes/ensure/deployment_test.go +++ b/internal/controller/common/utils/kubernetes/ensure/deployment_test.go @@ -78,6 +78,7 @@ func TestEnsureTLS(t *testing.T) { Spec: v3.PodSpec{ Containers: []v3.Container{ {Name: name, Image: "test"}, + {Name: "doNotUpdate", Image: "test"}, }, }, }, @@ -100,7 +101,7 @@ func TestEnsureTLS(t *testing.T) { }, Key: "cert", }, - }), + }, name), ) gomega.Expect(err).ToNot(gomega.HaveOccurred()) @@ -113,6 +114,8 @@ func TestEnsureTLS(t *testing.T) { gomega.Expect(existing.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name).To(gomega.Equal(TLSVolumeName)) gomega.Expect(existing.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath).To(gomega.Equal("/var/run/secrets/tas")) + gomega.Expect(existing.Spec.Template.Spec.Containers[1].VolumeMounts).To(gomega.BeEmpty()) + gomega.Expect(existing.Spec.Template.Spec.Volumes).To(gomega.HaveLen(1)) gomega.Expect(existing.Spec.Template.Spec.Volumes[0].Name).To(gomega.Equal(TLSVolumeName)) gomega.Expect(existing.Spec.Template.Spec.Volumes[0].Projected.Sources).To(gomega.HaveLen(2)) diff --git a/internal/controller/trillian/actions/db/deployment.go b/internal/controller/trillian/actions/db/deployment.go index 61afbde31..afed4d9c6 100644 --- a/internal/controller/trillian/actions/db/deployment.go +++ b/internal/controller/trillian/actions/db/deployment.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "slices" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils" @@ -110,7 +111,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli } } -func (i *deployAction) ensureDbDeployment(instance *rhtasv1alpha1.Trillian, sa string, secCont *v1.PodSecurityContext, labels map[string]string) func(deployment *v2.Deployment) error { +func (i deployAction) ensureDbDeployment(instance *rhtasv1alpha1.Trillian, sa string, secCont *v1.PodSecurityContext, labels map[string]string) func(deployment *v2.Deployment) error { return func(dp *v2.Deployment) error { switch { case instance.Status.Db.DatabaseSecretRef == nil: @@ -232,9 +233,9 @@ func (i *deployAction) ensureDbDeployment(instance *rhtasv1alpha1.Trillian, sa s } } -func (i *deployAction) ensureTLS(instance *rhtasv1alpha1.Trillian) func(deployment *v2.Deployment) error { +func (i deployAction) ensureTLS(instance *rhtasv1alpha1.Trillian) func(deployment *v2.Deployment) error { return func(dp *v2.Deployment) error { - if err := ensure.TLS(instance.Status.Db.TLS)(dp); err != nil { + if err := ensure.TLS(instance.Status.Db.TLS, actions.DbDeploymentName)(dp); err != nil { return err } @@ -258,9 +259,23 @@ func (i *deployAction) ensureTLS(instance *rhtasv1alpha1.Trillian) func(deployme container.LivenessProbe.Exec.Command = []string{"bash", "-c", livenessCommand + " --ssl"} - container.Args = append(container.Args, "--ssl-cert", ensure.TLSCertPath) - container.Args = append(container.Args, "--ssl-key", ensure.TLSKeyPath) + if i := slices.Index(container.Args, "--ssl-cert"); i == -1 { + container.Args = append(container.Args, "--ssl-cert", ensure.TLSCertPath) + } else { + if len(container.Args)-1 < i+1 { + container.Args = append(container.Args, ensure.TLSCertPath) + } + container.Args[i+1] = ensure.TLSCertPath + } + if i := slices.Index(container.Args, "--ssl-key"); i == -1 { + container.Args = append(container.Args, "--ssl-key", ensure.TLSKeyPath) + } else { + if len(container.Args)-1 < i+1 { + container.Args = append(container.Args, ensure.TLSKeyPath) + } + container.Args[i+1] = ensure.TLSKeyPath + } return nil } } diff --git a/internal/controller/trillian/actions/logserver/deployment.go b/internal/controller/trillian/actions/logserver/deployment.go index cb3e0d547..37f74549c 100644 --- a/internal/controller/trillian/actions/logserver/deployment.go +++ b/internal/controller/trillian/actions/logserver/deployment.go @@ -6,10 +6,14 @@ import ( "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/labels" "github.com/securesign/operator/internal/controller/trillian/actions" trillianUtils "github.com/securesign/operator/internal/controller/trillian/utils" + "golang.org/x/exp/maps" + apps "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -36,60 +40,40 @@ func (i deployAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Trill func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trillian) *action.Result { var ( - err error - updated bool + err error + result controllerutil.OperationResult ) labels := labels.For(actions.LogServerComponentName, actions.LogserverDeploymentName, instance.Name) - server, err := trillianUtils.CreateLogServerDeployment(ctx, i.Client, instance, constants.TrillianServerImage, actions.LogserverDeploymentName, actions.RBACName, labels) - if err != nil { - return i.Failed(err) - } - - caTrustRef := utils.TrustedCAAnnotationToReference(instance.Annotations) - // override if spec.trustedCA is defined - if instance.Spec.TrustedCA != nil { - caTrustRef = instance.Spec.TrustedCA - } - err = utils.SetTrustedCA(&server.Spec.Template, caTrustRef) - - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.ServerCondition, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian server: %w", err), instance) - } + insCopy := instance.DeepCopy() - if err = controllerutil.SetControllerReference(instance, server, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for server: %w", err)) + if insCopy.Spec.TrustedCA == nil { + insCopy.Spec.TrustedCA = utils.TrustedCAAnnotationToReference(instance.Annotations) } - if updated, err = i.Ensure(ctx, server); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + if result, err = kubernetes.CreateOrUpdate(ctx, i.Client, + &apps.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: actions.LogserverDeploymentName, + Namespace: instance.Namespace, + }, + }, + trillianUtils.EnsureServerDeployment(insCopy, constants.TrillianServerImage, actions.LogserverDeploymentName, actions.RBACName, labels), + ensure.ControllerReference[*apps.Deployment](insCopy, i.Client), + ensure.Labels[*apps.Deployment](maps.Keys(labels), labels), + ensure.Proxy(), + ensure.TrustedCA(insCopy.Spec.TrustedCA), + ensure.Optional(trillianUtils.UseTLS(insCopy), i.withTlsDB(ctx, insCopy)), + ); err != nil { + return i.Error(ctx, fmt.Errorf("could not create Trillian server: %w", err), instance, metav1.Condition{ Type: actions.ServerCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian server: %w", err), instance) } - if updated { + if result != controllerutil.OperationResultNone { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, Status: metav1.ConditionFalse, @@ -101,3 +85,23 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli return i.Continue() } } + +func (i deployAction) withTlsDB(ctx context.Context, instance *rhtasv1alpha1.Trillian) func(deployment *apps.Deployment) error { + return func(dp *apps.Deployment) error { + caPath, err := trillianUtils.CAPath(ctx, i.Client, instance) + if err != nil { + return fmt.Errorf("failed to get CA path: %w", err) + } + + c := kubernetes.FindContainerByNameOrCreate(&dp.Spec.Template.Spec, actions.LogserverDeploymentName) + c.Args = append(c.Args, "--mysql_tls_ca", caPath) + + mysqlServerName := "$(MYSQL_HOSTNAME)." + instance.Namespace + ".svc" + if !*instance.Spec.Db.Create { + mysqlServerName = "$(MYSQL_HOSTNAME)" + } + c.Args = append(c.Args, "--mysql_server_name", mysqlServerName) + return nil + } + +} diff --git a/internal/controller/trillian/actions/logsigner/deployment.go b/internal/controller/trillian/actions/logsigner/deployment.go index cc70dd702..fe173e046 100644 --- a/internal/controller/trillian/actions/logsigner/deployment.go +++ b/internal/controller/trillian/actions/logsigner/deployment.go @@ -6,10 +6,14 @@ import ( "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/labels" "github.com/securesign/operator/internal/controller/trillian/actions" trillianUtils "github.com/securesign/operator/internal/controller/trillian/utils" + "golang.org/x/exp/maps" + apps "k8s.io/api/apps/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -36,62 +40,40 @@ func (i deployAction) CanHandle(_ context.Context, instance *rhtasv1alpha1.Trill func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trillian) *action.Result { var ( - err error - updated bool + err error + result controllerutil.OperationResult ) labels := labels.For(actions.LogSignerComponentName, actions.LogsignerDeploymentName, instance.Name) - signer, err := trillianUtils.CreateLogServerDeployment(ctx, i.Client, instance, constants.TrillianLogSignerImage, actions.LogsignerDeploymentName, actions.RBACName, labels) - if err != nil { - return i.Failed(err) - } - - signer.Spec.Template.Spec.Containers[0].Args = append(signer.Spec.Template.Spec.Containers[0].Args, "--force_master=true") caTrustRef := utils.TrustedCAAnnotationToReference(instance.Annotations) // override if spec.trustedCA is defined if instance.Spec.TrustedCA != nil { caTrustRef = instance.Spec.TrustedCA } - err = utils.SetTrustedCA(&signer.Spec.Template, caTrustRef) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + if result, err = kubernetes.CreateOrUpdate(ctx, i.Client, + &apps.Deployment{ + ObjectMeta: metav1.ObjectMeta{ + Name: actions.LogsignerDeploymentName, + Namespace: instance.Namespace, + }, + }, + trillianUtils.EnsureServerDeployment(instance, constants.TrillianLogSignerImage, actions.LogsignerDeploymentName, actions.RBACName, labels, "--force_master=true"), + ensure.ControllerReference[*apps.Deployment](instance, i.Client), + ensure.Labels[*apps.Deployment](maps.Keys(labels), labels), + ensure.Proxy(), + ensure.TrustedCA(caTrustRef), + ); err != nil { + return i.Error(ctx, fmt.Errorf("could not create Trillian LogSigner: %w", err), instance, metav1.Condition{ Type: actions.SignerCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian LogSigner: %w", err), instance) - } - - if err = controllerutil.SetControllerReference(instance, signer, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for LogSigner deployment: %w", err)) - } - - if updated, err = i.Ensure(ctx, signer); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.SignerCondition, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian LogSigner deployment: %w", err), instance) } - if updated { + if result != controllerutil.OperationResultNone { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.SignerCondition, Status: metav1.ConditionFalse, diff --git a/internal/controller/trillian/utils/server-deployment.go b/internal/controller/trillian/utils/server-deployment.go index b52c42644..d6ab91cab 100644 --- a/internal/controller/trillian/utils/server-deployment.go +++ b/internal/controller/trillian/utils/server-deployment.go @@ -1,185 +1,136 @@ package trillianUtils import ( - "context" "errors" "strconv" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/trillian/actions" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" ) -func CreateLogServerDeployment(ctx context.Context, client client.Client, instance *v1alpha1.Trillian, image string, dpName string, sa string, labels map[string]string) (*apps.Deployment, error) { - if instance.Status.Db.DatabaseSecretRef == nil { - return nil, errors.New("reference to database secret is not set") - } - replicas := int32(1) - containerPorts := []core.ContainerPort{ - { - Protocol: core.ProtocolTCP, - ContainerPort: 8091, - }, - } +func EnsureServerDeployment(instance *v1alpha1.Trillian, image string, name string, sa string, labels map[string]string, args ...string) func(deployment *apps.Deployment) error { + return func(dp *apps.Deployment) error { + if instance.Status.Db.DatabaseSecretRef == nil { + return errors.New("reference to database secret is not set") + } - if instance.Spec.Monitoring.Enabled { - containerPorts = append(containerPorts, core.ContainerPort{ - Protocol: core.ProtocolTCP, - ContainerPort: 8090, - }) - } + spec := &dp.Spec + spec.Replicas = utils.Pointer[int32](1) + spec.Selector = &metav1.LabelSelector{ + MatchLabels: labels, + } - dep := &apps.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: dpName, - Namespace: instance.Namespace, - Labels: labels, - }, - Spec: apps.DeploymentSpec{ - Replicas: &replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, + template := &spec.Template + template.Labels = labels + template.Spec.ServiceAccountName = sa + + initContainer := kubernetes.FindInitContainerByNameOrCreate(&template.Spec, "wait-for-trillian-db") + initContainer.Image = constants.TrillianNetcatImage + + hostnameEnv := kubernetes.FindEnvByNameOrCreate(initContainer, "MYSQL_HOSTNAME") + hostnameEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretHost, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, }, - Template: core.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, + } + + portEnv := kubernetes.FindEnvByNameOrCreate(initContainer, "MYSQL_PORT") + portEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretPort, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, }, - Spec: core.PodSpec{ - ServiceAccountName: sa, - InitContainers: []core.Container{ - { - Name: "wait-for-trillian-db", - Image: constants.TrillianNetcatImage, - Env: []core.EnvVar{ - { - Name: "MYSQL_HOSTNAME", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretHost, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PORT", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPort, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - }, - Command: []string{ - "sh", - "-c", - "until nc -z -v -w30 $MYSQL_HOSTNAME $MYSQL_PORT; do echo \"Waiting for MySQL to start\"; sleep 5; done;", - }, - }, - }, - Containers: []core.Container{ - { - Args: []string{ - "--storage_system=mysql", - "--quota_system=mysql", - "--mysql_uri=$(MYSQL_USER):$(MYSQL_PASSWORD)@tcp($(MYSQL_HOSTNAME):$(MYSQL_PORT))/$(MYSQL_DATABASE)", - "--rpc_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.ServerPort)), - "--http_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.MetricsPort)), - "--alsologtostderr", - }, - Name: dpName, - Image: image, - Ports: containerPorts, - // Env variables from secret trillian-mysql - Env: []core.EnvVar{ - { - Name: "MYSQL_USER", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretUser, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PASSWORD", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPassword, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_HOSTNAME", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretHost, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PORT", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPort, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_DATABASE", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretDatabaseName, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - }, - }, - }, + }, + } + initContainer.Command = []string{ + "sh", + "-c", + "until nc -z -v -w30 $MYSQL_HOSTNAME $MYSQL_PORT; do echo \"Waiting for MySQL to start\"; sleep 5; done;", + } + + container := kubernetes.FindContainerByNameOrCreate(&template.Spec, name) + container.Image = image + + container.Args = append([]string{ + "--storage_system=mysql", + "--quota_system=mysql", + "--mysql_uri=$(MYSQL_USER):$(MYSQL_PASSWORD)@tcp($(MYSQL_HOSTNAME):$(MYSQL_PORT))/$(MYSQL_DATABASE)", + "--rpc_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.ServerPort)), + "--http_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.MetricsPort)), + "--alsologtostderr", + }, args...) + + //Ports = containerPorts + // Env variables from secret trillian-mysql + userEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_USER") + userEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretUser, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, }, }, - }, - } + } + + passwordEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_PASSWORD") + passwordEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretPassword, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + hostEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_HOSTNAME") + hostEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretHost, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } + + containerPortEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_PORT") + containerPortEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretPort, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, + } - // TLS communication to database - if UseTLS(instance) { - caPath, err := CAPath(ctx, client, instance) - if err != nil { - return nil, errors.New("failed to get CA path: " + err.Error()) + dbEnv := kubernetes.FindEnvByNameOrCreate(container, "MYSQL_DATABASE") + dbEnv.ValueFrom = &core.EnvVarSource{ + SecretKeyRef: &core.SecretKeySelector{ + Key: actions.SecretDatabaseName, + LocalObjectReference: core.LocalObjectReference{ + Name: instance.Status.Db.DatabaseSecretRef.Name, + }, + }, } - dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--mysql_tls_ca", caPath) + port := kubernetes.FindPortByNameOrCreate(container, "8091-tcp") + port.ContainerPort = 8091 + port.Protocol = core.ProtocolTCP - mysqlServerName := "$(MYSQL_HOSTNAME)." + instance.Namespace + ".svc" - if !*instance.Spec.Db.Create { - mysqlServerName = "$(MYSQL_HOSTNAME)" + if instance.Spec.Monitoring.Enabled { + monitoring := kubernetes.FindPortByNameOrCreate(container, "monitoring") + monitoring.ContainerPort = 8090 + monitoring.Protocol = core.ProtocolTCP } - dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--mysql_server_name", mysqlServerName) + return nil } - - utils.SetProxyEnvs(dep) - return dep, nil } diff --git a/internal/controller/trillian/utils/signer-deployment.go b/internal/controller/trillian/utils/signer-deployment.go deleted file mode 100644 index ff3ddfd98..000000000 --- a/internal/controller/trillian/utils/signer-deployment.go +++ /dev/null @@ -1,185 +0,0 @@ -package trillianUtils - -import ( - "context" - "errors" - "strconv" - - "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common/utils" - "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/trillian/actions" - apps "k8s.io/api/apps/v1" - core "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "sigs.k8s.io/controller-runtime/pkg/client" -) - -func CreateLogSignerDeployment(ctx context.Context, client client.Client, instance *v1alpha1.Trillian, image string, dpName string, sa string, labels map[string]string) (*apps.Deployment, error) { - if instance.Status.Db.DatabaseSecretRef == nil { - return nil, errors.New("reference to database secret is not set") - } - replicas := int32(1) - containerPorts := []core.ContainerPort{ - { - Protocol: core.ProtocolTCP, - ContainerPort: 8091, - }, - } - - if instance.Spec.Monitoring.Enabled { - containerPorts = append(containerPorts, core.ContainerPort{ - Protocol: core.ProtocolTCP, - ContainerPort: 8090, - }) - } - - dep := &apps.Deployment{ - ObjectMeta: metav1.ObjectMeta{ - Name: dpName, - Namespace: instance.Namespace, - Labels: labels, - }, - Spec: apps.DeploymentSpec{ - Replicas: &replicas, - Selector: &metav1.LabelSelector{ - MatchLabels: labels, - }, - Template: core.PodTemplateSpec{ - ObjectMeta: metav1.ObjectMeta{ - Labels: labels, - }, - Spec: core.PodSpec{ - ServiceAccountName: sa, - InitContainers: []core.Container{ - { - Name: "wait-for-trillian-db", - Image: constants.TrillianNetcatImage, - Env: []core.EnvVar{ - { - Name: "MYSQL_HOSTNAME", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretHost, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PORT", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPort, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - }, - Command: []string{ - "sh", - "-c", - "until nc -z -v -w30 $MYSQL_HOSTNAME $MYSQL_PORT; do echo \"Waiting for MySQL to start\"; sleep 5; done;", - }, - }, - }, - Containers: []core.Container{ - { - Args: []string{ - "--storage_system=mysql", - "--quota_system=mysql", - "--mysql_uri=$(MYSQL_USER):$(MYSQL_PASSWORD)@tcp($(MYSQL_HOSTNAME):$(MYSQL_PORT))/$(MYSQL_DATABASE)", - "--rpc_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.ServerPort)), - "--http_endpoint=0.0.0.0:" + strconv.Itoa(int(actions.MetricsPort)), - "--alsologtostderr", - }, - Name: dpName, - Image: image, - Ports: containerPorts, - // Env variables from secret trillian-mysql - Env: []core.EnvVar{ - { - Name: "MYSQL_USER", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretUser, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PASSWORD", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPassword, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_HOSTNAME", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretHost, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_PORT", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretPort, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - { - Name: "MYSQL_DATABASE", - ValueFrom: &core.EnvVarSource{ - SecretKeyRef: &core.SecretKeySelector{ - Key: actions.SecretDatabaseName, - LocalObjectReference: core.LocalObjectReference{ - Name: instance.Status.Db.DatabaseSecretRef.Name, - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - - // TLS communication to database - if UseTLS(instance) { - caPath, err := CAPath(ctx, client, instance) - if err != nil { - return nil, errors.New("failed to get CA path: " + err.Error()) - } - - dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--mysql_tls_ca", caPath) - - mysqlServerName := "$(MYSQL_HOSTNAME)." + instance.Namespace + ".svc" - if !*instance.Spec.Db.Create { - mysqlServerName = "$(MYSQL_HOSTNAME)" - } - dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--mysql_server_name", mysqlServerName) - } - - utils.SetProxyEnvs(dep) - return dep, nil -} diff --git a/internal/controller/trillian/utils/tls.go b/internal/controller/trillian/utils/tls.go index 99b609b65..878cd45f6 100644 --- a/internal/controller/trillian/utils/tls.go +++ b/internal/controller/trillian/utils/tls.go @@ -7,6 +7,8 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes/ensure" + "golang.org/x/exp/maps" "sigs.k8s.io/controller-runtime/pkg/client" ) @@ -30,7 +32,8 @@ func UseTLS(instance *rhtasv1alpha1.Trillian) bool { } func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.Trillian) (string, error) { - if instance.Spec.TrustedCA != nil { + switch { + case instance.Spec.TrustedCA != nil: cfgTrust, err := kubernetes.GetConfigMap(ctx, cli, instance.Namespace, instance.Spec.TrustedCA.Name) if err != nil { return "", err @@ -39,14 +42,10 @@ func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.Tril err = fmt.Errorf("%s ConfigMap can contain only 1 record", instance.Spec.TrustedCA.Name) return "", err } - for key := range cfgTrust.Data { - return "/var/run/configs/tas/ca-trust/" + key, nil - } - } - - if instance.Spec.TrustedCA == nil && kubernetes.IsOpenShift() { + return ensure.CATRustMountPath + maps.Keys(cfgTrust.Data)[0], nil + case kubernetes.IsOpenShift(): return "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt", nil + default: + return "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", nil } - - return "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", nil }