diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index 301334fe4..d78b63929 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -45,7 +45,6 @@ type CtlogService struct { // Port of Ctlog Log Server End point //+kubebuilder:validation:Minimum:=1 //+kubebuilder:validation:Maximum:=65535 - //+kubebuilder:default:=80 //+optional Port *int32 `json:"port,omitempty"` // Prefix is the name of the log. The prefix cannot be empty and can diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 04a559038..9d03fb5e9 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -48,6 +48,9 @@ type CTlogSpec struct { // publicKeyRef, rootCertificates and trillian will be overridden. //+optional ServerConfigRef *LocalObjectReference `json:"serverConfigRef,omitempty"` + // Configuration for enabling TLS (Transport Layer Security) encryption for CTlog. + //+optional + TLS TLS `json:"tls,omitempty"` } // CTlogStatus defines the observed state of CTlog component @@ -57,6 +60,7 @@ type CTlogStatus struct { PrivateKeyPasswordRef *SecretKeySelector `json:"privateKeyPasswordRef,omitempty"` PublicKeyRef *SecretKeySelector `json:"publicKeyRef,omitempty"` RootCertificates []SecretKeySelector `json:"rootCertificates,omitempty"` + TLS TLS `json:"tls,omitempty"` // The ID of a Trillian tree that stores the log data. TreeID *int64 `json:"treeID,omitempty"` // +listType=map diff --git a/api/v1alpha1/fulcio_types.go b/api/v1alpha1/fulcio_types.go index b9e05dec4..b5fc53163 100644 --- a/api/v1alpha1/fulcio_types.go +++ b/api/v1alpha1/fulcio_types.go @@ -14,7 +14,7 @@ type FulcioSpec struct { ExternalAccess ExternalAccess `json:"externalAccess,omitempty"` // Ctlog service configuration //+optional - //+kubebuilder:default:={port: 80, prefix: trusted-artifact-signer} + //+kubebuilder:default:={prefix: trusted-artifact-signer} Ctlog CtlogService `json:"ctlog,omitempty"` // Fulcio Configuration //+required diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index c22c5ddad..6b6005505 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -167,6 +167,7 @@ func (in *CTlogSpec) DeepCopyInto(out *CTlogSpec) { *out = new(LocalObjectReference) **out = **in } + in.TLS.DeepCopyInto(&out.TLS) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CTlogSpec. @@ -207,6 +208,7 @@ func (in *CTlogStatus) DeepCopyInto(out *CTlogStatus) { *out = make([]SecretKeySelector, len(*in)) copy(*out, *in) } + in.TLS.DeepCopyInto(&out.TLS) if in.TreeID != nil { in, out := &in.TreeID, &out.TreeID *out = new(int64) diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index 2d895b4d4..06eb08dbd 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -297,7 +297,7 @@ metadata: ] capabilities: Seamless Upgrades containerImage: registry.redhat.io/rhtas/rhtas-rhel9-operator@sha256:028b6eec7f821b18cf710237a7613ef76d2bacdeff56462368e4e186f26627cc - createdAt: "2024-09-11T13:45:32Z" + createdAt: "2024-09-16T09:07:25Z" features.operators.openshift.io/cnf: "false" features.operators.openshift.io/cni: "false" features.operators.openshift.io/csi: "false" diff --git a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 3faa3285f..0be687d4e 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -152,6 +152,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for CTlog. + properties: + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -343,6 +389,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: TLS (Transport Layer Security) Configuration for enabling + service encryption. + properties: + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: The ID of a Trillian tree that stores the log data. format: int64 diff --git a/bundle/manifests/rhtas.redhat.com_fulcios.yaml b/bundle/manifests/rhtas.redhat.com_fulcios.yaml index 118bea8b2..f949883cd 100644 --- a/bundle/manifests/rhtas.redhat.com_fulcios.yaml +++ b/bundle/manifests/rhtas.redhat.com_fulcios.yaml @@ -223,7 +223,6 @@ spec: (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -231,7 +230,6 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index e09499ed1..eeb880259 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -168,6 +168,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for CTlog. + properties: + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for + TLS encryption. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -375,7 +421,6 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -383,7 +428,6 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index 71a3e21c8..1560534b2 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -152,6 +152,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for CTlog. + properties: + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -343,6 +389,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: TLS (Transport Layer Security) Configuration for enabling + service encryption. + properties: + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for TLS + encryption. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: The ID of a Trillian tree that stores the log data. format: int64 diff --git a/config/crd/bases/rhtas.redhat.com_fulcios.yaml b/config/crd/bases/rhtas.redhat.com_fulcios.yaml index 00f495721..6643f450e 100644 --- a/config/crd/bases/rhtas.redhat.com_fulcios.yaml +++ b/config/crd/bases/rhtas.redhat.com_fulcios.yaml @@ -223,7 +223,6 @@ spec: (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -231,7 +230,6 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index d42cb6dcb..79bd6a6d8 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -168,6 +168,52 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for CTlog. + properties: + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + privateKeyRef: + description: Reference to the private key secret used for + TLS encryption. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + pattern: ^[-._a-zA-Z0-9]+$ + type: string + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - key + - name + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: privateKeyRef cannot be empty + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -375,7 +421,6 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -383,7 +428,6 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 diff --git a/internal/controller/common/utils/kubernetes/service.go b/internal/controller/common/utils/kubernetes/service.go index 1a68b549d..1c50fa953 100644 --- a/internal/controller/common/utils/kubernetes/service.go +++ b/internal/controller/common/utils/kubernetes/service.go @@ -2,14 +2,14 @@ package kubernetes import ( "context" - "fmt" + "errors" corev1 "k8s.io/api/core/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/types" - "sigs.k8s.io/controller-runtime/pkg/client" - + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" ) func CreateService(namespace string, name string, portName string, port int, targetPort int32, labels map[string]string) *corev1.Service { @@ -33,21 +33,25 @@ func CreateService(namespace string, name string, portName string, port int, tar } } -func GetInternalUrl(ctx context.Context, cli client.Client, namespace, serviceName string) (string, error) { - svc := &corev1.Service{ - ObjectMeta: metav1.ObjectMeta{ - Name: serviceName, - Namespace: namespace, - }, - } +func FindService(ctx context.Context, c client.Client, namespace string, labels map[string]string) (*corev1.Service, error) { + + list := &corev1.ServiceList{} - err := cli.Get(ctx, types.NamespacedName{ - Name: serviceName, - Namespace: namespace, - }, svc) + err := c.List(ctx, list, client.InNamespace(namespace), client.MatchingLabels(labels)) if err != nil { - return "", err + return nil, err + } + if len(list.Items) > 1 { + return nil, errors.New("duplicate resource") } - return fmt.Sprintf("%s.%s.svc.cluster.local", svc.Name, svc.Namespace), nil + + if len(list.Items) == 1 { + return &list.Items[0], nil + } + + return nil, apierrors.NewNotFound(schema.GroupResource{ + Group: list.GetObjectKind().GroupVersionKind().Group, + Resource: list.GetObjectKind().GroupVersionKind().Kind, + }, "") } diff --git a/internal/controller/ctlog/actions/deployment.go b/internal/controller/ctlog/actions/deployment.go index ad6462398..32efd2789 100644 --- a/internal/controller/ctlog/actions/deployment.go +++ b/internal/controller/ctlog/actions/deployment.go @@ -4,11 +4,12 @@ import ( "context" "fmt" - cutils "github.com/securesign/operator/internal/controller/common/utils" - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/action" + cutils "github.com/securesign/operator/internal/controller/common/utils" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" "k8s.io/apimachinery/pkg/api/meta" @@ -39,14 +40,33 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) err error ) - labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) + // TLS + switch { + case instance.Spec.TLS.CertRef != nil: + instance.Status.TLS = instance.Spec.TLS + case kubernetes.IsOpenShift(): + instance.Status.TLS = rhtasv1alpha1.TLS{ + CertRef: &rhtasv1alpha1.SecretKeySelector{ + LocalObjectReference: rhtasv1alpha1.LocalObjectReference{Name: instance.Name + "-ctlog-tls"}, + Key: "tls.crt", + }, + PrivateKeyRef: &rhtasv1alpha1.SecretKeySelector{ + LocalObjectReference: rhtasv1alpha1.LocalObjectReference{Name: instance.Name + "-ctlog-tls"}, + Key: "tls.key", + }, + } + default: + i.Logger.V(1).Info("Communication to trillian log server is insecure") + } + + labels := constants.LabelsFor(constants2.ComponentName, constants2.DeploymentName, instance.Name) switch { case instance.Spec.Trillian.Address == "": instance.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", trillian.LogserverDeploymentName, instance.Namespace) } - dp, err := utils.CreateDeployment(instance, DeploymentName, RBACName, labels, ServerTargetPort, MetricsPort) + dp, err := utils.CreateDeployment(instance, constants2.DeploymentName, constants2.RBACName, labels, constants2.ServerTargetPort, constants2.MetricsPort) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: constants.Ready, diff --git a/internal/controller/ctlog/actions/handle_fulcio_root.go b/internal/controller/ctlog/actions/handle_fulcio_root.go index 672d61a8c..ca710d771 100644 --- a/internal/controller/ctlog/actions/handle_fulcio_root.go +++ b/internal/controller/ctlog/actions/handle_fulcio_root.go @@ -8,6 +8,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/internal/controller/fulcio/actions" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -75,7 +76,7 @@ func (g handleFulcioCert) Handle(ctx context.Context, instance *v1alpha1.CTlog) } meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CertCondition, + Type: constants2.CertCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: "Cert not found", @@ -111,7 +112,7 @@ func (g handleFulcioCert) Handle(ctx context.Context, instance *v1alpha1.CTlog) } meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CertCondition, + Type: constants2.CertCondition, Status: metav1.ConditionTrue, Reason: "Resolved", }, diff --git a/internal/controller/ctlog/actions/handle_fulcio_root_test.go b/internal/controller/ctlog/actions/handle_fulcio_root_test.go index 33c522d68..899a57c94 100644 --- a/internal/controller/ctlog/actions/handle_fulcio_root_test.go +++ b/internal/controller/ctlog/actions/handle_fulcio_root_test.go @@ -4,6 +4,7 @@ import ( "context" "testing" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" testAction "github.com/securesign/operator/internal/testing/action" . "github.com/onsi/gomega" @@ -58,7 +59,7 @@ func Test_HandleFulcioCert_Autodiscover(t *testing.T) { g.Expect(i.Status.RootCertificates[0].Key).Should(Equal("key")) g.Expect(i.Status.RootCertificates[0].Name).Should(Equal("secret")) - g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, CertCondition)).To(BeTrue()) + g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, constants2.CertCondition)).To(BeTrue()) } func Test_HandleFulcioCert_Empty(t *testing.T) { @@ -150,7 +151,7 @@ func Test_HandleFulcioCert_Configured(t *testing.T) { g.Expect(i.Status.RootCertificates[1].Key).Should(Equal("key")) g.Expect(i.Status.RootCertificates[1].Name).Should(Equal("secret-2")) - g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, CertCondition)).To(BeTrue()) + g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, constants2.CertCondition)).To(BeTrue()) } func Test_HandleFulcioCert_Configured_Priority(t *testing.T) { @@ -201,7 +202,7 @@ func Test_HandleFulcioCert_Configured_Priority(t *testing.T) { g.Expect(i.Status.RootCertificates[0].Key).Should(Equal("key")) g.Expect(i.Status.RootCertificates[0].Name).Should(Equal("my-secret")) - g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, CertCondition)).To(BeTrue()) + g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, constants2.CertCondition)).To(BeTrue()) } func Test_HandleFulcioCert_Delete_ServerConfig(t *testing.T) { @@ -246,7 +247,7 @@ func Test_HandleFulcioCert_Delete_ServerConfig(t *testing.T) { g.Expect(a.CanHandle(context.TODO(), i)).To(BeTrue()) _ = a.Handle(context.TODO(), i) - g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, CertCondition)).To(BeTrue()) + g.Expect(meta.IsStatusConditionTrue(i.Status.Conditions, constants2.CertCondition)).To(BeTrue()) g.Expect(i.Status.ServerConfigRef).To(BeNil()) g.Expect(c.Get(context.TODO(), types.NamespacedName{Name: "ctlog-config", Namespace: instance.GetNamespace()}, &v1.Secret{})).To(HaveOccurred()) diff --git a/internal/controller/ctlog/actions/handle_keys.go b/internal/controller/ctlog/actions/handle_keys.go index 9e655e476..09e17e2de 100644 --- a/internal/controller/ctlog/actions/handle_keys.go +++ b/internal/controller/ctlog/actions/handle_keys.go @@ -8,6 +8,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" @@ -107,8 +108,8 @@ func (g handleKeys) Handle(ctx context.Context, instance *v1alpha1.CTlog) *actio data = map[string][]byte{"public": config.PublicKey} } - labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) - labels[CTLPubLabel] = "public" + labels := constants.LabelsFor(constants2.ComponentName, constants2.DeploymentName, instance.Name) + labels[constants2.CTLPubLabel] = "public" secret := k8sutils.CreateImmutableSecret(fmt.Sprintf(KeySecretNameFormat, instance.Name), instance.Namespace, data, labels) @@ -117,7 +118,7 @@ func (g handleKeys) Handle(ctx context.Context, instance *v1alpha1.CTlog) *actio } // ensure that only new key is exposed - if err := g.Client.DeleteAllOf(ctx, &v1.Secret{}, client.InNamespace(instance.Namespace), client.MatchingLabels(constants.LabelsFor(ComponentName, DeploymentName, instance.Name)), client.HasLabels{CTLPubLabel}); err != nil { + if err := g.Client.DeleteAllOf(ctx, &v1.Secret{}, client.InNamespace(instance.Namespace), client.MatchingLabels(constants.LabelsFor(constants2.ComponentName, constants2.DeploymentName, instance.Name)), client.HasLabels{constants2.CTLPubLabel}); err != nil { return g.Failed(err) } diff --git a/internal/controller/ctlog/actions/initialize.go b/internal/controller/ctlog/actions/initialize.go index 48510d43c..150f7dbf3 100644 --- a/internal/controller/ctlog/actions/initialize.go +++ b/internal/controller/ctlog/actions/initialize.go @@ -8,6 +8,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" commonUtils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -34,7 +35,7 @@ func (i initializeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CT ok bool err error ) - labels := constants.LabelsForComponent(ComponentName, instance.Name) + labels := constants.LabelsForComponent(constants2.ComponentName, instance.Name) ok, err = commonUtils.DeploymentIsRunning(ctx, i.Client, instance.Namespace, labels) switch { case errors.Is(err, commonUtils.ErrDeploymentNotReady): diff --git a/internal/controller/ctlog/actions/monitoring.go b/internal/controller/ctlog/actions/monitoring.go index 4e60affa7..3f36c5f6b 100644 --- a/internal/controller/ctlog/actions/monitoring.go +++ b/internal/controller/ctlog/actions/monitoring.go @@ -9,6 +9,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" v1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -37,11 +38,11 @@ func (i monitoringAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CT err error ) - monitoringLabels := constants.LabelsFor(ComponentName, MonitoringRoleName, instance.Name) + monitoringLabels := constants.LabelsFor(constants2.ComponentName, constants2.MonitoringRoleName, instance.Name) role := kubernetes.CreateRole( instance.Namespace, - MonitoringRoleName, + constants2.MonitoringRoleName, monitoringLabels, []v1.PolicyRule{ { @@ -68,12 +69,12 @@ func (i monitoringAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CT roleBinding := kubernetes.CreateRoleBinding( instance.Namespace, - MonitoringRoleName, + constants2.MonitoringRoleName, monitoringLabels, v1.RoleRef{ APIGroup: v1.SchemeGroupVersion.Group, Kind: "Role", - Name: MonitoringRoleName, + Name: constants2.MonitoringRoleName, }, []v1.Subject{ {Kind: "ServiceAccount", Name: "prometheus-k8s", Namespace: "openshift-monitoring"}, @@ -95,16 +96,16 @@ func (i monitoringAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CT serviceMonitor := kubernetes.CreateServiceMonitor( instance.Namespace, - DeploymentName, + constants2.DeploymentName, monitoringLabels, []monitoringv1.Endpoint{ { Interval: monitoringv1.Duration("30s"), - Port: MetricsPortName, + Port: constants2.MetricsPortName, Scheme: "http", }, }, - constants.LabelsForComponent(ComponentName, instance.Name), + constants.LabelsForComponent(constants2.ComponentName, instance.Name), ) if err = controllerutil.SetControllerReference(instance, serviceMonitor, i.Client.Scheme()); err != nil { diff --git a/internal/controller/ctlog/actions/rbac.go b/internal/controller/ctlog/actions/rbac.go index b5d0028e3..4d1a1461f 100644 --- a/internal/controller/ctlog/actions/rbac.go +++ b/internal/controller/ctlog/actions/rbac.go @@ -8,6 +8,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" v1 "k8s.io/api/core/v1" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -36,11 +37,11 @@ func (i rbacAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) * var ( err error ) - labels := constants.LabelsFor(ComponentName, RBACName, instance.Name) + labels := constants.LabelsFor(constants2.ComponentName, constants2.RBACName, instance.Name) sa := &v1.ServiceAccount{ ObjectMeta: metav1.ObjectMeta{ - Name: RBACName, + Name: constants2.RBACName, Namespace: instance.Namespace, Labels: labels, }, @@ -60,7 +61,7 @@ func (i rbacAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) * }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create SA: %w", err), instance) } - role := kubernetes.CreateRole(instance.Namespace, RBACName, labels, []rbacv1.PolicyRule{ + role := kubernetes.CreateRole(instance.Namespace, constants2.RBACName, labels, []rbacv1.PolicyRule{ { APIGroups: []string{""}, Resources: []string{"configmaps"}, @@ -86,13 +87,13 @@ func (i rbacAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) * }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Role: %w", err), instance) } - rb := kubernetes.CreateRoleBinding(instance.Namespace, RBACName, labels, rbacv1.RoleRef{ + rb := kubernetes.CreateRoleBinding(instance.Namespace, constants2.RBACName, labels, rbacv1.RoleRef{ APIGroup: v1.SchemeGroupVersion.Group, Kind: "Role", - Name: RBACName, + Name: constants2.RBACName, }, []rbacv1.Subject{ - {Kind: "ServiceAccount", Name: RBACName, Namespace: instance.Namespace}, + {Kind: "ServiceAccount", Name: constants2.RBACName, Namespace: instance.Namespace}, }) if err = ctrl.SetControllerReference(instance, rb, i.Client.Scheme()); err != nil { diff --git a/internal/controller/ctlog/actions/resolve_tree.go b/internal/controller/ctlog/actions/resolve_tree.go index 0c885551a..d7cf6a3a2 100644 --- a/internal/controller/ctlog/actions/resolve_tree.go +++ b/internal/controller/ctlog/actions/resolve_tree.go @@ -9,6 +9,7 @@ import ( "github.com/securesign/operator/internal/controller/common" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" actions2 "github.com/securesign/operator/internal/controller/trillian/actions" v1 "k8s.io/api/core/v1" @@ -80,7 +81,7 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.C tree, err = i.createTree(ctx, "ctlog-tree", trillUrl, constants.CreateTreeDeadline) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: ServerCondition, + Type: constants2.ServerCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), diff --git a/internal/controller/ctlog/actions/server_config.go b/internal/controller/ctlog/actions/server_config.go index 384102e1e..9f416a523 100644 --- a/internal/controller/ctlog/actions/server_config.go +++ b/internal/controller/ctlog/actions/server_config.go @@ -8,6 +8,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action" utils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" ctlogUtils "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" corev1 "k8s.io/api/core/v1" @@ -70,7 +71,7 @@ func (i serverConfig) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) instance.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", trillian.LogserverDeploymentName, instance.Namespace) } - labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) + labels := constants.LabelsFor(constants2.ComponentName, constants2.DeploymentName, instance.Name) trillianService := instance.DeepCopy().Spec.Trillian diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index b1f35e895..726efb38a 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -7,7 +7,10 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" + "github.com/securesign/operator/internal/controller/ctlog/utils" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -38,17 +41,32 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog updated bool ) - labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) + labels := constants.LabelsFor(constants2.ComponentName, constants2.ComponentName, instance.Name) - svc := kubernetes.CreateService(instance.Namespace, ComponentName, ServerPortName, ServerPort, ServerTargetPort, labels) + var port int + if utils.UseTLS(instance) { + port = constants2.HttpsServerPort + } else { + port = constants2.ServerPort + } + svc := kubernetes.CreateService(instance.Namespace, constants2.ComponentName, constants2.ServerPortName, port, constants2.ServerTargetPort, labels) if instance.Spec.Monitoring.Enabled { svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ - Name: MetricsPortName, + Name: constants2.MetricsPortName, Protocol: corev1.ProtocolTCP, - Port: MetricsPort, - TargetPort: intstr.FromInt32(MetricsPort), + Port: constants2.MetricsPort, + TargetPort: intstr.FromInt32(constants2.MetricsPort), }) } + + //TLS: Annotate service + if k8sutils.IsOpenShift() && instance.Spec.TLS.CertRef == nil { + if svc.Annotations == nil { + svc.Annotations = make(map[string]string) + } + svc.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = instance.Name + "-ctlog-tls" + } + if err = controllerutil.SetControllerReference(instance, svc, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Service: %w", err)) } diff --git a/internal/controller/ctlog/actions/constants.go b/internal/controller/ctlog/constants/constants.go similarity index 85% rename from internal/controller/ctlog/actions/constants.go rename to internal/controller/ctlog/constants/constants.go index 5ead8d88d..625ee451d 100644 --- a/internal/controller/ctlog/actions/constants.go +++ b/internal/controller/ctlog/constants/constants.go @@ -1,4 +1,4 @@ -package actions +package constants import "github.com/securesign/operator/internal/controller/constants" @@ -9,7 +9,8 @@ const ( MonitoringRoleName = "prometheus-k8s-ctlog" CertCondition = "FulcioCertAvailable" - ServerPortName = "http" + ServerPortName = "ctlog-server" + HttpsServerPort = 443 ServerPort = 80 ServerTargetPort = 6962 MetricsPortName = "metrics" diff --git a/internal/controller/ctlog/ctlog_controller.go b/internal/controller/ctlog/ctlog_controller.go index f4a7052fc..0802ecfea 100644 --- a/internal/controller/ctlog/ctlog_controller.go +++ b/internal/controller/ctlog/ctlog_controller.go @@ -22,6 +22,7 @@ import ( olpredicate "github.com/operator-framework/operator-lib/predicate" "github.com/securesign/operator/internal/controller/annotations" "github.com/securesign/operator/internal/controller/common/action/transitions" + "github.com/securesign/operator/internal/controller/ctlog/constants" "k8s.io/apimachinery/pkg/runtime/schema" "github.com/securesign/operator/internal/controller/ctlog/actions" @@ -89,7 +90,7 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl target := instance.DeepCopy() acs := []action.Action[*rhtasv1alpha1.CTlog]{ transitions.NewToPendingPhaseAction[*rhtasv1alpha1.CTlog](func(_ *rhtasv1alpha1.CTlog) []string { - return []string{actions.CertCondition} + return []string{constants.CertCondition} }), transitions.NewToCreatePhaseAction[*rhtasv1alpha1.CTlog](), diff --git a/internal/controller/ctlog/ctlog_controller_test.go b/internal/controller/ctlog/ctlog_controller_test.go index 54d60daa7..d9de4062b 100644 --- a/internal/controller/ctlog/ctlog_controller_test.go +++ b/internal/controller/ctlog/ctlog_controller_test.go @@ -23,7 +23,7 @@ import ( "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/actions" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" fulcio "github.com/securesign/operator/internal/controller/fulcio/actions" trillian "github.com/securesign/operator/internal/controller/trillian/actions" k8sTest "github.com/securesign/operator/internal/testing/kubernetes" @@ -149,13 +149,13 @@ var _ = Describe("CTlog controller", func() { deployment := &appsv1.Deployment{} By("Checking if Deployment was successfully created in the reconciliation") Eventually(func() error { - return k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment) + return k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment) }).Should(Succeed()) By("Checking if Service was successfully created in the reconciliation") service := &corev1.Service{} Eventually(func() error { - return k8sClient.Get(ctx, types.NamespacedName{Name: actions.ComponentName, Namespace: Namespace}, service) + return k8sClient.Get(ctx, types.NamespacedName{Name: constants2.ComponentName, Namespace: Namespace}, service) }).Should(Succeed()) Expect(service.Spec.Ports[0].Port).Should(Equal(int32(80))) @@ -173,14 +173,14 @@ var _ = Describe("CTlog controller", func() { By("Checking if controller will return deployment to desired state") deployment = &appsv1.Deployment{} Eventually(func() error { - return k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment) + return k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment) }).Should(Succeed()) replicas := int32(99) deployment.Spec.Replicas = &replicas Expect(k8sClient.Status().Update(ctx, deployment)).Should(Succeed()) Eventually(func(g Gomega) int32 { deployment = &appsv1.Deployment{} - g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment)).Should(Succeed()) + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment)).Should(Succeed()) return *deployment.Spec.Replicas }).Should(Equal(int32(1))) }) diff --git a/internal/controller/ctlog/ctlog_hot_update_test.go b/internal/controller/ctlog/ctlog_hot_update_test.go index be59556e5..6e1ec4e02 100644 --- a/internal/controller/ctlog/ctlog_hot_update_test.go +++ b/internal/controller/ctlog/ctlog_hot_update_test.go @@ -20,6 +20,7 @@ import ( "context" "time" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" k8sTest "github.com/securesign/operator/internal/testing/kubernetes" "github.com/securesign/operator/internal/controller/ctlog/utils" @@ -27,7 +28,6 @@ import ( "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/actions" fulcio "github.com/securesign/operator/internal/controller/fulcio/actions" trillian "github.com/securesign/operator/internal/controller/trillian/actions" "k8s.io/apimachinery/pkg/api/equality" @@ -125,7 +125,7 @@ var _ = Describe("CTlog update test", func() { deployment := &appsv1.Deployment{} By("Checking if Deployment was successfully created in the reconciliation") Eventually(func() error { - return k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment) + return k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment) }).Should(Succeed()) By("Move to Ready phase") @@ -160,22 +160,22 @@ var _ = Describe("CTlog update test", func() { By("CTL deployment is updated") Eventually(func() bool { updated := &appsv1.Deployment{} - Expect(k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, updated)).To(Succeed()) + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, updated)).To(Succeed()) return equality.Semantic.DeepDerivative(deployment.Spec.Template.Spec.Volumes, updated.Spec.Template.Spec.Volumes) }).Should(BeFalse()) By("Move to Ready phase") deployment = &appsv1.Deployment{} - Expect(k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment)).To(Succeed()) + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment)).To(Succeed()) Expect(k8sTest.SetDeploymentToReady(ctx, k8sClient, deployment)).To(Succeed()) By("Private key has changed") key, err := utils.CreatePrivateKey() Expect(err).To(Not(HaveOccurred())) Expect(k8sClient.Create(ctx, kubernetes.CreateSecret("key-secret", Namespace, - map[string][]byte{"private": key.PrivateKey}, constants.LabelsFor(actions.ComponentName, Name, instance.Name)))).To(Succeed()) + map[string][]byte{"private": key.PrivateKey}, constants.LabelsFor(constants2.ComponentName, Name, instance.Name)))).To(Succeed()) - Expect(k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, deployment)).To(Succeed()) + Expect(k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, deployment)).To(Succeed()) found := &v1alpha1.CTlog{} Eventually(func(g Gomega) error { g.Expect(k8sClient.Get(ctx, typeNamespaceName, found)).Should(Succeed()) @@ -198,7 +198,7 @@ var _ = Describe("CTlog update test", func() { By("CTL deployment is updated") Eventually(func(g Gomega) bool { updated := &appsv1.Deployment{} - g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: actions.DeploymentName, Namespace: Namespace}, updated)).To(Succeed()) + g.Expect(k8sClient.Get(ctx, types.NamespacedName{Name: constants2.DeploymentName, Namespace: Namespace}, updated)).To(Succeed()) return equality.Semantic.DeepDerivative(deployment.Spec.Template.Spec.Volumes, updated.Spec.Template.Spec.Volumes) }).Should(BeFalse()) }) diff --git a/internal/controller/ctlog/utils/ctlog_deployment.go b/internal/controller/ctlog/utils/ctlog_deployment.go index e8af3ba9e..8d50e07bc 100644 --- a/internal/controller/ctlog/utils/ctlog_deployment.go +++ b/internal/controller/ctlog/utils/ctlog_deployment.go @@ -1,6 +1,7 @@ package utils import ( + "errors" "fmt" "strconv" @@ -33,12 +34,17 @@ func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string Protocol: corev1.ProtocolTCP, }, } - + scheme := corev1.URISchemeHTTP appArgs := []string{ "--http_endpoint=0.0.0.0:" + strconv.Itoa(int(serverPort)), "--log_config=/ctfe-keys/config", "--alsologtostderr", } + if UseTLS(instance) { + scheme = corev1.URISchemeHTTPS + appArgs = append(appArgs, "--tls_certificate", "/var/run/secrets/tas/tls.crt") + appArgs = append(appArgs, "--tls_key", "/var/run/secrets/tas/tls.key") + } if instance.Spec.Monitoring.Enabled { appArgs = append(appArgs, "--metrics_endpoint=0.0.0.0:"+strconv.Itoa(int(metricsPort))) @@ -73,8 +79,9 @@ func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string LivenessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ - Path: "/healthz", - Port: intstr.FromInt32(serverPort), + Path: "/healthz", + Port: intstr.FromInt32(serverPort), + Scheme: scheme, }, }, InitialDelaySeconds: 10, @@ -86,8 +93,9 @@ func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string ReadinessProbe: &corev1.Probe{ ProbeHandler: corev1.ProbeHandler{ HTTPGet: &corev1.HTTPGetAction{ - Path: "/healthz", - Port: intstr.FromInt32(serverPort), + Path: "/healthz", + Port: intstr.FromInt32(serverPort), + Scheme: scheme, }, }, InitialDelaySeconds: 10, @@ -121,5 +129,10 @@ func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string }, } utils.SetProxyEnvs(dep) + + if err := utils.SetTLS(&dep.Spec.Template, instance.Status.TLS); err != nil { + return nil, errors.New("could not set TLS: " + err.Error()) + } + return dep, nil } diff --git a/internal/controller/ctlog/utils/tls.go b/internal/controller/ctlog/utils/tls.go new file mode 100644 index 000000000..58615a3de --- /dev/null +++ b/internal/controller/ctlog/utils/tls.go @@ -0,0 +1,20 @@ +package utils + +import ( + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" +) + +func UseTLS(instance *rhtasv1alpha1.CTlog) bool { + + if instance == nil { + return false + } + + // TLS enabled on Ctlog + if instance.Spec.TLS.CertRef != nil || kubernetes.IsOpenShift() { + return true + } + + return false +} diff --git a/internal/controller/fulcio/actions/deployment.go b/internal/controller/fulcio/actions/deployment.go index d0aea6334..dc22a2086 100644 --- a/internal/controller/fulcio/actions/deployment.go +++ b/internal/controller/fulcio/actions/deployment.go @@ -2,12 +2,17 @@ package actions import ( "context" + "errors" "fmt" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/action" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" + ctlogAction "github.com/securesign/operator/internal/controller/ctlog/constants" futils "github.com/securesign/operator/internal/controller/fulcio/utils" + "sigs.k8s.io/controller-runtime/pkg/client" + "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -36,16 +41,21 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio err error ) + instanceCopy := instance.DeepCopy() + if err = resolveCtlAddress(ctx, i.Client, instanceCopy); err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "Resolving CTLog address", + }) + i.StatusUpdate(ctx, instance) + return i.Requeue() + } + labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) - switch { - case instance.Spec.Ctlog.Address == "": - instance.Spec.Ctlog.Address = fmt.Sprintf("http://ctlog.%s.svc", instance.Namespace) - case instance.Spec.Ctlog.Port == nil: - port := int32(80) - instance.Spec.Ctlog.Port = &port - } - dp, err := futils.CreateDeployment(instance, DeploymentName, RBACName, labels) + dp, err := futils.CreateDeployment(instanceCopy, DeploymentName, RBACName, labels) if err != nil { if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ @@ -80,3 +90,38 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Fulcio return i.Continue() } } + +func resolveCtlAddress(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.Fulcio) error { + if instance.Spec.Ctlog.Prefix == "" { + return futils.CtlogPrefixNotSpecified + } + + if instance.Spec.Ctlog.Address != "" { + if instance.Spec.Ctlog.Port == nil { + return futils.CtlogPortNotSpecified + } + return nil + } + + svc, err := kubernetes.FindService(ctx, cli, instance.Namespace, constants.LabelsForComponent(ctlogAction.ComponentName, instance.Name)) + if err != nil { + return err + } + + for _, port := range svc.Spec.Ports { + if port.Name == ctlogAction.ServerPortName { + var protocol string + portCopy := port + instance.Spec.Ctlog.Port = &portCopy.Port + switch port.Port { + case 443: + protocol = "https://" + case 80: + protocol = "http://" + } + instance.Spec.Ctlog.Address = fmt.Sprintf("%s%s.%s.svc", protocol, svc.Name, svc.Namespace) + return nil + } + } + return errors.New("protocol name not found") +} diff --git a/internal/controller/fulcio/fulcio_controller_test.go b/internal/controller/fulcio/fulcio_controller_test.go index f7fc850cd..3fe67d463 100644 --- a/internal/controller/fulcio/fulcio_controller_test.go +++ b/internal/controller/fulcio/fulcio_controller_test.go @@ -32,6 +32,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + ctlogAction "github.com/securesign/operator/internal/controller/ctlog/constants" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -124,6 +125,8 @@ var _ = Describe("Fulcio controller", func() { }, }, } + Expect(k8sClient.Create(ctx, kubernetes.CreateConfigmap(Namespace, "trusted-ca-bundle", map[string]string{}, map[string]string{"ca-cert": "ca-cert-data"}))).To(Succeed()) + Expect(k8sClient.Create(ctx, kubernetes.CreateService(Namespace, ctlogAction.ComponentName, ctlogAction.ServerPortName, ctlogAction.ServerPort, ctlogAction.ServerPort, constants.LabelsForComponent(ctlogAction.ComponentName, instance.Name)))).To(Succeed()) err = k8sClient.Create(ctx, instance) Expect(err).To(Not(HaveOccurred())) } diff --git a/internal/controller/fulcio/fulcio_hot_update_test.go b/internal/controller/fulcio/fulcio_hot_update_test.go index 43b686ea4..4062fd812 100644 --- a/internal/controller/fulcio/fulcio_hot_update_test.go +++ b/internal/controller/fulcio/fulcio_hot_update_test.go @@ -32,6 +32,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + ctlogAction "github.com/securesign/operator/internal/controller/ctlog/constants" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -114,6 +115,7 @@ var _ = Describe("Fulcio hot update", func() { Monitoring: v1alpha1.MonitoringConfig{Enabled: false}, }, } + Expect(k8sClient.Create(ctx, kubernetes.CreateService(Namespace, ctlogAction.ComponentName, ctlogAction.ServerPortName, ctlogAction.ServerPort, ctlogAction.ServerPort, constants.LabelsForComponent(ctlogAction.ComponentName, instance.Name)))).To(Succeed()) err = k8sClient.Create(ctx, instance) Expect(err).To(Not(HaveOccurred())) } diff --git a/internal/controller/fulcio/utils/fulcio_deployment.go b/internal/controller/fulcio/utils/fulcio_deployment.go index a38544abd..b59caa2fb 100644 --- a/internal/controller/fulcio/utils/fulcio_deployment.go +++ b/internal/controller/fulcio/utils/fulcio_deployment.go @@ -29,6 +29,20 @@ func CreateDeployment(instance *v1alpha1.Fulcio, deploymentName string, sa strin return nil, errors.New("CA secret is not specified") } + var err error + switch { + case instance.Spec.Ctlog.Address == "": + err = fmt.Errorf("CreateDeployment: %w", CtlogAddressNotSpecified) + case instance.Spec.Ctlog.Port == nil: + err = fmt.Errorf("CreateDeployment: %w", CtlogPortNotSpecified) + case instance.Spec.Ctlog.Prefix == "": + err = fmt.Errorf("CreateDeployment: %w", CtlogPrefixNotSpecified) + } + + if err != nil { + return nil, err + } + containerPorts := []corev1.ContainerPort{ { Protocol: corev1.ProtocolTCP, @@ -56,26 +70,9 @@ func CreateDeployment(instance *v1alpha1.Fulcio, deploymentName string, sa strin "/var/run/fulcio-secrets/key.pem", "--fileca-cert", "/var/run/fulcio-secrets/cert.pem", + fmt.Sprintf("--ct-log-url=%s:%d/%s", instance.Spec.Ctlog.Address, *instance.Spec.Ctlog.Port, instance.Spec.Ctlog.Prefix), } - var err error - var ctlogUrl string - switch { - case instance.Spec.Ctlog.Address == "": - err = fmt.Errorf("CreateDeployment: %w", CtlogAddressNotSpecified) - case instance.Spec.Ctlog.Port == nil: - err = fmt.Errorf("CreateDeployment: %w", CtlogPortNotSpecified) - case instance.Spec.Ctlog.Prefix == "": - err = fmt.Errorf("CreateDeployment: %w", CtlogPrefixNotSpecified) - default: - ctlogUrl = fmt.Sprintf("%s:%d/%s", instance.Spec.Ctlog.Address, *instance.Spec.Ctlog.Port, instance.Spec.Ctlog.Prefix) - } - - if err != nil { - return nil, err - } - args = append(args, fmt.Sprintf("--ct-log-url=%s", ctlogUrl)) - env := make([]corev1.EnvVar, 0) if instance.Status.Certificate.PrivateKeyPasswordRef != nil { env = append(env, corev1.EnvVar{ diff --git a/internal/controller/securesign/actions/ensure_ctlog.go b/internal/controller/securesign/actions/ensure_ctlog.go index 539adfeeb..9fc7fc786 100644 --- a/internal/controller/securesign/actions/ensure_ctlog.go +++ b/internal/controller/securesign/actions/ensure_ctlog.go @@ -4,11 +4,11 @@ import ( "context" "github.com/securesign/operator/internal/controller/annotations" + ctlogConstants "github.com/securesign/operator/internal/controller/ctlog/constants" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/actions" "k8s.io/apimachinery/pkg/api/meta" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -40,7 +40,7 @@ func (i ctlogAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Secures ctlog.Name = instance.Name ctlog.Namespace = instance.Namespace - ctlog.Labels = constants.LabelsFor(actions.ComponentName, ctlog.Name, instance.Name) + ctlog.Labels = constants.LabelsFor(ctlogConstants.ComponentName, ctlog.Name, instance.Name) ctlog.Annotations = annotations.FilterInheritable(instance.Annotations) ctlog.Spec = instance.Spec.Ctlog diff --git a/internal/controller/tuf/actions/deployment.go b/internal/controller/tuf/actions/deployment.go index d7cace5a1..4d00bbbab 100644 --- a/internal/controller/tuf/actions/deployment.go +++ b/internal/controller/tuf/actions/deployment.go @@ -37,7 +37,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Tuf) * ) labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) - dp := tufutils.CreateTufDeployment(instance, DeploymentName, RBACName, labels) if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { diff --git a/internal/controller/tuf/tuf_controller_test.go b/internal/controller/tuf/tuf_controller_test.go index a3992ad4d..ecf5de53f 100644 --- a/internal/controller/tuf/tuf_controller_test.go +++ b/internal/controller/tuf/tuf_controller_test.go @@ -21,12 +21,12 @@ import ( "maps" "time" + actions2 "github.com/securesign/operator/internal/controller/ctlog/constants" k8sTest "github.com/securesign/operator/internal/testing/kubernetes" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" - actions2 "github.com/securesign/operator/internal/controller/ctlog/actions" "github.com/securesign/operator/internal/controller/tuf/actions" batchv1 "k8s.io/api/batch/v1" v1 "k8s.io/api/networking/v1" diff --git a/test/e2e/support/tas/ctlog/ctlog.go b/test/e2e/support/tas/ctlog/ctlog.go index 0f7b4e969..de77973e0 100644 --- a/test/e2e/support/tas/ctlog/ctlog.go +++ b/test/e2e/support/tas/ctlog/ctlog.go @@ -3,6 +3,7 @@ package ctlog import ( "context" + constants2 "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/test/e2e/support" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -10,7 +11,6 @@ import ( "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/actions" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/types" @@ -25,7 +25,7 @@ func Verify(ctx context.Context, cli client.Client, namespace string, name strin Eventually(func(g Gomega) (bool, error) { return kubernetes.DeploymentIsRunning(ctx, cli, namespace, map[string]string{ - kubernetes.ComponentLabel: actions.ComponentName, + kubernetes.ComponentLabel: constants2.ComponentName, }) }).Should(BeTrue()) } @@ -33,7 +33,7 @@ func Verify(ctx context.Context, cli client.Client, namespace string, name strin func GetServerPod(ctx context.Context, cli client.Client, ns string) func() *v1.Pod { return func() *v1.Pod { list := &v1.PodList{} - _ = cli.List(ctx, list, client.InNamespace(ns), client.MatchingLabels{kubernetes.ComponentLabel: actions.ComponentName, kubernetes.NameLabel: "ctlog"}) + _ = cli.List(ctx, list, client.InNamespace(ns), client.MatchingLabels{kubernetes.ComponentLabel: constants2.ComponentName, kubernetes.NameLabel: "ctlog"}) if len(list.Items) != 1 { return nil } diff --git a/test/e2e/update/ctlog_test.go b/test/e2e/update/ctlog_test.go index ea8da81d1..34634d791 100644 --- a/test/e2e/update/ctlog_test.go +++ b/test/e2e/update/ctlog_test.go @@ -6,6 +6,7 @@ import ( "context" "time" + ctlogAction "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/test/e2e/support/tas" "github.com/securesign/operator/test/e2e/support/tas/ctlog" @@ -15,7 +16,6 @@ import ( . "github.com/onsi/gomega" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/constants" - ctlogAction "github.com/securesign/operator/internal/controller/ctlog/actions" tufAction "github.com/securesign/operator/internal/controller/tuf/actions" "github.com/securesign/operator/test/e2e/support" v1 "k8s.io/api/core/v1" diff --git a/test/e2e/update/fulcio_test.go b/test/e2e/update/fulcio_test.go index 7e2ac7b76..f0ff4fd2d 100644 --- a/test/e2e/update/fulcio_test.go +++ b/test/e2e/update/fulcio_test.go @@ -7,6 +7,7 @@ import ( "encoding/json" "time" + ctlogAction "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/test/e2e/support/tas" fulcioAction "github.com/securesign/operator/internal/controller/fulcio/actions" @@ -18,7 +19,6 @@ import ( . "github.com/onsi/gomega" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/constants" - ctlogAction "github.com/securesign/operator/internal/controller/ctlog/actions" tufAction "github.com/securesign/operator/internal/controller/tuf/actions" "github.com/securesign/operator/test/e2e/support" v1 "k8s.io/api/core/v1" diff --git a/test/e2e/upgrade_test.go b/test/e2e/upgrade_test.go index a7975cf6a..a7f9a3e94 100644 --- a/test/e2e/upgrade_test.go +++ b/test/e2e/upgrade_test.go @@ -10,6 +10,7 @@ import ( "strings" "time" + ctl "github.com/securesign/operator/internal/controller/ctlog/constants" "github.com/securesign/operator/test/e2e/support/tas/ctlog" "github.com/securesign/operator/test/e2e/support/tas/fulcio" "github.com/securesign/operator/test/e2e/support/tas/rekor" @@ -25,7 +26,6 @@ import ( tasv1alpha "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/constants" - ctl "github.com/securesign/operator/internal/controller/ctlog/actions" fulcioAction "github.com/securesign/operator/internal/controller/fulcio/actions" rekorAction "github.com/securesign/operator/internal/controller/rekor/actions" "github.com/securesign/operator/internal/controller/securesign/actions"