diff --git a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml index b17090abb..be2302691 100644 --- a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -16182,20 +16182,84 @@ spec: type: object tls: default: - endpoint: + ingress: + ca: + duration: 43800h + cert: + duration: 8760h + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h + cert: + duration: 8760h + ovn: + ca: + duration: 43800h + cert: + duration: 8760h properties: caBundleSecretName: type: string - endpoint: - additionalProperties: - properties: - enabled: - type: boolean - type: object + ingress: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + enabled: + type: boolean + type: object + podLevel: + properties: + enabled: + type: boolean + internal: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + type: object + ovn: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + type: object type: object type: object required: diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index 02b8eb2de..7d5244e11 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -75,8 +75,8 @@ type OpenStackControlPlaneSpec struct { NodeSelector map[string]string `json:"nodeSelector,omitempty"` // +kubebuilder:validation:Optional - // +kubebuilder:default={endpoint: {public: {enabled: true}, internal: {enabled: false}}} - //+operator-sdk:csv:customresourcedefinitions:type=spec + // +operator-sdk:csv:customresourcedefinitions:type=spec + // +kubebuilder:default={ingress: {enabled: true, ca: {duration: "43800h"}, cert: {duration: "8760h"}}, podLevel: {enabled: false, internal:{ca: {duration: "43800h"}, cert: {duration: "8760h"}}, ovn: {ca: {duration: "43800h"}, cert: {duration: "8760h"}}}} // TLS - Parameters related to the TLS TLS TLSSection `json:"tls"` @@ -189,8 +189,11 @@ type OpenStackControlPlaneSpec struct { type TLSSection struct { // +kubebuilder:validation:optional //+operator-sdk:csv:customresourcedefinitions:type=spec - // The key must be the endpoint type (public, internal) - Endpoint map[service.Endpoint]TLSEndpointConfig `json:"endpoint,omitempty"` + Ingress TLSIngressConfig `json:"ingress,omitempty"` + + // +kubebuilder:validation:optional + //+operator-sdk:csv:customresourcedefinitions:type=spec + PodLevel TLSPodLevelConfig `json:"podLevel,omitempty"` // +kubebuilder:validation:optional //+operator-sdk:csv:customresourcedefinitions:type=spec @@ -200,12 +203,67 @@ type TLSSection struct { tls.Ca `json:",inline"` } -// TLSEndpointConfig defines the desired state of TLSEndpoint configuration -type TLSEndpointConfig struct { +// TLSIngressConfig defines the desired state of the TLS configuration for the ingress configuration (route) +type TLSIngressConfig struct { // +kubebuilder:validation:Optional // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} // Enabled - Whether TLS should be enabled for endpoint type Enabled bool `json:"enabled"` + + // +kubebuilder:validation:optional + //+operator-sdk:csv:customresourcedefinitions:type=spec + CertSection `json:",inline"` +} + +// TLSPodLevelConfig defines the desired state of the TLS configuration for TLS termination at the pod level +type TLSPodLevelConfig struct { + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec,xDescriptors={"urn:alm:descriptor:com.tectonic.ui:booleanSwitch"} + // Enabled - Whether TLS should be enabled for endpoint type + Enabled bool `json:"enabled"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // Internal - default CA used for all OpenStackControlPlane and OpenStackDataplane endpoints, + // except OVN related CA and certs + Internal CertSection `json:"internal,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // Ovn - CA used for all OVN services on OpenStackControlPlane and OpenStackDataplane + Ovn CertSection `json:"ovn,omitempty"` +} + +// CertSection defines details for CA config and its certs +type CertSection struct { + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // Cert - defines details for cert config + Cert CertConfig `json:"cert,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // Ca - defines details for CA cert config + Ca CertConfig `json:"ca,omitempty"` +} + +// CertConfig defines details for cert configs +type CertConfig struct { + // The requested 'duration' (i.e. lifetime) of the Certificate. + // The Certificate will be renewed either 2/3 through its duration or + // `renewBefore` period before its expiry, whichever is later. Minimum + // accepted duration is 1 hour. Value must be in units accepted by Go + // time.ParseDuration https://golang.org/pkg/time/#ParseDuration + // +optional + Duration *metav1.Duration `json:"duration,omitempty"` + + // How long before the currently issued certificate's expiry + // cert-manager should renew the certificate. The default is 2/3 of the + // issued certificate's duration. Minimum accepted value is 5 minutes. + // Value must be in units accepted by Go time.ParseDuration + // https://golang.org/pkg/time/#ParseDuration + // +optional + RenewBefore *metav1.Duration `json:"renewBefore,omitempty"` } // DNSMasqSection defines the desired state of DNSMasq service @@ -768,8 +826,12 @@ func SetupDefaults() { // Enabled - returns status of tls configuration for the passed in endpoint type func (t *TLSSection) Enabled(endpt service.Endpoint) bool { if t != nil { - if cfg, ok := t.Endpoint[endpt]; ok && cfg.Enabled { - return true + switch endpt { + case service.EndpointPublic: + return t.Ingress.Enabled + + case service.EndpointInternal: + return t.PodLevel.Enabled } } return false diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index c7f370b23..c087f1adb 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -26,10 +26,10 @@ import ( redisv1beta1 "github.com/openstack-k8s-operators/infra-operator/apis/redis/v1beta1" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/route" - "github.com/openstack-k8s-operators/lib-common/modules/common/service" "github.com/openstack-k8s-operators/lib-common/modules/storage" apiv1beta1 "github.com/openstack-k8s-operators/mariadb-operator/api/v1beta1" ovn_operatorapiv1beta1 "github.com/openstack-k8s-operators/ovn-operator/api/v1beta1" + "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" ) @@ -50,6 +50,48 @@ func (in *BarbicanSection) DeepCopy() *BarbicanSection { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertConfig) DeepCopyInto(out *CertConfig) { + *out = *in + if in.Duration != nil { + in, out := &in.Duration, &out.Duration + *out = new(v1.Duration) + **out = **in + } + if in.RenewBefore != nil { + in, out := &in.RenewBefore, &out.RenewBefore + *out = new(v1.Duration) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertConfig. +func (in *CertConfig) DeepCopy() *CertConfig { + if in == nil { + return nil + } + out := new(CertConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertSection) DeepCopyInto(out *CertSection) { + *out = *in + in.Cert.DeepCopyInto(&out.Cert) + in.Ca.DeepCopyInto(&out.Ca) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertSection. +func (in *CertSection) DeepCopy() *CertSection { + if in == nil { + return nil + } + out := new(CertSection) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *CinderSection) DeepCopyInto(out *CinderSection) { *out = *in @@ -690,30 +732,43 @@ func (in *TLSCAStatus) DeepCopy() *TLSCAStatus { } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSEndpointConfig) DeepCopyInto(out *TLSEndpointConfig) { +func (in *TLSIngressConfig) DeepCopyInto(out *TLSIngressConfig) { *out = *in + in.CertSection.DeepCopyInto(&out.CertSection) } -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSEndpointConfig. -func (in *TLSEndpointConfig) DeepCopy() *TLSEndpointConfig { +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSIngressConfig. +func (in *TLSIngressConfig) DeepCopy() *TLSIngressConfig { if in == nil { return nil } - out := new(TLSEndpointConfig) + out := new(TLSIngressConfig) in.DeepCopyInto(out) return out } // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *TLSSection) DeepCopyInto(out *TLSSection) { +func (in *TLSPodLevelConfig) DeepCopyInto(out *TLSPodLevelConfig) { *out = *in - if in.Endpoint != nil { - in, out := &in.Endpoint, &out.Endpoint - *out = make(map[service.Endpoint]TLSEndpointConfig, len(*in)) - for key, val := range *in { - (*out)[key] = val - } + in.Internal.DeepCopyInto(&out.Internal) + in.Ovn.DeepCopyInto(&out.Ovn) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSPodLevelConfig. +func (in *TLSPodLevelConfig) DeepCopy() *TLSPodLevelConfig { + if in == nil { + return nil } + out := new(TLSPodLevelConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *TLSSection) DeepCopyInto(out *TLSSection) { + *out = *in + in.Ingress.DeepCopyInto(&out.Ingress) + in.PodLevel.DeepCopyInto(&out.PodLevel) out.Ca = in.Ca } diff --git a/apis/go.mod b/apis/go.mod index d5a0d7eb9..344c9bffc 100644 --- a/apis/go.mod +++ b/apis/go.mod @@ -11,13 +11,13 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.3.1-0.20240306142853-6b5d6005953d github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66e43861199 github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996 - github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70 + github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3 github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91 github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240307113114-033a606862c3 github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240306153230-dc65ab49ebc0 github.com/openstack-k8s-operators/lib-common/modules/storage v0.3.1-0.20240306153230-dc65ab49ebc0 github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb - github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4 + github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67 github.com/openstack-k8s-operators/nova-operator/api v0.3.1-0.20240307151724-2fc1351673af github.com/openstack-k8s-operators/octavia-operator/api v0.3.1-0.20240305155754-2dcd200b721a diff --git a/apis/go.sum b/apis/go.sum index 7b19dd465..2db1570e6 100644 --- a/apis/go.sum +++ b/apis/go.sum @@ -85,8 +85,8 @@ github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66 github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66e43861199/go.mod h1:63UcRnUoHAyeXwUJa/6tmphZf4ScoY2+s7ItDV+m3BQ= github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996 h1:+wkmeYGCYfbA+hoAIdShomyptqoqyJ33VYUxUaJoAVA= github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996/go.mod h1:Hzq/OQJ/CC2HeohMw7jh3eqQpIf3FEC2kQSw48bWV+s= -github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70 h1:aLQuVEQKwV2nM4n232/7TnA50t5DD05deEvKyl6Gd5Y= -github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70/go.mod h1:yPqJ+WU8jApuDXNUjpTxMafihuZpX3Yik9ZXqGaxYBQ= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3 h1:GJgS/TApDzvNj6lyEr1du6twi539QT2LOu5pqU0dZdA= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3/go.mod h1:yPqJ+WU8jApuDXNUjpTxMafihuZpX3Yik9ZXqGaxYBQ= github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91 h1:3yvrS33IOQibrXJJlVs/fDxLi5RCZlN5oDrR2c8aShk= github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91/go.mod h1:Yac7wRClzl1/a7uBso4w8wq6Rjm+JLIouEsLre7VSDE= github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240307113114-033a606862c3 h1:jMxdglPqLMuIM+s1aC1tYXz/NihB/BaMyutReg2fXpg= @@ -99,8 +99,8 @@ github.com/openstack-k8s-operators/lib-common/modules/storage v0.3.1-0.202403061 github.com/openstack-k8s-operators/lib-common/modules/storage v0.3.1-0.20240306153230-dc65ab49ebc0/go.mod h1:hKoDyLpp/Hc6fE1rYhlgXw8pYUPyRDKLgBrkAda5IPA= github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb h1:CdhjKduaBLkpXfpg9CfVssrewBYnsfTztIC7WlurAWk= github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb/go.mod h1:WjZonBUlokd/WM3bzlGqW0KncogYyxUDmWmKvxSPlLE= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4 h1:SJT4etdZrncTpCDRyLG9oV9+dWVpngzxrSpcJeWzVuM= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4/go.mod h1:f9IIyWeoskWoeWaDFF3qmAJ2Kqyovfi0Ar/QUfk3qag= +github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee h1:UYxzWJ1HixHQ+jPoZ/PeTqCUxVr1+kha4YJpV/UwL64= +github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee/go.mod h1:f9IIyWeoskWoeWaDFF3qmAJ2Kqyovfi0Ar/QUfk3qag= github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67 h1:7BPdD7bAuzcl08/EiGDOJNBtfVnwuxm7F2acbC+kpuc= github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67/go.mod h1:gOepjTKpq6rF0Lf69edviPOjFpjw4LHan/tWC4LB4Fs= github.com/openstack-k8s-operators/nova-operator/api v0.3.1-0.20240307151724-2fc1351673af h1:EuR34g9uahKG8YKp91FVvj5MNGR0Y+Q9aeu4Y3E8m+U= diff --git a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml index b17090abb..be2302691 100644 --- a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -16182,20 +16182,84 @@ spec: type: object tls: default: - endpoint: + ingress: + ca: + duration: 43800h + cert: + duration: 8760h + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h + cert: + duration: 8760h + ovn: + ca: + duration: 43800h + cert: + duration: 8760h properties: caBundleSecretName: type: string - endpoint: - additionalProperties: - properties: - enabled: - type: boolean - type: object + ingress: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + enabled: + type: boolean + type: object + podLevel: + properties: + enabled: + type: boolean + internal: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + type: object + ovn: + properties: + ca: + properties: + duration: + type: string + renewBefore: + type: string + type: object + cert: + properties: + duration: + type: string + renewBefore: + type: string + type: object + type: object type: object type: object required: diff --git a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml index 5816b514f..e30074916 100644 --- a/config/manifests/bases/openstack-operator.clusterserviceversion.yaml +++ b/config/manifests/bases/openstack-operator.clusterserviceversion.yaml @@ -392,14 +392,46 @@ spec: - description: TLS - Parameters related to the TLS displayName: TLS path: tls - - description: The key must be the endpoint type (public, internal) - displayName: Endpoint - path: tls.endpoint + - displayName: Ingress + path: tls.ingress + - description: Ca - defines details for CA cert config + displayName: Ca + path: tls.ingress.ca + - description: Cert - defines details for cert config + displayName: Cert + path: tls.ingress.cert - description: Enabled - Whether TLS should be enabled for endpoint type displayName: Enabled - path: tls.endpoint.enabled + path: tls.ingress.enabled x-descriptors: - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - displayName: Pod Level + path: tls.podLevel + - description: Enabled - Whether TLS should be enabled for endpoint type + displayName: Enabled + path: tls.podLevel.enabled + x-descriptors: + - urn:alm:descriptor:com.tectonic.ui:booleanSwitch + - description: Internal - default CA used for all OpenStackControlPlane and + OpenStackDataplane endpoints, except OVN related CA and certs + displayName: Internal + path: tls.podLevel.internal + - description: Ca - defines details for CA cert config + displayName: Ca + path: tls.podLevel.internal.ca + - description: Cert - defines details for cert config + displayName: Cert + path: tls.podLevel.internal.cert + - description: Ovn - CA used for all OVN services on OpenStackControlPlane and + OpenStackDataplane + displayName: Ovn + path: tls.podLevel.ovn + - description: Ca - defines details for CA cert config + displayName: Ca + path: tls.podLevel.ovn.ca + - description: Cert - defines details for cert config + displayName: Cert + path: tls.podLevel.ovn.cert statusDescriptors: - description: Conditions displayName: Conditions diff --git a/config/samples/core_v1beta1_openstackcontrolplane.yaml b/config/samples/core_v1beta1_openstackcontrolplane.yaml index 017e1020e..f409e81c0 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane.yaml @@ -5,12 +5,6 @@ metadata: spec: secret: osp-secret storageClass: local-storage - #tls: - # endpoint: - # internal: - # enabled: false - # public: - # enabled: true keystone: template: databaseInstance: openstack diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml index 8073c6052..1d2bff529 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml @@ -5,12 +5,6 @@ metadata: spec: secret: osp-secret storageClass: local-storage - #tls: - # endpoint: - # internal: - # enabled: false - # public: - # enabled: true dns: template: override: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml index bb8710128..7503caa91 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml @@ -5,12 +5,6 @@ metadata: spec: secret: osp-secret storageClass: local-storage - #tls: - # endpoint: - # internal: - # enabled: false - # public: - # enabled: true dns: template: override: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml index 713309acd..3cbaa8555 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml @@ -5,12 +5,6 @@ metadata: spec: secret: osp-secret storageClass: local-storage - #tls: - # endpoint: - # internal: - # enabled: false - # public: - # enabled: true dns: template: override: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tlse.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tlse.yaml index 230bc539a..60b0b201f 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tlse.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_tlse.yaml @@ -6,11 +6,8 @@ spec: secret: osp-secret storageClass: local-storage tls: - endpoint: - internal: - enabled: true - public: - enabled: true + podLevel: + enabled: true dns: template: override: diff --git a/go.mod b/go.mod index dd08aa678..e34540b5c 100644 --- a/go.mod +++ b/go.mod @@ -19,14 +19,14 @@ require ( github.com/openstack-k8s-operators/glance-operator/api v0.3.1-0.20240306142853-6b5d6005953d github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66e43861199 github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996 - github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70 + github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3 github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91 github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240307113114-033a606862c3 github.com/openstack-k8s-operators/lib-common/modules/certmanager v0.0.0-20240306153230-dc65ab49ebc0 github.com/openstack-k8s-operators/lib-common/modules/common v0.3.1-0.20240306153230-dc65ab49ebc0 github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240306153230-dc65ab49ebc0 github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb - github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4 + github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67 github.com/openstack-k8s-operators/nova-operator/api v0.3.1-0.20240307151724-2fc1351673af github.com/openstack-k8s-operators/octavia-operator/api v0.3.1-0.20240305155754-2dcd200b721a diff --git a/go.sum b/go.sum index 0b8b691d7..46689880d 100644 --- a/go.sum +++ b/go.sum @@ -99,8 +99,8 @@ github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66 github.com/openstack-k8s-operators/heat-operator/api v0.3.1-0.20240307055016-f66e43861199/go.mod h1:63UcRnUoHAyeXwUJa/6tmphZf4ScoY2+s7ItDV+m3BQ= github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996 h1:+wkmeYGCYfbA+hoAIdShomyptqoqyJ33VYUxUaJoAVA= github.com/openstack-k8s-operators/horizon-operator/api v0.3.1-0.20240304130922-946bc7dd0996/go.mod h1:Hzq/OQJ/CC2HeohMw7jh3eqQpIf3FEC2kQSw48bWV+s= -github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70 h1:aLQuVEQKwV2nM4n232/7TnA50t5DD05deEvKyl6Gd5Y= -github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240304123904-038a5ec77a70/go.mod h1:yPqJ+WU8jApuDXNUjpTxMafihuZpX3Yik9ZXqGaxYBQ= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3 h1:GJgS/TApDzvNj6lyEr1du6twi539QT2LOu5pqU0dZdA= +github.com/openstack-k8s-operators/infra-operator/apis v0.3.1-0.20240308113717-eaf5876d69c3/go.mod h1:yPqJ+WU8jApuDXNUjpTxMafihuZpX3Yik9ZXqGaxYBQ= github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91 h1:3yvrS33IOQibrXJJlVs/fDxLi5RCZlN5oDrR2c8aShk= github.com/openstack-k8s-operators/ironic-operator/api v0.3.1-0.20240229174131-28e3aee56d91/go.mod h1:Yac7wRClzl1/a7uBso4w8wq6Rjm+JLIouEsLre7VSDE= github.com/openstack-k8s-operators/keystone-operator/api v0.3.1-0.20240307113114-033a606862c3 h1:jMxdglPqLMuIM+s1aC1tYXz/NihB/BaMyutReg2fXpg= @@ -117,8 +117,8 @@ github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.202403061532 github.com/openstack-k8s-operators/lib-common/modules/test v0.3.1-0.20240306153230-dc65ab49ebc0/go.mod h1:/ZkLOznBDxjChwIFFK3xg3EZ13WmZPP4ehu5wWy1T8E= github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb h1:CdhjKduaBLkpXfpg9CfVssrewBYnsfTztIC7WlurAWk= github.com/openstack-k8s-operators/manila-operator/api v0.3.1-0.20240305194401-0fda28a84acb/go.mod h1:WjZonBUlokd/WM3bzlGqW0KncogYyxUDmWmKvxSPlLE= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4 h1:SJT4etdZrncTpCDRyLG9oV9+dWVpngzxrSpcJeWzVuM= -github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308154211-31e51e9ec6b4/go.mod h1:f9IIyWeoskWoeWaDFF3qmAJ2Kqyovfi0Ar/QUfk3qag= +github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee h1:UYxzWJ1HixHQ+jPoZ/PeTqCUxVr1+kha4YJpV/UwL64= +github.com/openstack-k8s-operators/mariadb-operator/api v0.3.1-0.20240308170012-6b04e3e9b9ee/go.mod h1:f9IIyWeoskWoeWaDFF3qmAJ2Kqyovfi0Ar/QUfk3qag= github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67 h1:7BPdD7bAuzcl08/EiGDOJNBtfVnwuxm7F2acbC+kpuc= github.com/openstack-k8s-operators/neutron-operator/api v0.3.1-0.20240305155525-acb164bd7d67/go.mod h1:gOepjTKpq6rF0Lf69edviPOjFpjw4LHan/tWC4LB4Fs= github.com/openstack-k8s-operators/nova-operator/api v0.3.1-0.20240307151724-2fc1351673af h1:EuR34g9uahKG8YKp91FVvj5MNGR0Y+Q9aeu4Y3E8m+U= diff --git a/pkg/openstack/barbican.go b/pkg/openstack/barbican.go index fdf523c84..f22b67b5b 100644 --- a/pkg/openstack/barbican.go +++ b/pkg/openstack/barbican.go @@ -81,6 +81,7 @@ func ReconcileBarbican(ctx context.Context, instance *corev1beta1.OpenStackContr instance.Spec.Barbican.APIOverride, corev1beta1.OpenStackControlPlaneExposeBarbicanReadyCondition, false, // TODO: (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Barbican.Template.BarbicanAPI.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/ca.go b/pkg/openstack/ca.go index d22ee19b7..3c1872057 100644 --- a/pkg/openstack/ca.go +++ b/pkg/openstack/ca.go @@ -94,49 +94,60 @@ func ReconcileCAs(ctx context.Context, instance *corev1.OpenStackControlPlane, h } instance.Status.TLS.CAList = []corev1.TLSCAStatus{} + // create CA for ingress and public podLevel termination + ctrlResult, err = ensureRootCA( + ctx, + instance, + helper, + issuerReq, + tls.DefaultCAPrefix+string(service.EndpointPublic), + map[string]string{}, + bundle, + caOnlyBundle, + instance.Spec.TLS.Ingress.Ca, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } - // create RootCA cert and Issuer that uses the generated CA certificate to issue certs - for _, endpoint := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { - labels := map[string]string{} - if endpoint == service.EndpointInternal { - labels[certmanager.RootCAIssuerInternalLabel] = "" - } - caName := tls.DefaultCAPrefix + string(endpoint) - // always create a root CA and issuer for the endpoint as we can - // not expect that all services are yet configured to be provided with - // a custom secret holding the cert/private key - caCert, ctrlResult, err := createRootCACertAndIssuer( - ctx, - instance, - helper, - issuerReq, - caName, - labels, - ) - if err != nil { - return ctrlResult, err - } else if (ctrlResult != ctrl.Result{}) { - return ctrlResult, nil - } - - err = bundle.getCertsFromPEM(caCert) - if err != nil { - return ctrl.Result{}, err - } - err = caOnlyBundle.getCertsFromPEM(caCert) - if err != nil { - return ctrl.Result{}, err - } - - status := corev1.TLSCAStatus{ - Name: caName, - } - if len(caOnlyBundle.certs) > 0 { - status.Expires = caOnlyBundle.certs[0].expire.Format(time.RFC3339) - } + // create CA for internal podLevel termination + ctrlResult, err = ensureRootCA( + ctx, + instance, + helper, + issuerReq, + tls.DefaultCAPrefix+string(service.EndpointInternal), + map[string]string{certmanager.RootCAIssuerInternalLabel: ""}, + bundle, + caOnlyBundle, + instance.Spec.TLS.PodLevel.Internal.Ca, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } - instance.Status.TLS.CAList = append(instance.Status.TLS.CAList, status) + // create CA for ovn + ctrlResult, err = ensureRootCA( + ctx, + instance, + helper, + issuerReq, + tls.DefaultCAPrefix+"ovn", + map[string]string{certmanager.RootCAIssuerOvnDBLabel: ""}, + bundle, + caOnlyBundle, + instance.Spec.TLS.PodLevel.Ovn.Ca, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil } + instance.Status.Conditions.MarkTrue(corev1.OpenStackControlPlaneCAReadyCondition, corev1.OpenStackControlPlaneCAReadyMessage) // create/update combined CA secret @@ -228,6 +239,56 @@ func ReconcileCAs(ctx context.Context, instance *corev1.OpenStackControlPlane, h return ctrl.Result{}, nil } +func ensureRootCA( + ctx context.Context, + instance *corev1.OpenStackControlPlane, + helper *helper.Helper, + issuerReq *certmgrv1.Issuer, + caName string, + labels map[string]string, + bundle *caBundle, + caOnlyBundle *caBundle, + caCfg corev1.CertConfig, +) (ctrl.Result, error) { + // always create a root CA and issuer for the endpoint as we can + // not expect that all services are yet configured to be provided with + // a custom secret holding the cert/private key + caCert, ctrlResult, err := createRootCACertAndIssuer( + ctx, + instance, + helper, + issuerReq, + caName, + labels, + caCfg, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + + err = bundle.getCertsFromPEM(caCert) + if err != nil { + return ctrl.Result{}, err + } + err = caOnlyBundle.getCertsFromPEM(caCert) + if err != nil { + return ctrl.Result{}, err + } + + status := corev1.TLSCAStatus{ + Name: caName, + } + if len(caOnlyBundle.certs) > 0 { + status.Expires = caOnlyBundle.certs[0].expire.Format(time.RFC3339) + } + + instance.Status.TLS.CAList = append(instance.Status.TLS.CAList, status) + + return ctrl.Result{}, nil +} + func createRootCACertAndIssuer( ctx context.Context, instance *corev1.OpenStackControlPlane, @@ -235,6 +296,7 @@ func createRootCACertAndIssuer( selfsignedIssuerReq *certmgrv1.Issuer, caName string, labels map[string]string, + caCfg corev1.CertConfig, ) ([]byte, ctrl.Result, error) { // create RootCA Certificate used to sign certificates caCertReq := certmanager.Cert( @@ -254,6 +316,8 @@ func createRootCACertAndIssuer( Kind: selfsignedIssuerReq.Kind, Group: selfsignedIssuerReq.GroupVersionKind().Group, }, + Duration: caCfg.Duration, + RenewBefore: caCfg.RenewBefore, }) cert := certmanager.NewCertificate(caCertReq, 5) diff --git a/pkg/openstack/cinder.go b/pkg/openstack/cinder.go index 8622160af..037d816bf 100644 --- a/pkg/openstack/cinder.go +++ b/pkg/openstack/cinder.go @@ -83,6 +83,7 @@ func ReconcileCinder(ctx context.Context, instance *corev1beta1.OpenStackControl instance.Spec.Cinder.APIOverride, corev1beta1.OpenStackControlPlaneExposeCinderReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Cinder.Template.CinderAPI.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/common.go b/pkg/openstack/common.go index 459f6c66f..8fea2d3c0 100644 --- a/pkg/openstack/common.go +++ b/pkg/openstack/common.go @@ -188,9 +188,10 @@ func EnsureEndpointConfig( owner metav1.Object, svcs *k8s_corev1.ServiceList, svcOverrides map[service.Endpoint]service.RoutedOverrideSpec, - publicOverride corev1.Override, + ingressOverride corev1.Override, condType condition.Type, serviceTLSDisabled bool, + tlsConfig tls.API, ) (Endpoints, ctrl.Result, error) { endpoints := Endpoints{ EndpointDetails: map[service.Endpoint]EndpointDetail{}, @@ -209,9 +210,9 @@ func EnsureEndpointConfig( ed.Service.OverrideSpec = svcOverrides[ed.Type] // TLS on the pod level is enabled if - // * TLS is enabled for internal endpoint + // * TLS is enabled for pod level // * the particular service has not TLS.Disabled set to true - if tlsEndpointConfig := instance.Spec.TLS.Endpoint[service.EndpointInternal]; tlsEndpointConfig.Enabled && !serviceTLSDisabled { + if instance.Spec.TLS.PodLevel.Enabled && !serviceTLSDisabled { ed.Service.TLS.Enabled = true } else { ed.Service.TLS.Enabled = false @@ -223,47 +224,65 @@ func EnsureEndpointConfig( ed.Route.Create = svc.ObjectMeta.Annotations[service.AnnotationIngressCreateKey] == "true" && svc.Spec.Type == k8s_corev1.ServiceTypeClusterIP - if publicOverride.Route != nil { - ed.Route.OverrideSpec = *publicOverride.Route + if ingressOverride.Route != nil { + ed.Route.OverrideSpec = *ingressOverride.Route } - // if public endpoint TLS is enabled - if tlsEndpointConfig := instance.Spec.TLS.Endpoint[ed.Type]; tlsEndpointConfig.Enabled { + // if TLS termination at the ingress (route) is enabled + if instance.Spec.TLS.Ingress.Enabled { // TLS for route enabled if public endpoint TLS is true ed.Route.TLS.Enabled = true // if a custom cert secret was provided we'll use this for // the route, otherwise the issuer is used to request one // for the endpoint. - if publicOverride.TLS != nil && publicOverride.TLS.SecretName != "" { - ed.Route.TLS.SecretName = ptr.To(publicOverride.TLS.SecretName) + if ingressOverride.TLS != nil && ingressOverride.TLS.SecretName != "" { + ed.Route.TLS.SecretName = ptr.To(ingressOverride.TLS.SecretName) + validateSecret := &tls.GenericService{SecretName: ed.Route.TLS.SecretName} + _, ctrlResult, err := validateSecret.ValidateCertSecret(ctx, helper, instance.GetNamespace()) + if err != nil { + return endpoints, ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return endpoints, ctrlResult, nil + } } else { // use public issuer to create cert for the route ed.Route.TLS.IssuerName = ptr.To(tls.DefaultCAPrefix + ed.Type.String()) } + } - // For re-encryption the route required the internal CA bundle to validate - // internal certificate from route -> service -> pod. Add the internal CA bundle when - // * TLS is enabled for internal endpoint - // * the particular service has not TLS.Disabled set to true - if ed.Service.TLS.Enabled { - ed.Service.TLS.CaBundleSecretName = tls.CABundleSecret - // create certificate for public pod virthost - // TODO: (mschuppert) - if ed.Route.Create == false and custom cert secret provided - // for the public endpoint, use this and not the issuer. This is the case when - // env got deployed with LoadBalancer service instead of a route for the public - // endpoint. - // request certificate + if ed.Service.TLS.Enabled { + ed.Service.TLS.CaBundleSecretName = tls.CABundleSecret + + // if a custom cert secret was provided and ed.Route.Create == false + // we'll use this for the service, otherwise issue a cert. This is for + // use case where you deploy without ingress/routes and also use + // a LoadBalancer (MetalLB) for the public endpoints. + if !ed.Route.Create && (tlsConfig.API.Public.SecretName != nil && *tlsConfig.API.Public.SecretName != "") { + ed.Service.TLS.SecretName = tlsConfig.API.Public.SecretName + _, ctrlResult, err := ed.Service.TLS.GenericService.ValidateCertSecret(ctx, helper, instance.GetNamespace()) + if err != nil { + return endpoints, ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return endpoints, ctrlResult, nil + } + } else { + // issue a certificate for public pod virthost certRequest := certmanager.CertificateRequest{ IssuerName: tls.DefaultCAPrefix + ed.Type.String(), CertName: fmt.Sprintf("%s-svc", ed.Name), - Duration: nil, Hostnames: []string{fmt.Sprintf("%s.%s.svc", ed.Name, instance.Namespace)}, Ips: nil, Annotations: ed.Annotations, Labels: ed.Labels, Usages: nil, } + if instance.Spec.TLS.Ingress.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.Ingress.Cert.Duration.Duration + } + if instance.Spec.TLS.Ingress.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.Ingress.Cert.RenewBefore.Duration + } certSecret, ctrlResult, err := certmanager.EnsureCert( ctx, helper, @@ -293,13 +312,18 @@ func EnsureEndpointConfig( certRequest := certmanager.CertificateRequest{ IssuerName: tls.DefaultCAPrefix + ed.Type.String(), CertName: fmt.Sprintf("%s-svc", ed.Name), - Duration: nil, Hostnames: []string{fmt.Sprintf("%s.%s.svc", ed.Name, instance.Namespace)}, Ips: nil, Annotations: ed.Annotations, Labels: ed.Labels, Usages: nil, } + if instance.Spec.TLS.PodLevel.Internal.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.PodLevel.Internal.Cert.Duration.Duration + } + if instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore.Duration + } certSecret, ctrlResult, err := certmanager.EnsureCert( ctx, helper, @@ -400,7 +424,7 @@ func (ed *EndpointDetail) ensureRoute( ed.Labels = map[string]string{ooAppSelector: labelVal} } - ctrlResult, err := ed.CreateRoute(ctx, helper, owner) + ctrlResult, err := ed.CreateRoute(ctx, instance, helper, owner) if err != nil { instance.Status.Conditions.Set(condition.FalseCondition( condType, @@ -426,6 +450,7 @@ func (ed *EndpointDetail) ensureRoute( // CreateRoute - func (ed *EndpointDetail) CreateRoute( ctx context.Context, + instance *corev1.OpenStackControlPlane, helper *helper.Helper, owner metav1.Object, ) (ctrl.Result, error) { @@ -504,13 +529,18 @@ func (ed *EndpointDetail) CreateRoute( certRequest := certmanager.CertificateRequest{ IssuerName: *ed.Route.TLS.IssuerName, CertName: fmt.Sprintf("%s-route", ed.Name), - Duration: nil, Hostnames: []string{*ed.Hostname}, Ips: nil, Annotations: ed.Annotations, Labels: ed.Labels, Usages: nil, } + if instance.Spec.TLS.Ingress.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.Ingress.Cert.Duration.Duration + } + if instance.Spec.TLS.Ingress.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.Ingress.Cert.RenewBefore.Duration + } //create the cert using our issuer for the endpoint certSecret, ctrlResult, err = certmanager.EnsureCert( ctx, @@ -533,11 +563,11 @@ func (ed *EndpointDetail) CreateRoute( } // for internal TLS (TLSE) use routev1.TLSTerminationReencrypt - if ed.Service.TLS.Enabled { + if ed.Service.TLS.Enabled && ed.Service.TLS.SecretName != nil { // get the TLSInternalCABundleFile to add it to the route // to be able to validate public/internal service endpoints tlsConfig.DestinationCACertificate, ctrlResult, err = secret.GetDataFromSecret( - ctx, helper, ed.Service.TLS.CaBundleSecretName, 5, tls.InternalCABundleKey) + ctx, helper, *ed.Service.TLS.SecretName, 5, tls.CAKey) if err != nil { return ctrlResult, err } else if (ctrlResult != ctrl.Result{}) { diff --git a/pkg/openstack/designate.go b/pkg/openstack/designate.go index cf3e6c2d0..37b29fa12 100644 --- a/pkg/openstack/designate.go +++ b/pkg/openstack/designate.go @@ -7,6 +7,7 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/helper" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -76,6 +77,7 @@ func ReconcileDesignate(ctx context.Context, instance *corev1beta1.OpenStackCont instance.Spec.Designate.APIOverride, corev1beta1.OpenStackControlPlaneExposeDesignateReadyCondition, true, // TODO: (mschuppert) disable TLS for now until implemented + tls.API{}, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/galera.go b/pkg/openstack/galera.go index 8f1ddab85..9dc056d3d 100644 --- a/pkg/openstack/galera.go +++ b/pkg/openstack/galera.go @@ -58,6 +58,12 @@ func ReconcileGaleras( "client auth", }, } + if instance.Spec.TLS.PodLevel.Internal.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.PodLevel.Internal.Cert.Duration.Duration + } + if instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore.Duration + } certSecret, ctrlResult, err := certmanager.EnsureCert( ctx, helper, diff --git a/pkg/openstack/glance.go b/pkg/openstack/glance.go index 3668175ec..d61fc2cc5 100644 --- a/pkg/openstack/glance.go +++ b/pkg/openstack/glance.go @@ -115,6 +115,7 @@ func ReconcileGlance(ctx context.Context, instance *corev1beta1.OpenStackControl instance.Spec.Glance.APIOverride[name], corev1beta1.OpenStackControlPlaneExposeGlanceReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + glanceAPI.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/heat.go b/pkg/openstack/heat.go index f578602d0..833999363 100644 --- a/pkg/openstack/heat.go +++ b/pkg/openstack/heat.go @@ -96,6 +96,7 @@ func ReconcileHeat(ctx context.Context, instance *corev1beta1.OpenStackControlPl instance.Spec.Heat.APIOverride, corev1beta1.OpenStackControlPlaneExposeHeatReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Heat.Template.HeatAPI.TLS, ) if err != nil { return ctrlResult, err @@ -131,6 +132,7 @@ func ReconcileHeat(ctx context.Context, instance *corev1beta1.OpenStackControlPl instance.Spec.Heat.CnfAPIOverride, corev1beta1.OpenStackControlPlaneExposeHeatReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Heat.Template.HeatCfnAPI.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/horizon.go b/pkg/openstack/horizon.go index bd9946f61..0e1e94e64 100644 --- a/pkg/openstack/horizon.go +++ b/pkg/openstack/horizon.go @@ -7,6 +7,7 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/helper" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -84,6 +85,13 @@ func ReconcileHorizon(ctx context.Context, instance *corev1beta1.OpenStackContro instance.Spec.Horizon.APIOverride, corev1beta1.OpenStackControlPlaneExposeHorizonReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + tls.API{ + API: tls.APIService{ + Public: tls.GenericService{ + SecretName: instance.Spec.Horizon.Template.TLS.SecretName, + }, + }, + }, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/ironic.go b/pkg/openstack/ironic.go index aa1126a26..5c110e7cd 100644 --- a/pkg/openstack/ironic.go +++ b/pkg/openstack/ironic.go @@ -94,6 +94,7 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl instance.Spec.Ironic.APIOverride, corev1beta1.OpenStackControlPlaneExposeIronicReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Ironic.Template.IronicAPI.TLS, ) if err != nil { return ctrlResult, err @@ -130,6 +131,7 @@ func ReconcileIronic(ctx context.Context, instance *corev1beta1.OpenStackControl instance.Spec.Ironic.InspectorOverride, corev1beta1.OpenStackControlPlaneExposeIronicReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Ironic.Template.IronicInspector.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/keystone.go b/pkg/openstack/keystone.go index efb6892b7..bab5c1613 100644 --- a/pkg/openstack/keystone.go +++ b/pkg/openstack/keystone.go @@ -84,6 +84,7 @@ func ReconcileKeystoneAPI(ctx context.Context, instance *corev1beta1.OpenStackCo instance.Spec.Keystone.APIOverride, corev1beta1.OpenStackControlPlaneExposeKeystoneAPIReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Keystone.Template.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/manila.go b/pkg/openstack/manila.go index ce69e5ef8..b0ed614d1 100644 --- a/pkg/openstack/manila.go +++ b/pkg/openstack/manila.go @@ -84,6 +84,7 @@ func ReconcileManila(ctx context.Context, instance *corev1beta1.OpenStackControl instance.Spec.Manila.APIOverride, corev1beta1.OpenStackControlPlaneExposeManilaReadyCondition, false, // TODO: (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Manila.Template.ManilaAPI.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/neutron.go b/pkg/openstack/neutron.go index 0a6077011..ea22fcdc7 100644 --- a/pkg/openstack/neutron.go +++ b/pkg/openstack/neutron.go @@ -83,6 +83,7 @@ func ReconcileNeutron(ctx context.Context, instance *corev1beta1.OpenStackContro instance.Spec.Neutron.APIOverride, corev1beta1.OpenStackControlPlaneExposeNeutronReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Neutron.Template.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/nova.go b/pkg/openstack/nova.go index ba0f4258f..3ad37a08f 100644 --- a/pkg/openstack/nova.go +++ b/pkg/openstack/nova.go @@ -149,6 +149,7 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl instance.Spec.Nova.APIOverride, corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Nova.Template.APIServiceTemplate.TLS, ) if err != nil { return ctrlResult, err @@ -234,6 +235,13 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl instance.Spec.Nova.CellOverride[cellName].NoVNCProxy, corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + tls.API{ + API: tls.APIService{ + Public: tls.GenericService{ + SecretName: cellTemplate.NoVNCProxyServiceTemplate.TLS.SecretName, + }, + }, + }, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/octavia.go b/pkg/openstack/octavia.go index 815041c4b..160e29573 100644 --- a/pkg/openstack/octavia.go +++ b/pkg/openstack/octavia.go @@ -23,6 +23,7 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/helper" "github.com/openstack-k8s-operators/lib-common/modules/common/service" + "github.com/openstack-k8s-operators/lib-common/modules/common/tls" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" @@ -92,6 +93,7 @@ func ReconcileOctavia(ctx context.Context, instance *corev1beta1.OpenStackContro instance.Spec.Octavia.APIOverride, corev1beta1.OpenStackControlPlaneExposeOctaviaReadyCondition, true, // TODO: (mschuppert) disable TLS for now until implemented + tls.API{}, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/openstackclient.go b/pkg/openstack/openstackclient.go index 4d8dcb47e..06f115b9d 100644 --- a/pkg/openstack/openstackclient.go +++ b/pkg/openstack/openstackclient.go @@ -47,11 +47,8 @@ func ReconcileOpenStackClient(ctx context.Context, instance *corev1.OpenStackCon op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), openstackclient, func() error { instance.Spec.OpenStackClient.Template.DeepCopyInto(&openstackclient.Spec) - for _, config := range instance.Spec.TLS.Endpoint { - if config.Enabled { - openstackclient.Spec.Ca.CaBundleSecretName = tls.CABundleSecret - break - } + if instance.Spec.TLS.Ingress.Enabled || instance.Spec.TLS.PodLevel.Enabled { + openstackclient.Spec.Ca.CaBundleSecretName = tls.CABundleSecret } err := controllerutil.SetControllerReference(helper.GetBeforeObject(), openstackclient, helper.GetScheme()) diff --git a/pkg/openstack/placement.go b/pkg/openstack/placement.go index 01b9376df..03d9c420b 100644 --- a/pkg/openstack/placement.go +++ b/pkg/openstack/placement.go @@ -82,6 +82,7 @@ func ReconcilePlacementAPI(ctx context.Context, instance *corev1beta1.OpenStackC instance.Spec.Placement.APIOverride, corev1beta1.OpenStackControlPlaneExposePlacementAPIReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Placement.Template.TLS, ) if err != nil { return ctrlResult, err diff --git a/pkg/openstack/rabbitmq.go b/pkg/openstack/rabbitmq.go index 726d4f946..697d00e94 100644 --- a/pkg/openstack/rabbitmq.go +++ b/pkg/openstack/rabbitmq.go @@ -181,6 +181,12 @@ func reconcileRabbitMQ( CertName: fmt.Sprintf("%s-svc", rabbitmq.Name), Hostnames: []string{hostname}, } + if instance.Spec.TLS.PodLevel.Internal.Cert.Duration != nil { + certRequest.Duration = &instance.Spec.TLS.PodLevel.Internal.Cert.Duration.Duration + } + if instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore != nil { + certRequest.RenewBefore = &instance.Spec.TLS.PodLevel.Internal.Cert.RenewBefore.Duration + } certSecret, ctrlResult, err := certmanager.EnsureCert( ctx, helper, diff --git a/pkg/openstack/swift.go b/pkg/openstack/swift.go index 6c15e9086..de2596ec4 100644 --- a/pkg/openstack/swift.go +++ b/pkg/openstack/swift.go @@ -84,6 +84,7 @@ func ReconcileSwift(ctx context.Context, instance *corev1beta1.OpenStackControlP instance.Spec.Swift.ProxyOverride, corev1beta1.OpenStackControlPlaneExposeSwiftReadyCondition, false, // TODO (mschuppert) could be removed when all integrated service support TLS + instance.Spec.Swift.Template.SwiftProxy.TLS, ) if err != nil { return ctrlResult, err diff --git a/tests/functional/base_test.go b/tests/functional/base_test.go index e14aa5a60..d67654ee2 100644 --- a/tests/functional/base_test.go +++ b/tests/functional/base_test.go @@ -46,6 +46,7 @@ type Names struct { RoleBindingName types.NamespacedName RootCAPublicName types.NamespacedName RootCAInternalName types.NamespacedName + RootCAOvnName types.NamespacedName SelfSignedIssuerName types.NamespacedName CABundleName types.NamespacedName OpenStackClientName types.NamespacedName @@ -65,6 +66,9 @@ func CreateNames(openstackControlplaneName types.NamespacedName) Names { RootCAInternalName: types.NamespacedName{ Namespace: openstackControlplaneName.Namespace, Name: "rootca-internal"}, + RootCAOvnName: types.NamespacedName{ + Namespace: openstackControlplaneName.Namespace, + Name: "rootca-ovn"}, SelfSignedIssuerName: types.NamespacedName{ Namespace: openstackControlplaneName.Namespace, Name: "selfsigned-issuer"}, @@ -211,9 +215,13 @@ func GetDefaultOpenStackControlPlaneSpec() map[string]interface{} { } tlsTemplate := map[string]interface{}{ - "endpoint": map[string]interface{}{ - "public": map[string]interface{}{ - "enabled": true, + "ingress": map[string]interface{}{ + "enabled": true, + "ca": map[string]interface{}{ + "duration": "100h", + }, + "cert": map[string]interface{}{ + "duration": "10h", }, }, } @@ -329,3 +337,24 @@ func CreateInternalCACertSecret(name types.NamespacedName) *k8s_corev1.Secret { return s } + +func CreateOvnCACertSecret(name types.NamespacedName) *k8s_corev1.Secret { + certBase64 := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJmekNDQVNhZ0F3SUJBZ0lRUWxlcTNZcDBtU2kwVDNiTm03Q29UVEFLQmdncWhrak9QUVFEQWpBZ01SNHcKSEFZRFZRUURFeFZ5YjI5MFkyRXRhM1YwZEd3dGFXNTBaWEp1WVd3d0hoY05NalF3TVRFMU1URTBOelUwV2hjTgpNelF3TVRFeU1URTBOelUwV2pBZ01SNHdIQVlEVlFRREV4VnliMjkwWTJFdGEzVjBkR3d0YVc1MFpYSnVZV3d3CldUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFTRk9rNHJPUldVUGhoTjUrK09EN1I2MW5Gb1lBY0QKenpvUS91SW93NktjeGhwRWNQTDFxb3ZZUGxUYUJabEh3c2FpNE50VHA4aDA1RHVRSGZKOE9JNXFvMEl3UURBTwpCZ05WSFE4QkFmOEVCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVXE3TGtFSk1TCm1MOVpKWjBSOUluKzZkclhycEl3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnVlN1K00ydnZ3QlF3eTJHMVlhdkkKQld2RGtSNlRla0I5U0VqdzJIblRSMWtDSUZSNFNkWGFPQkFGWjVHa2RLWCtSY2IzaDFIZm52eFJEVW96bTl2agphenp3Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K==" + keyBase64 := "LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUV3dlQ2dFZMUWRrVnlXUDV1VnJ3RWRyZ0VLK3drdmttRjFKa0xNYzJCUVFvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFaFRwT0t6a1ZsRDRZVGVmdmpnKzBldFp4YUdBSEE4ODZFUDdpS01PaW5NWWFSSER5OWFxTAoyRDVVMmdXWlI4TEdvdURiVTZmSWRPUTdrQjN5ZkRpT2FnPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo==" + + cert, _ := base64.StdEncoding.DecodeString(certBase64) + key, _ := base64.StdEncoding.DecodeString(keyBase64) + + s := &k8s_corev1.Secret{} + Eventually(func(g Gomega) { + s = th.CreateSecret( + name, + map[string][]byte{ + "ca.crt": []byte(cert), + "tls.crt": []byte(cert), + "tls.key": []byte(key), + }) + }, timeout, interval).Should(Succeed()) + + return s +} diff --git a/tests/functional/openstackoperator_controller_test.go b/tests/functional/openstackoperator_controller_test.go index 6df6ea225..ad5d78cf8 100644 --- a/tests/functional/openstackoperator_controller_test.go +++ b/tests/functional/openstackoperator_controller_test.go @@ -29,7 +29,6 @@ import ( "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - "github.com/openstack-k8s-operators/lib-common/modules/common/service" . "github.com/openstack-k8s-operators/lib-common/modules/common/test/helpers" "github.com/openstack-k8s-operators/lib-common/modules/common/tls" clientv1 "github.com/openstack-k8s-operators/openstack-operator/apis/client/v1beta1" @@ -49,6 +48,7 @@ var _ = Describe("OpenStackOperator controller", func() { // it is not used, just to make sure reconcile proceeds and creates the ca-bundle. DeferCleanup(k8sClient.Delete, ctx, CreatePublicCACertSecret(names.RootCAPublicName)) DeferCleanup(k8sClient.Delete, ctx, CreateInternalCACertSecret(names.RootCAInternalName)) + DeferCleanup(k8sClient.Delete, ctx, CreateOvnCACertSecret(names.RootCAOvnName)) // create cert secrets for galera instances DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.DBCertName)) DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.DBCell1CertName)) @@ -68,8 +68,8 @@ var _ = Describe("OpenStackOperator controller", func() { Expect(OSCtlplane.Spec.Rabbitmq.Enabled).Should(BeTrue()) Expect(OSCtlplane.Spec.Memcached.Enabled).Should(BeTrue()) Expect(OSCtlplane.Spec.Keystone.Enabled).Should(BeTrue()) - Expect(OSCtlplane.Spec.TLS.Endpoint[service.EndpointPublic].Enabled).Should(BeTrue()) - Expect(OSCtlplane.Spec.TLS.Endpoint[service.EndpointInternal].Enabled).Should(BeFalse()) + Expect(OSCtlplane.Spec.TLS.Ingress.Enabled).Should(BeTrue()) + Expect(OSCtlplane.Spec.TLS.PodLevel.Enabled).Should(BeFalse()) // galera exists Eventually(func(g Gomega) { @@ -100,15 +100,15 @@ var _ = Describe("OpenStackOperator controller", func() { It("should create selfsigned issuer and public+internal CA and issuer", func() { OSCtlplane := GetOpenStackControlPlane(names.OpenStackControlplaneName) - Expect(OSCtlplane.Spec.TLS.Endpoint[service.EndpointPublic].Enabled).Should(BeTrue()) - Expect(OSCtlplane.Spec.TLS.Endpoint[service.EndpointInternal].Enabled).Should(BeFalse()) + Expect(OSCtlplane.Spec.TLS.Ingress.Enabled).Should(BeTrue()) + Expect(OSCtlplane.Spec.TLS.PodLevel.Enabled).Should(BeFalse()) // creates selfsigned issuer Eventually(func(g Gomega) { crtmgr.GetIssuer(names.SelfSignedIssuerName) }, timeout, interval).Should(Succeed()) - // creates public+internal root CA and issuer + // creates public, internal and ovn root CA and issuer Eventually(func(g Gomega) { // ca cert cert := crtmgr.GetCert(names.RootCAPublicName) @@ -121,7 +121,6 @@ var _ = Describe("OpenStackOperator controller", func() { issuer := crtmgr.GetIssuer(names.RootCAPublicName) g.Expect(issuer).Should(Not(BeNil())) g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAPublicName.Name)) - }, timeout, interval).Should(Succeed()) Eventually(func(g Gomega) { // ca cert @@ -135,7 +134,19 @@ var _ = Describe("OpenStackOperator controller", func() { issuer := crtmgr.GetIssuer(names.RootCAInternalName) g.Expect(issuer).Should(Not(BeNil())) g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAInternalName.Name)) - + }, timeout, interval).Should(Succeed()) + Eventually(func(g Gomega) { + // ca cert + cert := crtmgr.GetCert(names.RootCAOvnName) + g.Expect(cert).Should(Not(BeNil())) + g.Expect(cert.Spec.CommonName).Should(Equal(names.RootCAOvnName.Name)) + g.Expect(cert.Spec.IsCA).Should(BeTrue()) + g.Expect(cert.Spec.IssuerRef.Name).Should(Equal(names.SelfSignedIssuerName.Name)) + g.Expect(cert.Spec.SecretName).Should(Equal(names.RootCAOvnName.Name)) + // issuer + issuer := crtmgr.GetIssuer(names.RootCAOvnName) + g.Expect(issuer).Should(Not(BeNil())) + g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAOvnName.Name)) }, timeout, interval).Should(Succeed()) }) @@ -144,6 +155,8 @@ var _ = Describe("OpenStackOperator controller", func() { crtmgr.GetIssuer(names.RootCAPublicName) crtmgr.GetCert(names.RootCAInternalName) crtmgr.GetIssuer(names.RootCAInternalName) + crtmgr.GetCert(names.RootCAOvnName) + crtmgr.GetIssuer(names.RootCAOvnName) Eventually(func(g Gomega) { th.GetSecret(names.RootCAPublicName) diff --git a/tests/kuttl/common/assert-sample-deployment.yaml b/tests/kuttl/common/assert-sample-deployment.yaml index 817cd6ae9..4e61fe05a 100644 --- a/tests/kuttl/common/assert-sample-deployment.yaml +++ b/tests/kuttl/common/assert-sample-deployment.yaml @@ -172,11 +172,24 @@ spec: barbicanKeystoneListener: replicas: 1 tls: - endpoint: + ingress: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + ovn: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s status: conditions: - message: Setup complete diff --git a/tests/kuttl/tests/collapsed/01-assert-collapsed-cell.yaml b/tests/kuttl/tests/collapsed/01-assert-collapsed-cell.yaml index 5a26be942..bd9ef4e3a 100644 --- a/tests/kuttl/tests/collapsed/01-assert-collapsed-cell.yaml +++ b/tests/kuttl/tests/collapsed/01-assert-collapsed-cell.yaml @@ -125,11 +125,24 @@ spec: barbicanKeystoneListener: replicas: 1 tls: - endpoint: + ingress: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + ovn: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s status: conditions: - message: Setup complete diff --git a/tests/kuttl/tests/galera-3replicas/01-assert-galera-3replicas.yaml b/tests/kuttl/tests/galera-3replicas/01-assert-galera-3replicas.yaml index 218a3de93..65de085f4 100644 --- a/tests/kuttl/tests/galera-3replicas/01-assert-galera-3replicas.yaml +++ b/tests/kuttl/tests/galera-3replicas/01-assert-galera-3replicas.yaml @@ -128,11 +128,24 @@ spec: secret: osp-secret serviceUser: ceilometer tls: - endpoint: + ingress: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + ovn: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s status: conditions: - message: Setup complete diff --git a/tests/kuttl/tests/galera-basic/01-assert-galera.yaml b/tests/kuttl/tests/galera-basic/01-assert-galera.yaml index 1429299d2..11e350b9e 100644 --- a/tests/kuttl/tests/galera-basic/01-assert-galera.yaml +++ b/tests/kuttl/tests/galera-basic/01-assert-galera.yaml @@ -147,11 +147,24 @@ spec: swiftProxy: replicas: 1 tls: - endpoint: + ingress: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + enabled: true + podLevel: + enabled: false internal: - enabled: false - public: - enabled: true + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s + ovn: + ca: + duration: 43800h0m0s + cert: + duration: 8760h0m0s status: conditions: - message: Setup complete