From 33083c2b28eafd69bd3453d2947eefb5d609e0af Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Tue, 9 Jul 2024 13:26:32 +0200 Subject: [PATCH 01/34] Add TLS to Rekor and Trillian services --- api/v1alpha1/common.go | 15 ++ api/v1alpha1/rekor_types.go | 3 + api/v1alpha1/rekor_types_test.go | 5 + api/v1alpha1/trillian_types.go | 13 + api/v1alpha1/trillian_types_test.go | 12 + api/v1alpha1/zz_generated.deepcopy.go | 65 +++++ bundle/manifests/rhtas.redhat.com_rekors.yaml | 56 +++++ .../rhtas.redhat.com_securesigns.yaml | 178 +++++++++++++ .../manifests/rhtas.redhat.com_trillians.yaml | 122 +++++++++ config/crd/bases/rhtas.redhat.com_rekors.yaml | 56 +++++ .../bases/rhtas.redhat.com_securesigns.yaml | 178 +++++++++++++ .../crd/bases/rhtas.redhat.com_trillians.yaml | 122 +++++++++ .../rekor/actions/server/config_map.go | 82 ++++++ .../rekor/actions/server/deployment.go | 67 +++++ internal/controller/rekor/rekor_controller.go | 2 + .../trillian/actions/logserver/deployment.go | 67 +++++ .../trillian/actions/logserver/service.go | 13 + test/e2e/tls_configuration_test.go | 237 ++++++++++++++++++ 18 files changed, 1293 insertions(+) create mode 100644 internal/controller/rekor/actions/server/config_map.go create mode 100644 test/e2e/tls_configuration_test.go diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index 301334fe4..e878904d9 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -107,6 +107,7 @@ type Pvc struct { AccessModes []PersistentVolumeAccessMode `json:"accessModes,omitempty"` } +<<<<<<< HEAD type Auth struct { // Environmental variables used to define authentication parameters //+optional @@ -114,6 +115,20 @@ type Auth struct { // Secret ref to be mounted inside a pod, Mount path defaults to /var/run/secrets/tas/auth //+optional SecretMount []SecretKeySelector `json:"secretMount,omitempty"` +======= +// TLSCert defines fields for TLS certificate +// +kubebuilder:validation:XValidation:rule=(!has(self.certRef) || has(self.privateKeyRef)),message=privateKeyRef cannot be empty +type TLSCert struct { + // Reference to the private key + //+optional + PrivateKeyRef *SecretKeySelector `json:"privateKeyRef,omitempty"` + // Reference to service certificate + //+optional + CertRef *SecretKeySelector `json:"certRef,omitempty"` + // Reference to CA certificate + //+optional + CACertRef *LocalObjectReference `json:"caCertRef,omitempty"` +>>>>>>> bddb484 (Add TLS to Rekor and Trillian services) } // TLS (Transport Layer Security) Configuration for enabling service encryption. diff --git a/api/v1alpha1/rekor_types.go b/api/v1alpha1/rekor_types.go index 812a6888e..74a4cf620 100644 --- a/api/v1alpha1/rekor_types.go +++ b/api/v1alpha1/rekor_types.go @@ -39,6 +39,9 @@ type RekorSpec struct { // +patchMergeKey=treeID // +kubebuilder:default:={} Sharding []RekorLogRange `json:"sharding,omitempty"` + // Reference to TLS server certificate, private key and CA certificate + //+optional + TLSCertificate TLSCert `json:"tls"` } type RekorSigner struct { diff --git a/api/v1alpha1/rekor_types_test.go b/api/v1alpha1/rekor_types_test.go index 322b7a794..896812a03 100644 --- a/api/v1alpha1/rekor_types_test.go +++ b/api/v1alpha1/rekor_types_test.go @@ -315,6 +315,11 @@ var _ = Describe("Rekor", func() { EncodedPublicKey: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFWkZ0Nk5FcU14YWVVNzZsbmxZekZVTmpGUUdIcQpORjQ2QlBDVGxQL0ZnZk1aak42MDhjRFhmM0xNNWhUYnZOeUNFYWJFKzRNYk9jRU1YaERRVWxZRnZBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==", }, }, + TLSCertificate: TLSCert{ + CACertRef: &LocalObjectReference{ + Name: "ca-configmap", + }, + }, }, } diff --git a/api/v1alpha1/trillian_types.go b/api/v1alpha1/trillian_types.go index 838504433..1b6227db7 100644 --- a/api/v1alpha1/trillian_types.go +++ b/api/v1alpha1/trillian_types.go @@ -27,6 +27,10 @@ type TrillianSpec struct { //+kubebuilder:validation:XValidation:rule=((!self.create && self.databaseSecretRef != null) || self.create),message=databaseSecretRef cannot be empty //+kubebuilder:default:={create: true, pvc: {size: "5Gi", retain: true, accessModes: {ReadWriteOnce}}} Db TrillianDB `json:"database,omitempty"` + //+optional + TrillianServer TrillianServer `json:"server,omitempty"` + //+optional + TrillianSigner TrillianSigner `json:"signer,omitempty"` // Enable Monitoring for Logsigner and Logserver Monitoring MonitoringConfig `json:"monitoring,omitempty"` // ConfigMap with additional bundle of trusted CA @@ -55,6 +59,15 @@ type TrillianDB struct { TLS TLS `json:"tls,omitempty"` } +type TrillianServer struct { + // Secret with TLS server certificate, private key and CA certificate + TLSCertificate TLSCert `json:"tls"` +} +type TrillianSigner struct { + // Secret with TLS server certificate, private key and CA certificate + TLSCertificate TLSCert `json:"tls"` +} + // TrillianStatus defines the observed state of Trillian type TrillianStatus struct { Db TrillianDB `json:"database,omitempty"` diff --git a/api/v1alpha1/trillian_types_test.go b/api/v1alpha1/trillian_types_test.go index 2d38fd486..2176a9a70 100644 --- a/api/v1alpha1/trillian_types_test.go +++ b/api/v1alpha1/trillian_types_test.go @@ -157,6 +157,18 @@ var _ = Describe("Trillian", func() { Name: "secret", }, }, + TrillianServer: TrillianServer{ + TLSCertificate: TLSCert{ + CertRef: &SecretKeySelector{ + Key: "cert", + LocalObjectReference: LocalObjectReference{Name: "server-secret"}, + }, + PrivateKeyRef: &SecretKeySelector{ + Key: "key", + LocalObjectReference: LocalObjectReference{Name: "server-secret"}, + }, + }, + }, }, } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 8d1642b6f..da8cb2c33 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -784,6 +784,7 @@ func (in *RekorSpec) DeepCopyInto(out *RekorSpec) { *out = make([]RekorLogRange, len(*in)) copy(*out, *in) } + in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RekorSpec. @@ -1216,6 +1217,36 @@ func (in *Tink) DeepCopy() *Tink { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSCert) DeepCopyInto(out *TLSCert) { + *out = *in + if in.PrivateKeyRef != nil { + in, out := &in.PrivateKeyRef, &out.PrivateKeyRef + *out = new(SecretKeySelector) + **out = **in + } + if in.CertRef != nil { + in, out := &in.CertRef, &out.CertRef + *out = new(SecretKeySelector) + **out = **in + } + if in.CACertRef != nil { + in, out := &in.CACertRef, &out.CACertRef + *out = new(LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCert. +func (in *TLSCert) DeepCopy() *TLSCert { + if in == nil { + return nil + } + out := new(TLSCert) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Trillian) DeepCopyInto(out *Trillian) { *out = *in @@ -1302,6 +1333,22 @@ func (in *TrillianList) DeepCopyObject() runtime.Object { return nil } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrillianServer) DeepCopyInto(out *TrillianServer) { + *out = *in + in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrillianServer. +func (in *TrillianServer) DeepCopy() *TrillianServer { + if in == nil { + return nil + } + out := new(TrillianServer) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrillianService) DeepCopyInto(out *TrillianService) { *out = *in @@ -1322,10 +1369,28 @@ func (in *TrillianService) DeepCopy() *TrillianService { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TrillianSigner) DeepCopyInto(out *TrillianSigner) { + *out = *in + in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrillianSigner. +func (in *TrillianSigner) DeepCopy() *TrillianSigner { + if in == nil { + return nil + } + out := new(TrillianSigner) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrillianSpec) DeepCopyInto(out *TrillianSpec) { *out = *in in.Db.DeepCopyInto(&out.Db) + in.TrillianServer.DeepCopyInto(&out.TrillianServer) + in.TrillianSigner.DeepCopyInto(&out.TrillianSigner) out.Monitoring = in.Monitoring if in.TrustedCA != nil { in, out := &in.TrustedCA, &out.TrustedCA diff --git a/bundle/manifests/rhtas.redhat.com_rekors.yaml b/bundle/manifests/rhtas.redhat.com_rekors.yaml index 7f2606baa..90e2d9727 100644 --- a/bundle/manifests/rhtas.redhat.com_rekors.yaml +++ b/bundle/manifests/rhtas.redhat.com_rekors.yaml @@ -256,6 +256,62 @@ spec: type: object x-kubernetes-map-type: atomic type: object + tls: + description: Reference to TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index 1eea0a2dd..513a961df 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -664,6 +664,62 @@ spec: type: object x-kubernetes-map-type: atomic type: object + tls: + description: Reference to TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -854,6 +910,128 @@ spec: - name type: object x-kubernetes-map-type: atomic + server: + properties: + tls: + description: Secret with TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object + signer: + properties: + tls: + description: Secret with TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/bundle/manifests/rhtas.redhat.com_trillians.yaml b/bundle/manifests/rhtas.redhat.com_trillians.yaml index 98ac8c36c..5c5ef6ff5 100644 --- a/bundle/manifests/rhtas.redhat.com_trillians.yaml +++ b/bundle/manifests/rhtas.redhat.com_trillians.yaml @@ -207,6 +207,128 @@ spec: - name type: object x-kubernetes-map-type: atomic + server: + properties: + tls: + description: Secret with TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object + signer: + properties: + tls: + description: Secret with TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object type: object status: description: TrillianStatus defines the observed state of Trillian diff --git a/config/crd/bases/rhtas.redhat.com_rekors.yaml b/config/crd/bases/rhtas.redhat.com_rekors.yaml index d3eb90838..1db685f9b 100644 --- a/config/crd/bases/rhtas.redhat.com_rekors.yaml +++ b/config/crd/bases/rhtas.redhat.com_rekors.yaml @@ -256,6 +256,62 @@ spec: type: object x-kubernetes-map-type: atomic type: object + tls: + description: Reference to TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 16193a723..69deec53a 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -664,6 +664,62 @@ spec: type: object x-kubernetes-map-type: atomic type: object + tls: + description: Reference to TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -854,6 +910,128 @@ spec: - name type: object x-kubernetes-map-type: atomic + server: + properties: + tls: + description: Secret with TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object + signer: + properties: + tls: + description: Secret with TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/config/crd/bases/rhtas.redhat.com_trillians.yaml b/config/crd/bases/rhtas.redhat.com_trillians.yaml index cb1c67d28..b94525db7 100644 --- a/config/crd/bases/rhtas.redhat.com_trillians.yaml +++ b/config/crd/bases/rhtas.redhat.com_trillians.yaml @@ -207,6 +207,128 @@ spec: - name type: object x-kubernetes-map-type: atomic + server: + properties: + tls: + description: Secret with TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object + signer: + properties: + tls: + description: Secret with TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) + required: + - tls + type: object type: object status: description: TrillianStatus defines the observed state of Trillian diff --git a/internal/controller/rekor/actions/server/config_map.go b/internal/controller/rekor/actions/server/config_map.go new file mode 100644 index 000000000..d87f8918a --- /dev/null +++ b/internal/controller/rekor/actions/server/config_map.go @@ -0,0 +1,82 @@ +package server + +import ( + "context" + "fmt" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "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" + "github.com/securesign/operator/internal/controller/rekor/actions" + corev1 "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" +) + +func NewCAConfigMapAction() action.Action[*rhtasv1alpha1.Rekor] { + return &configMapAction{} +} + +type configMapAction struct { + action.BaseAction +} + +func (i configMapAction) Name() string { + return "create CA configMap" +} + +func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") + // signingKeySecret: OCP related + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + return c.Reason == constants.Creating || c.Reason == constants.Ready && cm == nil && signingKeySecret != nil +} + +func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { + var ( + err error + updated bool + ) + + labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) + + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ca-configmap", + Namespace: instance.Namespace, + Labels: labels, + }, + Data: map[string]string{}, + } + + if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + if updated, err = i.Ensure(ctx, configMap); err != nil { + 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 configMap: %w", err), instance) + } + + //TLS: Annotate configMap + configMap.Annotations = map[string]string{"service.beta.openshift.io/inject-cabundle": "true"} + err = i.Client.Update(ctx, configMap) + if err != nil { + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate configMap: %w", err), instance) + } + + if updated { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + return i.StatusUpdate(ctx, instance) + } else { + return i.Continue() + } +} diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 974a7e478..6b871334b 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -17,6 +17,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + corev1 "k8s.io/api/core/v1" ) func NewDeployAction() action.Action[*rhtasv1alpha1.Rekor] { @@ -68,6 +70,71 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could create server Deployment: %w", err), instance) } + + // TLS certificate + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + if instance.Spec.TLSCertificate.CACertRef != nil { + dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TLSCertificate.CACertRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: "ca.crt", // User should use this key. + Path: "ca.crt", + }, + }, + }, + }, + }, + }, + }, + }) + } else if signingKeySecret != nil { + dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "ca-configmap", + }, + Items: []corev1.KeyToPath{ + { + Key: "service-ca.crt", + Path: "ca.crt", + }, + }, + }, + }, + }, + }, + }, + }) + } else { + i.Logger.V(1).Info("Communication between services is insecure") + } + + if instance.Spec.TLSCertificate.CACertRef != nil || signingKeySecret != nil { + dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/etc/ssl/certs", + ReadOnly: true, + }) + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_ca_cert", "/etc/ssl/certs/ca.crt") + } + if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err)) } diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index 6cfeb776d..b75d0df2c 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -110,6 +110,7 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions2.NewRBACAction(), server.NewShardingConfigAction(), server.NewResolveTreeAction(), + server.NewCAConfigMapAction(), server.NewCreatePvcAction(), server.NewDeployAction(), server.NewCreateServiceAction(), @@ -167,6 +168,7 @@ func (r *RekorReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&rhtasv1alpha1.Rekor{}). Owns(&v12.Deployment{}). Owns(&v13.Service{}). + Owns(&v13.ConfigMap{}). Owns(&v1.Ingress{}). Owns(&batchv1.CronJob{}). Complete(r) diff --git a/internal/controller/trillian/actions/logserver/deployment.go b/internal/controller/trillian/actions/logserver/deployment.go index faef2bd34..843539afd 100644 --- a/internal/controller/trillian/actions/logserver/deployment.go +++ b/internal/controller/trillian/actions/logserver/deployment.go @@ -14,6 +14,8 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + corev1 "k8s.io/api/core/v1" ) func NewDeployAction() action.Action[*rhtasv1alpha1.Trillian] { @@ -68,6 +70,71 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian server: %w", err), instance) } + // TLS certificate + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil { + server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TrillianServer.TLSCertificate.CertRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: instance.Spec.TrillianServer.TLSCertificate.CertRef.Key, + Path: "tls.crt", + }, + }, + }, + }, + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TrillianServer.TLSCertificate.PrivateKeyRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: instance.Spec.TrillianServer.TLSCertificate.PrivateKeyRef.Key, + Path: "tls.key", + }, + }, + }, + }, + }, + }, + }, + }) + } else if signingKeySecret != nil { + i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") + server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "log-server-" + instance.Name + "-tls-secret", + }, + }, + }) + } else { + i.Logger.V(1).Info("Communication between services is insecure") + } + + if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil || signingKeySecret != nil { + server.Spec.Template.Spec.Containers[0].VolumeMounts = append(server.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/etc/ssl/certs", + ReadOnly: true, + }) + server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_cert_file", "/etc/ssl/certs/tls.crt") + server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_key_file", "/etc/ssl/certs/tls.key") + } + 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)) } diff --git a/internal/controller/trillian/actions/logserver/service.go b/internal/controller/trillian/actions/logserver/service.go index 774911f48..be74c388a 100644 --- a/internal/controller/trillian/actions/logserver/service.go +++ b/internal/controller/trillian/actions/logserver/service.go @@ -73,6 +73,19 @@ func (i createServiceAction) Handle(ctx context.Context, instance *rhtasv1alpha1 return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create logserver Service: %w", err), instance) } + //TLS: Annotate service + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + if signingKeySecret != nil && instance.Spec.TrillianServer.TLSCertificate.CertRef == nil { + if logserverService.Annotations == nil { + logserverService.Annotations = make(map[string]string) + } + logserverService.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = "log-server-" + instance.Name + "-tls-secret" + err := i.Client.Update(ctx, logserverService) + if err != nil { + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate logserver service: %w", err), instance) + } + } + if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, diff --git a/test/e2e/tls_configuration_test.go b/test/e2e/tls_configuration_test.go new file mode 100644 index 000000000..419bee46d --- /dev/null +++ b/test/e2e/tls_configuration_test.go @@ -0,0 +1,237 @@ +//go:build integration + +package e2e + +import ( + "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "net" + "os" + "time" + + "github.com/securesign/operator/internal/controller/common/utils" + "sigs.k8s.io/controller-runtime/pkg/client" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/test/e2e/support" + "github.com/securesign/operator/test/e2e/support/tas" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +var _ = Describe("Securesign TLS Configuration", Ordered, func() { + cli, _ := CreateClient() + ctx := context.TODO() + + // var targetImageName string + var namespace *v1.Namespace + var securesign *v1alpha1.Securesign + + var caKey *rsa.PrivateKey + var caCert *x509.Certificate + var caCertPEM string + var err error + + AfterEach(func() { + if CurrentSpecReport().Failed() { + if val, present := os.LookupEnv("CI"); present && val == "true" { + support.DumpNamespace(ctx, cli, namespace.Name) + } + } + }) + + BeforeAll(func() { + namespace = support.CreateTestNamespace(ctx, cli) + DeferCleanup(func() { + cli.Delete(ctx, namespace) + }) + + securesign = &v1alpha1.Securesign{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace.Name, + Name: "test", + Annotations: map[string]string{ + "rhtas.redhat.com/metrics": "false", + }, + }, + Spec: v1alpha1.SecuresignSpec{ + Rekor: v1alpha1.RekorSpec{ + ExternalAccess: v1alpha1.ExternalAccess{ + Enabled: true, + }, + RekorSearchUI: v1alpha1.RekorSearchUI{ + Enabled: utils.Pointer(true), + }, + }, + Fulcio: v1alpha1.FulcioSpec{ + ExternalAccess: v1alpha1.ExternalAccess{ + Enabled: true, + }, + Config: v1alpha1.FulcioConfig{ + OIDCIssuers: []v1alpha1.OIDCIssuer{ + { + ClientID: support.OidcClientID(), + IssuerURL: support.OidcIssuerUrl(), + Issuer: support.OidcIssuerUrl(), + Type: "email", + }, + }}, + Certificate: v1alpha1.FulcioCert{ + OrganizationName: "MyOrg", + OrganizationEmail: "my@email.org", + CommonName: "fulcio", + }, + }, + Ctlog: v1alpha1.CTlogSpec{}, + Tuf: v1alpha1.TufSpec{ + ExternalAccess: v1alpha1.ExternalAccess{ + Enabled: true, + }, + }, + Trillian: v1alpha1.TrillianSpec{Db: v1alpha1.TrillianDB{ + Create: utils.Pointer(true), + }}, + }, + } + }) + + Describe("User-Specified TLS Certificate Configuration", func() { + BeforeAll(func() { + caKey, caCert, _, caCertPEM, err = generateCA() + if err != nil { + fmt.Printf("Failed to generate CA: %v\n", err) + return + } + ca_configmap := map[string]string{ + "ca.crt": caCertPEM, + } + createConfigMap(ctx, cli, namespace.Name, "ca-configmap", ca_configmap) + + var trillianKey string + var trillianCert string + trillianKey, trillianCert, err = generateServerCert(caCert, caKey, "trillian-log-server:8090") + if err != nil { + fmt.Printf("Failed to generate trillian server certificate: %v\n", err) + return + } + trillian_data := map[string]string{ + "key": trillianKey, + "cert": trillianCert, + } + createSecret(ctx, cli, namespace.Name, "trillian-server-secret", trillian_data) + + Expect(cli.Create(ctx, securesign)).To(Succeed()) + }) + + It("All components are running", func() { + tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) + tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) + tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) + tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) + tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) + }) + }) +}) + +func createSecret(ctx context.Context, cli client.Client, namespace, name string, data map[string]string) { + secretData := make(map[string][]byte) + for key, value := range data { + secretData[key] = []byte(value) + } + + secret := &v1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Data: secretData, + } + + Expect(cli.Create(ctx, secret)).To(Succeed()) +} + +func createConfigMap(ctx context.Context, cli client.Client, namespace, name string, data map[string]string) { + configMap := &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Data: data, + } + Expect(cli.Create(ctx, configMap)).To(Succeed()) +} + +func generateCA() (*rsa.PrivateKey, *x509.Certificate, string, string, error) { + caKey, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return nil, nil, "", "", err + } + + caTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{ + CommonName: "My CA", + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(0, 2, 0), + IsCA: true, + KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, + BasicConstraintsValid: true, + } + + caCertDER, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, &caKey.PublicKey, caKey) + if err != nil { + return nil, nil, "", "", err + } + + caCert, err := x509.ParseCertificate(caCertDER) + if err != nil { + return nil, nil, "", "", err + } + + caKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caKey)}) + caCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCertDER}) + + return caKey, caCert, string(caKeyPEM), string(caCertPEM), nil +} + +func generateServerCert(caCert *x509.Certificate, caKey *rsa.PrivateKey, serverName string) (string, string, error) { + serverKey, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return "", "", err + } + + serverTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(2), + Subject: pkix.Name{ + CommonName: "local", + Organization: []string{"RedHat"}, + OrganizationalUnit: []string{"RHTAS"}, + }, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(0, 2, 0), + KeyUsage: x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + } + + serverTemplate.DNSNames = []string{"*", serverName} + serverTemplate.IPAddresses = []net.IP{net.ParseIP("0.0.0.0")} + + serverCertDER, err := x509.CreateCertificate(rand.Reader, serverTemplate, caCert, &serverKey.PublicKey, caKey) + if err != nil { + return "", "", err + } + + serverKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(serverKey)}) + serverCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverCertDER}) + + return string(serverKeyPEM), string(serverCertPEM), nil +} From f48f6e5fa1180ee8ca857c7d74ee0f8ae8611e7f Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Tue, 9 Jul 2024 13:56:30 +0200 Subject: [PATCH 02/34] updates tls e2e --- test/e2e/tls_configuration_test.go | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/test/e2e/tls_configuration_test.go b/test/e2e/tls_configuration_test.go index 419bee46d..6a65e4f9f 100644 --- a/test/e2e/tls_configuration_test.go +++ b/test/e2e/tls_configuration_test.go @@ -96,9 +96,23 @@ var _ = Describe("Securesign TLS Configuration", Ordered, func() { Enabled: true, }, }, - Trillian: v1alpha1.TrillianSpec{Db: v1alpha1.TrillianDB{ - Create: utils.Pointer(true), - }}, + Trillian: v1alpha1.TrillianSpec{ + Db: v1alpha1.TrillianDB{ + Create: utils.Pointer(true), + }, + TrillianServer: v1alpha1.TrillianServer{ + TLSCertificate: v1alpha1.TLSCert{ + CertRef: &v1alpha1.SecretKeySelector{ + Key: "cert", + LocalObjectReference: v1alpha1.LocalObjectReference{Name: "trillian-server-secret"}, + }, + PrivateKeyRef: &v1alpha1.SecretKeySelector{ + Key: "key", + LocalObjectReference: v1alpha1.LocalObjectReference{Name: "trillian-server-secret"}, + }, + }, + }, + }, }, } }) @@ -132,11 +146,11 @@ var _ = Describe("Securesign TLS Configuration", Ordered, func() { }) It("All components are running", func() { - tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) + // tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) - tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) - tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) - tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) + // tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) + // tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) + // tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) }) }) }) From 78faaa2661a05cba62a5190a77bbdc40d9dd809c Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Mon, 5 Aug 2024 14:43:28 +0200 Subject: [PATCH 03/34] updates --- api/v1alpha1/common.go | 4 +- api/v1alpha1/trillian_types.go | 6 -- api/v1alpha1/zz_generated.deepcopy.go | 17 ------ .../bases/rhtas.redhat.com_securesigns.yaml | 61 ------------------- .../crd/bases/rhtas.redhat.com_trillians.yaml | 61 ------------------- config/samples/rhtas_v1alpha1_securesign.yaml | 4 +- .../rekor/actions/server/config_map.go | 4 +- .../trillian/actions/logserver/deployment.go | 2 +- .../trillian/actions/logserver/service.go | 2 +- 9 files changed, 8 insertions(+), 153 deletions(-) diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index e878904d9..86f929b1b 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -43,9 +43,9 @@ type CtlogService struct { //+optional Address string `json:"address,omitempty"` // Port of Ctlog Log Server End point - //+kubebuilder:validation:Minimum:=1 + //+kubebuilder:validation:Minimum:=0 //+kubebuilder:validation:Maximum:=65535 - //+kubebuilder:default:=80 + //+kubebuilder:default:=0 //+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/trillian_types.go b/api/v1alpha1/trillian_types.go index 1b6227db7..6a0615b8a 100644 --- a/api/v1alpha1/trillian_types.go +++ b/api/v1alpha1/trillian_types.go @@ -29,8 +29,6 @@ type TrillianSpec struct { Db TrillianDB `json:"database,omitempty"` //+optional TrillianServer TrillianServer `json:"server,omitempty"` - //+optional - TrillianSigner TrillianSigner `json:"signer,omitempty"` // Enable Monitoring for Logsigner and Logserver Monitoring MonitoringConfig `json:"monitoring,omitempty"` // ConfigMap with additional bundle of trusted CA @@ -63,10 +61,6 @@ type TrillianServer struct { // Secret with TLS server certificate, private key and CA certificate TLSCertificate TLSCert `json:"tls"` } -type TrillianSigner struct { - // Secret with TLS server certificate, private key and CA certificate - TLSCertificate TLSCert `json:"tls"` -} // TrillianStatus defines the observed state of Trillian type TrillianStatus struct { diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index da8cb2c33..5181515a4 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1369,28 +1369,11 @@ func (in *TrillianService) DeepCopy() *TrillianService { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TrillianSigner) DeepCopyInto(out *TrillianSigner) { - *out = *in - in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrillianSigner. -func (in *TrillianSigner) DeepCopy() *TrillianSigner { - if in == nil { - return nil - } - out := new(TrillianSigner) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrillianSpec) DeepCopyInto(out *TrillianSpec) { *out = *in in.Db.DeepCopyInto(&out.Db) in.TrillianServer.DeepCopyInto(&out.TrillianServer) - in.TrillianSigner.DeepCopyInto(&out.TrillianSigner) out.Monitoring = in.Monitoring if in.TrustedCA != nil { in, out := &in.TrustedCA, &out.TrustedCA diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 69deec53a..478018227 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -971,67 +971,6 @@ spec: required: - tls type: object - signer: - properties: - tls: - description: Secret with TLS server certificate, private key - and CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) - required: - - tls - type: object type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/config/crd/bases/rhtas.redhat.com_trillians.yaml b/config/crd/bases/rhtas.redhat.com_trillians.yaml index b94525db7..86a6f84a8 100644 --- a/config/crd/bases/rhtas.redhat.com_trillians.yaml +++ b/config/crd/bases/rhtas.redhat.com_trillians.yaml @@ -268,67 +268,6 @@ spec: required: - tls type: object - signer: - properties: - tls: - description: Secret with TLS server certificate, private key and - CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) - required: - - tls - type: object type: object status: description: TrillianStatus defines the observed state of Trillian diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index 6c8d360fe..69c962490 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -23,8 +23,8 @@ spec: config: OIDCIssuers: - ClientID: "trusted-artifact-signer" - IssuerURL: "https://your-oidc-issuer-url" - Issuer: "https://your-oidc-issuer-url" + IssuerURL: "https://keycloak-keycloak-system.apps.rosa.av42p-79zot-u82.x8pi.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + Issuer: "https://keycloak-keycloak-system.apps.rosa.av42p-79zot-u82.x8pi.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" Type: "email" certificate: organizationName: Red Hat diff --git a/internal/controller/rekor/actions/server/config_map.go b/internal/controller/rekor/actions/server/config_map.go index d87f8918a..e422197e4 100644 --- a/internal/controller/rekor/actions/server/config_map.go +++ b/internal/controller/rekor/actions/server/config_map.go @@ -30,9 +30,9 @@ func (i configMapAction) Name() string { func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") - // signingKeySecret: OCP related + // signingKeySecret: OCP signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") - return c.Reason == constants.Creating || c.Reason == constants.Ready && cm == nil && signingKeySecret != nil + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && signingKeySecret != nil && instance.Spec.TLSCertificate.CACertRef == nil } func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { diff --git a/internal/controller/trillian/actions/logserver/deployment.go b/internal/controller/trillian/actions/logserver/deployment.go index 843539afd..da9e17d50 100644 --- a/internal/controller/trillian/actions/logserver/deployment.go +++ b/internal/controller/trillian/actions/logserver/deployment.go @@ -116,7 +116,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli Name: "tls-cert", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: "log-server-" + instance.Name + "-tls-secret", + SecretName: instance.Name + "-trillian-log-server-tls-secret", }, }, }) diff --git a/internal/controller/trillian/actions/logserver/service.go b/internal/controller/trillian/actions/logserver/service.go index be74c388a..c2d9d33ba 100644 --- a/internal/controller/trillian/actions/logserver/service.go +++ b/internal/controller/trillian/actions/logserver/service.go @@ -79,7 +79,7 @@ func (i createServiceAction) Handle(ctx context.Context, instance *rhtasv1alpha1 if logserverService.Annotations == nil { logserverService.Annotations = make(map[string]string) } - logserverService.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = "log-server-" + instance.Name + "-tls-secret" + logserverService.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = instance.Name + "-trillian-log-server-tls-secret" err := i.Client.Update(ctx, logserverService) if err != nil { return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate logserver service: %w", err), instance) From 81eeeb15c6c0663fc59f8326dfdbf18e327f5dc4 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 12:03:00 +0200 Subject: [PATCH 04/34] updates: Create Tree Jobs, enable TLS on Trillian, Rekor and Ctlog --- api/v1alpha1/ctlog_types.go | 4 + api/v1alpha1/ctlog_types_test.go | 10 + api/v1alpha1/zz_generated.deepcopy.go | 6 + bundle/manifests/rhtas.redhat.com_ctlogs.yaml | 111 ++++++++++ .../manifests/rhtas.redhat.com_fulcios.yaml | 4 +- .../rhtas.redhat.com_securesigns.yaml | 121 ++++++----- .../manifests/rhtas.redhat.com_trillians.yaml | 61 ------ config/crd/bases/rhtas.redhat.com_ctlogs.yaml | 111 ++++++++++ .../crd/bases/rhtas.redhat.com_fulcios.yaml | 4 +- .../bases/rhtas.redhat.com_securesigns.yaml | 60 +++++- config/samples/rhtas_v1alpha1_securesign.yaml | 4 +- internal/controller/common/create_tree.go | 98 --------- .../controller/ctlog/actions/config_map.go | 79 +++++++ .../controller/ctlog/actions/constants.go | 16 +- .../ctlog/actions/create_tree_job.go | 191 +++++++++++++++++ .../controller/ctlog/actions/deployment.go | 102 ++++++++++ internal/controller/ctlog/actions/rbac.go | 2 +- .../controller/ctlog/actions/resolve_tree.go | 69 +++++-- .../ctlog/actions/resolve_tree_test.go | 88 ++++---- internal/controller/ctlog/actions/service.go | 27 ++- internal/controller/ctlog/ctlog_controller.go | 5 +- .../controller/ctlog/ctlog_controller_test.go | 12 ++ internal/controller/rekor/actions/rbac.go | 2 +- .../rekor/actions/server/create_tree_job.go | 192 ++++++++++++++++++ .../rekor/actions/server/deployment.go | 2 +- .../rekor/actions/server/resolve_tree.go | 69 +++++-- .../rekor/actions/server/resolve_tree_test.go | 90 ++++---- internal/controller/rekor/rekor_controller.go | 1 + 28 files changed, 1154 insertions(+), 387 deletions(-) delete mode 100644 internal/controller/common/create_tree.go create mode 100644 internal/controller/ctlog/actions/config_map.go create mode 100644 internal/controller/ctlog/actions/create_tree_job.go create mode 100644 internal/controller/rekor/actions/server/create_tree_job.go diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 5c644bcd7..923f5d2bd 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"` + // Reference to TLS server certificate, private key and CA certificate + //+optional + TLSCertificate TLSCert `json:"tls"` } // 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"` + TLSCertificate *TLSCert `json:"tls,omitempty"` // The ID of a Trillian tree that stores the log data. // +kubebuilder:validation:Type=number TreeID *int64 `json:"treeID,omitempty"` diff --git a/api/v1alpha1/ctlog_types_test.go b/api/v1alpha1/ctlog_types_test.go index 3026af7d8..55ad7618b 100644 --- a/api/v1alpha1/ctlog_types_test.go +++ b/api/v1alpha1/ctlog_types_test.go @@ -136,6 +136,16 @@ var _ = Describe("CTlog", func() { Address: "trillian-system.default.svc", Port: &port, }, + TLSCertificate: TLSCert{ + CertRef: &SecretKeySelector{ + Key: "cert", + LocalObjectReference: LocalObjectReference{Name: "secret"}, + }, + PrivateKeyRef: &SecretKeySelector{ + Key: "key", + LocalObjectReference: LocalObjectReference{Name: "secret"}, + }, + }, }, } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 5181515a4..5e2d29593 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.TLSCertificate.DeepCopyInto(&out.TLSCertificate) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CTlogSpec. @@ -207,6 +208,11 @@ func (in *CTlogStatus) DeepCopyInto(out *CTlogStatus) { *out = make([]SecretKeySelector, len(*in)) copy(*out, *in) } + if in.TLSCertificate != nil { + in, out := &in.TLSCertificate, &out.TLSCertificate + *out = new(TLSCert) + (*in).DeepCopyInto(*out) + } if in.TreeID != nil { in, out := &in.TreeID, &out.TreeID *out = new(int64) diff --git a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 1d4802c09..6aa0ac173 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -152,6 +152,62 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Reference to TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -343,6 +399,61 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: TLSCert defines fields for TLS certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || 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..5eceefc64 100644 --- a/bundle/manifests/rhtas.redhat.com_fulcios.yaml +++ b/bundle/manifests/rhtas.redhat.com_fulcios.yaml @@ -231,11 +231,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 + default: 0 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer prefix: default: trusted-artifact-signer diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index 513a961df..adb219bac 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -168,6 +168,62 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Reference to TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -383,11 +439,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 + default: 0 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer prefix: default: trusted-artifact-signer @@ -971,67 +1027,6 @@ spec: required: - tls type: object - signer: - properties: - tls: - description: Secret with TLS server certificate, private key - and CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) - required: - - tls - type: object type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/bundle/manifests/rhtas.redhat.com_trillians.yaml b/bundle/manifests/rhtas.redhat.com_trillians.yaml index 5c5ef6ff5..96330ca3b 100644 --- a/bundle/manifests/rhtas.redhat.com_trillians.yaml +++ b/bundle/manifests/rhtas.redhat.com_trillians.yaml @@ -268,67 +268,6 @@ spec: required: - tls type: object - signer: - properties: - tls: - description: Secret with TLS server certificate, private key and - CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) - required: - - tls - type: object type: object status: description: TrillianStatus defines the observed state of Trillian diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index 798ed7369..3f22fd0b0 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -152,6 +152,62 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Reference to TLS server certificate, private key and + CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -343,6 +399,61 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: TLSCert defines fields for TLS certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || 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..587d976f2 100644 --- a/config/crd/bases/rhtas.redhat.com_fulcios.yaml +++ b/config/crd/bases/rhtas.redhat.com_fulcios.yaml @@ -231,11 +231,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 + default: 0 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer prefix: default: trusted-artifact-signer diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 478018227..54d592960 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -168,6 +168,62 @@ spec: - name type: object x-kubernetes-map-type: atomic + tls: + description: Reference to TLS server certificate, private key + and CA certificate + properties: + caCertRef: + description: Reference to CA certificate + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic + certRef: + description: Reference to service certificate + 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 + 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.certRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -383,11 +439,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 80 + default: 0 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 1 + minimum: 0 type: integer prefix: default: trusted-artifact-signer diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index 69c962490..f8f7d93d9 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -23,8 +23,8 @@ spec: config: OIDCIssuers: - ClientID: "trusted-artifact-signer" - IssuerURL: "https://keycloak-keycloak-system.apps.rosa.av42p-79zot-u82.x8pi.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" - Issuer: "https://keycloak-keycloak-system.apps.rosa.av42p-79zot-u82.x8pi.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + IssuerURL: "https://keycloak-keycloak-system.apps.rosa.iduhn-ah6m6-dk9.o468.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + Issuer: "https://keycloak-keycloak-system.apps.rosa.iduhn-ah6m6-dk9.o468.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" Type: "email" certificate: organizationName: Red Hat diff --git a/internal/controller/common/create_tree.go b/internal/controller/common/create_tree.go deleted file mode 100644 index 0a60e0f50..000000000 --- a/internal/controller/common/create_tree.go +++ /dev/null @@ -1,98 +0,0 @@ -package common - -import ( - "context" - "fmt" - "net" - "time" - - "github.com/google/trillian" - "github.com/google/trillian/client" - "github.com/securesign/operator/internal/controller/common/utils/kubernetes" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/protobuf/types/known/durationpb" - "k8s.io/klog/v2" -) - -// reference code https://github.com/sigstore/scaffolding/blob/main/cmd/trillian/createtree/main.go -func CreateTrillianTree(ctx context.Context, displayName string, trillianURL string, deadline int64) (*trillian.Tree, error) { - var err error - inContainer, err := kubernetes.ContainerMode() - if err == nil { - if !inContainer { - fmt.Println("Operator is running on localhost. You need to port-forward services.") - for it := 0; it < 60; it++ { - if rawConnect("localhost", "8091") { - fmt.Println("Connection is open.") - trillianURL = "localhost:8091" - break - } else { - fmt.Println("Execute `oc port-forward service/trillian-logserver 8091 8091` in your namespace to continue.") - time.Sleep(time.Duration(5) * time.Second) - } - } - - } - } else { - klog.Info("Can't recognise operator mode - expecting in-container run") - } - req, err := newRequest(displayName) - if err != nil { - return nil, err - } - var opts grpc.DialOption - klog.Warning("Using an insecure gRPC connection to Trillian") - opts = grpc.WithTransportCredentials(insecure.NewCredentials()) - conn, err := grpc.Dial(trillianURL, opts) - if err != nil { - return nil, fmt.Errorf("failed to dial: %w", err) - } - defer func() { _ = conn.Close() }() - - adminClient := trillian.NewTrillianAdminClient(conn) - logClient := trillian.NewTrillianLogClient(conn) - - timeout := time.Duration(deadline) * time.Second - ctx2, cancel := context.WithTimeout(ctx, timeout) - tree, err := client.CreateAndInitTree(ctx2, req, adminClient, logClient) - defer cancel() - if err != nil { - return nil, fmt.Errorf("could not create Trillian tree: %w", err) - } - return tree, err -} - -func rawConnect(host string, port string) bool { - timeout := time.Second - conn, err := net.DialTimeout("tcp", net.JoinHostPort(host, port), timeout) - if err != nil { - return false - } - if conn != nil { - defer func() { _ = conn.Close() }() - return true - } - return false -} - -func newRequest(displayName string) (*trillian.CreateTreeRequest, error) { - ts, ok := trillian.TreeState_value[trillian.TreeState_ACTIVE.String()] - if !ok { - return nil, fmt.Errorf("unknown TreeState: %v", trillian.TreeState_ACTIVE) - } - - tt, ok := trillian.TreeType_value[trillian.TreeType_LOG.String()] - if !ok { - return nil, fmt.Errorf("unknown TreeType: %v", trillian.TreeType_LOG) - } - - ctr := &trillian.CreateTreeRequest{Tree: &trillian.Tree{ - TreeState: trillian.TreeState(ts), - TreeType: trillian.TreeType(tt), - DisplayName: displayName, - MaxRootDuration: durationpb.New(time.Hour), - }} - - return ctr, nil -} diff --git a/internal/controller/ctlog/actions/config_map.go b/internal/controller/ctlog/actions/config_map.go new file mode 100644 index 000000000..354b76878 --- /dev/null +++ b/internal/controller/ctlog/actions/config_map.go @@ -0,0 +1,79 @@ +package actions + +import ( + "context" + "fmt" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "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" + corev1 "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" +) + +func NewCAConfigMapAction() action.Action[*rhtasv1alpha1.CTlog] { + return &configMapAction{} +} + +type configMapAction struct { + action.BaseAction +} + +func (i configMapAction) Name() string { + return "create CA configMap" +} + +func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Spec.TLSCertificate.CACertRef == nil +} + +func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { + var ( + err error + updated bool + ) + + labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) + + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ca-configmap", + Namespace: instance.Namespace, + Labels: labels, + }, + Data: map[string]string{}, + } + + if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + if updated, err = i.Ensure(ctx, configMap); err != nil { + 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 configMap: %w", err), instance) + } + + //TLS: Annotate configMap + configMap.Annotations = map[string]string{"service.beta.openshift.io/inject-cabundle": "true"} + err = i.Client.Update(ctx, configMap) + if err != nil { + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate configMap: %w", err), instance) + } + + if updated { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + return i.StatusUpdate(ctx, instance) + } else { + return i.Continue() + } +} diff --git a/internal/controller/ctlog/actions/constants.go b/internal/controller/ctlog/actions/constants.go index 5ead8d88d..9e1a264d7 100644 --- a/internal/controller/ctlog/actions/constants.go +++ b/internal/controller/ctlog/actions/constants.go @@ -8,13 +8,15 @@ const ( RBACName = "ctlog" MonitoringRoleName = "prometheus-k8s-ctlog" - CertCondition = "FulcioCertAvailable" - ServerPortName = "http" - ServerPort = 80 - ServerTargetPort = 6962 - MetricsPortName = "metrics" - MetricsPort = 6963 - ServerCondition = "ServerAvailable" + CertCondition = "FulcioCertAvailable" + ServerPortName = "http" + ServerPort = 80 + HttpsServerPortName = "https" + HttpsServerPort = 443 + ServerTargetPort = 6962 + MetricsPortName = "metrics" + MetricsPort = 6963 + ServerCondition = "ServerAvailable" CTLPubLabel = constants.LabelNamespace + "/ctfe.pub" ) diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go new file mode 100644 index 000000000..ce9059f01 --- /dev/null +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -0,0 +1,191 @@ +package actions + +import ( + "context" + "fmt" + + 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" + "github.com/securesign/operator/internal/controller/ctlog/utils" + actions2 "github.com/securesign/operator/internal/controller/trillian/actions" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.CTlog] { + return &createTreeJobAction{} +} + +type createTreeJobAction struct { + action.BaseAction +} + +func (i createTreeJobAction) Name() string { + return "create tree job" +} + +func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, "ctlog-tree-id-config") + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil +} + +func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { + var ( + err error + updated bool + ) + + CtlogTreeJobName := "ctlog-create-tree" + configMapName := "ctlog-tree-id-config" + var trillUrl string + + switch { + case instance.Spec.Trillian.Port == nil: + err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) + case instance.Spec.Trillian.Address == "": + trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) + default: + trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) + } + if err != nil { + return i.Failed(err) + } + i.Logger.V(1).Info("trillian logserver", "address", trillUrl) + + if c := meta.FindStatusCondition(instance.Status.Conditions, CtlogTreeJobName); c == nil { + instance.SetCondition(metav1.Condition{ + Type: CtlogTreeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "Creating ctlog tree Job", + }) + } + + labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) + + // Needed for configMap clean-up + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: instance.Namespace, + Labels: labels, + }, + Data: map[string]string{}, + } + if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + if updated, err = i.Ensure(ctx, configMap); err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + } + if updated { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + } + + parallelism := int32(1) + completions := int32(1) + activeDeadlineSeconds := int64(600) + backoffLimit := int32(5) + + signingKeySecret, _ := kubernetes.GetSecret(i.Client, "openshift-service-ca", "signing-key") + trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) + cmd := "" + switch { + case trustedCAAnnotation != nil: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + case signingKeySecret != nil: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + default: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree", trillUrl) + } + command := []string{ + "/bin/sh", + "-c", + fmt.Sprintf(` + TREE_ID=$(%s) + if [ $? -eq 0 ]; then + echo "TREE_ID=$TREE_ID" + # Read the service account token + TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + # Read the namespace + NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) + # OpenShift API server URL + API_SERVER=https://openshift.default.svc + # Create or update the ConfigMap + curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/merge-patch+json" \ + -d '{ + "data": { + "tree_id": "'$TREE_ID'" + } + }' + if [ $? -ne 0 ]; then + echo "Failed to update ConfigMap" >&2 + exit 1 + fi + else + echo "Failed to create tree" >&2 + exit 1 + fi + `, cmd, configMapName), + } + env := []corev1.EnvVar{} + + job := kubernetes.CreateJob(instance.Namespace, CtlogTreeJobName, labels, constants.CreateTreeImage, RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) + } + + if trustedCAAnnotation != nil { + err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + if err != nil { + return i.Failed(err) + } + } + + if signingKeySecret != nil && trustedCAAnnotation == nil { + job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: instance.Name + "-trillian-log-server-tls-secret", + }, + }, + }) + job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/etc/ssl/certs", + ReadOnly: true, + }) + } + + _, err = i.Ensure(ctx, job) + if err != nil { + return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) + } + + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: CtlogTreeJobName, + Status: metav1.ConditionTrue, + Reason: constants.Ready, + Message: "ctlog tree Job Created", + }) + + return i.Continue() +} diff --git a/internal/controller/ctlog/actions/deployment.go b/internal/controller/ctlog/actions/deployment.go index ad6462398..2b3fc56a1 100644 --- a/internal/controller/ctlog/actions/deployment.go +++ b/internal/controller/ctlog/actions/deployment.go @@ -8,9 +8,11 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "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" "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" + corev1 "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" @@ -41,6 +43,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") switch { case instance.Spec.Trillian.Address == "": instance.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", trillian.LogserverDeploymentName, instance.Namespace) @@ -61,6 +64,105 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) return i.Failed(err) } + // TLS certificate + if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil { + dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TLSCertificate.CertRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: instance.Spec.TLSCertificate.CertRef.Key, + Path: "tls.crt", + }, + }, + }, + }, + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TLSCertificate.PrivateKeyRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: instance.Spec.TLSCertificate.PrivateKeyRef.Key, + Path: "tls.key", + }, + }, + }, + }, + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Spec.TLSCertificate.CACertRef.Name, + }, + Items: []corev1.KeyToPath{ + { + Key: "ca.crt", // User should use this key. + Path: "ca.crt", + }, + }, + }, + }, + }, + }, + }, + }) + } else if signingKeySecret != nil { + i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") + dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Projected: &corev1.ProjectedVolumeSource{ + Sources: []corev1.VolumeProjection{ + { + Secret: &corev1.SecretProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: instance.Name + "-ctlog-tls-secret", + }, + }, + }, + { + ConfigMap: &corev1.ConfigMapProjection{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "ca-configmap", + }, + Items: []corev1.KeyToPath{ + { + Key: "service-ca.crt", + Path: "ca.crt", + }, + }, + }, + }, + }, + }, + }, + }) + } else { + i.Logger.V(1).Info("Communication between services is insecure") + } + + if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil || signingKeySecret != nil { + dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/etc/ssl/certs", + ReadOnly: true, + }) + // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_certificate", "/etc/ssl/certs/tls.crt") + // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_key", "/etc/ssl/certs/tls.key") + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", "/etc/ssl/certs/ca.crt") + } + if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err)) } diff --git a/internal/controller/ctlog/actions/rbac.go b/internal/controller/ctlog/actions/rbac.go index b5d0028e3..cb097b96d 100644 --- a/internal/controller/ctlog/actions/rbac.go +++ b/internal/controller/ctlog/actions/rbac.go @@ -64,7 +64,7 @@ func (i rbacAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) * { APIGroups: []string{""}, Resources: []string{"configmaps"}, - Verbs: []string{"create", "get", "update"}, + Verbs: []string{"create", "get", "update", "patch"}, }, { APIGroups: []string{""}, diff --git a/internal/controller/ctlog/actions/resolve_tree.go b/internal/controller/ctlog/actions/resolve_tree.go index 0c885551a..678abc6ba 100644 --- a/internal/controller/ctlog/actions/resolve_tree.go +++ b/internal/controller/ctlog/actions/resolve_tree.go @@ -3,25 +3,23 @@ package actions import ( "context" "fmt" + "strconv" + "time" "github.com/google/trillian" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) -type createTree func(ctx context.Context, displayName string, trillianURL string, deadline int64) (*trillian.Tree, error) - func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtasv1alpha1.CTlog] { a := &resolveTreeAction{ - createTree: common.CreateTrillianTree, + timeout: time.Duration(constants.CreateTreeDeadline) * time.Second, } for _, opt := range opts { @@ -32,7 +30,7 @@ func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtas type resolveTreeAction struct { action.BaseAction - createTree createTree + timeout time.Duration } func (i resolveTreeAction) Name() string { @@ -62,23 +60,58 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.C } var err error var tree *trillian.Tree - var trillUrl string - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) + cm := &v1.ConfigMap{} + deadline := time.Now().Add(i.timeout) + for time.Now().Before(deadline) { + err = i.Client.Get(ctx, types.NamespacedName{Name: "ctlog-tree-id-config", Namespace: instance.Namespace}, cm) + if err == nil && cm.Data != nil { + break + } + if err != nil { + i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) + } + time.Sleep(2 * time.Second) } + if err != nil { + i.Logger.V(1).Error(fmt.Errorf("timed out waiting for the ConfigMap"), err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: fmt.Sprintf("timed out waiting for the ConfigMap: %v", err), + }) + return i.Failed(fmt.Errorf("timed out waiting for the ConfigMap: %s", "configmap not found")) + } + + if cm.Data == nil { + err = fmt.Errorf("ConfigMap data is empty") + i.Logger.V(1).Error(err, err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) return i.Failed(err) } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - tree, err = i.createTree(ctx, "ctlog-tree", trillUrl, constants.CreateTreeDeadline) - if err != nil { + treeId, exists := cm.Data["tree_id"] + treeIdInt, err := strconv.ParseInt(treeId, 10, 64) + tree = &trillian.Tree{TreeId: treeIdInt} + if !exists { + i.Logger.V(1).Error(err, err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + return i.Failed(err) + } + + if !exists { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: ServerCondition, Status: metav1.ConditionFalse, diff --git a/internal/controller/ctlog/actions/resolve_tree_test.go b/internal/controller/ctlog/actions/resolve_tree_test.go index 9b0bd684b..106587c63 100644 --- a/internal/controller/ctlog/actions/resolve_tree_test.go +++ b/internal/controller/ctlog/actions/resolve_tree_test.go @@ -2,20 +2,18 @@ package actions import ( "context" - "errors" "fmt" "reflect" "testing" + "time" + v1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" - "github.com/google/trillian" . "github.com/onsi/gomega" 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/utils" - "github.com/securesign/operator/internal/controller/trillian/actions" testAction "github.com/securesign/operator/internal/testing/action" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -115,7 +113,7 @@ func TestResolveTree_Handle(t *testing.T) { type env struct { spec rhtasv1alpha1.CTlogSpec statusTreeId *int64 - createTree createTree + configMap *v1.ConfigMap } type want struct { result *action.Result @@ -133,7 +131,15 @@ func TestResolveTree_Handle(t *testing.T) { TreeID: nil, Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, nil), + configMap: &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ctlog-tree-id-config", + Namespace: "default", + }, + Data: map[string]string{ + "tree_id": "5555555", + }, + }, }, want: want{ result: testAction.StatusUpdate(), @@ -146,7 +152,7 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "update tree", + name: "update tree from spec", env: env{ spec: rhtasv1alpha1.CTlogSpec{ TreeID: ptr.To(int64(123456)), @@ -184,16 +190,22 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "unable to create a new tree", + name: "ConfigMap data is empty", env: env{ spec: rhtasv1alpha1.CTlogSpec{ TreeID: nil, Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(nil, errors.New("timeout error"), nil), + configMap: &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "ctlog-tree-id-config", + Namespace: "default", + }, + Data: map[string]string{}, + }, }, want: want{ - result: testAction.FailedWithStatusUpdate(fmt.Errorf("could not create trillian tree: timeout error")), + result: testAction.Failed(fmt.Errorf("ConfigMap data is empty")), verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { g.Expect(ctlog.Spec.TreeID).Should(BeNil()) g.Expect(ctlog.Status.TreeID).Should(BeNil()) @@ -201,43 +213,20 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "resolve trillian address", + name: "ConfigMap not found", env: env{ spec: rhtasv1alpha1.CTlogSpec{ Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, func(displayName string, trillianURL string, deadline int64) { - g.Expect(trillianURL).Should(Equal(fmt.Sprintf("%s.%s.svc:%d", actions.LogserverDeploymentName, "default", 8091))) - }), - }, - want: want{ - result: testAction.StatusUpdate(), - }, - }, - { - name: "custom trillian address", - env: env{ - spec: rhtasv1alpha1.CTlogSpec{ - Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(1234)), Address: "custom-address.namespace.svc"}, - }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, func(displayName string, trillianURL string, deadline int64) { - g.Expect(trillianURL).Should(Equal(fmt.Sprintf("custom-address.namespace.svc:%d", 1234))) - }), }, want: want{ - result: testAction.StatusUpdate(), - }, - }, - { - name: "trillian port not specified", - env: env{ - spec: rhtasv1alpha1.CTlogSpec{ - Trillian: rhtasv1alpha1.TrillianService{Port: nil}, + result: testAction.Failed(fmt.Errorf("timed out waiting for the ConfigMap: configmap not found")), + verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { + g.Expect(ctlog.Status.Conditions).To(ContainElement( + WithTransform(func(c metav1.Condition) string { return c.Message }, ContainSubstring("timed out waiting for the ConfigMap:")), + )) }, }, - want: want{ - result: testAction.Failed(fmt.Errorf("resolve treeID: %v", utils.TrillianPortNotSpecified)), - }, }, } for _, tt := range tests { @@ -265,12 +254,12 @@ func TestResolveTree_Handle(t *testing.T) { WithStatusSubresource(instance). Build() - a := testAction.PrepareAction(c, NewResolveTreeAction(func(t *resolveTreeAction) { - if tt.env.createTree == nil { - t.createTree = mockCreateTree(nil, errors.New("createTree should not be executed"), nil) - } else { - t.createTree = tt.env.createTree - } + if tt.env.configMap != nil { + c.Create(ctx, tt.env.configMap) + } + + a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { + a.timeout = 5 * time.Second // Reduced timeout for testing })) if got := a.Handle(ctx, instance); !reflect.DeepEqual(got, tt.want.result) { @@ -282,12 +271,3 @@ func TestResolveTree_Handle(t *testing.T) { }) } } - -func mockCreateTree(tree *trillian.Tree, err error, verify func(displayName string, trillianURL string, deadline int64)) createTree { - return func(ctx context.Context, displayName string, trillianURL string, deadline int64) (*trillian.Tree, error) { - if verify != nil { - verify(displayName, trillianURL, deadline) - } - return tree, err - } -} diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index b1f35e895..5ddc8c7c9 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -7,6 +7,7 @@ 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" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -40,7 +41,19 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) - svc := kubernetes.CreateService(instance.Namespace, ComponentName, ServerPortName, ServerPort, ServerTargetPort, labels) + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + var port int + var portName string + if instance.Spec.TLSCertificate.CertRef != nil || signingKeySecret != nil { + // port = HttpsServerPort // TODO + // portName = HttpsServerPortName + port = ServerPort + portName = ServerPortName + } else { + port = ServerPort + portName = ServerPortName + } + svc := kubernetes.CreateService(instance.Namespace, ComponentName, portName, port, ServerTargetPort, labels) if instance.Spec.Monitoring.Enabled { svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ Name: MetricsPortName, @@ -62,6 +75,18 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create service: %w", err), instance) } + //TLS: Annotate service + if signingKeySecret != nil && instance.Spec.TLSCertificate.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-secret" + err := i.Client.Update(ctx, svc) + if err != nil { + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate service: %w", err), instance) + } + } + if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "Service created"}) diff --git a/internal/controller/ctlog/ctlog_controller.go b/internal/controller/ctlog/ctlog_controller.go index f4a7052fc..6488cced4 100644 --- a/internal/controller/ctlog/ctlog_controller.go +++ b/internal/controller/ctlog/ctlog_controller.go @@ -93,12 +93,14 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl }), transitions.NewToCreatePhaseAction[*rhtasv1alpha1.CTlog](), + actions.NewRBACAction(), + actions.NewCAConfigMapAction(), actions.NewHandleFulcioCertAction(), actions.NewHandleKeysAction(), + actions.NewCreateTreeJobAction(), actions.NewResolveTreeAction(), actions.NewServerConfigAction(), - actions.NewRBACAction(), actions.NewDeployAction(), actions.NewServiceAction(), actions.NewCreateMonitorAction(), @@ -155,6 +157,7 @@ func (r *CTlogReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&rhtasv1alpha1.CTlog{}). Owns(&v1.Deployment{}). Owns(&v12.Service{}). + Owns(&v12.ConfigMap{}). WatchesMetadata(partialSecret, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { val, ok := object.GetLabels()["app.kubernetes.io/instance"] if ok { diff --git a/internal/controller/ctlog/ctlog_controller_test.go b/internal/controller/ctlog/ctlog_controller_test.go index 54d60daa7..c76c4bbb1 100644 --- a/internal/controller/ctlog/ctlog_controller_test.go +++ b/internal/controller/ctlog/ctlog_controller_test.go @@ -96,6 +96,17 @@ var _ = Describe("CTlog controller", func() { Spec: v1alpha1.CTlogSpec{ TreeID: &ptr, + TLSCertificate: v1alpha1.TLSCert{ + CertRef: &v1alpha1.SecretKeySelector{ + Key: "cert", + LocalObjectReference: v1alpha1.LocalObjectReference{Name: "secret-crt"}, + }, + PrivateKeyRef: &v1alpha1.SecretKeySelector{ + Key: "key", + LocalObjectReference: v1alpha1.LocalObjectReference{Name: "secret-key"}, + }, + CACertRef: &v1alpha1.LocalObjectReference{Name: "ca-configmap"}, + }, }, } err = k8sClient.Create(ctx, instance) @@ -158,6 +169,7 @@ var _ = Describe("CTlog controller", func() { return k8sClient.Get(ctx, types.NamespacedName{Name: actions.ComponentName, Namespace: Namespace}, service) }).Should(Succeed()) Expect(service.Spec.Ports[0].Port).Should(Equal(int32(80))) + // Expect(service.Spec.Ports[0].Port).Should(Equal(int32(443))) // TODO By("Move to Ready phase") // Workaround to succeed condition for Ready phase diff --git a/internal/controller/rekor/actions/rbac.go b/internal/controller/rekor/actions/rbac.go index 22144f21e..daba4e9dd 100644 --- a/internal/controller/rekor/actions/rbac.go +++ b/internal/controller/rekor/actions/rbac.go @@ -64,7 +64,7 @@ func (i rbacAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) * { APIGroups: []string{""}, Resources: []string{"configmaps"}, - Verbs: []string{"create", "get", "update"}, + Verbs: []string{"create", "get", "update", "patch"}, }, { APIGroups: []string{""}, diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go new file mode 100644 index 000000000..8488aa747 --- /dev/null +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -0,0 +1,192 @@ +package server + +import ( + "context" + "fmt" + + 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" + "github.com/securesign/operator/internal/controller/rekor/actions" + "github.com/securesign/operator/internal/controller/rekor/utils" + actions2 "github.com/securesign/operator/internal/controller/trillian/actions" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.Rekor] { + return &createTreeJobAction{} +} + +type createTreeJobAction struct { + action.BaseAction +} + +func (i createTreeJobAction) Name() string { + return "create tree job" +} + +func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, "rekor-tree-id-config") + c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil +} + +func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { + var ( + err error + updated bool + ) + + RekorTreeJobName := "rekor-create-tree" + configMapName := "rekor-tree-id-config" + var trillUrl string + + switch { + case instance.Spec.Trillian.Port == nil: + err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) + case instance.Spec.Trillian.Address == "": + trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) + default: + trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) + } + if err != nil { + return i.Failed(err) + } + i.Logger.V(1).Info("trillian logserver", "address", trillUrl) + + if c := meta.FindStatusCondition(instance.Status.Conditions, RekorTreeJobName); c == nil { + instance.SetCondition(metav1.Condition{ + Type: RekorTreeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "Creating rekor tree Job", + }) + } + + labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) + + // Needed for configMap clean-up + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: configMapName, + Namespace: instance.Namespace, + Labels: labels, + }, + Data: map[string]string{}, + } + if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + if updated, err = i.Ensure(ctx, configMap); err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + } + if updated { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + } + + parallelism := int32(1) + completions := int32(1) + activeDeadlineSeconds := int64(600) + backoffLimit := int32(5) + + signingKeySecret, _ := kubernetes.GetSecret(i.Client, "openshift-service-ca", "signing-key") + trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) + cmd := "" + switch { + case trustedCAAnnotation != nil: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + case signingKeySecret != nil: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + default: + cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree", trillUrl) + } + command := []string{ + "/bin/sh", + "-c", + fmt.Sprintf(` + TREE_ID=$(%s) + if [ $? -eq 0 ]; then + echo "TREE_ID=$TREE_ID" + # Read the service account token + TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + # Read the namespace + NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) + # OpenShift API server URL + API_SERVER=https://openshift.default.svc + # Create or update the ConfigMap + curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/merge-patch+json" \ + -d '{ + "data": { + "tree_id": "'$TREE_ID'" + } + }' + if [ $? -ne 0 ]; then + echo "Failed to update ConfigMap" >&2 + exit 1 + fi + else + echo "Failed to create tree" >&2 + exit 1 + fi + `, cmd, configMapName), + } + env := []corev1.EnvVar{} + + job := kubernetes.CreateJob(instance.Namespace, RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) + } + + if trustedCAAnnotation != nil { + err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + if err != nil { + return i.Failed(err) + } + } + + if signingKeySecret != nil && trustedCAAnnotation == nil { + job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, + corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: instance.Name + "-trillian-log-server-tls-secret", + }, + }, + }) + job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, + corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/etc/ssl/certs", + ReadOnly: true, + }) + } + + _, err = i.Ensure(ctx, job) + if err != nil { + return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) + } + + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: RekorTreeJobName, + Status: metav1.ConditionTrue, + Reason: constants.Ready, + Message: "rekor tree Job Created", + }) + + return i.Continue() +} diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 6b871334b..8f28297f1 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -132,7 +132,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) MountPath: "/etc/ssl/certs", ReadOnly: true, }) - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_ca_cert", "/etc/ssl/certs/ca.crt") + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_log_server.tls_ca_cert", "/etc/ssl/certs/ca.crt") } if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { diff --git a/internal/controller/rekor/actions/server/resolve_tree.go b/internal/controller/rekor/actions/server/resolve_tree.go index 122511b8c..7e6aa703d 100644 --- a/internal/controller/rekor/actions/server/resolve_tree.go +++ b/internal/controller/rekor/actions/server/resolve_tree.go @@ -3,26 +3,24 @@ package server import ( "context" "fmt" + "strconv" + "time" "github.com/google/trillian" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/internal/controller/common" "github.com/securesign/operator/internal/controller/common/action" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/rekor/actions" - "github.com/securesign/operator/internal/controller/rekor/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/equality" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" ) -type createTree func(ctx context.Context, displayName string, trillianURL string, deadline int64) (*trillian.Tree, error) - func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtasv1alpha1.Rekor] { a := &resolveTreeAction{ - createTree: common.CreateTrillianTree, + timeout: time.Duration(constants.CreateTreeDeadline) * time.Second, } for _, opt := range opts { @@ -33,7 +31,7 @@ func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtas type resolveTreeAction struct { action.BaseAction - createTree createTree + timeout time.Duration } func (i resolveTreeAction) Name() string { @@ -63,23 +61,58 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.R } var err error var tree *trillian.Tree - var trillUrl string - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) + cm := &v1.ConfigMap{} + deadline := time.Now().Add(i.timeout) + for time.Now().Before(deadline) { + err = i.Client.Get(ctx, types.NamespacedName{Name: "rekor-tree-id-config", Namespace: instance.Namespace}, cm) + if err == nil && cm.Data != nil { + break + } + if err != nil { + i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) + } + time.Sleep(2 * time.Second) } + if err != nil { + i.Logger.V(1).Error(fmt.Errorf("timed out waiting for the ConfigMap"), err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: fmt.Sprintf("timed out waiting for the ConfigMap: %v", err), + }) + return i.Failed(fmt.Errorf("timed out waiting for the ConfigMap: %s", "configmap not found")) + } + + if cm.Data == nil { + err = fmt.Errorf("ConfigMap data is empty") + i.Logger.V(1).Error(err, err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) return i.Failed(err) } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - tree, err = i.createTree(ctx, "rekor-tree", trillUrl, constants.CreateTreeDeadline) - if err != nil { + treeId, exists := cm.Data["tree_id"] + treeIdInt, err := strconv.ParseInt(treeId, 10, 64) + tree = &trillian.Tree{TreeId: treeIdInt} + if !exists { + i.Logger.V(1).Error(err, err.Error()) + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + return i.Failed(err) + } + + if !exists { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, Status: metav1.ConditionFalse, diff --git a/internal/controller/rekor/actions/server/resolve_tree_test.go b/internal/controller/rekor/actions/server/resolve_tree_test.go index 26917022e..9769e9e96 100644 --- a/internal/controller/rekor/actions/server/resolve_tree_test.go +++ b/internal/controller/rekor/actions/server/resolve_tree_test.go @@ -2,19 +2,17 @@ package server import ( "context" - "errors" "fmt" "reflect" "testing" + "time" - "github.com/google/trillian" . "github.com/onsi/gomega" 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/rekor/utils" - "github.com/securesign/operator/internal/controller/trillian/actions" testAction "github.com/securesign/operator/internal/testing/action" + v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" @@ -114,7 +112,7 @@ func TestResolveTree_Handle(t *testing.T) { type env struct { spec rhtasv1alpha1.RekorSpec statusTreeId *int64 - createTree createTree + configMap *v1.ConfigMap } type want struct { result *action.Result @@ -132,7 +130,15 @@ func TestResolveTree_Handle(t *testing.T) { TreeID: nil, Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, nil), + configMap: &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rekor-tree-id-config", + Namespace: "default", + }, + Data: map[string]string{ + "tree_id": "5555555", + }, + }, }, want: want{ result: testAction.StatusUpdate(), @@ -145,7 +151,7 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "update tree", + name: "update tree from spec", env: env{ spec: rhtasv1alpha1.RekorSpec{ TreeID: ptr.To(int64(123456)), @@ -183,16 +189,22 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "unable to create a new tree", + name: "ConfigMap data is empty", env: env{ spec: rhtasv1alpha1.RekorSpec{ TreeID: nil, Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(nil, errors.New("timeout error"), nil), + configMap: &v1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: "rekor-tree-id-config", + Namespace: "default", + }, + Data: map[string]string{}, + }, }, want: want{ - result: testAction.FailedWithStatusUpdate(fmt.Errorf("could not create trillian tree: timeout error")), + result: testAction.Failed(fmt.Errorf("ConfigMap data is empty")), verify: func(g Gomega, rekor *rhtasv1alpha1.Rekor) { g.Expect(rekor.Spec.TreeID).Should(BeNil()) g.Expect(rekor.Status.TreeID).Should(BeNil()) @@ -200,43 +212,20 @@ func TestResolveTree_Handle(t *testing.T) { }, }, { - name: "resolve trillian address", + name: "ConfigMap not found", env: env{ spec: rhtasv1alpha1.RekorSpec{ - Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(1234))}, - }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, func(displayName string, trillianURL string, deadline int64) { - g.Expect(trillianURL).Should(Equal(fmt.Sprintf("%s.%s.svc:%d", actions.LogserverDeploymentName, "default", 1234))) - }), - }, - want: want{ - result: testAction.StatusUpdate(), - }, - }, - { - name: "custom trillian address", - env: env{ - spec: rhtasv1alpha1.RekorSpec{ - Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(1234)), Address: "custom-address.namespace.svc"}, + Trillian: rhtasv1alpha1.TrillianService{Port: ptr.To(int32(8091))}, }, - createTree: mockCreateTree(&trillian.Tree{TreeId: 5555555}, nil, func(displayName string, trillianURL string, deadline int64) { - g.Expect(trillianURL).Should(Equal(fmt.Sprintf("custom-address.namespace.svc:%d", 1234))) - }), }, want: want{ - result: testAction.StatusUpdate(), - }, - }, - { - name: "trillian port not specified", - env: env{ - spec: rhtasv1alpha1.RekorSpec{ - Trillian: rhtasv1alpha1.TrillianService{Port: nil}, + result: testAction.Failed(fmt.Errorf("timed out waiting for the ConfigMap: configmap not found")), + verify: func(g Gomega, rekor *rhtasv1alpha1.Rekor) { + g.Expect(rekor.Status.Conditions).To(ContainElement( + WithTransform(func(c metav1.Condition) string { return c.Message }, ContainSubstring("timed out waiting for the ConfigMap:")), + )) }, }, - want: want{ - result: testAction.Failed(fmt.Errorf("resolve treeID: %v", utils.TrillianPortNotSpecified)), - }, }, } for _, tt := range tests { @@ -264,12 +253,12 @@ func TestResolveTree_Handle(t *testing.T) { WithStatusSubresource(instance). Build() - a := testAction.PrepareAction(c, NewResolveTreeAction(func(t *resolveTreeAction) { - if tt.env.createTree == nil { - t.createTree = mockCreateTree(nil, errors.New("createTree should not be executed"), nil) - } else { - t.createTree = tt.env.createTree - } + if tt.env.configMap != nil { + c.Create(ctx, tt.env.configMap) + } + + a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { + a.timeout = 5 * time.Second // Reduced timeout for testing })) if got := a.Handle(ctx, instance); !reflect.DeepEqual(got, tt.want.result) { @@ -281,12 +270,3 @@ func TestResolveTree_Handle(t *testing.T) { }) } } - -func mockCreateTree(tree *trillian.Tree, err error, verify func(displayName string, trillianURL string, deadline int64)) createTree { - return func(ctx context.Context, displayName string, trillianURL string, deadline int64) (*trillian.Tree, error) { - if verify != nil { - verify(displayName, trillianURL, deadline) - } - return tree, err - } -} diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index b75d0df2c..b52de8d6e 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -109,6 +109,7 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions2.NewRBACAction(), server.NewShardingConfigAction(), + server.NewCreateTreeJobAction(), server.NewResolveTreeAction(), server.NewCAConfigMapAction(), server.NewCreatePvcAction(), From 8268ca530f6cde59b25f12a60a4763f7bea8b141 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 12:11:54 +0200 Subject: [PATCH 05/34] update --- internal/controller/constants/images.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/controller/constants/images.go b/internal/controller/constants/images.go index ba904613e..3cbb8e03e 100644 --- a/internal/controller/constants/images.go +++ b/internal/controller/constants/images.go @@ -25,4 +25,5 @@ var ( ClientServerImage_f = "registry.redhat.io/rhtas/client-server-f-rhel9@sha256:8c8c4bfcbc8728ee46a427a4179622e4437e3502aa4b29af7539bf2eee999ff6" SegmentBackupImage = "registry.redhat.io/rhtas/segment-reporting-rhel9@sha256:c7fa18f6dec1fdd308d5a6ed74f5f6bf2bd30d6759d7d2464875b6e80f269fb2" TimestampAuthorityImage = "registry.redhat.io/rhtas/timestamp-authority-rhel9@sha256:d957041e1f10faf087333b9f1d39b2bb4b26edd37a812192e67771c423950def" + CreateTreeImage = "quay.io/redhat-user-workloads/rhtas-tenant/trillian/createtree@sha256:d4d3a99e8da94a89312babe65545634fa91fdf14dd2a6f8da4be489a7ef52d90" ) From 6fabfd84ab53539983e3a63e5a831c31136ab2d6 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 12:16:37 +0200 Subject: [PATCH 06/34] fix lint --- internal/controller/ctlog/actions/resolve_tree_test.go | 5 ++++- .../controller/rekor/actions/server/resolve_tree_test.go | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/internal/controller/ctlog/actions/resolve_tree_test.go b/internal/controller/ctlog/actions/resolve_tree_test.go index 106587c63..b4e180648 100644 --- a/internal/controller/ctlog/actions/resolve_tree_test.go +++ b/internal/controller/ctlog/actions/resolve_tree_test.go @@ -255,7 +255,10 @@ func TestResolveTree_Handle(t *testing.T) { Build() if tt.env.configMap != nil { - c.Create(ctx, tt.env.configMap) + err := c.Create(ctx, tt.env.configMap) + if err != nil { + t.Fatalf("failed to create config map: %v", err) + } } a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { diff --git a/internal/controller/rekor/actions/server/resolve_tree_test.go b/internal/controller/rekor/actions/server/resolve_tree_test.go index 9769e9e96..dea62581c 100644 --- a/internal/controller/rekor/actions/server/resolve_tree_test.go +++ b/internal/controller/rekor/actions/server/resolve_tree_test.go @@ -254,7 +254,10 @@ func TestResolveTree_Handle(t *testing.T) { Build() if tt.env.configMap != nil { - c.Create(ctx, tt.env.configMap) + err := c.Create(ctx, tt.env.configMap) + if err != nil { + t.Fatalf("failed to create config map: %v", err) + } } a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { From b018066191e6e012cf9d03be8845636975e2c2dd Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 14:30:41 +0200 Subject: [PATCH 07/34] updates --- config/samples/rhtas_v1alpha1_securesign.yaml | 4 ++-- .../controller/ctlog/actions/create_tree_job.go | 4 ---- internal/controller/ctlog/actions/service.go | 13 +------------ .../rekor/actions/server/create_tree_job.go | 4 ---- test/e2e/tls_configuration_test.go | 5 ++--- 5 files changed, 5 insertions(+), 25 deletions(-) diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index f8f7d93d9..6c8d360fe 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -23,8 +23,8 @@ spec: config: OIDCIssuers: - ClientID: "trusted-artifact-signer" - IssuerURL: "https://keycloak-keycloak-system.apps.rosa.iduhn-ah6m6-dk9.o468.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" - Issuer: "https://keycloak-keycloak-system.apps.rosa.iduhn-ah6m6-dk9.o468.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + IssuerURL: "https://your-oidc-issuer-url" + Issuer: "https://your-oidc-issuer-url" Type: "email" certificate: organizationName: Red Hat diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index ce9059f01..7eb398ec0 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -118,13 +118,9 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 TREE_ID=$(%s) if [ $? -eq 0 ]; then echo "TREE_ID=$TREE_ID" - # Read the service account token TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - # Read the namespace NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - # OpenShift API server URL API_SERVER=https://openshift.default.svc - # Create or update the ConfigMap curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index 5ddc8c7c9..5509350ae 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -41,19 +41,8 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) + svc := kubernetes.CreateService(instance.Namespace, ComponentName, ServerPortName, ServerPort, ServerTargetPort, labels) signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") - var port int - var portName string - if instance.Spec.TLSCertificate.CertRef != nil || signingKeySecret != nil { - // port = HttpsServerPort // TODO - // portName = HttpsServerPortName - port = ServerPort - portName = ServerPortName - } else { - port = ServerPort - portName = ServerPortName - } - svc := kubernetes.CreateService(instance.Namespace, ComponentName, portName, port, ServerTargetPort, labels) if instance.Spec.Monitoring.Enabled { svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ Name: MetricsPortName, diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index 8488aa747..0d72bc444 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -119,13 +119,9 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 TREE_ID=$(%s) if [ $? -eq 0 ]; then echo "TREE_ID=$TREE_ID" - # Read the service account token TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - # Read the namespace NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - # OpenShift API server URL API_SERVER=https://openshift.default.svc - # Create or update the ConfigMap curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ diff --git a/test/e2e/tls_configuration_test.go b/test/e2e/tls_configuration_test.go index 6a65e4f9f..1e7f32d9a 100644 --- a/test/e2e/tls_configuration_test.go +++ b/test/e2e/tls_configuration_test.go @@ -22,7 +22,6 @@ import ( . "github.com/onsi/gomega" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/test/e2e/support" - "github.com/securesign/operator/test/e2e/support/tas" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -142,12 +141,12 @@ var _ = Describe("Securesign TLS Configuration", Ordered, func() { } createSecret(ctx, cli, namespace.Name, "trillian-server-secret", trillian_data) - Expect(cli.Create(ctx, securesign)).To(Succeed()) + // Expect(cli.Create(ctx, securesign)).To(Succeed()) }) It("All components are running", func() { // tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) - tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) + // tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) // tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) // tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) // tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) From c7dd2eeb1f9357a166b00895bb62604960531822 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 14:49:08 +0200 Subject: [PATCH 08/34] update e2e --- test/e2e/tls_configuration_test.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/e2e/tls_configuration_test.go b/test/e2e/tls_configuration_test.go index 1e7f32d9a..6a65e4f9f 100644 --- a/test/e2e/tls_configuration_test.go +++ b/test/e2e/tls_configuration_test.go @@ -22,6 +22,7 @@ import ( . "github.com/onsi/gomega" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/test/e2e/support" + "github.com/securesign/operator/test/e2e/support/tas" v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -141,12 +142,12 @@ var _ = Describe("Securesign TLS Configuration", Ordered, func() { } createSecret(ctx, cli, namespace.Name, "trillian-server-secret", trillian_data) - // Expect(cli.Create(ctx, securesign)).To(Succeed()) + Expect(cli.Create(ctx, securesign)).To(Succeed()) }) It("All components are running", func() { // tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) - // tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) + tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) // tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) // tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) // tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) From cd12c141f4ba7aa6c26441df5bfeb24f47b80e53 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 15:20:21 +0200 Subject: [PATCH 09/34] make API_SERVER generic --- internal/controller/ctlog/actions/create_tree_job.go | 2 +- internal/controller/rekor/actions/server/create_tree_job.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index 7eb398ec0..7fdac418d 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -120,7 +120,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 echo "TREE_ID=$TREE_ID" TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://openshift.default.svc + API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index 0d72bc444..ef6428771 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -121,7 +121,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 echo "TREE_ID=$TREE_ID" TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://openshift.default.svc + API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/merge-patch+json" \ From e149cff42de2208b1e17e5f39de21b1a04e01fb3 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 19:35:16 +0200 Subject: [PATCH 10/34] updates(images+ctlog cm) --- internal/controller/ctlog/actions/config_map.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/internal/controller/ctlog/actions/config_map.go b/internal/controller/ctlog/actions/config_map.go index 354b76878..4895644c0 100644 --- a/internal/controller/ctlog/actions/config_map.go +++ b/internal/controller/ctlog/actions/config_map.go @@ -29,7 +29,9 @@ func (i configMapAction) Name() string { func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Spec.TLSCertificate.CACertRef == nil + // signingKeySecret: OCP + signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && signingKeySecret != nil && instance.Spec.TLSCertificate.CACertRef == nil } func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { From b1b428d918efc1aa645a5c555ebe87f0b5b21ed3 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 22:14:43 +0200 Subject: [PATCH 11/34] test operator image --- .github/workflows/main.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 60ce142a8..c3fa260f1 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -463,7 +463,8 @@ jobs: - name: Deploy operator container env: OPENSHIFT: false - run: make deploy + # run: make deploy + run: make deploy IMG=quay.io/fghanmi/my_operator:v4.6.1 # TODO: deploy ingress and execute e2e - name: Deploy RTHAS From 752d860fa1b68fa288a229ff2704ae754f69f8ea Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 22:54:28 +0200 Subject: [PATCH 12/34] remove tls e2e --- test/e2e/tls_configuration_test.go | 251 ----------------------------- 1 file changed, 251 deletions(-) delete mode 100644 test/e2e/tls_configuration_test.go diff --git a/test/e2e/tls_configuration_test.go b/test/e2e/tls_configuration_test.go deleted file mode 100644 index 6a65e4f9f..000000000 --- a/test/e2e/tls_configuration_test.go +++ /dev/null @@ -1,251 +0,0 @@ -//go:build integration - -package e2e - -import ( - "context" - "crypto/rand" - "crypto/rsa" - "crypto/x509" - "crypto/x509/pkix" - "encoding/pem" - "fmt" - "math/big" - "net" - "os" - "time" - - "github.com/securesign/operator/internal/controller/common/utils" - "sigs.k8s.io/controller-runtime/pkg/client" - - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" - "github.com/securesign/operator/api/v1alpha1" - "github.com/securesign/operator/test/e2e/support" - "github.com/securesign/operator/test/e2e/support/tas" - v1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -var _ = Describe("Securesign TLS Configuration", Ordered, func() { - cli, _ := CreateClient() - ctx := context.TODO() - - // var targetImageName string - var namespace *v1.Namespace - var securesign *v1alpha1.Securesign - - var caKey *rsa.PrivateKey - var caCert *x509.Certificate - var caCertPEM string - var err error - - AfterEach(func() { - if CurrentSpecReport().Failed() { - if val, present := os.LookupEnv("CI"); present && val == "true" { - support.DumpNamespace(ctx, cli, namespace.Name) - } - } - }) - - BeforeAll(func() { - namespace = support.CreateTestNamespace(ctx, cli) - DeferCleanup(func() { - cli.Delete(ctx, namespace) - }) - - securesign = &v1alpha1.Securesign{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace.Name, - Name: "test", - Annotations: map[string]string{ - "rhtas.redhat.com/metrics": "false", - }, - }, - Spec: v1alpha1.SecuresignSpec{ - Rekor: v1alpha1.RekorSpec{ - ExternalAccess: v1alpha1.ExternalAccess{ - Enabled: true, - }, - RekorSearchUI: v1alpha1.RekorSearchUI{ - Enabled: utils.Pointer(true), - }, - }, - Fulcio: v1alpha1.FulcioSpec{ - ExternalAccess: v1alpha1.ExternalAccess{ - Enabled: true, - }, - Config: v1alpha1.FulcioConfig{ - OIDCIssuers: []v1alpha1.OIDCIssuer{ - { - ClientID: support.OidcClientID(), - IssuerURL: support.OidcIssuerUrl(), - Issuer: support.OidcIssuerUrl(), - Type: "email", - }, - }}, - Certificate: v1alpha1.FulcioCert{ - OrganizationName: "MyOrg", - OrganizationEmail: "my@email.org", - CommonName: "fulcio", - }, - }, - Ctlog: v1alpha1.CTlogSpec{}, - Tuf: v1alpha1.TufSpec{ - ExternalAccess: v1alpha1.ExternalAccess{ - Enabled: true, - }, - }, - Trillian: v1alpha1.TrillianSpec{ - Db: v1alpha1.TrillianDB{ - Create: utils.Pointer(true), - }, - TrillianServer: v1alpha1.TrillianServer{ - TLSCertificate: v1alpha1.TLSCert{ - CertRef: &v1alpha1.SecretKeySelector{ - Key: "cert", - LocalObjectReference: v1alpha1.LocalObjectReference{Name: "trillian-server-secret"}, - }, - PrivateKeyRef: &v1alpha1.SecretKeySelector{ - Key: "key", - LocalObjectReference: v1alpha1.LocalObjectReference{Name: "trillian-server-secret"}, - }, - }, - }, - }, - }, - } - }) - - Describe("User-Specified TLS Certificate Configuration", func() { - BeforeAll(func() { - caKey, caCert, _, caCertPEM, err = generateCA() - if err != nil { - fmt.Printf("Failed to generate CA: %v\n", err) - return - } - ca_configmap := map[string]string{ - "ca.crt": caCertPEM, - } - createConfigMap(ctx, cli, namespace.Name, "ca-configmap", ca_configmap) - - var trillianKey string - var trillianCert string - trillianKey, trillianCert, err = generateServerCert(caCert, caKey, "trillian-log-server:8090") - if err != nil { - fmt.Printf("Failed to generate trillian server certificate: %v\n", err) - return - } - trillian_data := map[string]string{ - "key": trillianKey, - "cert": trillianCert, - } - createSecret(ctx, cli, namespace.Name, "trillian-server-secret", trillian_data) - - Expect(cli.Create(ctx, securesign)).To(Succeed()) - }) - - It("All components are running", func() { - // tas.VerifySecuresign(ctx, cli, namespace.Name, securesign.Name) - tas.VerifyTrillian(ctx, cli, namespace.Name, securesign.Name, true) - // tas.VerifyCTLog(ctx, cli, namespace.Name, securesign.Name) - // tas.VerifyTuf(ctx, cli, namespace.Name, securesign.Name) - // tas.VerifyRekor(ctx, cli, namespace.Name, securesign.Name) - }) - }) -}) - -func createSecret(ctx context.Context, cli client.Client, namespace, name string, data map[string]string) { - secretData := make(map[string][]byte) - for key, value := range data { - secretData[key] = []byte(value) - } - - secret := &v1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Namespace: namespace, - Name: name, - }, - Data: secretData, - } - - Expect(cli.Create(ctx, secret)).To(Succeed()) -} - -func createConfigMap(ctx context.Context, cli client.Client, namespace, name string, data map[string]string) { - configMap := &v1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Data: data, - } - Expect(cli.Create(ctx, configMap)).To(Succeed()) -} - -func generateCA() (*rsa.PrivateKey, *x509.Certificate, string, string, error) { - caKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - return nil, nil, "", "", err - } - - caTemplate := &x509.Certificate{ - SerialNumber: big.NewInt(1), - Subject: pkix.Name{ - CommonName: "My CA", - }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(0, 2, 0), - IsCA: true, - KeyUsage: x509.KeyUsageCertSign | x509.KeyUsageDigitalSignature, - BasicConstraintsValid: true, - } - - caCertDER, err := x509.CreateCertificate(rand.Reader, caTemplate, caTemplate, &caKey.PublicKey, caKey) - if err != nil { - return nil, nil, "", "", err - } - - caCert, err := x509.ParseCertificate(caCertDER) - if err != nil { - return nil, nil, "", "", err - } - - caKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(caKey)}) - caCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: caCertDER}) - - return caKey, caCert, string(caKeyPEM), string(caCertPEM), nil -} - -func generateServerCert(caCert *x509.Certificate, caKey *rsa.PrivateKey, serverName string) (string, string, error) { - serverKey, err := rsa.GenerateKey(rand.Reader, 4096) - if err != nil { - return "", "", err - } - - serverTemplate := &x509.Certificate{ - SerialNumber: big.NewInt(2), - Subject: pkix.Name{ - CommonName: "local", - Organization: []string{"RedHat"}, - OrganizationalUnit: []string{"RHTAS"}, - }, - NotBefore: time.Now(), - NotAfter: time.Now().AddDate(0, 2, 0), - KeyUsage: x509.KeyUsageDigitalSignature, - ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, - } - - serverTemplate.DNSNames = []string{"*", serverName} - serverTemplate.IPAddresses = []net.IP{net.ParseIP("0.0.0.0")} - - serverCertDER, err := x509.CreateCertificate(rand.Reader, serverTemplate, caCert, &serverKey.PublicKey, caKey) - if err != nil { - return "", "", err - } - - serverKeyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(serverKey)}) - serverCertPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: serverCertDER}) - - return string(serverKeyPEM), string(serverCertPEM), nil -} From a54637631564e0f77c48b7f7c10cd1c3c85545f8 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 8 Aug 2024 23:25:36 +0200 Subject: [PATCH 13/34] update --- .github/workflows/main.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index c3fa260f1..60ce142a8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -463,8 +463,7 @@ jobs: - name: Deploy operator container env: OPENSHIFT: false - # run: make deploy - run: make deploy IMG=quay.io/fghanmi/my_operator:v4.6.1 + run: make deploy # TODO: deploy ingress and execute e2e - name: Deploy RTHAS From 9515212ce201a6ff5aa58ba4b824339002e4efed Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Fri, 9 Aug 2024 09:54:00 +0200 Subject: [PATCH 14/34] update api/v1alpha1/common.go --- api/v1alpha1/common.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index 86f929b1b..e878904d9 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -43,9 +43,9 @@ type CtlogService struct { //+optional Address string `json:"address,omitempty"` // Port of Ctlog Log Server End point - //+kubebuilder:validation:Minimum:=0 + //+kubebuilder:validation:Minimum:=1 //+kubebuilder:validation:Maximum:=65535 - //+kubebuilder:default:=0 + //+kubebuilder:default:=80 //+optional Port *int32 `json:"port,omitempty"` // Prefix is the name of the log. The prefix cannot be empty and can From bd5435e399ed5cdaf4d258ac42cb9211994596e9 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Sat, 17 Aug 2024 16:04:23 +0200 Subject: [PATCH 15/34] updates --- api/v1alpha1/fulcio_types.go | 2 +- bundle/manifests/rhtas-operator.clusterserviceversion.yaml | 6 +++--- bundle/manifests/rhtas.redhat.com_fulcios.yaml | 5 ++--- bundle/manifests/rhtas.redhat.com_securesigns.yaml | 5 ++--- config/crd/bases/rhtas.redhat.com_fulcios.yaml | 5 ++--- config/crd/bases/rhtas.redhat.com_securesigns.yaml | 5 ++--- internal/controller/ctlog/actions/create_tree_job.go | 6 +++--- internal/controller/rekor/actions/server/create_tree_job.go | 6 +++--- 8 files changed, 18 insertions(+), 22 deletions(-) diff --git a/api/v1alpha1/fulcio_types.go b/api/v1alpha1/fulcio_types.go index daf3d3add..3da17d3d5 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/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index ac4f809bd..ce8bfc04f 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -92,8 +92,8 @@ metadata: "OIDCIssuers": [ { "ClientID": "trusted-artifact-signer", - "Issuer": "https://your-oidc-issuer-url", - "IssuerURL": "https://your-oidc-issuer-url", + "Issuer": "https://keycloak-keycloak-system.apps.rosa.tbc2f-pzqvt-33r.f86b.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", + "IssuerURL": "https://keycloak-keycloak-system.apps.rosa.tbc2f-pzqvt-33r.f86b.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", "Type": "email" } ] @@ -309,7 +309,7 @@ metadata: features.operators.openshift.io/token-auth-azure: "false" features.operators.openshift.io/token-auth-gcp: "false" operators.openshift.io/valid-subscription: '["Red Hat Trusted Artifact Signer"]' - operators.operatorframework.io/builder: operator-sdk-v1.34.2 + operators.operatorframework.io/builder: operator-sdk-v1.34.1 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 repository: https://github.com/securesign/secure-sign-operator support: Red Hat diff --git a/bundle/manifests/rhtas.redhat.com_fulcios.yaml b/bundle/manifests/rhtas.redhat.com_fulcios.yaml index 5eceefc64..79ccee746 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,11 +230,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 0 + default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 0 + minimum: 1 type: integer prefix: default: trusted-artifact-signer diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index adb219bac..e66e499fb 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -431,7 +431,6 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -439,11 +438,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 0 + default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 0 + minimum: 1 type: integer prefix: default: trusted-artifact-signer diff --git a/config/crd/bases/rhtas.redhat.com_fulcios.yaml b/config/crd/bases/rhtas.redhat.com_fulcios.yaml index 587d976f2..b665ee36a 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,11 +230,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 0 + default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 0 + minimum: 1 type: integer prefix: default: trusted-artifact-signer diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 54d592960..1e495fc9e 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -431,7 +431,6 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: - port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: @@ -439,11 +438,11 @@ spec: description: Address to Ctlog Log Server End point type: string port: - default: 0 + default: 80 description: Port of Ctlog Log Server End point format: int32 maximum: 65535 - minimum: 0 + minimum: 1 type: integer prefix: default: trusted-artifact-signer diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index 7fdac418d..f848e1b29 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -105,11 +105,11 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) case signingKeySecret != nil: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) default: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=ctlog-tree", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree", trillUrl) } command := []string{ "/bin/sh", diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index ef6428771..61f678b23 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -106,11 +106,11 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) case signingKeySecret != nil: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) default: - cmd = fmt.Sprintf("./createtree --admin_server=%s --display_name=rekor-tree", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree", trillUrl) } command := []string{ "/bin/sh", From d46f49505bef28f1b6f5dde73d8226f4ddf3abe6 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 21 Aug 2024 18:43:37 +0200 Subject: [PATCH 16/34] review updates --- api/v1alpha1/common.go | 5 ++--- .../rhtas-operator.clusterserviceversion.yaml | 4 ++-- config/samples/rhtas_v1alpha1_securesign.yaml | 4 ++-- .../actions/{config_map.go => ca_configmap.go} | 4 +--- .../controller/ctlog/actions/create_tree_job.go | 17 +++++++---------- internal/controller/ctlog/actions/deployment.go | 15 +++++++-------- .../controller/ctlog/actions/resolve_tree.go | 1 - internal/controller/ctlog/actions/service.go | 4 +--- .../server/{config_map.go => ca_configmap.go} | 0 .../rekor/actions/server/create_tree_job.go | 17 +++++++---------- .../rekor/actions/server/deployment.go | 9 ++++----- .../rekor/actions/server/resolve_tree.go | 1 - .../trillian/actions/logserver/deployment.go | 11 +++++------ .../trillian/actions/logserver/service.go | 3 +-- 14 files changed, 39 insertions(+), 56 deletions(-) rename internal/controller/ctlog/actions/{config_map.go => ca_configmap.go} (92%) rename internal/controller/rekor/actions/server/{config_map.go => ca_configmap.go} (100%) diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index e878904d9..c4f1a5ab3 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -107,7 +107,6 @@ type Pvc struct { AccessModes []PersistentVolumeAccessMode `json:"accessModes,omitempty"` } -<<<<<<< HEAD type Auth struct { // Environmental variables used to define authentication parameters //+optional @@ -115,7 +114,8 @@ type Auth struct { // Secret ref to be mounted inside a pod, Mount path defaults to /var/run/secrets/tas/auth //+optional SecretMount []SecretKeySelector `json:"secretMount,omitempty"` -======= +} + // TLSCert defines fields for TLS certificate // +kubebuilder:validation:XValidation:rule=(!has(self.certRef) || has(self.privateKeyRef)),message=privateKeyRef cannot be empty type TLSCert struct { @@ -128,7 +128,6 @@ type TLSCert struct { // Reference to CA certificate //+optional CACertRef *LocalObjectReference `json:"caCertRef,omitempty"` ->>>>>>> bddb484 (Add TLS to Rekor and Trillian services) } // TLS (Transport Layer Security) Configuration for enabling service encryption. diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index ce8bfc04f..dfa4b5c42 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -92,8 +92,8 @@ metadata: "OIDCIssuers": [ { "ClientID": "trusted-artifact-signer", - "Issuer": "https://keycloak-keycloak-system.apps.rosa.tbc2f-pzqvt-33r.f86b.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", - "IssuerURL": "https://keycloak-keycloak-system.apps.rosa.tbc2f-pzqvt-33r.f86b.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", + "Issuer": "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", + "IssuerURL": "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", "Type": "email" } ] diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index 6c8d360fe..a0eac6ad1 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -23,8 +23,8 @@ spec: config: OIDCIssuers: - ClientID: "trusted-artifact-signer" - IssuerURL: "https://your-oidc-issuer-url" - Issuer: "https://your-oidc-issuer-url" + IssuerURL: "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + Issuer: "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" Type: "email" certificate: organizationName: Red Hat diff --git a/internal/controller/ctlog/actions/config_map.go b/internal/controller/ctlog/actions/ca_configmap.go similarity index 92% rename from internal/controller/ctlog/actions/config_map.go rename to internal/controller/ctlog/actions/ca_configmap.go index 4895644c0..63f2c7f72 100644 --- a/internal/controller/ctlog/actions/config_map.go +++ b/internal/controller/ctlog/actions/ca_configmap.go @@ -29,9 +29,7 @@ func (i configMapAction) Name() string { func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") - // signingKeySecret: OCP - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && signingKeySecret != nil && instance.Spec.TLSCertificate.CACertRef == nil + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && k8sutils.IsOpenShift() && instance.Spec.TLSCertificate.CACertRef == nil } func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index f848e1b29..f56832b48 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -100,14 +100,13 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 activeDeadlineSeconds := int64(600) backoffLimit := int32(5) - signingKeySecret, _ := kubernetes.GetSecret(i.Client, "openshift-service-ca", "signing-key") trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) cmd := "" switch { case trustedCAAnnotation != nil: cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) - case signingKeySecret != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + case kubernetes.IsOpenShift(): + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) default: cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree", trillUrl) } @@ -146,14 +145,12 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) } - if trustedCAAnnotation != nil { - err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) - if err != nil { - return i.Failed(err) - } + err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + if err != nil { + return i.Failed(err) } - if signingKeySecret != nil && trustedCAAnnotation == nil { + if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, corev1.Volume{ Name: "tls-cert", @@ -166,7 +163,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: "tls-cert", - MountPath: "/etc/ssl/certs", + MountPath: "/var/run/secrets/tas", ReadOnly: true, }) } diff --git a/internal/controller/ctlog/actions/deployment.go b/internal/controller/ctlog/actions/deployment.go index 2b3fc56a1..124715c75 100644 --- a/internal/controller/ctlog/actions/deployment.go +++ b/internal/controller/ctlog/actions/deployment.go @@ -8,7 +8,7 @@ import ( rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/action" - k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" @@ -43,7 +43,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") switch { case instance.Spec.Trillian.Address == "": instance.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", trillian.LogserverDeploymentName, instance.Namespace) @@ -115,7 +114,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) }, }, }) - } else if signingKeySecret != nil { + } else if kubernetes.IsOpenShift() { i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, corev1.Volume{ @@ -151,16 +150,16 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) i.Logger.V(1).Info("Communication between services is insecure") } - if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil || signingKeySecret != nil { + if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil || kubernetes.IsOpenShift() { dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: "tls-cert", - MountPath: "/etc/ssl/certs", + MountPath: "/var/run/secrets/tas", ReadOnly: true, }) - // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_certificate", "/etc/ssl/certs/tls.crt") - // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_key", "/etc/ssl/certs/tls.key") - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", "/etc/ssl/certs/ca.crt") + // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_certificate", "/var/run/secrets/tas/tls.crt") + // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_key", "/var/run/secrets/tas/tls.key") + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", "/var/run/secrets/tas/ca.crt") } if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { diff --git a/internal/controller/ctlog/actions/resolve_tree.go b/internal/controller/ctlog/actions/resolve_tree.go index 678abc6ba..eca2040cf 100644 --- a/internal/controller/ctlog/actions/resolve_tree.go +++ b/internal/controller/ctlog/actions/resolve_tree.go @@ -71,7 +71,6 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.C if err != nil { i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) } - time.Sleep(2 * time.Second) } if err != nil { diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index 5509350ae..c2077a75f 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -7,7 +7,6 @@ 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" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/meta" @@ -42,7 +41,6 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) svc := kubernetes.CreateService(instance.Namespace, ComponentName, ServerPortName, ServerPort, ServerTargetPort, labels) - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") if instance.Spec.Monitoring.Enabled { svc.Spec.Ports = append(svc.Spec.Ports, corev1.ServicePort{ Name: MetricsPortName, @@ -65,7 +63,7 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog } //TLS: Annotate service - if signingKeySecret != nil && instance.Spec.TLSCertificate.CertRef == nil { + if kubernetes.IsOpenShift() && instance.Spec.TLSCertificate.CertRef == nil { if svc.Annotations == nil { svc.Annotations = make(map[string]string) } diff --git a/internal/controller/rekor/actions/server/config_map.go b/internal/controller/rekor/actions/server/ca_configmap.go similarity index 100% rename from internal/controller/rekor/actions/server/config_map.go rename to internal/controller/rekor/actions/server/ca_configmap.go diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index 61f678b23..e29d81d9b 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -101,14 +101,13 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 activeDeadlineSeconds := int64(600) backoffLimit := int32(5) - signingKeySecret, _ := kubernetes.GetSecret(i.Client, "openshift-service-ca", "signing-key") trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) cmd := "" switch { case trustedCAAnnotation != nil: cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) - case signingKeySecret != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/etc/ssl/certs/tls.crt", trillUrl) + case kubernetes.IsOpenShift(): + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) default: cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree", trillUrl) } @@ -147,14 +146,12 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) } - if trustedCAAnnotation != nil { - err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) - if err != nil { - return i.Failed(err) - } + err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + if err != nil { + return i.Failed(err) } - if signingKeySecret != nil && trustedCAAnnotation == nil { + if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, corev1.Volume{ Name: "tls-cert", @@ -167,7 +164,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: "tls-cert", - MountPath: "/etc/ssl/certs", + MountPath: "/var/run/secrets/tas", ReadOnly: true, }) } diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 8f28297f1..2f6fc30b0 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -72,7 +72,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) } // TLS certificate - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") if instance.Spec.TLSCertificate.CACertRef != nil { dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, corev1.Volume{ @@ -97,7 +96,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) }, }, }) - } else if signingKeySecret != nil { + } else if k8sutils.IsOpenShift() { dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, corev1.Volume{ Name: "tls-cert", @@ -125,14 +124,14 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) i.Logger.V(1).Info("Communication between services is insecure") } - if instance.Spec.TLSCertificate.CACertRef != nil || signingKeySecret != nil { + if instance.Spec.TLSCertificate.CACertRef != nil || k8sutils.IsOpenShift() { dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: "tls-cert", - MountPath: "/etc/ssl/certs", + MountPath: "/var/run/secrets/tas", ReadOnly: true, }) - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_log_server.tls_ca_cert", "/etc/ssl/certs/ca.crt") + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_log_server.tls_ca_cert", "/var/run/secrets/tas/ca.crt") } if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { diff --git a/internal/controller/rekor/actions/server/resolve_tree.go b/internal/controller/rekor/actions/server/resolve_tree.go index 7e6aa703d..edb617e16 100644 --- a/internal/controller/rekor/actions/server/resolve_tree.go +++ b/internal/controller/rekor/actions/server/resolve_tree.go @@ -72,7 +72,6 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.R if err != nil { i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) } - time.Sleep(2 * time.Second) } if err != nil { diff --git a/internal/controller/trillian/actions/logserver/deployment.go b/internal/controller/trillian/actions/logserver/deployment.go index da9e17d50..162bdf2d7 100644 --- a/internal/controller/trillian/actions/logserver/deployment.go +++ b/internal/controller/trillian/actions/logserver/deployment.go @@ -71,7 +71,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli } // TLS certificate - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil { server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, corev1.Volume{ @@ -109,7 +108,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli }, }, }) - } else if signingKeySecret != nil { + } else if k8sutils.IsOpenShift() { i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, corev1.Volume{ @@ -124,15 +123,15 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli i.Logger.V(1).Info("Communication between services is insecure") } - if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil || signingKeySecret != nil { + if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil || k8sutils.IsOpenShift() { server.Spec.Template.Spec.Containers[0].VolumeMounts = append(server.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: "tls-cert", - MountPath: "/etc/ssl/certs", + MountPath: "/var/run/secrets/tas", ReadOnly: true, }) - server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_cert_file", "/etc/ssl/certs/tls.crt") - server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_key_file", "/etc/ssl/certs/tls.key") + server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_cert_file", "/var/run/secrets/tas/tls.crt") + server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_key_file", "/var/run/secrets/tas/tls.key") } if err = controllerutil.SetControllerReference(instance, server, i.Client.Scheme()); err != nil { diff --git a/internal/controller/trillian/actions/logserver/service.go b/internal/controller/trillian/actions/logserver/service.go index c2d9d33ba..b57d3e050 100644 --- a/internal/controller/trillian/actions/logserver/service.go +++ b/internal/controller/trillian/actions/logserver/service.go @@ -74,8 +74,7 @@ func (i createServiceAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } //TLS: Annotate service - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") - if signingKeySecret != nil && instance.Spec.TrillianServer.TLSCertificate.CertRef == nil { + if k8sutils.IsOpenShift() && instance.Spec.TrillianServer.TLSCertificate.CertRef == nil { if logserverService.Annotations == nil { logserverService.Annotations = make(map[string]string) } From 5f73e758e6ddfe5989e701570a15efe80e948121 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 21 Aug 2024 18:56:05 +0200 Subject: [PATCH 17/34] fix conflicts --- api/v1alpha1/zz_generated.deepcopy.go | 43 ++++++------------- .../rhtas-operator.clusterserviceversion.yaml | 4 +- config/samples/rhtas_v1alpha1_securesign.yaml | 4 +- internal/controller/constants/images.go | 2 +- 4 files changed, 18 insertions(+), 35 deletions(-) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 5e2d29593..b2dc81bd3 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -1048,6 +1048,19 @@ func (in *TLS) DeepCopy() *TLS { return nil } out := new(TLS) + if in.CACertRef != nil { + in, out := &in.CACertRef, &out.CACertRef + *out = new(LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCert. +func (in *TLSCert) DeepCopy() *TLSCert { + if in == nil { + return nil + } + out := new(TLSCert) in.DeepCopyInto(out) return out } @@ -1223,36 +1236,6 @@ func (in *Tink) DeepCopy() *Tink { return out } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSCert) DeepCopyInto(out *TLSCert) { - *out = *in - if in.PrivateKeyRef != nil { - in, out := &in.PrivateKeyRef, &out.PrivateKeyRef - *out = new(SecretKeySelector) - **out = **in - } - if in.CertRef != nil { - in, out := &in.CertRef, &out.CertRef - *out = new(SecretKeySelector) - **out = **in - } - if in.CACertRef != nil { - in, out := &in.CACertRef, &out.CACertRef - *out = new(LocalObjectReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCert. -func (in *TLSCert) DeepCopy() *TLSCert { - if in == nil { - return nil - } - out := new(TLSCert) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *Trillian) DeepCopyInto(out *Trillian) { *out = *in diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index dfa4b5c42..162ea86a2 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -92,8 +92,8 @@ metadata: "OIDCIssuers": [ { "ClientID": "trusted-artifact-signer", - "Issuer": "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", - "IssuerURL": "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer", + "Issuer": "https://your-oidc-issuer-url", + "IssuerURL": "https://your-oidc-issuer-url", "Type": "email" } ] diff --git a/config/samples/rhtas_v1alpha1_securesign.yaml b/config/samples/rhtas_v1alpha1_securesign.yaml index a0eac6ad1..6c8d360fe 100644 --- a/config/samples/rhtas_v1alpha1_securesign.yaml +++ b/config/samples/rhtas_v1alpha1_securesign.yaml @@ -23,8 +23,8 @@ spec: config: OIDCIssuers: - ClientID: "trusted-artifact-signer" - IssuerURL: "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" - Issuer: "https://keycloak-keycloak-system.apps.rosa.ersmh-9o3fp-99x.qre7.p3.openshiftapps.com/auth/realms/trusted-artifact-signer" + IssuerURL: "https://your-oidc-issuer-url" + Issuer: "https://your-oidc-issuer-url" Type: "email" certificate: organizationName: Red Hat diff --git a/internal/controller/constants/images.go b/internal/controller/constants/images.go index 3cbb8e03e..edd9a141b 100644 --- a/internal/controller/constants/images.go +++ b/internal/controller/constants/images.go @@ -25,5 +25,5 @@ var ( ClientServerImage_f = "registry.redhat.io/rhtas/client-server-f-rhel9@sha256:8c8c4bfcbc8728ee46a427a4179622e4437e3502aa4b29af7539bf2eee999ff6" SegmentBackupImage = "registry.redhat.io/rhtas/segment-reporting-rhel9@sha256:c7fa18f6dec1fdd308d5a6ed74f5f6bf2bd30d6759d7d2464875b6e80f269fb2" TimestampAuthorityImage = "registry.redhat.io/rhtas/timestamp-authority-rhel9@sha256:d957041e1f10faf087333b9f1d39b2bb4b26edd37a812192e67771c423950def" - CreateTreeImage = "quay.io/redhat-user-workloads/rhtas-tenant/trillian/createtree@sha256:d4d3a99e8da94a89312babe65545634fa91fdf14dd2a6f8da4be489a7ef52d90" + CreateTreeImage = "registry.redhat.io/rhtas/trillian-createtree-rhel9@sha256:0a793e68b9398d73a47012cab0f9edf7b0b917060d59b4afdc9efc5e034595c8" ) From c7d4f69a0f7cf5ebfa4339178ee3edc39ee1758c Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 28 Aug 2024 20:44:47 +0200 Subject: [PATCH 18/34] improve resolve_tree --- .../controller/ctlog/actions/resolve_tree.go | 53 +++++-------------- .../ctlog/actions/resolve_tree_test.go | 21 +++----- .../rekor/actions/server/resolve_tree.go | 53 +++++-------------- .../rekor/actions/server/resolve_tree_test.go | 15 ++---- 4 files changed, 41 insertions(+), 101 deletions(-) diff --git a/internal/controller/ctlog/actions/resolve_tree.go b/internal/controller/ctlog/actions/resolve_tree.go index eca2040cf..4e639c825 100644 --- a/internal/controller/ctlog/actions/resolve_tree.go +++ b/internal/controller/ctlog/actions/resolve_tree.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "strconv" - "time" "github.com/google/trillian" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" @@ -18,9 +17,7 @@ import ( ) func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtasv1alpha1.CTlog] { - a := &resolveTreeAction{ - timeout: time.Duration(constants.CreateTreeDeadline) * time.Second, - } + a := &resolveTreeAction{} for _, opt := range opts { opt(a) @@ -30,7 +27,6 @@ func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtas type resolveTreeAction struct { action.BaseAction - timeout time.Duration } func (i resolveTreeAction) Name() string { @@ -62,55 +58,33 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.C var tree *trillian.Tree cm := &v1.ConfigMap{} - deadline := time.Now().Add(i.timeout) - for time.Now().Before(deadline) { - err = i.Client.Get(ctx, types.NamespacedName{Name: "ctlog-tree-id-config", Namespace: instance.Namespace}, cm) - if err == nil && cm.Data != nil { - break - } - if err != nil { - i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) - } - } - - if err != nil { - i.Logger.V(1).Error(fmt.Errorf("timed out waiting for the ConfigMap"), err.Error()) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: fmt.Sprintf("timed out waiting for the ConfigMap: %v", err), - }) - return i.Failed(fmt.Errorf("timed out waiting for the ConfigMap: %s", "configmap not found")) + err = i.Client.Get(ctx, types.NamespacedName{Name: "ctlog-tree-id-config", Namespace: instance.Namespace}, cm) + if err != nil || cm.Data == nil { + i.Logger.Info("ConfigMap not ready or data is empty, requeuing reconciliation") + return i.Requeue() } - if cm.Data == nil { - err = fmt.Errorf("ConfigMap data is empty") + treeId, exists := cm.Data["tree_id"] + if !exists { + err = fmt.Errorf("ConfigMap missing tree_id") i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: ServerCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - return i.Failed(err) - } - - treeId, exists := cm.Data["tree_id"] - treeIdInt, err := strconv.ParseInt(treeId, 10, 64) - tree = &trillian.Tree{TreeId: treeIdInt} - if !exists { - i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: constants.Ready, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - return i.Failed(err) + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create trillian tree: %v", err), instance) } - - if !exists { + treeIdInt, err := strconv.ParseInt(treeId, 10, 64) + if err != nil { + i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: ServerCondition, Status: metav1.ConditionFalse, @@ -125,6 +99,7 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.C }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create trillian tree: %v", err), instance) } + tree = &trillian.Tree{TreeId: treeIdInt} i.Recorder.Eventf(instance, v1.EventTypeNormal, "TrillianTreeCreated", "New Trillian tree created: %d", tree.TreeId) instance.Status.TreeID = &tree.TreeId diff --git a/internal/controller/ctlog/actions/resolve_tree_test.go b/internal/controller/ctlog/actions/resolve_tree_test.go index b4e180648..21ce7f432 100644 --- a/internal/controller/ctlog/actions/resolve_tree_test.go +++ b/internal/controller/ctlog/actions/resolve_tree_test.go @@ -2,10 +2,8 @@ package actions import ( "context" - "fmt" "reflect" "testing" - "time" v1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" @@ -165,7 +163,7 @@ func TestResolveTree_Handle(t *testing.T) { verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { g.Expect(ctlog.Spec.TreeID).ShouldNot(BeNil()) g.Expect(ctlog.Status.TreeID).ShouldNot(BeNil()) - g.Expect(ctlog.Spec.TreeID).To(HaveValue(BeNumerically(">", 0))) + g.Expect(ctlog.Status.TreeID).To(HaveValue(BeNumerically(">", 0))) g.Expect(ctlog.Spec.TreeID).To(HaveValue(BeNumerically("==", *ctlog.Status.TreeID))) }, }, @@ -183,7 +181,7 @@ func TestResolveTree_Handle(t *testing.T) { verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { g.Expect(ctlog.Spec.TreeID).ShouldNot(BeNil()) g.Expect(ctlog.Status.TreeID).ShouldNot(BeNil()) - g.Expect(ctlog.Spec.TreeID).To(HaveValue(BeNumerically(">", 0))) + g.Expect(ctlog.Status.TreeID).To(HaveValue(BeNumerically(">", 0))) g.Expect(ctlog.Spec.TreeID).To(HaveValue(BeNumerically("==", *ctlog.Status.TreeID))) g.Expect(ctlog.Status.TreeID).To(HaveValue(BeNumerically("==", 123456))) }, @@ -205,7 +203,7 @@ func TestResolveTree_Handle(t *testing.T) { }, }, want: want{ - result: testAction.Failed(fmt.Errorf("ConfigMap data is empty")), + result: testAction.Requeue(), verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { g.Expect(ctlog.Spec.TreeID).Should(BeNil()) g.Expect(ctlog.Status.TreeID).Should(BeNil()) @@ -220,11 +218,10 @@ func TestResolveTree_Handle(t *testing.T) { }, }, want: want{ - result: testAction.Failed(fmt.Errorf("timed out waiting for the ConfigMap: configmap not found")), + result: testAction.Requeue(), verify: func(g Gomega, ctlog *rhtasv1alpha1.CTlog) { - g.Expect(ctlog.Status.Conditions).To(ContainElement( - WithTransform(func(c metav1.Condition) string { return c.Message }, ContainSubstring("timed out waiting for the ConfigMap:")), - )) + g.Expect(ctlog.Spec.TreeID).Should(BeNil()) + g.Expect(ctlog.Status.TreeID).Should(BeNil()) }, }, }, @@ -261,12 +258,10 @@ func TestResolveTree_Handle(t *testing.T) { } } - a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { - a.timeout = 5 * time.Second // Reduced timeout for testing - })) + a := testAction.PrepareAction(c, NewResolveTreeAction()) if got := a.Handle(ctx, instance); !reflect.DeepEqual(got, tt.want.result) { - t.Errorf("CanHandle() = %v, want %v", got, tt.want.result) + t.Errorf("Handle() = %v, want %v", got, tt.want.result) } if tt.want.verify != nil { tt.want.verify(g, instance) diff --git a/internal/controller/rekor/actions/server/resolve_tree.go b/internal/controller/rekor/actions/server/resolve_tree.go index edb617e16..5f1dfe402 100644 --- a/internal/controller/rekor/actions/server/resolve_tree.go +++ b/internal/controller/rekor/actions/server/resolve_tree.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "strconv" - "time" "github.com/google/trillian" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" @@ -19,9 +18,7 @@ import ( ) func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtasv1alpha1.Rekor] { - a := &resolveTreeAction{ - timeout: time.Duration(constants.CreateTreeDeadline) * time.Second, - } + a := &resolveTreeAction{} for _, opt := range opts { opt(a) @@ -31,7 +28,6 @@ func NewResolveTreeAction(opts ...func(*resolveTreeAction)) action.Action[*rhtas type resolveTreeAction struct { action.BaseAction - timeout time.Duration } func (i resolveTreeAction) Name() string { @@ -63,55 +59,33 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.R var tree *trillian.Tree cm := &v1.ConfigMap{} - deadline := time.Now().Add(i.timeout) - for time.Now().Before(deadline) { - err = i.Client.Get(ctx, types.NamespacedName{Name: "rekor-tree-id-config", Namespace: instance.Namespace}, cm) - if err == nil && cm.Data != nil { - break - } - if err != nil { - i.Logger.V(1).Error(fmt.Errorf("waiting for the ConfigMap"), err.Error()) - } - } - - if err != nil { - i.Logger.V(1).Error(fmt.Errorf("timed out waiting for the ConfigMap"), err.Error()) - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: fmt.Sprintf("timed out waiting for the ConfigMap: %v", err), - }) - return i.Failed(fmt.Errorf("timed out waiting for the ConfigMap: %s", "configmap not found")) + err = i.Client.Get(ctx, types.NamespacedName{Name: "rekor-tree-id-config", Namespace: instance.Namespace}, cm) + if err != nil || cm.Data == nil { + i.Logger.Info("ConfigMap not ready or data is empty, requeuing reconciliation") + return i.Requeue() } - if cm.Data == nil { - err = fmt.Errorf("ConfigMap data is empty") + treeId, exists := cm.Data["tree_id"] + if !exists { + err = fmt.Errorf("ConfigMap missing tree_id") i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: actions.ServerCondition, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - return i.Failed(err) - } - - treeId, exists := cm.Data["tree_id"] - treeIdInt, err := strconv.ParseInt(treeId, 10, 64) - tree = &trillian.Tree{TreeId: treeIdInt} - if !exists { - i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: constants.Ready, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) - return i.Failed(err) + return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create trillian tree: %v", err), instance) } - - if !exists { + treeIdInt, err := strconv.ParseInt(treeId, 10, 64) + if err != nil { + i.Logger.V(1).Error(err, err.Error()) meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, Status: metav1.ConditionFalse, @@ -126,6 +100,7 @@ func (i resolveTreeAction) Handle(ctx context.Context, instance *rhtasv1alpha1.R }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create trillian tree: %v", err), instance) } + tree = &trillian.Tree{TreeId: treeIdInt} i.Recorder.Eventf(instance, v1.EventTypeNormal, "TrillianTreeCreated", "New Trillian tree created: %d", tree.TreeId) instance.Status.TreeID = &tree.TreeId diff --git a/internal/controller/rekor/actions/server/resolve_tree_test.go b/internal/controller/rekor/actions/server/resolve_tree_test.go index dea62581c..296fbc5a2 100644 --- a/internal/controller/rekor/actions/server/resolve_tree_test.go +++ b/internal/controller/rekor/actions/server/resolve_tree_test.go @@ -2,10 +2,8 @@ package server import ( "context" - "fmt" "reflect" "testing" - "time" . "github.com/onsi/gomega" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" @@ -204,7 +202,7 @@ func TestResolveTree_Handle(t *testing.T) { }, }, want: want{ - result: testAction.Failed(fmt.Errorf("ConfigMap data is empty")), + result: testAction.Requeue(), verify: func(g Gomega, rekor *rhtasv1alpha1.Rekor) { g.Expect(rekor.Spec.TreeID).Should(BeNil()) g.Expect(rekor.Status.TreeID).Should(BeNil()) @@ -219,11 +217,10 @@ func TestResolveTree_Handle(t *testing.T) { }, }, want: want{ - result: testAction.Failed(fmt.Errorf("timed out waiting for the ConfigMap: configmap not found")), + result: testAction.Requeue(), verify: func(g Gomega, rekor *rhtasv1alpha1.Rekor) { - g.Expect(rekor.Status.Conditions).To(ContainElement( - WithTransform(func(c metav1.Condition) string { return c.Message }, ContainSubstring("timed out waiting for the ConfigMap:")), - )) + g.Expect(rekor.Spec.TreeID).Should(BeNil()) + g.Expect(rekor.Status.TreeID).Should(BeNil()) }, }, }, @@ -260,9 +257,7 @@ func TestResolveTree_Handle(t *testing.T) { } } - a := testAction.PrepareAction(c, NewResolveTreeAction(func(a *resolveTreeAction) { - a.timeout = 5 * time.Second // Reduced timeout for testing - })) + a := testAction.PrepareAction(c, NewResolveTreeAction()) if got := a.Handle(ctx, instance); !reflect.DeepEqual(got, tt.want.result) { t.Errorf("CanHandle() = %v, want %v", got, tt.want.result) From aef2cf9794d72b47819b148942a8d4fe28e38add Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Sat, 31 Aug 2024 10:52:32 +0200 Subject: [PATCH 19/34] update: create_tree --- internal/controller/ctlog/actions/create_tree_job.go | 2 +- internal/controller/rekor/actions/server/create_tree_job.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index f56832b48..1912c0540 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -176,7 +176,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: CtlogTreeJobName, Status: metav1.ConditionTrue, - Reason: constants.Ready, + Reason: constants.Creating, Message: "ctlog tree Job Created", }) diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index e29d81d9b..bcb9d4deb 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -177,7 +177,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: RekorTreeJobName, Status: metav1.ConditionTrue, - Reason: constants.Ready, + Reason: constants.Creating, Message: "rekor tree Job Created", }) From 467e3cf9cdf42e45ce2411eccc1707444dbb9af3 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Mon, 2 Sep 2024 17:53:20 +0200 Subject: [PATCH 20/34] add CREATE_TREE_IMAGE var to manager cli --- cmd/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/main.go b/cmd/main.go index 9cb9e4c76..1875c3014 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -122,6 +122,7 @@ func main() { utils.StringFlagOrEnv(&constants.SegmentBackupImage, "segment-backup-job-image", "SEGMENT_BACKUP_JOB_IMAGE", constants.SegmentBackupImage, "The image used for the segment backup job") flag.StringVar(&clidownload.CliHostName, "cli-server-hostname", "", "The hostname for the cli server") utils.StringFlagOrEnv(&constants.TimestampAuthorityImage, "timestamp-authority-image", "TIMESTAMP_AUTHORITY_IMAGE", constants.TimestampAuthorityImage, "The image used for Timestamp Authority") + utils.StringFlagOrEnv(&constants.CreateTreeImage, "create-tree-image", "CREATE_TREE_IMAGE", constants.CreateTreeImage, "The image used for the Trillian create tree job") klog.InitFlags(flag.CommandLine) flag.Parse() From dba5a134571ebb43d898a98c0033882c57d8ddb4 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 11 Sep 2024 12:50:38 +0200 Subject: [PATCH 21/34] solve conflicts, updates --- api/v1alpha1/common.go | 14 -- api/v1alpha1/ctlog_types.go | 12 +- api/v1alpha1/ctlog_types_test.go | 10 -- api/v1alpha1/rekor_types.go | 4 +- api/v1alpha1/rekor_types_test.go | 5 - api/v1alpha1/trillian_types.go | 10 +- api/v1alpha1/trillian_types_test.go | 12 -- api/v1alpha1/zz_generated.deepcopy.go | 38 +++-- bundle/manifests/rhtas.redhat.com_ctlogs.yaml | 63 ++++--- bundle/manifests/rhtas.redhat.com_rekors.yaml | 68 ++------ .../rhtas.redhat.com_securesigns.yaml | 156 ++++++------------ .../manifests/rhtas.redhat.com_trillians.yaml | 99 +++++++---- config/crd/bases/rhtas.redhat.com_ctlogs.yaml | 63 ++++--- config/crd/bases/rhtas.redhat.com_rekors.yaml | 68 ++------ .../bases/rhtas.redhat.com_securesigns.yaml | 156 ++++++------------ .../crd/bases/rhtas.redhat.com_trillians.yaml | 99 +++++++---- .../controller/ctlog/actions/ca_configmap.go | 79 --------- .../ctlog/actions/create_tree_job.go | 24 ++- .../controller/ctlog/actions/deployment.go | 120 +++----------- internal/controller/ctlog/actions/service.go | 21 +-- internal/controller/ctlog/ctlog_controller.go | 2 - .../controller/ctlog/ctlog_controller_test.go | 11 -- internal/controller/ctlog/utils/tls.go | 32 ++++ .../rekor/actions/server/ca_configmap.go | 82 --------- .../rekor/actions/server/create_tree_job.go | 24 ++- .../rekor/actions/server/deployment.go | 74 +-------- internal/controller/rekor/rekor_controller.go | 2 - .../rekor/utils/rekor_deployment.go | 15 +- internal/controller/rekor/utils/tls.go | 45 +++++ .../trillian/actions/logserver/deployment.go | 86 +++------- .../trillian/actions/logserver/service.go | 20 +-- .../trillian/utils/server-deployment.go | 9 + 32 files changed, 561 insertions(+), 962 deletions(-) delete mode 100644 internal/controller/ctlog/actions/ca_configmap.go create mode 100644 internal/controller/ctlog/utils/tls.go delete mode 100644 internal/controller/rekor/actions/server/ca_configmap.go create mode 100644 internal/controller/rekor/utils/tls.go diff --git a/api/v1alpha1/common.go b/api/v1alpha1/common.go index c4f1a5ab3..301334fe4 100644 --- a/api/v1alpha1/common.go +++ b/api/v1alpha1/common.go @@ -116,20 +116,6 @@ type Auth struct { SecretMount []SecretKeySelector `json:"secretMount,omitempty"` } -// TLSCert defines fields for TLS certificate -// +kubebuilder:validation:XValidation:rule=(!has(self.certRef) || has(self.privateKeyRef)),message=privateKeyRef cannot be empty -type TLSCert struct { - // Reference to the private key - //+optional - PrivateKeyRef *SecretKeySelector `json:"privateKeyRef,omitempty"` - // Reference to service certificate - //+optional - CertRef *SecretKeySelector `json:"certRef,omitempty"` - // Reference to CA certificate - //+optional - CACertRef *LocalObjectReference `json:"caCertRef,omitempty"` -} - // TLS (Transport Layer Security) Configuration for enabling service encryption. // +kubebuilder:validation:XValidation:rule=(!has(self.certificateRef) || has(self.privateKeyRef)),message=privateKeyRef cannot be empty type TLS struct { diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 923f5d2bd..7a0ca90a8 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -48,9 +48,14 @@ type CTlogSpec struct { // publicKeyRef, rootCertificates and trillian will be overridden. //+optional ServerConfigRef *LocalObjectReference `json:"serverConfigRef,omitempty"` - // Reference to TLS server certificate, private key and CA certificate + + // ConfigMap with additional bundle of trusted CA + //+optional + TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` + + // Configuration for enabling TLS (Transport Layer Security) encryption for manged database. //+optional - TLSCertificate TLSCert `json:"tls"` + TLS TLS `json:"tls,omitempty"` } // CTlogStatus defines the observed state of CTlog component @@ -60,7 +65,8 @@ type CTlogStatus struct { PrivateKeyPasswordRef *SecretKeySelector `json:"privateKeyPasswordRef,omitempty"` PublicKeyRef *SecretKeySelector `json:"publicKeyRef,omitempty"` RootCertificates []SecretKeySelector `json:"rootCertificates,omitempty"` - TLSCertificate *TLSCert `json:"tls,omitempty"` + TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` + TLSCertificate *TLS `json:"tls,omitempty"` // The ID of a Trillian tree that stores the log data. // +kubebuilder:validation:Type=number TreeID *int64 `json:"treeID,omitempty"` diff --git a/api/v1alpha1/ctlog_types_test.go b/api/v1alpha1/ctlog_types_test.go index 55ad7618b..3026af7d8 100644 --- a/api/v1alpha1/ctlog_types_test.go +++ b/api/v1alpha1/ctlog_types_test.go @@ -136,16 +136,6 @@ var _ = Describe("CTlog", func() { Address: "trillian-system.default.svc", Port: &port, }, - TLSCertificate: TLSCert{ - CertRef: &SecretKeySelector{ - Key: "cert", - LocalObjectReference: LocalObjectReference{Name: "secret"}, - }, - PrivateKeyRef: &SecretKeySelector{ - Key: "key", - LocalObjectReference: LocalObjectReference{Name: "secret"}, - }, - }, }, } diff --git a/api/v1alpha1/rekor_types.go b/api/v1alpha1/rekor_types.go index 74a4cf620..5e2804f31 100644 --- a/api/v1alpha1/rekor_types.go +++ b/api/v1alpha1/rekor_types.go @@ -39,9 +39,9 @@ type RekorSpec struct { // +patchMergeKey=treeID // +kubebuilder:default:={} Sharding []RekorLogRange `json:"sharding,omitempty"` - // Reference to TLS server certificate, private key and CA certificate + // ConfigMap with additional bundle of trusted CA //+optional - TLSCertificate TLSCert `json:"tls"` + TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` } type RekorSigner struct { diff --git a/api/v1alpha1/rekor_types_test.go b/api/v1alpha1/rekor_types_test.go index 896812a03..322b7a794 100644 --- a/api/v1alpha1/rekor_types_test.go +++ b/api/v1alpha1/rekor_types_test.go @@ -315,11 +315,6 @@ var _ = Describe("Rekor", func() { EncodedPublicKey: "LS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS0KTUZrd0V3WUhLb1pJemowQ0FRWUlLb1pJemowREFRY0RRZ0FFWkZ0Nk5FcU14YWVVNzZsbmxZekZVTmpGUUdIcQpORjQ2QlBDVGxQL0ZnZk1aak42MDhjRFhmM0xNNWhUYnZOeUNFYWJFKzRNYk9jRU1YaERRVWxZRnZBPT0KLS0tLS1FTkQgUFVCTElDIEtFWS0tLS0tCg==", }, }, - TLSCertificate: TLSCert{ - CACertRef: &LocalObjectReference{ - Name: "ca-configmap", - }, - }, }, } diff --git a/api/v1alpha1/trillian_types.go b/api/v1alpha1/trillian_types.go index 6a0615b8a..4d7a05336 100644 --- a/api/v1alpha1/trillian_types.go +++ b/api/v1alpha1/trillian_types.go @@ -28,7 +28,7 @@ type TrillianSpec struct { //+kubebuilder:default:={create: true, pvc: {size: "5Gi", retain: true, accessModes: {ReadWriteOnce}}} Db TrillianDB `json:"database,omitempty"` //+optional - TrillianServer TrillianServer `json:"server,omitempty"` + Server TrillianServer `json:"server,omitempty"` // Enable Monitoring for Logsigner and Logserver Monitoring MonitoringConfig `json:"monitoring,omitempty"` // ConfigMap with additional bundle of trusted CA @@ -58,13 +58,15 @@ type TrillianDB struct { } type TrillianServer struct { - // Secret with TLS server certificate, private key and CA certificate - TLSCertificate TLSCert `json:"tls"` + // Configuration for enabling TLS (Transport Layer Security) encryption for manged database. + //+optional + TLS TLS `json:"tls,omitempty"` } // TrillianStatus defines the observed state of Trillian type TrillianStatus struct { - Db TrillianDB `json:"database,omitempty"` + Db TrillianDB `json:"database,omitempty"` + Server TrillianServer `json:"server,omitempty"` // +listType=map // +listMapKey=type // +patchStrategy=merge diff --git a/api/v1alpha1/trillian_types_test.go b/api/v1alpha1/trillian_types_test.go index 2176a9a70..2d38fd486 100644 --- a/api/v1alpha1/trillian_types_test.go +++ b/api/v1alpha1/trillian_types_test.go @@ -157,18 +157,6 @@ var _ = Describe("Trillian", func() { Name: "secret", }, }, - TrillianServer: TrillianServer{ - TLSCertificate: TLSCert{ - CertRef: &SecretKeySelector{ - Key: "cert", - LocalObjectReference: LocalObjectReference{Name: "server-secret"}, - }, - PrivateKeyRef: &SecretKeySelector{ - Key: "key", - LocalObjectReference: LocalObjectReference{Name: "server-secret"}, - }, - }, - }, }, } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index b2dc81bd3..f33a1a63f 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -167,7 +167,12 @@ func (in *CTlogSpec) DeepCopyInto(out *CTlogSpec) { *out = new(LocalObjectReference) **out = **in } - in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) + if in.TrustedCA != nil { + in, out := &in.TrustedCA, &out.TrustedCA + *out = new(LocalObjectReference) + **out = **in + } + in.TLS.DeepCopyInto(&out.TLS) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CTlogSpec. @@ -208,9 +213,14 @@ func (in *CTlogStatus) DeepCopyInto(out *CTlogStatus) { *out = make([]SecretKeySelector, len(*in)) copy(*out, *in) } + if in.TrustedCA != nil { + in, out := &in.TrustedCA, &out.TrustedCA + *out = new(LocalObjectReference) + **out = **in + } if in.TLSCertificate != nil { in, out := &in.TLSCertificate, &out.TLSCertificate - *out = new(TLSCert) + *out = new(TLS) (*in).DeepCopyInto(*out) } if in.TreeID != nil { @@ -790,7 +800,11 @@ func (in *RekorSpec) DeepCopyInto(out *RekorSpec) { *out = make([]RekorLogRange, len(*in)) copy(*out, *in) } - in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) + if in.TrustedCA != nil { + in, out := &in.TrustedCA, &out.TrustedCA + *out = new(LocalObjectReference) + **out = **in + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RekorSpec. @@ -1048,19 +1062,6 @@ func (in *TLS) DeepCopy() *TLS { return nil } out := new(TLS) - if in.CACertRef != nil { - in, out := &in.CACertRef, &out.CACertRef - *out = new(LocalObjectReference) - **out = **in - } -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSCert. -func (in *TLSCert) DeepCopy() *TLSCert { - if in == nil { - return nil - } - out := new(TLSCert) in.DeepCopyInto(out) return out } @@ -1325,7 +1326,7 @@ func (in *TrillianList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *TrillianServer) DeepCopyInto(out *TrillianServer) { *out = *in - in.TLSCertificate.DeepCopyInto(&out.TLSCertificate) + in.TLS.DeepCopyInto(&out.TLS) } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TrillianServer. @@ -1362,7 +1363,7 @@ func (in *TrillianService) DeepCopy() *TrillianService { func (in *TrillianSpec) DeepCopyInto(out *TrillianSpec) { *out = *in in.Db.DeepCopyInto(&out.Db) - in.TrillianServer.DeepCopyInto(&out.TrillianServer) + in.Server.DeepCopyInto(&out.Server) out.Monitoring = in.Monitoring if in.TrustedCA != nil { in, out := &in.TrustedCA, &out.TrustedCA @@ -1385,6 +1386,7 @@ func (in *TrillianSpec) DeepCopy() *TrillianSpec { func (in *TrillianStatus) DeepCopyInto(out *TrillianStatus) { *out = *in in.Db.DeepCopyInto(&out.Db) + in.Server.DeepCopyInto(&out.Server) if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions *out = make([]metav1.Condition, len(*in)) diff --git a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 6aa0ac173..4b72b786e 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -153,23 +153,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: Reference to TLS server certificate, private key and - CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -187,7 +176,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -207,7 +197,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -230,6 +220,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty @@ -400,22 +402,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: TLSCert defines fields for TLS certificate + description: TLS (Transport Layer Security) Configuration for enabling + service encryption. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -433,7 +425,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -453,7 +446,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + 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_rekors.yaml b/bundle/manifests/rhtas.redhat.com_rekors.yaml index 90e2d9727..968fbe929 100644 --- a/bundle/manifests/rhtas.redhat.com_rekors.yaml +++ b/bundle/manifests/rhtas.redhat.com_rekors.yaml @@ -256,62 +256,6 @@ spec: type: object x-kubernetes-map-type: atomic type: object - tls: - description: Reference to TLS server certificate, private key and - CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -334,6 +278,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object status: description: RekorStatus defines the observed state of Rekor diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index e66e499fb..a2566c784 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -169,23 +169,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: Reference to TLS server certificate, private key - and CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -203,7 +192,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -223,7 +213,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -246,6 +236,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty @@ -719,62 +721,6 @@ spec: type: object x-kubernetes-map-type: atomic type: object - tls: - description: Reference to TLS server certificate, private key - and CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -797,6 +743,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object trillian: description: TrillianSpec defines the desired state of Trillian @@ -953,38 +911,15 @@ spec: required: - enabled type: object - trustedCA: - description: ConfigMap with additional bundle of trusted CA - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic server: properties: tls: - description: Secret with TLS server certificate, private key - and CA certificate + description: Configuration for enabling TLS (Transport Layer + Security) encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used + for TLS encryption. properties: key: description: The key of the secret to select from. @@ -1002,7 +937,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used + for TLS encryption. properties: key: description: The key of the secret to select from. @@ -1022,10 +958,20 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) + type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string required: - - tls + - name type: object + x-kubernetes-map-type: atomic type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/bundle/manifests/rhtas.redhat.com_trillians.yaml b/bundle/manifests/rhtas.redhat.com_trillians.yaml index 96330ca3b..de2f2d51b 100644 --- a/bundle/manifests/rhtas.redhat.com_trillians.yaml +++ b/bundle/manifests/rhtas.redhat.com_trillians.yaml @@ -195,38 +195,15 @@ spec: required: - enabled type: object - trustedCA: - description: ConfigMap with additional bundle of trusted CA - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic server: properties: tls: - description: Secret with TLS server certificate, private key and - CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -244,7 +221,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -264,10 +242,20 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) + type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string required: - - tls + - name type: object + x-kubernetes-map-type: atomic type: object status: description: TrillianStatus defines the observed state of Trillian @@ -471,6 +459,55 @@ spec: required: - create type: object + server: + properties: + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. + 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)) + type: object type: object type: object served: true diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index 3f22fd0b0..2cd2cac8c 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -153,23 +153,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: Reference to TLS server certificate, private key and - CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -187,7 +176,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -207,7 +197,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -230,6 +220,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty @@ -400,22 +402,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: TLSCert defines fields for TLS certificate + description: TLS (Transport Layer Security) Configuration for enabling + service encryption. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -433,7 +425,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for TLS + encryption. properties: key: description: The key of the secret to select from. Must be @@ -453,7 +446,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + 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_rekors.yaml b/config/crd/bases/rhtas.redhat.com_rekors.yaml index 1db685f9b..8f6baa5d8 100644 --- a/config/crd/bases/rhtas.redhat.com_rekors.yaml +++ b/config/crd/bases/rhtas.redhat.com_rekors.yaml @@ -256,62 +256,6 @@ spec: type: object x-kubernetes-map-type: atomic type: object - tls: - description: Reference to TLS server certificate, private key and - CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -334,6 +278,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object status: description: RekorStatus defines the observed state of Rekor diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 1e495fc9e..d6afc2ee9 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -169,23 +169,12 @@ spec: type: object x-kubernetes-map-type: atomic tls: - description: Reference to TLS server certificate, private key - and CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -203,7 +192,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -223,7 +213,7 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) treeID: description: |- The ID of a Trillian tree that stores the log data. @@ -246,6 +236,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty @@ -719,62 +721,6 @@ spec: type: object x-kubernetes-map-type: atomic type: object - tls: - description: Reference to TLS server certificate, private key - and CA certificate - properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate - 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 - 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.certRef) || has(self.privateKeyRef)) treeID: description: |- ID of Merkle tree in Trillian backend @@ -797,6 +743,18 @@ spec: minimum: 1 type: integer type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object trillian: description: TrillianSpec defines the desired state of Trillian @@ -953,38 +911,15 @@ spec: required: - enabled type: object - trustedCA: - description: ConfigMap with additional bundle of trusted CA - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic server: properties: tls: - description: Secret with TLS server certificate, private key - and CA certificate + description: Configuration for enabling TLS (Transport Layer + Security) encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used + for TLS encryption. properties: key: description: The key of the secret to select from. @@ -1002,7 +937,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used + for TLS encryption. properties: key: description: The key of the secret to select from. @@ -1022,10 +958,20 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) + type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string required: - - tls + - name type: object + x-kubernetes-map-type: atomic type: object tsa: description: TimestampAuthoritySpec defines the desired state of TimestampAuthority diff --git a/config/crd/bases/rhtas.redhat.com_trillians.yaml b/config/crd/bases/rhtas.redhat.com_trillians.yaml index 86a6f84a8..5d6ffcd59 100644 --- a/config/crd/bases/rhtas.redhat.com_trillians.yaml +++ b/config/crd/bases/rhtas.redhat.com_trillians.yaml @@ -195,38 +195,15 @@ spec: required: - enabled type: object - trustedCA: - description: ConfigMap with additional bundle of trusted CA - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic server: properties: tls: - description: Secret with TLS server certificate, private key and - CA certificate + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. properties: - caCertRef: - description: Reference to CA certificate - properties: - name: - description: |- - Name of the referent. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - required: - - name - type: object - x-kubernetes-map-type: atomic - certRef: - description: Reference to service certificate + certificateRef: + description: Reference to the certificate secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -244,7 +221,8 @@ spec: type: object x-kubernetes-map-type: atomic privateKeyRef: - description: Reference to the private key + description: Reference to the private key secret used for + TLS encryption. properties: key: description: The key of the secret to select from. Must @@ -264,10 +242,20 @@ spec: type: object x-kubernetes-validations: - message: privateKeyRef cannot be empty - rule: (!has(self.certRef) || has(self.privateKeyRef)) + rule: (!has(self.certificateRef) || has(self.privateKeyRef)) + type: object + trustedCA: + description: ConfigMap with additional bundle of trusted CA + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string required: - - tls + - name type: object + x-kubernetes-map-type: atomic type: object status: description: TrillianStatus defines the observed state of Trillian @@ -471,6 +459,55 @@ spec: required: - create type: object + server: + properties: + tls: + description: Configuration for enabling TLS (Transport Layer Security) + encryption for manged database. + 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)) + type: object type: object type: object served: true diff --git a/internal/controller/ctlog/actions/ca_configmap.go b/internal/controller/ctlog/actions/ca_configmap.go deleted file mode 100644 index 63f2c7f72..000000000 --- a/internal/controller/ctlog/actions/ca_configmap.go +++ /dev/null @@ -1,79 +0,0 @@ -package actions - -import ( - "context" - "fmt" - - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "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" - corev1 "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" -) - -func NewCAConfigMapAction() action.Action[*rhtasv1alpha1.CTlog] { - return &configMapAction{} -} - -type configMapAction struct { - action.BaseAction -} - -func (i configMapAction) Name() string { - return "create CA configMap" -} - -func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && k8sutils.IsOpenShift() && instance.Spec.TLSCertificate.CACertRef == nil -} - -func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { - var ( - err error - updated bool - ) - - labels := constants.LabelsFor(ComponentName, DeploymentName, instance.Name) - - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ca-configmap", - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - 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 configMap: %w", err), instance) - } - - //TLS: Annotate configMap - configMap.Annotations = map[string]string{"service.beta.openshift.io/inject-cabundle": "true"} - err = i.Client.Update(ctx, configMap) - if err != nil { - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate configMap: %w", err), instance) - } - - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - return i.StatusUpdate(ctx, instance) - } else { - return i.Continue() - } -} diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index 1912c0540..2dc5d92da 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -8,10 +8,12 @@ import ( "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/common/utils/kubernetes/job" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" actions2 "github.com/securesign/operator/internal/controller/trillian/actions" corev1 "k8s.io/api/core/v1" + apiErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -101,10 +103,24 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 backoffLimit := int32(5) trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) + caPath, err := utils.CAPath(ctx, i.Client, instance) + if err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + i.StatusUpdate(ctx, instance) + if apiErrors.IsNotFound(err) { + return i.Requeue() + } + return i.Failed(err) + } cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=%s", trillUrl, caPath) case kubernetes.IsOpenShift(): cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) default: @@ -140,12 +156,12 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } env := []corev1.EnvVar{} - job := kubernetes.CreateJob(instance.Namespace, CtlogTreeJobName, labels, constants.CreateTreeImage, RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + job := job.CreateJob(instance.Namespace, CtlogTreeJobName, labels, constants.CreateTreeImage, RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) } - err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) if err != nil { return i.Failed(err) } @@ -156,7 +172,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 Name: "tls-cert", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-log-server-tls-secret", + SecretName: instance.Name + "-trillian-server-tls", }, }, }) diff --git a/internal/controller/ctlog/actions/deployment.go b/internal/controller/ctlog/actions/deployment.go index 124715c75..70c570c9b 100644 --- a/internal/controller/ctlog/actions/deployment.go +++ b/internal/controller/ctlog/actions/deployment.go @@ -12,7 +12,7 @@ import ( "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" - corev1 "k8s.io/api/core/v1" + apiErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -58,108 +58,32 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could create server Deployment: %w", err), instance) } - err = cutils.SetTrustedCA(&dp.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + caTrustRef := cutils.TrustedCAAnnotationToReference(instance.Annotations) + // override if spec.trustedCA is defined + if instance.Spec.TrustedCA != nil { + caTrustRef = instance.Spec.TrustedCA + } + err = cutils.SetTrustedCA(&dp.Spec.Template, caTrustRef) if err != nil { return i.Failed(err) } - // TLS certificate - if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil { - dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TLSCertificate.CertRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: instance.Spec.TLSCertificate.CertRef.Key, - Path: "tls.crt", - }, - }, - }, - }, - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TLSCertificate.PrivateKeyRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: instance.Spec.TLSCertificate.PrivateKeyRef.Key, - Path: "tls.key", - }, - }, - }, - }, - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TLSCertificate.CACertRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: "ca.crt", // User should use this key. - Path: "ca.crt", - }, - }, - }, - }, - }, - }, - }, - }) - } else if kubernetes.IsOpenShift() { - i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") - dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Name + "-ctlog-tls-secret", - }, - }, - }, - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "ca-configmap", - }, - Items: []corev1.KeyToPath{ - { - Key: "service-ca.crt", - Path: "ca.crt", - }, - }, - }, - }, - }, - }, - }, - }) - } else { - i.Logger.V(1).Info("Communication between services is insecure") - } - - if instance.Spec.TLSCertificate.CertRef != nil && instance.Spec.TLSCertificate.CACertRef != nil || kubernetes.IsOpenShift() { - dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, + if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + caPath, err := utils.CAPath(ctx, i.Client, instance) + if err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), }) - // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_certificate", "/var/run/secrets/tas/tls.crt") - // dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--tls_key", "/var/run/secrets/tas/tls.key") - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", "/var/run/secrets/tas/ca.crt") + i.StatusUpdate(ctx, instance) + if apiErrors.IsNotFound(err) { + return i.Requeue() + } + return i.Failed(err) + } + dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", caPath) } if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index c2077a75f..be9c67364 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -49,6 +49,15 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog TargetPort: intstr.FromInt32(MetricsPort), }) } + + //TLS: Annotate service + if kubernetes.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)) } @@ -62,18 +71,6 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create service: %w", err), instance) } - //TLS: Annotate service - if kubernetes.IsOpenShift() && instance.Spec.TLSCertificate.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-secret" - err := i.Client.Update(ctx, svc) - if err != nil { - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate service: %w", err), instance) - } - } - if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "Service created"}) diff --git a/internal/controller/ctlog/ctlog_controller.go b/internal/controller/ctlog/ctlog_controller.go index 6488cced4..a32a6c6ce 100644 --- a/internal/controller/ctlog/ctlog_controller.go +++ b/internal/controller/ctlog/ctlog_controller.go @@ -94,7 +94,6 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl transitions.NewToCreatePhaseAction[*rhtasv1alpha1.CTlog](), actions.NewRBACAction(), - actions.NewCAConfigMapAction(), actions.NewHandleFulcioCertAction(), actions.NewHandleKeysAction(), actions.NewCreateTreeJobAction(), @@ -157,7 +156,6 @@ func (r *CTlogReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&rhtasv1alpha1.CTlog{}). Owns(&v1.Deployment{}). Owns(&v12.Service{}). - Owns(&v12.ConfigMap{}). WatchesMetadata(partialSecret, handler.EnqueueRequestsFromMapFunc(func(ctx context.Context, object client.Object) []reconcile.Request { val, ok := object.GetLabels()["app.kubernetes.io/instance"] if ok { diff --git a/internal/controller/ctlog/ctlog_controller_test.go b/internal/controller/ctlog/ctlog_controller_test.go index c76c4bbb1..07d09f17a 100644 --- a/internal/controller/ctlog/ctlog_controller_test.go +++ b/internal/controller/ctlog/ctlog_controller_test.go @@ -96,17 +96,6 @@ var _ = Describe("CTlog controller", func() { Spec: v1alpha1.CTlogSpec{ TreeID: &ptr, - TLSCertificate: v1alpha1.TLSCert{ - CertRef: &v1alpha1.SecretKeySelector{ - Key: "cert", - LocalObjectReference: v1alpha1.LocalObjectReference{Name: "secret-crt"}, - }, - PrivateKeyRef: &v1alpha1.SecretKeySelector{ - Key: "key", - LocalObjectReference: v1alpha1.LocalObjectReference{Name: "secret-key"}, - }, - CACertRef: &v1alpha1.LocalObjectReference{Name: "ca-configmap"}, - }, }, } err = k8sClient.Create(ctx, instance) diff --git a/internal/controller/ctlog/utils/tls.go b/internal/controller/ctlog/utils/tls.go new file mode 100644 index 000000000..b4c456955 --- /dev/null +++ b/internal/controller/ctlog/utils/tls.go @@ -0,0 +1,32 @@ +package utils + +import ( + "context" + "fmt" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.CTlog) (string, error) { + if instance.Spec.TrustedCA != nil { + cfgTrust, err := kubernetes.GetConfigMap(ctx, cli, instance.Namespace, instance.Spec.TrustedCA.Name) + if err != nil { + return "", err + } + if len(cfgTrust.Data) != 1 { + 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 "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt", nil + } + + return "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", nil +} diff --git a/internal/controller/rekor/actions/server/ca_configmap.go b/internal/controller/rekor/actions/server/ca_configmap.go deleted file mode 100644 index e422197e4..000000000 --- a/internal/controller/rekor/actions/server/ca_configmap.go +++ /dev/null @@ -1,82 +0,0 @@ -package server - -import ( - "context" - "fmt" - - rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - "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" - "github.com/securesign/operator/internal/controller/rekor/actions" - corev1 "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" -) - -func NewCAConfigMapAction() action.Action[*rhtasv1alpha1.Rekor] { - return &configMapAction{} -} - -type configMapAction struct { - action.BaseAction -} - -func (i configMapAction) Name() string { - return "create CA configMap" -} - -func (i configMapAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - cm, _ := k8sutils.GetConfigMap(ctx, i.Client, instance.Namespace, "ca-configmap") - // signingKeySecret: OCP - signingKeySecret, _ := k8sutils.GetSecret(i.Client, "openshift-service-ca", "signing-key") - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && signingKeySecret != nil && instance.Spec.TLSCertificate.CACertRef == nil -} - -func (i configMapAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { - var ( - err error - updated bool - ) - - labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) - - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: "ca-configmap", - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - 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 configMap: %w", err), instance) - } - - //TLS: Annotate configMap - configMap.Annotations = map[string]string{"service.beta.openshift.io/inject-cabundle": "true"} - err = i.Client.Update(ctx, configMap) - if err != nil { - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate configMap: %w", err), instance) - } - - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - return i.StatusUpdate(ctx, instance) - } else { - return i.Continue() - } -} diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index bcb9d4deb..0682cbc92 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -8,11 +8,13 @@ import ( "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/common/utils/kubernetes/job" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/rekor/actions" "github.com/securesign/operator/internal/controller/rekor/utils" actions2 "github.com/securesign/operator/internal/controller/trillian/actions" corev1 "k8s.io/api/core/v1" + apiErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ctrl "sigs.k8s.io/controller-runtime" @@ -102,10 +104,24 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 backoffLimit := int32(5) trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) + caPath, err := utils.CAPath(ctx, i.Client, instance) + if err != nil { + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ + Type: constants.Ready, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + i.StatusUpdate(ctx, instance) + if apiErrors.IsNotFound(err) { + return i.Requeue() + } + return i.Failed(err) + } cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/configs/tas/ca-trust/ca-bundle.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=%s", trillUrl, caPath) case kubernetes.IsOpenShift(): cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) default: @@ -141,12 +157,12 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } env := []corev1.EnvVar{} - job := kubernetes.CreateJob(instance.Namespace, RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + job := job.CreateJob(instance.Namespace, RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) } - err = cutils.SetTrustedCA(&job.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) if err != nil { return i.Failed(err) } @@ -157,7 +173,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 Name: "tls-cert", VolumeSource: corev1.VolumeSource{ Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-log-server-tls-secret", + SecretName: instance.Name + "-trillian-server-tls", }, }, }) diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 2f6fc30b0..410fa694a 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -17,8 +17,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" - corev1 "k8s.io/api/core/v1" ) func NewDeployAction() action.Action[*rhtasv1alpha1.Rekor] { @@ -50,9 +48,14 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) insCopy.Spec.Trillian.Address = fmt.Sprintf("%s.%s.svc", actions2.LogserverDeploymentName, instance.Namespace) } i.Logger.V(1).Info("trillian logserver", "address", insCopy.Spec.Trillian.Address) - dp, err := utils.CreateRekorDeployment(insCopy, actions.ServerDeploymentName, actions.RBACName, labels) + dp, err := utils.CreateRekorDeployment(ctx, i.Client, insCopy, actions.ServerDeploymentName, actions.RBACName, labels) if err == nil { - err = cutils.SetTrustedCA(&dp.Spec.Template, cutils.TrustedCAAnnotationToReference(instance.Annotations)) + caTrustRef := cutils.TrustedCAAnnotationToReference(instance.Annotations) + // override if spec.trustedCA is defined + if instance.Spec.TrustedCA != nil { + caTrustRef = instance.Spec.TrustedCA + } + err = cutils.SetTrustedCA(&dp.Spec.Template, caTrustRef) } if err != nil { @@ -71,69 +74,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could create server Deployment: %w", err), instance) } - // TLS certificate - if instance.Spec.TLSCertificate.CACertRef != nil { - dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TLSCertificate.CACertRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: "ca.crt", // User should use this key. - Path: "ca.crt", - }, - }, - }, - }, - }, - }, - }, - }) - } else if k8sutils.IsOpenShift() { - dp.Spec.Template.Spec.Volumes = append(dp.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - ConfigMap: &corev1.ConfigMapProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: "ca-configmap", - }, - Items: []corev1.KeyToPath{ - { - Key: "service-ca.crt", - Path: "ca.crt", - }, - }, - }, - }, - }, - }, - }, - }) - } else { - i.Logger.V(1).Info("Communication between services is insecure") - } - - if instance.Spec.TLSCertificate.CACertRef != nil || k8sutils.IsOpenShift() { - dp.Spec.Template.Spec.Containers[0].VolumeMounts = append(dp.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_log_server.tls_ca_cert", "/var/run/secrets/tas/ca.crt") - } - if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err)) } diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index b52de8d6e..db0cd03d8 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -111,7 +111,6 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl server.NewShardingConfigAction(), server.NewCreateTreeJobAction(), server.NewResolveTreeAction(), - server.NewCAConfigMapAction(), server.NewCreatePvcAction(), server.NewDeployAction(), server.NewCreateServiceAction(), @@ -169,7 +168,6 @@ func (r *RekorReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&rhtasv1alpha1.Rekor{}). Owns(&v12.Deployment{}). Owns(&v13.Service{}). - Owns(&v13.ConfigMap{}). Owns(&v1.Ingress{}). Owns(&batchv1.CronJob{}). Complete(r) diff --git a/internal/controller/rekor/utils/rekor_deployment.go b/internal/controller/rekor/utils/rekor_deployment.go index e4b60ca49..de05ef96f 100644 --- a/internal/controller/rekor/utils/rekor_deployment.go +++ b/internal/controller/rekor/utils/rekor_deployment.go @@ -1,9 +1,12 @@ package utils import ( + "context" + "errors" "fmt" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" @@ -13,7 +16,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func CreateRekorDeployment(instance *v1alpha1.Rekor, dpName string, sa string, labels map[string]string) (*apps.Deployment, error) { +func CreateRekorDeployment(ctx context.Context, client client.Client, instance *v1alpha1.Rekor, dpName string, sa string, labels map[string]string) (*apps.Deployment, error) { switch { case instance.Status.ServerConfigRef == nil: return nil, fmt.Errorf("CreateRekorDeployment: %w", ServerConfigNotSpecified) @@ -200,6 +203,16 @@ func CreateRekorDeployment(instance *v1alpha1.Rekor, dpName string, sa string, l }, }, } + + // TLS communication to Trillian logserver + 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, "--trillian_log_server.tls_ca_cert", caPath) + } + utils.SetProxyEnvs(dep) return dep, nil } diff --git a/internal/controller/rekor/utils/tls.go b/internal/controller/rekor/utils/tls.go new file mode 100644 index 000000000..d8272a69d --- /dev/null +++ b/internal/controller/rekor/utils/tls.go @@ -0,0 +1,45 @@ +package utils + +import ( + "context" + "fmt" + + rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +func UseTLS(instance *rhtasv1alpha1.Rekor) bool { + + if instance == nil { + return false + } + // TLS enabled on Trillian logserver + if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + return true + } + + return false +} + +func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.Rekor) (string, error) { + if instance.Spec.TrustedCA != nil { + cfgTrust, err := kubernetes.GetConfigMap(ctx, cli, instance.Namespace, instance.Spec.TrustedCA.Name) + if err != nil { + return "", err + } + if len(cfgTrust.Data) != 1 { + 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 "/var/run/secrets/kubernetes.io/serviceaccount/service-ca.crt", nil + } + + return "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt", nil +} diff --git a/internal/controller/trillian/actions/logserver/deployment.go b/internal/controller/trillian/actions/logserver/deployment.go index 162bdf2d7..7da02f2d3 100644 --- a/internal/controller/trillian/actions/logserver/deployment.go +++ b/internal/controller/trillian/actions/logserver/deployment.go @@ -14,8 +14,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" - k8sutils "github.com/securesign/operator/internal/controller/common/utils/kubernetes" - corev1 "k8s.io/api/core/v1" + "github.com/securesign/operator/internal/controller/common/utils/kubernetes" ) func NewDeployAction() action.Action[*rhtasv1alpha1.Trillian] { @@ -41,6 +40,25 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli updated bool ) + // TLS + switch { + case instance.Spec.Server.TLS.CertRef != nil: + instance.Status.Server.TLS = instance.Spec.Server.TLS + case kubernetes.IsOpenShift(): + instance.Status.Server.TLS = rhtasv1alpha1.TLS{ + CertRef: &rhtasv1alpha1.SecretKeySelector{ + LocalObjectReference: rhtasv1alpha1.LocalObjectReference{Name: instance.Name + "-trillian-server-tls"}, + Key: "tls.crt", + }, + PrivateKeyRef: &rhtasv1alpha1.SecretKeySelector{ + LocalObjectReference: rhtasv1alpha1.LocalObjectReference{Name: instance.Name + "-trillian-server-tls"}, + Key: "tls.key", + }, + } + default: + i.Logger.V(1).Info("Communication to trillian log server is insecure") + } + labels := constants.LabelsFor(actions.LogServerComponentName, actions.LogserverDeploymentName, instance.Name) server, err := trillianUtils.CreateLogServerDeployment(ctx, i.Client, instance, constants.TrillianServerImage, actions.LogserverDeploymentName, actions.RBACName, labels) if err != nil { @@ -70,70 +88,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Trilli return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create Trillian server: %w", err), instance) } - // TLS certificate - if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil { - server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Projected: &corev1.ProjectedVolumeSource{ - Sources: []corev1.VolumeProjection{ - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TrillianServer.TLSCertificate.CertRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: instance.Spec.TrillianServer.TLSCertificate.CertRef.Key, - Path: "tls.crt", - }, - }, - }, - }, - { - Secret: &corev1.SecretProjection{ - LocalObjectReference: corev1.LocalObjectReference{ - Name: instance.Spec.TrillianServer.TLSCertificate.PrivateKeyRef.Name, - }, - Items: []corev1.KeyToPath{ - { - Key: instance.Spec.TrillianServer.TLSCertificate.PrivateKeyRef.Key, - Path: "tls.key", - }, - }, - }, - }, - }, - }, - }, - }) - } else if k8sutils.IsOpenShift() { - i.Logger.V(1).Info("TLS: Using secrets/signing-key secret") - server.Spec.Template.Spec.Volumes = append(server.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-log-server-tls-secret", - }, - }, - }) - } else { - i.Logger.V(1).Info("Communication between services is insecure") - } - - if instance.Spec.TrillianServer.TLSCertificate.CertRef != nil || k8sutils.IsOpenShift() { - server.Spec.Template.Spec.Containers[0].VolumeMounts = append(server.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_cert_file", "/var/run/secrets/tas/tls.crt") - server.Spec.Template.Spec.Containers[0].Args = append(server.Spec.Template.Spec.Containers[0].Args, "--tls_key_file", "/var/run/secrets/tas/tls.key") - } - 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)) } diff --git a/internal/controller/trillian/actions/logserver/service.go b/internal/controller/trillian/actions/logserver/service.go index b57d3e050..f3afd8b4c 100644 --- a/internal/controller/trillian/actions/logserver/service.go +++ b/internal/controller/trillian/actions/logserver/service.go @@ -53,6 +53,14 @@ func (i createServiceAction) Handle(ctx context.Context, instance *rhtasv1alpha1 }) } + //TLS: Annotate service + if k8sutils.IsOpenShift() && instance.Spec.Server.TLS.CertRef == nil { + if logserverService.Annotations == nil { + logserverService.Annotations = make(map[string]string) + } + logserverService.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = instance.Name + "-trillian-server-tls" + } + if err = controllerutil.SetControllerReference(instance, logserverService, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for logserver Service: %w", err)) } @@ -73,18 +81,6 @@ func (i createServiceAction) Handle(ctx context.Context, instance *rhtasv1alpha1 return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not create logserver Service: %w", err), instance) } - //TLS: Annotate service - if k8sutils.IsOpenShift() && instance.Spec.TrillianServer.TLSCertificate.CertRef == nil { - if logserverService.Annotations == nil { - logserverService.Annotations = make(map[string]string) - } - logserverService.Annotations["service.beta.openshift.io/serving-cert-secret-name"] = instance.Name + "-trillian-log-server-tls-secret" - err := i.Client.Update(ctx, logserverService) - if err != nil { - return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could not annotate logserver service: %w", err), instance) - } - } - if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: actions.ServerCondition, diff --git a/internal/controller/trillian/utils/server-deployment.go b/internal/controller/trillian/utils/server-deployment.go index 8416808d0..00370528e 100644 --- a/internal/controller/trillian/utils/server-deployment.go +++ b/internal/controller/trillian/utils/server-deployment.go @@ -180,6 +180,15 @@ func CreateLogServerDeployment(ctx context.Context, client client.Client, instan dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--mysql_server_name", mysqlServerName) } + // Server TLS communication + if err := utils.SetTLS(&dep.Spec.Template, instance.Status.Server.TLS); err != nil { + return nil, errors.New("could not set TLS: " + err.Error()) + } + if instance.Status.Server.TLS.CertRef != nil { + dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--tls_cert_file", "/var/run/secrets/tas/tls.crt") + dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--tls_key_file", "/var/run/secrets/tas/tls.key") + } + utils.SetProxyEnvs(dep) return dep, nil } From 93191cb3e8bbf8f186c9460424793757d3665b03 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 11 Sep 2024 13:05:37 +0200 Subject: [PATCH 22/34] solve conflicts --- .../ctlog/actions/create_tree_job.go | 2 +- .../controller/ctlog/actions/deployment.go | 22 +------------------ .../ctlog/utils/ctlog_deployment.go | 15 ++++++++++++- 3 files changed, 16 insertions(+), 23 deletions(-) diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index 2dc5d92da..891c8c67a 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -120,7 +120,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=%s", trillUrl, caPath) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=%s", trillUrl, caPath) case kubernetes.IsOpenShift(): cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) default: diff --git a/internal/controller/ctlog/actions/deployment.go b/internal/controller/ctlog/actions/deployment.go index 70c570c9b..32425b78d 100644 --- a/internal/controller/ctlog/actions/deployment.go +++ b/internal/controller/ctlog/actions/deployment.go @@ -8,11 +8,9 @@ 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" "github.com/securesign/operator/internal/controller/constants" "github.com/securesign/operator/internal/controller/ctlog/utils" trillian "github.com/securesign/operator/internal/controller/trillian/actions" - apiErrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -48,7 +46,7 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) 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(ctx, i.Client, instance, DeploymentName, RBACName, labels, ServerTargetPort, MetricsPort) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ Type: constants.Ready, @@ -68,24 +66,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) return i.Failed(err) } - if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { - caPath, err := utils.CAPath(ctx, i.Client, instance) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - i.StatusUpdate(ctx, instance) - if apiErrors.IsNotFound(err) { - return i.Requeue() - } - return i.Failed(err) - } - dp.Spec.Template.Spec.Containers[0].Args = append(dp.Spec.Template.Spec.Containers[0].Args, "--trillian_tls_ca_cert_file", caPath) - } - if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err)) } diff --git a/internal/controller/ctlog/utils/ctlog_deployment.go b/internal/controller/ctlog/utils/ctlog_deployment.go index e8af3ba9e..082caa306 100644 --- a/internal/controller/ctlog/utils/ctlog_deployment.go +++ b/internal/controller/ctlog/utils/ctlog_deployment.go @@ -1,19 +1,23 @@ package utils import ( + "context" + "errors" "fmt" "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" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/util/intstr" + "sigs.k8s.io/controller-runtime/pkg/client" ) -func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string, labels map[string]string, serverPort, metricsPort int32) (*appsv1.Deployment, error) { +func CreateDeployment(ctx context.Context, client client.Client, instance *v1alpha1.CTlog, deploymentName string, sa string, labels map[string]string, serverPort, metricsPort int32) (*appsv1.Deployment, error) { switch { case instance.Status.ServerConfigRef == nil: return nil, fmt.Errorf("CreateCTLogDeployment: %w", ServerConfigNotSpecified) @@ -120,6 +124,15 @@ func CreateDeployment(instance *v1alpha1.CTlog, deploymentName string, sa string }, }, } + + if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + 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, "--trillian_tls_ca_cert_file", caPath) + } + utils.SetProxyEnvs(dep) return dep, nil } From c512c859d66074cc70bbdeecf3d7784b28b56cae Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 15:32:53 +0200 Subject: [PATCH 23/34] fix comments --- api/v1alpha1/ctlog_types.go | 2 +- api/v1alpha1/trillian_types.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 7a0ca90a8..9cd93b845 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -53,7 +53,7 @@ type CTlogSpec struct { //+optional TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` - // Configuration for enabling TLS (Transport Layer Security) encryption for manged database. + // Configuration for enabling TLS (Transport Layer Security) encryption CTlog. //+optional TLS TLS `json:"tls,omitempty"` } diff --git a/api/v1alpha1/trillian_types.go b/api/v1alpha1/trillian_types.go index 4d7a05336..29ce2cd66 100644 --- a/api/v1alpha1/trillian_types.go +++ b/api/v1alpha1/trillian_types.go @@ -58,7 +58,7 @@ type TrillianDB struct { } type TrillianServer struct { - // Configuration for enabling TLS (Transport Layer Security) encryption for manged database. + // Configuration for enabling TLS (Transport Layer Security) encryption for Trillian server. //+optional TLS TLS `json:"tls,omitempty"` } From 128470e4a22bc48f6a3ca27b0b506cd89029eb5c Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 15:39:52 +0200 Subject: [PATCH 24/34] remove unsed comment --- internal/controller/ctlog/ctlog_controller_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/controller/ctlog/ctlog_controller_test.go b/internal/controller/ctlog/ctlog_controller_test.go index 07d09f17a..54d60daa7 100644 --- a/internal/controller/ctlog/ctlog_controller_test.go +++ b/internal/controller/ctlog/ctlog_controller_test.go @@ -158,7 +158,6 @@ var _ = Describe("CTlog controller", func() { return k8sClient.Get(ctx, types.NamespacedName{Name: actions.ComponentName, Namespace: Namespace}, service) }).Should(Succeed()) Expect(service.Spec.Ports[0].Port).Should(Equal(int32(80))) - // Expect(service.Spec.Ports[0].Port).Should(Equal(int32(443))) // TODO By("Move to Ready phase") // Workaround to succeed condition for Ready phase From d55f9152e4327139588c0227075c4552d152f9c2 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 15:53:55 +0200 Subject: [PATCH 25/34] fix typo --- api/v1alpha1/ctlog_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 9cd93b845..24940e625 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -53,7 +53,7 @@ type CTlogSpec struct { //+optional TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` - // Configuration for enabling TLS (Transport Layer Security) encryption CTlog. + // Configuration for enabling TLS (Transport Layer Security) encryption for CTlog. //+optional TLS TLS `json:"tls,omitempty"` } From 03d0bf2d495b343b2d84de1cab22bcdcda595d6b Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 15:55:09 +0200 Subject: [PATCH 26/34] update manifests --- bundle/manifests/rhtas.redhat.com_ctlogs.yaml | 2 +- bundle/manifests/rhtas.redhat.com_securesigns.yaml | 4 ++-- bundle/manifests/rhtas.redhat.com_trillians.yaml | 4 ++-- config/crd/bases/rhtas.redhat.com_ctlogs.yaml | 2 +- config/crd/bases/rhtas.redhat.com_securesigns.yaml | 4 ++-- config/crd/bases/rhtas.redhat.com_trillians.yaml | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 4b72b786e..43632d831 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -154,7 +154,7 @@ spec: x-kubernetes-map-type: atomic tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for CTlog. properties: certificateRef: description: Reference to the certificate secret used for TLS diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index a2566c784..6a179e033 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -170,7 +170,7 @@ spec: x-kubernetes-map-type: atomic tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for CTlog. properties: certificateRef: description: Reference to the certificate secret used for @@ -915,7 +915,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer - Security) encryption for manged database. + Security) encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used diff --git a/bundle/manifests/rhtas.redhat.com_trillians.yaml b/bundle/manifests/rhtas.redhat.com_trillians.yaml index de2f2d51b..cde495792 100644 --- a/bundle/manifests/rhtas.redhat.com_trillians.yaml +++ b/bundle/manifests/rhtas.redhat.com_trillians.yaml @@ -199,7 +199,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used for @@ -463,7 +463,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used for diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index 2cd2cac8c..957f50c3b 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -154,7 +154,7 @@ spec: x-kubernetes-map-type: atomic tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for CTlog. properties: certificateRef: description: Reference to the certificate secret used for TLS diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index d6afc2ee9..240338ae9 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -170,7 +170,7 @@ spec: x-kubernetes-map-type: atomic tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for CTlog. properties: certificateRef: description: Reference to the certificate secret used for @@ -915,7 +915,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer - Security) encryption for manged database. + Security) encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used diff --git a/config/crd/bases/rhtas.redhat.com_trillians.yaml b/config/crd/bases/rhtas.redhat.com_trillians.yaml index 5d6ffcd59..a20306f13 100644 --- a/config/crd/bases/rhtas.redhat.com_trillians.yaml +++ b/config/crd/bases/rhtas.redhat.com_trillians.yaml @@ -199,7 +199,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used for @@ -463,7 +463,7 @@ spec: properties: tls: description: Configuration for enabling TLS (Transport Layer Security) - encryption for manged database. + encryption for Trillian server. properties: certificateRef: description: Reference to the certificate secret used for From 1dc5287bc340fa93c2c0247aed2084acff9a7276 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 17:19:46 +0200 Subject: [PATCH 27/34] updates --- api/v1alpha1/ctlog_types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index 24940e625..c075c6766 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -66,7 +66,7 @@ type CTlogStatus struct { PublicKeyRef *SecretKeySelector `json:"publicKeyRef,omitempty"` RootCertificates []SecretKeySelector `json:"rootCertificates,omitempty"` TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` - TLSCertificate *TLS `json:"tls,omitempty"` + TLS TLS `json:"tls,omitempty"` // The ID of a Trillian tree that stores the log data. // +kubebuilder:validation:Type=number TreeID *int64 `json:"treeID,omitempty"` From a8248c74d37da004fd560d79e87c646dca9f9977 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Thu, 12 Sep 2024 17:21:15 +0200 Subject: [PATCH 28/34] updates --- api/v1alpha1/zz_generated.deepcopy.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index f33a1a63f..6e14dbe6a 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -218,11 +218,7 @@ func (in *CTlogStatus) DeepCopyInto(out *CTlogStatus) { *out = new(LocalObjectReference) **out = **in } - if in.TLSCertificate != nil { - in, out := &in.TLSCertificate, &out.TLSCertificate - *out = new(TLS) - (*in).DeepCopyInto(*out) - } + in.TLS.DeepCopyInto(&out.TLS) if in.TreeID != nil { in, out := &in.TreeID, &out.TreeID *out = new(int64) From c97bae30331848dd8882092205cdfe2b80a02a88 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Fri, 13 Sep 2024 09:08:36 +0200 Subject: [PATCH 29/34] remove unused changes --- api/v1alpha1/ctlog_types.go | 5 - api/v1alpha1/fulcio_types.go | 2 +- api/v1alpha1/zz_generated.deepcopy.go | 2 - bundle/manifests/rhtas.redhat.com_ctlogs.yaml | 92 ------------------- .../manifests/rhtas.redhat.com_fulcios.yaml | 1 + .../rhtas.redhat.com_securesigns.yaml | 47 +--------- config/crd/bases/rhtas.redhat.com_ctlogs.yaml | 92 ------------------- .../crd/bases/rhtas.redhat.com_fulcios.yaml | 1 + .../bases/rhtas.redhat.com_securesigns.yaml | 47 +--------- internal/controller/ctlog/actions/service.go | 8 -- 10 files changed, 5 insertions(+), 292 deletions(-) diff --git a/api/v1alpha1/ctlog_types.go b/api/v1alpha1/ctlog_types.go index c075c6766..137afd76b 100644 --- a/api/v1alpha1/ctlog_types.go +++ b/api/v1alpha1/ctlog_types.go @@ -52,10 +52,6 @@ type CTlogSpec struct { // ConfigMap with additional bundle of trusted CA //+optional TrustedCA *LocalObjectReference `json:"trustedCA,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 @@ -66,7 +62,6 @@ type CTlogStatus struct { PublicKeyRef *SecretKeySelector `json:"publicKeyRef,omitempty"` RootCertificates []SecretKeySelector `json:"rootCertificates,omitempty"` TrustedCA *LocalObjectReference `json:"trustedCA,omitempty"` - TLS TLS `json:"tls,omitempty"` // The ID of a Trillian tree that stores the log data. // +kubebuilder:validation:Type=number TreeID *int64 `json:"treeID,omitempty"` diff --git a/api/v1alpha1/fulcio_types.go b/api/v1alpha1/fulcio_types.go index 3da17d3d5..daf3d3add 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:={prefix: trusted-artifact-signer} + //+kubebuilder:default:={port: 80, 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 6e14dbe6a..6f7f56b6a 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -172,7 +172,6 @@ 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. @@ -218,7 +217,6 @@ func (in *CTlogStatus) DeepCopyInto(out *CTlogStatus) { *out = new(LocalObjectReference) **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.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 43632d831..19201b099 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -152,52 +152,6 @@ 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. @@ -401,52 +355,6 @@ 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 79ccee746..118bea8b2 100644 --- a/bundle/manifests/rhtas.redhat.com_fulcios.yaml +++ b/bundle/manifests/rhtas.redhat.com_fulcios.yaml @@ -223,6 +223,7 @@ spec: (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: + port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: diff --git a/bundle/manifests/rhtas.redhat.com_securesigns.yaml b/bundle/manifests/rhtas.redhat.com_securesigns.yaml index 6a179e033..f403d79e1 100644 --- a/bundle/manifests/rhtas.redhat.com_securesigns.yaml +++ b/bundle/manifests/rhtas.redhat.com_securesigns.yaml @@ -168,52 +168,6 @@ 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. @@ -433,6 +387,7 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: + port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index 957f50c3b..dc24645a7 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -152,52 +152,6 @@ 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. @@ -401,52 +355,6 @@ 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 b665ee36a..00f495721 100644 --- a/config/crd/bases/rhtas.redhat.com_fulcios.yaml +++ b/config/crd/bases/rhtas.redhat.com_fulcios.yaml @@ -223,6 +223,7 @@ spec: (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: + port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: diff --git a/config/crd/bases/rhtas.redhat.com_securesigns.yaml b/config/crd/bases/rhtas.redhat.com_securesigns.yaml index 240338ae9..de88fea1e 100644 --- a/config/crd/bases/rhtas.redhat.com_securesigns.yaml +++ b/config/crd/bases/rhtas.redhat.com_securesigns.yaml @@ -168,52 +168,6 @@ 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. @@ -433,6 +387,7 @@ spec: || (has(self.MetaIssuers) && (size(self.MetaIssuers) > 0)) ctlog: default: + port: 80 prefix: trusted-artifact-signer description: Ctlog service configuration properties: diff --git a/internal/controller/ctlog/actions/service.go b/internal/controller/ctlog/actions/service.go index be9c67364..387183af6 100644 --- a/internal/controller/ctlog/actions/service.go +++ b/internal/controller/ctlog/actions/service.go @@ -50,14 +50,6 @@ func (i serviceAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog }) } - //TLS: Annotate service - if kubernetes.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)) } From 76c0b0879e6a9be6802cd530cd793041ae1d6d62 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Fri, 13 Sep 2024 09:13:18 +0200 Subject: [PATCH 30/34] remove unused changes --- bundle/manifests/rhtas-operator.clusterserviceversion.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml index 162ea86a2..ac4f809bd 100644 --- a/bundle/manifests/rhtas-operator.clusterserviceversion.yaml +++ b/bundle/manifests/rhtas-operator.clusterserviceversion.yaml @@ -309,7 +309,7 @@ metadata: features.operators.openshift.io/token-auth-azure: "false" features.operators.openshift.io/token-auth-gcp: "false" operators.openshift.io/valid-subscription: '["Red Hat Trusted Artifact Signer"]' - operators.operatorframework.io/builder: operator-sdk-v1.34.1 + operators.operatorframework.io/builder: operator-sdk-v1.34.2 operators.operatorframework.io/project_layout: go.kubebuilder.io/v4 repository: https://github.com/securesign/secure-sign-operator support: Red Hat From 98cc6b4944b5c9ee3d1cbb23e2cf08dfa772efd3 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Fri, 13 Sep 2024 12:08:22 +0200 Subject: [PATCH 31/34] updates: reviews --- .../controller/ctlog/actions/constants.go | 22 ++++++++------ .../ctlog/actions/create_tree_job.go | 24 +++++++-------- .../controller/rekor/actions/constants.go | 4 +++ .../rekor/actions/server/create_tree_job.go | 30 +++++++++---------- .../trillian/trillian_controller.go | 3 +- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/internal/controller/ctlog/actions/constants.go b/internal/controller/ctlog/actions/constants.go index 9e1a264d7..c1ae0b302 100644 --- a/internal/controller/ctlog/actions/constants.go +++ b/internal/controller/ctlog/actions/constants.go @@ -8,15 +8,19 @@ const ( RBACName = "ctlog" MonitoringRoleName = "prometheus-k8s-ctlog" - CertCondition = "FulcioCertAvailable" - ServerPortName = "http" - ServerPort = 80 - HttpsServerPortName = "https" - HttpsServerPort = 443 - ServerTargetPort = 6962 - MetricsPortName = "metrics" - MetricsPort = 6963 - ServerCondition = "ServerAvailable" + CertCondition = "FulcioCertAvailable" + ServerPortName = "http" + ServerPort = 80 + HttpsServerPortName = "https" + HttpsServerPort = 443 + ServerTargetPort = 6962 + MetricsPortName = "metrics" + MetricsPort = 6963 + ServerCondition = "ServerAvailable" + CtlogTreeName = "ctlog-tree" + CtlogTreeJobName = "ctlog-create-tree" + CtlogTreeJobCondition = "CtlogTreeJobAvailable" + CtlogTreeJobConfigMapName = "ctlog-tree-id-config" CTLPubLabel = constants.LabelNamespace + "/ctfe.pub" ) diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index 891c8c67a..c3bd47eea 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -33,7 +33,7 @@ func (i createTreeJobAction) Name() string { } func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, "ctlog-tree-id-config") + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, CtlogTreeJobConfigMapName) c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil } @@ -44,8 +44,6 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 updated bool ) - CtlogTreeJobName := "ctlog-create-tree" - configMapName := "ctlog-tree-id-config" var trillUrl string switch { @@ -66,7 +64,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 Type: CtlogTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Creating, - Message: "Creating ctlog tree Job", + Message: "Creating tree Job", }) } @@ -75,7 +73,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 // Needed for configMap clean-up configMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, + Name: CtlogTreeJobConfigMapName, Namespace: instance.Namespace, Labels: labels, }, @@ -86,14 +84,14 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } if updated, err = i.Ensure(ctx, configMap); err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: CtlogTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), }) } if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, + meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: CtlogTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) } @@ -106,7 +104,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 caPath, err := utils.CAPath(ctx, i.Client, instance) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: CtlogTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), @@ -120,11 +118,11 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=%s", trillUrl, caPath) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, CtlogTreeName, caPath) case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, CtlogTreeName) default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=ctlog-tree", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, CtlogTreeName) } command := []string{ "/bin/sh", @@ -152,7 +150,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 echo "Failed to create tree" >&2 exit 1 fi - `, cmd, configMapName), + `, cmd, CtlogTreeJobConfigMapName), } env := []corev1.EnvVar{} @@ -193,7 +191,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 Type: CtlogTreeJobName, Status: metav1.ConditionTrue, Reason: constants.Creating, - Message: "ctlog tree Job Created", + Message: "tree Job Created", }) return i.Continue() diff --git a/internal/controller/rekor/actions/constants.go b/internal/controller/rekor/actions/constants.go index 359729279..77a38c1c6 100644 --- a/internal/controller/rekor/actions/constants.go +++ b/internal/controller/rekor/actions/constants.go @@ -23,4 +23,8 @@ const ( ServerCondition = "ServerAvailable" RedisCondition = "RedisAvailable" SignerCondition = "SignerAvailable" + RekorTreeName = "rekor-tree" + RekorTreeJobName = "rekor-create-tree" + RekorTreeJobCondition = "RekorTreeJobAvailable" + RekorTreeJobConfigMapName = "rekor-tree-id-config" ) diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index 0682cbc92..cd72b8254 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -34,7 +34,7 @@ func (i createTreeJobAction) Name() string { } func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, "rekor-tree-id-config") + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, actions.RekorTreeJobConfigMapName) c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil } @@ -45,8 +45,6 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 updated bool ) - RekorTreeJobName := "rekor-create-tree" - configMapName := "rekor-tree-id-config" var trillUrl string switch { @@ -62,12 +60,12 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - if c := meta.FindStatusCondition(instance.Status.Conditions, RekorTreeJobName); c == nil { + if c := meta.FindStatusCondition(instance.Status.Conditions, actions.RekorTreeJobName); c == nil { instance.SetCondition(metav1.Condition{ - Type: RekorTreeJobName, + Type: actions.RekorTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Creating, - Message: "Creating rekor tree Job", + Message: "Creating tree Job", }) } @@ -76,7 +74,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 // Needed for configMap clean-up configMap := &corev1.ConfigMap{ ObjectMeta: metav1.ObjectMeta{ - Name: configMapName, + Name: actions.RekorTreeJobConfigMapName, Namespace: instance.Namespace, Labels: labels, }, @@ -87,7 +85,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } if updated, err = i.Ensure(ctx, configMap); err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: actions.RekorTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), @@ -107,7 +105,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 caPath, err := utils.CAPath(ctx, i.Client, instance) if err != nil { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: constants.Ready, + Type: actions.RekorTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Failure, Message: err.Error(), @@ -121,11 +119,11 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 cmd := "" switch { case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=%s", trillUrl, caPath) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, actions.RekorTreeName, caPath) case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, actions.RekorTreeName) default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=rekor-tree", trillUrl) + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, actions.RekorTreeName) } command := []string{ "/bin/sh", @@ -153,11 +151,11 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 echo "Failed to create tree" >&2 exit 1 fi - `, cmd, configMapName), + `, cmd, actions.RekorTreeJobConfigMapName), } env := []corev1.EnvVar{} - job := job.CreateJob(instance.Namespace, RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + job := job.CreateJob(instance.Namespace, actions.RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) } @@ -191,10 +189,10 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 } meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: RekorTreeJobName, + Type: actions.RekorTreeJobName, Status: metav1.ConditionTrue, Reason: constants.Creating, - Message: "rekor tree Job Created", + Message: "tree Job Created", }) return i.Continue() diff --git a/internal/controller/trillian/trillian_controller.go b/internal/controller/trillian/trillian_controller.go index 6d75ee00d..5d2afc67a 100644 --- a/internal/controller/trillian/trillian_controller.go +++ b/internal/controller/trillian/trillian_controller.go @@ -28,6 +28,7 @@ import ( "github.com/securesign/operator/internal/controller/common/action/transitions" "github.com/securesign/operator/internal/controller/common/action" + actions2 "github.com/securesign/operator/internal/controller/ctlog/actions" "github.com/securesign/operator/internal/controller/trillian/actions" "github.com/securesign/operator/internal/controller/trillian/actions/db" "github.com/securesign/operator/internal/controller/trillian/actions/logserver" @@ -89,7 +90,7 @@ func (r *TrillianReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c target := instance.DeepCopy() actions := []action.Action[*rhtasv1alpha1.Trillian]{ transitions.NewToPendingPhaseAction[*rhtasv1alpha1.Trillian](func(t *rhtasv1alpha1.Trillian) []string { - components := []string{actions.ServerCondition, actions.SignerCondition} + components := []string{actions.ServerCondition, actions.SignerCondition, actions2.CtlogTreeJobCondition} if utils.IsEnabled(t.Spec.Db.Create) { components = append(components, actions.DbCondition) } From b6cf94941b0e089bdfab2d50c60a5285e07e9c2a Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Fri, 13 Sep 2024 12:24:46 +0200 Subject: [PATCH 32/34] updates2: reviews --- bundle/manifests/rhtas.redhat.com_ctlogs.yaml | 14 ++++++++++++++ config/crd/bases/rhtas.redhat.com_ctlogs.yaml | 14 ++++++++++++++ .../controller/ctlog/actions/create_tree_job.go | 1 + .../rekor/actions/server/create_tree_job.go | 1 + 4 files changed, 30 insertions(+) diff --git a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml index 19201b099..01276f8ba 100644 --- a/bundle/manifests/rhtas.redhat.com_ctlogs.yaml +++ b/bundle/manifests/rhtas.redhat.com_ctlogs.yaml @@ -359,6 +359,20 @@ spec: description: The ID of a Trillian tree that stores the log data. format: int64 type: number + trustedCA: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object type: object served: true diff --git a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml index dc24645a7..605b4afbf 100644 --- a/config/crd/bases/rhtas.redhat.com_ctlogs.yaml +++ b/config/crd/bases/rhtas.redhat.com_ctlogs.yaml @@ -359,6 +359,20 @@ spec: description: The ID of a Trillian tree that stores the log data. format: int64 type: number + trustedCA: + description: |- + LocalObjectReference contains enough information to let you locate the + referenced object inside the same namespace. + properties: + name: + description: |- + Name of the referent. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + required: + - name + type: object + x-kubernetes-map-type: atomic type: object type: object served: true diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go index c3bd47eea..df977d95a 100644 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ b/internal/controller/ctlog/actions/create_tree_job.go @@ -93,6 +93,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: CtlogTreeJobName, Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") } parallelism := int32(1) diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go index cd72b8254..87211481b 100644 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ b/internal/controller/rekor/actions/server/create_tree_job.go @@ -94,6 +94,7 @@ func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1 if updated { meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) + i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") } parallelism := int32(1) From cab998c7965e42ae3a0a8be04026cffd66190c4a Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Sat, 14 Sep 2024 19:34:46 +0200 Subject: [PATCH 33/34] generic create_tree_job --- .../action/transitions/create_tree_job.go | 210 ++++++++++++++++++ .../ctlog/actions/create_tree_job.go | 199 ----------------- internal/controller/ctlog/ctlog_controller.go | 26 ++- .../ctlog/utils/ctlog_deployment.go | 4 +- internal/controller/ctlog/utils/tls.go | 13 ++ .../rekor/actions/server/create_tree_job.go | 200 ----------------- internal/controller/rekor/rekor_controller.go | 26 ++- 7 files changed, 275 insertions(+), 403 deletions(-) create mode 100644 internal/controller/common/action/transitions/create_tree_job.go delete mode 100644 internal/controller/ctlog/actions/create_tree_job.go delete mode 100644 internal/controller/rekor/actions/server/create_tree_job.go diff --git a/internal/controller/common/action/transitions/create_tree_job.go b/internal/controller/common/action/transitions/create_tree_job.go new file mode 100644 index 000000000..466bab675 --- /dev/null +++ b/internal/controller/common/action/transitions/create_tree_job.go @@ -0,0 +1,210 @@ +package transitions + +import ( + "context" + "fmt" + + "github.com/securesign/operator/internal/apis" + "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/common/utils/kubernetes/job" + "github.com/securesign/operator/internal/controller/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" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +type TreeJobSupplier[T apis.ConditionsAwareObject] func( + instance T, +) ( + trillianAddress string, + instanceName string, + treeJobConfigMapName string, + treeJobName string, + treeDisplayName string, + trillianDeploymentName string, + namespace string, + trillianPort *int32, + caPath string, + rbac string, + labels map[string]string, + annotations map[string]string, + treeID *int64, + err error, +) + +func NewCreateTreeJobAction[T apis.ConditionsAwareObject](supplier TreeJobSupplier[T]) action.Action[T] { + return &createTreeJobAction[T]{supplier: supplier} +} + +type createTreeJobAction[T apis.ConditionsAwareObject] struct { + action.BaseAction + supplier TreeJobSupplier[T] +} + +func (i createTreeJobAction[T]) Name() string { + return "create tree job" +} + +func (i createTreeJobAction[T]) CanHandle(ctx context.Context, instance T) bool { + _, _, treeJobConfigMapName, _, _, _, _, _, _, _, _, _, treeID, err := i.supplier(instance) + if err != nil { + return false + } + cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.GetNamespace(), treeJobConfigMapName) + c := meta.FindStatusCondition(instance.GetConditions(), constants.Ready) + return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && treeID == nil +} + +func (i createTreeJobAction[T]) Handle(ctx context.Context, instance T) *action.Result { + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName, namespace, trillianPort, caPath, rbac, labels, annotations, _, err := i.supplier(instance) + + if err != nil { + return i.Failed(fmt.Errorf("failed to get job details: %w", err)) + } + + var trillUrl string + + switch { + case trillianPort == nil: + err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) + case trillianAddress == "": + trillUrl = fmt.Sprintf("%s.%s.svc:%d", trillianDeploymentName, namespace, *trillianPort) + default: + trillUrl = fmt.Sprintf("%s:%d", trillianAddress, *trillianPort) + } + if err != nil { + return i.Failed(err) + } + + i.Logger.V(1).Info("trillian logserver", "address", trillUrl) + + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "Creating tree Job", + }) + + // Needed for configMap clean-up + configMap := &corev1.ConfigMap{ + ObjectMeta: metav1.ObjectMeta{ + Name: treeJobConfigMapName, + Namespace: instance.GetNamespace(), + Labels: labels, + }, + Data: map[string]string{}, + } + + if err := controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) + } + + updated, err := i.Ensure(ctx, configMap) + if err != nil { + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Failure, + Message: err.Error(), + }) + return i.Failed(err) + } + if updated { + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionFalse, + Reason: constants.Creating, + Message: "ConfigMap created", + }) + i.Recorder.Event(instance, corev1.EventTypeNormal, "TreeConfigCreated", "ConfigMap for TreeID created") + } + + parallelism := int32(1) + completions := int32(1) + activeDeadlineSeconds := int64(600) + backoffLimit := int32(5) + + trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(annotations) + + cmd := "" + switch { + case trustedCAAnnotation != nil: + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, treeDisplayName, caPath) + case kubernetes.IsOpenShift(): + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, treeDisplayName) + default: + cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, treeDisplayName) + } + command := []string{ + "/bin/sh", + "-c", + fmt.Sprintf(` + TREE_ID=$(%s) + if [ $? -eq 0 ]; then + echo "TREE_ID=$TREE_ID" + TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) + NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) + API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} + curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ + -H "Authorization: Bearer $TOKEN" \ + -H "Content-Type: application/merge-patch+json" \ + -d '{ + "data": { + "tree_id": "'$TREE_ID'" + } + }' + if [ $? -ne 0 ]; then + echo "Failed to update ConfigMap" >&2 + exit 1 + fi + else + echo "Failed to create tree" >&2 + exit 1 + fi + `, cmd, treeJobConfigMapName), + } + env := []corev1.EnvVar{} + + job := job.CreateJob(namespace, treeJobName, labels, constants.CreateTreeImage, rbac, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) + if err := ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { + return i.Failed(fmt.Errorf("could not set controller reference for job: %w", err)) + } + + if err := cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation); err != nil { + return i.Failed(err) + } + + if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { + job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, corev1.Volume{ + Name: "tls-cert", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: instanceName + "-trillian-server-tls", + }, + }, + }) + job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ + Name: "tls-cert", + MountPath: "/var/run/secrets/tas", + ReadOnly: true, + }) + } + + if _, err := i.Ensure(ctx, job); err != nil { + return i.Failed(fmt.Errorf("failed to ensure the job: %w", err)) + } + + instance.SetCondition(metav1.Condition{ + Type: treeJobName, + Status: metav1.ConditionTrue, + Reason: constants.Creating, + Message: "Tree Job created", + }) + + return i.Continue() +} diff --git a/internal/controller/ctlog/actions/create_tree_job.go b/internal/controller/ctlog/actions/create_tree_job.go deleted file mode 100644 index df977d95a..000000000 --- a/internal/controller/ctlog/actions/create_tree_job.go +++ /dev/null @@ -1,199 +0,0 @@ -package actions - -import ( - "context" - "fmt" - - 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/common/utils/kubernetes/job" - "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/ctlog/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" - corev1 "k8s.io/api/core/v1" - apiErrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.CTlog] { - return &createTreeJobAction{} -} - -type createTreeJobAction struct { - action.BaseAction -} - -func (i createTreeJobAction) Name() string { - return "create tree job" -} - -func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.CTlog) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, CtlogTreeJobConfigMapName) - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil -} - -func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.CTlog) *action.Result { - var ( - err error - updated bool - ) - - var trillUrl string - - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) - } - if err != nil { - return i.Failed(err) - } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - - if c := meta.FindStatusCondition(instance.Status.Conditions, CtlogTreeJobName); c == nil { - instance.SetCondition(metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Creating, - Message: "Creating tree Job", - }) - } - - labels := constants.LabelsFor(ComponentName, ComponentName, instance.Name) - - // Needed for configMap clean-up - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: CtlogTreeJobConfigMapName, - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - } - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") - } - - parallelism := int32(1) - completions := int32(1) - activeDeadlineSeconds := int64(600) - backoffLimit := int32(5) - - trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) - caPath, err := utils.CAPath(ctx, i.Client, instance) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - i.StatusUpdate(ctx, instance) - if apiErrors.IsNotFound(err) { - return i.Requeue() - } - return i.Failed(err) - } - cmd := "" - switch { - case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, CtlogTreeName, caPath) - case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, CtlogTreeName) - default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, CtlogTreeName) - } - command := []string{ - "/bin/sh", - "-c", - fmt.Sprintf(` - TREE_ID=$(%s) - if [ $? -eq 0 ]; then - echo "TREE_ID=$TREE_ID" - TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} - curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/merge-patch+json" \ - -d '{ - "data": { - "tree_id": "'$TREE_ID'" - } - }' - if [ $? -ne 0 ]; then - echo "Failed to update ConfigMap" >&2 - exit 1 - fi - else - echo "Failed to create tree" >&2 - exit 1 - fi - `, cmd, CtlogTreeJobConfigMapName), - } - env := []corev1.EnvVar{} - - job := job.CreateJob(instance.Namespace, CtlogTreeJobName, labels, constants.CreateTreeImage, RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) - if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) - } - - err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) - if err != nil { - return i.Failed(err) - } - - if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { - job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-server-tls", - }, - }, - }) - job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - } - - _, err = i.Ensure(ctx, job) - if err != nil { - return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) - } - - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: CtlogTreeJobName, - Status: metav1.ConditionTrue, - Reason: constants.Creating, - Message: "tree Job Created", - }) - - return i.Continue() -} diff --git a/internal/controller/ctlog/ctlog_controller.go b/internal/controller/ctlog/ctlog_controller.go index a32a6c6ce..ca1c6e3dc 100644 --- a/internal/controller/ctlog/ctlog_controller.go +++ b/internal/controller/ctlog/ctlog_controller.go @@ -22,9 +22,11 @@ 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/constants" "k8s.io/apimachinery/pkg/runtime/schema" "github.com/securesign/operator/internal/controller/ctlog/actions" + "github.com/securesign/operator/internal/controller/ctlog/utils" fulcioActions "github.com/securesign/operator/internal/controller/fulcio/actions" v12 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + actions2 "github.com/securesign/operator/internal/controller/trillian/actions" ) // CTlogReconciler reconciles a CTlog object @@ -96,7 +99,28 @@ func (r *CTlogReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions.NewRBACAction(), actions.NewHandleFulcioCertAction(), actions.NewHandleKeysAction(), - actions.NewCreateTreeJobAction(), + transitions.NewCreateTreeJobAction[*rhtasv1alpha1.CTlog](func(instance *rhtasv1alpha1.CTlog) ( + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName string, + namespace string, trillianPort *int32, caPath string, rbac string, labels map[string]string, annotations map[string]string, + treeID *int64, err error, + ) { + caPath, err = utils.CAPath(ctx, r.Client, instance) + labels = constants.LabelsFor(actions.ComponentName, actions.ComponentName, instance.Name) + return instance.Spec.Trillian.Address, + instance.Name, + actions.CtlogTreeJobConfigMapName, + actions.CtlogTreeJobName, + actions.CtlogTreeName, + actions2.LogserverDeploymentName, + instance.Namespace, + instance.Spec.Trillian.Port, + caPath, + actions.RBACName, + labels, + instance.Annotations, + instance.Status.TreeID, + err + }), actions.NewResolveTreeAction(), actions.NewServerConfigAction(), diff --git a/internal/controller/ctlog/utils/ctlog_deployment.go b/internal/controller/ctlog/utils/ctlog_deployment.go index 082caa306..a8075b12d 100644 --- a/internal/controller/ctlog/utils/ctlog_deployment.go +++ b/internal/controller/ctlog/utils/ctlog_deployment.go @@ -8,7 +8,6 @@ import ( "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" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" @@ -125,7 +124,8 @@ func CreateDeployment(ctx context.Context, client client.Client, instance *v1alp }, } - if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + useTLS := UseTLS(instance) + if useTLS { caPath, err := CAPath(ctx, client, instance) if err != nil { return nil, errors.New("failed to get CA path: " + err.Error()) diff --git a/internal/controller/ctlog/utils/tls.go b/internal/controller/ctlog/utils/tls.go index b4c456955..bfeb1ae1f 100644 --- a/internal/controller/ctlog/utils/tls.go +++ b/internal/controller/ctlog/utils/tls.go @@ -9,6 +9,19 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) +func UseTLS(instance *rhtasv1alpha1.CTlog) bool { + + if instance == nil { + return false + } + // TLS enabled on Trillian logserver + if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { + return true + } + + return false +} + func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.CTlog) (string, error) { if instance.Spec.TrustedCA != nil { cfgTrust, err := kubernetes.GetConfigMap(ctx, cli, instance.Namespace, instance.Spec.TrustedCA.Name) diff --git a/internal/controller/rekor/actions/server/create_tree_job.go b/internal/controller/rekor/actions/server/create_tree_job.go deleted file mode 100644 index 87211481b..000000000 --- a/internal/controller/rekor/actions/server/create_tree_job.go +++ /dev/null @@ -1,200 +0,0 @@ -package server - -import ( - "context" - "fmt" - - 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/common/utils/kubernetes/job" - "github.com/securesign/operator/internal/controller/constants" - "github.com/securesign/operator/internal/controller/rekor/actions" - "github.com/securesign/operator/internal/controller/rekor/utils" - actions2 "github.com/securesign/operator/internal/controller/trillian/actions" - corev1 "k8s.io/api/core/v1" - apiErrors "k8s.io/apimachinery/pkg/api/errors" - "k8s.io/apimachinery/pkg/api/meta" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" -) - -func NewCreateTreeJobAction() action.Action[*rhtasv1alpha1.Rekor] { - return &createTreeJobAction{} -} - -type createTreeJobAction struct { - action.BaseAction -} - -func (i createTreeJobAction) Name() string { - return "create tree job" -} - -func (i createTreeJobAction) CanHandle(ctx context.Context, instance *rhtasv1alpha1.Rekor) bool { - cm, _ := kubernetes.GetConfigMap(ctx, i.Client, instance.Namespace, actions.RekorTreeJobConfigMapName) - c := meta.FindStatusCondition(instance.Status.Conditions, constants.Ready) - return (c.Reason == constants.Creating || c.Reason == constants.Ready) && cm == nil && instance.Status.TreeID == nil -} - -func (i createTreeJobAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) *action.Result { - var ( - err error - updated bool - ) - - var trillUrl string - - switch { - case instance.Spec.Trillian.Port == nil: - err = fmt.Errorf("%s: %v", i.Name(), utils.TrillianPortNotSpecified) - case instance.Spec.Trillian.Address == "": - trillUrl = fmt.Sprintf("%s.%s.svc:%d", actions2.LogserverDeploymentName, instance.Namespace, *instance.Spec.Trillian.Port) - default: - trillUrl = fmt.Sprintf("%s:%d", instance.Spec.Trillian.Address, *instance.Spec.Trillian.Port) - } - if err != nil { - return i.Failed(err) - } - i.Logger.V(1).Info("trillian logserver", "address", trillUrl) - - if c := meta.FindStatusCondition(instance.Status.Conditions, actions.RekorTreeJobName); c == nil { - instance.SetCondition(metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Creating, - Message: "Creating tree Job", - }) - } - - labels := constants.LabelsFor(actions.ServerComponentName, actions.ServerDeploymentName, instance.Name) - - // Needed for configMap clean-up - configMap := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: actions.RekorTreeJobConfigMapName, - Namespace: instance.Namespace, - Labels: labels, - }, - Data: map[string]string{}, - } - if err = controllerutil.SetControllerReference(instance, configMap, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for configMap: %w", err)) - } - if updated, err = i.Ensure(ctx, configMap); err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - } - if updated { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{Type: constants.Ready, - Status: metav1.ConditionFalse, Reason: constants.Creating, Message: "ConfigMap created"}) - i.Recorder.Event(instance, corev1.EventTypeNormal, "ConfigMapCreated", "New ConfigMap created") - } - - parallelism := int32(1) - completions := int32(1) - activeDeadlineSeconds := int64(600) - backoffLimit := int32(5) - - trustedCAAnnotation := cutils.TrustedCAAnnotationToReference(instance.Annotations) - caPath, err := utils.CAPath(ctx, i.Client, instance) - if err != nil { - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionFalse, - Reason: constants.Failure, - Message: err.Error(), - }) - i.StatusUpdate(ctx, instance) - if apiErrors.IsNotFound(err) { - return i.Requeue() - } - return i.Failed(err) - } - cmd := "" - switch { - case trustedCAAnnotation != nil: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=%s", trillUrl, actions.RekorTreeName, caPath) - case kubernetes.IsOpenShift(): - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s --tls_cert_file=/var/run/secrets/tas/tls.crt", trillUrl, actions.RekorTreeName) - default: - cmd = fmt.Sprintf("/createtree --admin_server=%s --display_name=%s", trillUrl, actions.RekorTreeName) - } - command := []string{ - "/bin/sh", - "-c", - fmt.Sprintf(` - TREE_ID=$(%s) - if [ $? -eq 0 ]; then - echo "TREE_ID=$TREE_ID" - TOKEN=$(cat /var/run/secrets/kubernetes.io/serviceaccount/token) - NAMESPACE=$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace) - API_SERVER=https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT} - curl -k -X PATCH $API_SERVER/api/v1/namespaces/$NAMESPACE/configmaps/"%s" \ - -H "Authorization: Bearer $TOKEN" \ - -H "Content-Type: application/merge-patch+json" \ - -d '{ - "data": { - "tree_id": "'$TREE_ID'" - } - }' - if [ $? -ne 0 ]; then - echo "Failed to update ConfigMap" >&2 - exit 1 - fi - else - echo "Failed to create tree" >&2 - exit 1 - fi - `, cmd, actions.RekorTreeJobConfigMapName), - } - env := []corev1.EnvVar{} - - job := job.CreateJob(instance.Namespace, actions.RekorTreeJobName, labels, constants.CreateTreeImage, actions.RBACName, parallelism, completions, activeDeadlineSeconds, backoffLimit, command, env) - if err = ctrl.SetControllerReference(instance, job, i.Client.Scheme()); err != nil { - return i.Failed(fmt.Errorf("could not set controller reference for Job: %w", err)) - } - - err = cutils.SetTrustedCA(&job.Spec.Template, trustedCAAnnotation) - if err != nil { - return i.Failed(err) - } - - if kubernetes.IsOpenShift() && trustedCAAnnotation == nil { - job.Spec.Template.Spec.Volumes = append(job.Spec.Template.Spec.Volumes, - corev1.Volume{ - Name: "tls-cert", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: instance.Name + "-trillian-server-tls", - }, - }, - }) - job.Spec.Template.Spec.Containers[0].VolumeMounts = append(job.Spec.Template.Spec.Containers[0].VolumeMounts, - corev1.VolumeMount{ - Name: "tls-cert", - MountPath: "/var/run/secrets/tas", - ReadOnly: true, - }) - } - - _, err = i.Ensure(ctx, job) - if err != nil { - return i.Failed(fmt.Errorf("failed to Ensure the job: %w", err)) - } - - meta.SetStatusCondition(&instance.Status.Conditions, metav1.Condition{ - Type: actions.RekorTreeJobName, - Status: metav1.ConditionTrue, - Reason: constants.Creating, - Message: "tree Job Created", - }) - - return i.Continue() -} diff --git a/internal/controller/rekor/rekor_controller.go b/internal/controller/rekor/rekor_controller.go index db0cd03d8..380afadb1 100644 --- a/internal/controller/rekor/rekor_controller.go +++ b/internal/controller/rekor/rekor_controller.go @@ -24,12 +24,14 @@ 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/constants" actions2 "github.com/securesign/operator/internal/controller/rekor/actions" backfillredis "github.com/securesign/operator/internal/controller/rekor/actions/backfillRedis" "github.com/securesign/operator/internal/controller/rekor/actions/redis" "github.com/securesign/operator/internal/controller/rekor/actions/server" "github.com/securesign/operator/internal/controller/rekor/actions/ui" + "github.com/securesign/operator/internal/controller/rekor/utils" v13 "k8s.io/api/core/v1" v1 "k8s.io/api/networking/v1" "k8s.io/client-go/tools/record" @@ -43,6 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" + actions3 "github.com/securesign/operator/internal/controller/trillian/actions" batchv1 "k8s.io/api/batch/v1" ) @@ -109,7 +112,28 @@ func (r *RekorReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl actions2.NewRBACAction(), server.NewShardingConfigAction(), - server.NewCreateTreeJobAction(), + transitions.NewCreateTreeJobAction[*rhtasv1alpha1.Rekor](func(instance *rhtasv1alpha1.Rekor) ( + trillianAddress, instanceName, treeJobConfigMapName, treeJobName, treeDisplayName, trillianDeploymentName string, + namespace string, trillianPort *int32, caPath string, rbac string, labels map[string]string, annotations map[string]string, + treeID *int64, err error, + ) { + caPath, err = utils.CAPath(ctx, r.Client, instance) + labels = constants.LabelsFor(actions2.ServerComponentName, actions2.ServerDeploymentName, instance.Name) + return instance.Spec.Trillian.Address, + instance.Name, + actions2.RekorTreeJobConfigMapName, + actions2.RekorTreeJobName, + actions2.RekorTreeName, + actions3.LogserverDeploymentName, + instance.Namespace, + instance.Spec.Trillian.Port, + caPath, + actions2.RBACName, + labels, + instance.Annotations, + instance.Status.TreeID, + err + }), server.NewResolveTreeAction(), server.NewCreatePvcAction(), server.NewDeployAction(), From 25f265b6a82a8469c7762feb6e9ee63febc31975 Mon Sep 17 00:00:00 2001 From: Firas Ghanmi Date: Wed, 18 Sep 2024 10:01:07 +0200 Subject: [PATCH 34/34] enhance useTLS --- .../controller/ctlog/ctlog_controller_test.go | 7 +++ .../ctlog/utils/ctlog_deployment.go | 17 ++++-- .../rekor/actions/server/deployment.go | 1 - .../controller/rekor/rekor_controller_test.go | 7 +++ .../rekor/utils/rekor_deployment.go | 17 ++++-- internal/controller/rekor/utils/tls.go | 61 ++++++++++++++++--- 6 files changed, 91 insertions(+), 19 deletions(-) diff --git a/internal/controller/ctlog/ctlog_controller_test.go b/internal/controller/ctlog/ctlog_controller_test.go index 54d60daa7..fe81f0585 100644 --- a/internal/controller/ctlog/ctlog_controller_test.go +++ b/internal/controller/ctlog/ctlog_controller_test.go @@ -32,6 +32,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + rutils "github.com/securesign/operator/internal/controller/rekor/utils" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -82,6 +83,12 @@ var _ = Describe("CTlog controller", func() { }) It("should successfully reconcile a custom resource for CTlog", func() { + + By("mocking UseTrillianTLS") + rutils.MockUseTrillianTLS = func(ctx context.Context, serviceAddr string, tlsCACertFile string) (bool, error) { + return false, nil + } + By("creating the custom resource for the Kind CTlog") err := k8sClient.Get(ctx, typeNamespaceName, instance) if err != nil && errors.IsNotFound(err) { diff --git a/internal/controller/ctlog/utils/ctlog_deployment.go b/internal/controller/ctlog/utils/ctlog_deployment.go index a8075b12d..6df9441da 100644 --- a/internal/controller/ctlog/utils/ctlog_deployment.go +++ b/internal/controller/ctlog/utils/ctlog_deployment.go @@ -9,6 +9,7 @@ import ( "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils" "github.com/securesign/operator/internal/controller/constants" + rutils "github.com/securesign/operator/internal/controller/rekor/utils" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -124,12 +125,18 @@ func CreateDeployment(ctx context.Context, client client.Client, instance *v1alp }, } - useTLS := UseTLS(instance) + // TLS communication to Trillian logserver + trillianSvc := fmt.Sprintf(instance.Spec.Trillian.Address+":%d", *instance.Spec.Trillian.Port) + caPath, err := CAPath(ctx, client, instance) + if err != nil { + return nil, errors.New("failed to get CA path: " + err.Error()) + } + + useTLS := false + if useTLS, err = rutils.UseTrillianTLS(ctx, trillianSvc, caPath); err != nil { + return nil, errors.New("failed to check TLS: " + err.Error()) + } if useTLS { - 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, "--trillian_tls_ca_cert_file", caPath) } diff --git a/internal/controller/rekor/actions/server/deployment.go b/internal/controller/rekor/actions/server/deployment.go index 410fa694a..bb9531a9b 100644 --- a/internal/controller/rekor/actions/server/deployment.go +++ b/internal/controller/rekor/actions/server/deployment.go @@ -73,7 +73,6 @@ func (i deployAction) Handle(ctx context.Context, instance *rhtasv1alpha1.Rekor) }) return i.FailedWithStatusUpdate(ctx, fmt.Errorf("could create server Deployment: %w", err), instance) } - if err = controllerutil.SetControllerReference(instance, dp, i.Client.Scheme()); err != nil { return i.Failed(fmt.Errorf("could not set controller reference for Deployment: %w", err)) } diff --git a/internal/controller/rekor/rekor_controller_test.go b/internal/controller/rekor/rekor_controller_test.go index 3b2a074ee..5961dc93b 100644 --- a/internal/controller/rekor/rekor_controller_test.go +++ b/internal/controller/rekor/rekor_controller_test.go @@ -41,6 +41,7 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + utils2 "github.com/securesign/operator/internal/controller/rekor/utils" batchv1 "k8s.io/api/batch/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" @@ -96,6 +97,12 @@ var _ = Describe("Rekor controller", func() { }) It("should successfully reconcile a custom resource for Rekor", func() { + + By("mocking UseTrillianTLS") + utils2.MockUseTrillianTLS = func(ctx context.Context, serviceAddr string, tlsCACertFile string) (bool, error) { + return false, nil + } + By("creating the custom resource for the Kind Rekor") err := k8sClient.Get(ctx, typeNamespaceName, instance) if err != nil && errors.IsNotFound(err) { diff --git a/internal/controller/rekor/utils/rekor_deployment.go b/internal/controller/rekor/utils/rekor_deployment.go index de05ef96f..1f260642a 100644 --- a/internal/controller/rekor/utils/rekor_deployment.go +++ b/internal/controller/rekor/utils/rekor_deployment.go @@ -205,12 +205,17 @@ func CreateRekorDeployment(ctx context.Context, client client.Client, instance * } // TLS communication to Trillian logserver - 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, "--trillian_log_server.tls_ca_cert", caPath) + trillianSvc := fmt.Sprintf(instance.Spec.Trillian.Address+":%d", *instance.Spec.Trillian.Port) + caPath, err := CAPath(ctx, client, instance) + if err != nil { + return nil, errors.New("failed to get CA path: " + err.Error()) + } + useTLS := false + if useTLS, err = UseTrillianTLS(ctx, trillianSvc, caPath); err != nil { + return nil, errors.New("failed to check TLS: " + err.Error()) + } + if useTLS { + dep.Spec.Template.Spec.Containers[0].Args = append(dep.Spec.Template.Spec.Containers[0].Args, "--trillian_log_server.tls=true") } utils.SetProxyEnvs(dep) diff --git a/internal/controller/rekor/utils/tls.go b/internal/controller/rekor/utils/tls.go index d8272a69d..b26741261 100644 --- a/internal/controller/rekor/utils/tls.go +++ b/internal/controller/rekor/utils/tls.go @@ -2,24 +2,71 @@ package utils import ( "context" + "crypto/tls" + "crypto/x509" "fmt" + "os" + "path/filepath" + "strings" + "time" rhtasv1alpha1 "github.com/securesign/operator/api/v1alpha1" "github.com/securesign/operator/internal/controller/common/utils/kubernetes" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials" "sigs.k8s.io/controller-runtime/pkg/client" ) -func UseTLS(instance *rhtasv1alpha1.Rekor) bool { +// Mock used in tests +var MockUseTrillianTLS func(ctx context.Context, serviceAddr string, tlsCACertFile string) (bool, error) - if instance == nil { - return false +// checks if trillian-logserver service supports TLS +func UseTrillianTLS(ctx context.Context, serviceAddr string, tlsCACertFile string) (bool, error) { + + if MockUseTrillianTLS != nil { + return MockUseTrillianTLS(ctx, serviceAddr, "") + } + + if kubernetes.IsOpenShift() { + return true, nil + } + + timeout := 5 * time.Second + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + hostname := serviceAddr + if idx := strings.Index(serviceAddr, ":"); idx != -1 { + hostname = serviceAddr[:idx] + } + + var creds credentials.TransportCredentials + if tlsCACertFile != "" { + tlsCaCert, err := os.ReadFile(filepath.Clean(tlsCACertFile)) + if err != nil { + return false, fmt.Errorf("failed to load tls ca cert: %v", err) + } + certPool := x509.NewCertPool() + if !certPool.AppendCertsFromPEM(tlsCaCert) { + return false, fmt.Errorf("failed to append CA certificate to pool") + } + creds = credentials.NewTLS(&tls.Config{ + ServerName: hostname, + RootCAs: certPool, + MinVersion: tls.VersionTLS12, + }) + } + + conn, err := grpc.DialContext(ctx, serviceAddr, grpc.WithTransportCredentials(creds), grpc.WithBlock()) + if err != nil { + fmt.Printf("gRPC service at %s is not TLS secured: %v\n", serviceAddr, err) + return false, nil } - // TLS enabled on Trillian logserver - if instance.Spec.TrustedCA != nil || kubernetes.IsOpenShift() { - return true + if err := conn.Close(); err != nil { + return false, fmt.Errorf("failed to close connection: %v", err) } - return false + return true, nil } func CAPath(ctx context.Context, cli client.Client, instance *rhtasv1alpha1.Rekor) (string, error) {