Skip to content

Commit

Permalink
Merge pull request #779 from stuggi/introduce_libvirt_ca
Browse files Browse the repository at this point in the history
[tls] introduce dedicated CA for libvirt and update default cert durations
  • Loading branch information
openshift-merge-bot[bot] authored Apr 26, 2024
2 parents 5d262fb + 9bb7f2a commit 8d70a75
Show file tree
Hide file tree
Showing 12 changed files with 246 additions and 39 deletions.
36 changes: 30 additions & 6 deletions apis/bases/core.openstack.org_openstackcontrolplanes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17103,22 +17103,27 @@ spec:
default:
ingress:
ca:
duration: 43800h
duration: 87600h
cert:
duration: 8760h
duration: 10950h
enabled: true
podLevel:
enabled: true
internal:
ca:
duration: 43800h
duration: 87600h
cert:
duration: 8760h
ovn:
duration: 10950h
libvirt:
ca:
duration: 87600h
cert:
duration: 43800h
ovn:
ca:
duration: 87600h
cert:
duration: 8760h
duration: 10950h
properties:
caBundleSecretName:
type: string
Expand Down Expand Up @@ -17166,6 +17171,25 @@ spec:
type: string
type: object
type: object
libvirt:
properties:
ca:
properties:
customIssuer:
type: string
duration:
type: string
renewBefore:
type: string
type: object
cert:
properties:
duration:
type: string
renewBefore:
type: string
type: object
type: object
ovn:
properties:
ca:
Expand Down
19 changes: 18 additions & 1 deletion apis/core/v1beta1/openstackcontrolplane_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ const (

// OvnDbCaName -
OvnDbCaName = tls.DefaultCAPrefix + "ovn"
// LibvirtCaName -
LibvirtCaName = tls.DefaultCAPrefix + "libvirt"
)

// OpenStackControlPlaneSpec defines the desired state of OpenStackControlPlane
Expand All @@ -78,7 +80,7 @@ type OpenStackControlPlaneSpec struct {

// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
// +kubebuilder:default={ingress: {enabled: true, ca: {duration: "43800h"}, cert: {duration: "8760h"}}, podLevel: {enabled: true, internal:{ca: {duration: "43800h"}, cert: {duration: "8760h"}}, ovn: {ca: {duration: "43800h"}, cert: {duration: "8760h"}}}}
// +kubebuilder:default={ingress: {enabled: true, ca: {duration: "87600h"}, cert: {duration: "10950h"}}, podLevel: {enabled: true, internal:{ca: {duration: "87600h"}, cert: {duration: "10950h"}}, libvirt: {ca: {duration: "87600h"}, cert: {duration: "43800h"}}, ovn: {ca: {duration: "87600h"}, cert: {duration: "10950h"}}}}
// TLS - Parameters related to the TLS
TLS TLSSection `json:"tls"`

Expand Down Expand Up @@ -227,6 +229,11 @@ type TLSPodLevelConfig struct {
// except OVN related CA and certs
Internal CertSection `json:"internal,omitempty"`

// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
// Libvirt - CA used for libvirt/qemu services on OpenStackControlPlane and OpenStackDataplane
Libvirt CertSection `json:"libvirt,omitempty"`

// +kubebuilder:validation:Optional
// +operator-sdk:csv:customresourcedefinitions:type=spec
// Ovn - CA used for all OVN services on OpenStackControlPlane and OpenStackDataplane
Expand Down Expand Up @@ -882,3 +889,13 @@ func (instance OpenStackControlPlane) GetOvnIssuer() string {

return OvnDbCaName
}

// GetLibvirtIssuer - returns the libvirt CA issuer name or custom if configured
func (instance OpenStackControlPlane) GetLibvirtIssuer() string {
// use custom issuer if set
if instance.Spec.TLS.PodLevel.Libvirt.Ca.IsCustomIssuer() {
return *instance.Spec.TLS.PodLevel.Libvirt.Ca.CustomIssuer
}

return LibvirtCaName
}
1 change: 1 addition & 0 deletions apis/core/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

36 changes: 30 additions & 6 deletions config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17103,22 +17103,27 @@ spec:
default:
ingress:
ca:
duration: 43800h
duration: 87600h
cert:
duration: 8760h
duration: 10950h
enabled: true
podLevel:
enabled: true
internal:
ca:
duration: 43800h
duration: 87600h
cert:
duration: 8760h
ovn:
duration: 10950h
libvirt:
ca:
duration: 87600h
cert:
duration: 43800h
ovn:
ca:
duration: 87600h
cert:
duration: 8760h
duration: 10950h
properties:
caBundleSecretName:
type: string
Expand Down Expand Up @@ -17166,6 +17171,25 @@ spec:
type: string
type: object
type: object
libvirt:
properties:
ca:
properties:
customIssuer:
type: string
duration:
type: string
renewBefore:
type: string
type: object
cert:
properties:
duration:
type: string
renewBefore:
type: string
type: object
type: object
ovn:
properties:
ca:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,16 @@ spec:
- description: Cert - defines details for cert config
displayName: Cert
path: tls.podLevel.internal.cert
- description: Libvirt - CA used for libvirt/qemu services on OpenStackControlPlane
and OpenStackDataplane
displayName: Libvirt
path: tls.podLevel.libvirt
- description: Ca - defines details for CA cert config
displayName: Ca
path: tls.podLevel.libvirt.ca
- description: Cert - defines details for cert config
displayName: Cert
path: tls.podLevel.libvirt.cert
- description: Ovn - CA used for all OVN services on OpenStackControlPlane and
OpenStackDataplane
displayName: Ovn
Expand Down
67 changes: 65 additions & 2 deletions pkg/openstack/ca.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,15 +224,79 @@ func ReconcileCAs(ctx context.Context, instance *corev1.OpenStackControlPlane, h

}

// create CA for libvirt
issuerLabels = map[string]string{certmanager.RootCAIssuerLibvirtLabel: ""}
if !instance.Spec.TLS.PodLevel.Libvirt.Ca.IsCustomIssuer() {
ctrlResult, err = ensureRootCA(
ctx,
instance,
helper,
issuerReq,
corev1.LibvirtCaName,
issuerLabels,
bundle,
caOnlyBundle,
instance.Spec.TLS.PodLevel.Libvirt.Ca.CertConfig,
)
if err != nil {
return ctrlResult, err
} else if (ctrlResult != ctrl.Result{}) {
return ctrlResult, nil
}
} else {
customIssuer := *instance.Spec.TLS.PodLevel.Libvirt.Ca.CustomIssuer
// add CA labelselector to issuer
caCertSecretName, err := addIssuerLabel(ctx, helper, customIssuer, instance.Namespace, issuerLabels)
if err != nil {
instance.Status.Conditions.Set(condition.FalseCondition(
corev1.OpenStackControlPlaneCAReadyCondition,
condition.ErrorReason,
condition.SeverityWarning,
corev1.OpenStackControlPlaneCAReadyErrorMessage,
"issuer",
customIssuer,
err.Error()))
if k8s_errors.IsNotFound(err) {
timeout := time.Second * 10
Log.Info(fmt.Sprintf("Custom Issuer %s not found, reconcile in %s", customIssuer, timeout.String()))

return ctrl.Result{RequeueAfter: timeout}, nil
}

return ctrlResult, err
}

caCert, ctrlResult, err := getCAFromSecret(ctx, instance, helper, caCertSecretName)
if err != nil {
return ctrl.Result{}, err
} else if (ctrlResult != ctrl.Result{}) {
return ctrlResult, nil
}

ctrlResult, err = ensureCaBundles(
instance,
customIssuer,
caCert,
bundle,
caOnlyBundle,
)
if err != nil {
return ctrl.Result{}, err
} else if (ctrlResult != ctrl.Result{}) {
return ctrlResult, nil
}
}

// create CA for ovn
issuerLabels = map[string]string{certmanager.RootCAIssuerOvnDBLabel: ""}
if !instance.Spec.TLS.PodLevel.Ovn.Ca.IsCustomIssuer() {
ctrlResult, err = ensureRootCA(
ctx,
instance,
helper,
issuerReq,
corev1.OvnDbCaName,
map[string]string{certmanager.RootCAIssuerOvnDBLabel: ""},
issuerLabels,
bundle,
caOnlyBundle,
instance.Spec.TLS.PodLevel.Ovn.Ca.CertConfig,
Expand Down Expand Up @@ -284,7 +348,6 @@ func ReconcileCAs(ctx context.Context, instance *corev1.OpenStackControlPlane, h
} else if (ctrlResult != ctrl.Result{}) {
return ctrlResult, nil
}

}

instance.Status.Conditions.MarkTrue(corev1.OpenStackControlPlaneCAReadyCondition, corev1.OpenStackControlPlaneCAReadyMessage)
Expand Down
4 changes: 4 additions & 0 deletions tests/functional/base_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ type Names struct {
RootCAPublicName types.NamespacedName
RootCAInternalName types.NamespacedName
RootCAOvnName types.NamespacedName
RootCALibvirtName types.NamespacedName
SelfSignedIssuerName types.NamespacedName
CustomIssuerName types.NamespacedName
CustomServiceCertSecretName types.NamespacedName
Expand Down Expand Up @@ -83,6 +84,9 @@ func CreateNames(openstackControlplaneName types.NamespacedName) Names {
RootCAOvnName: types.NamespacedName{
Namespace: openstackControlplaneName.Namespace,
Name: "rootca-ovn"},
RootCALibvirtName: types.NamespacedName{
Namespace: openstackControlplaneName.Namespace,
Name: "rootca-libvirt"},
SelfSignedIssuerName: types.NamespacedName{
Namespace: openstackControlplaneName.Namespace,
Name: "selfsigned-issuer"},
Expand Down
44 changes: 44 additions & 0 deletions tests/functional/openstackoperator_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ var _ = Describe("OpenStackOperator controller", func() {
DeferCleanup(k8sClient.Delete, ctx, CreateCertSecret(names.RootCAPublicName))
DeferCleanup(k8sClient.Delete, ctx, CreateCertSecret(names.RootCAInternalName))
DeferCleanup(k8sClient.Delete, ctx, CreateCertSecret(names.RootCAOvnName))
DeferCleanup(k8sClient.Delete, ctx, CreateCertSecret(names.RootCALibvirtName))
// create cert secrets for galera instances
DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.DBCertName))
DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(names.DBCell1CertName))
Expand Down Expand Up @@ -167,6 +168,19 @@ var _ = Describe("OpenStackOperator controller", func() {
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAOvnName.Name))
}, timeout, interval).Should(Succeed())
Eventually(func(g Gomega) {
// ca cert
cert := crtmgr.GetCert(names.RootCALibvirtName)
g.Expect(cert).Should(Not(BeNil()))
g.Expect(cert.Spec.CommonName).Should(Equal(names.RootCALibvirtName.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.RootCALibvirtName.Name))
// issuer
issuer := crtmgr.GetIssuer(names.RootCALibvirtName)
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCALibvirtName.Name))
}, timeout, interval).Should(Succeed())
})

It("should create full ca bundle", func() {
Expand All @@ -176,6 +190,8 @@ var _ = Describe("OpenStackOperator controller", func() {
crtmgr.GetIssuer(names.RootCAInternalName)
crtmgr.GetCert(names.RootCAOvnName)
crtmgr.GetIssuer(names.RootCAOvnName)
crtmgr.GetCert(names.RootCALibvirtName)
crtmgr.GetIssuer(names.RootCALibvirtName)

Eventually(func(g Gomega) {
th.GetSecret(names.RootCAPublicName)
Expand Down Expand Up @@ -357,6 +373,19 @@ var _ = Describe("OpenStackOperator controller", func() {
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAOvnName.Name))
}, timeout, interval).Should(Succeed())
Eventually(func(g Gomega) {
// ca cert
cert := crtmgr.GetCert(names.RootCALibvirtName)
g.Expect(cert).Should(Not(BeNil()))
g.Expect(cert.Spec.CommonName).Should(Equal(names.RootCALibvirtName.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.RootCALibvirtName.Name))
// issuer
issuer := crtmgr.GetIssuer(names.RootCALibvirtName)
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCALibvirtName.Name))
}, timeout, interval).Should(Succeed())

th.ExpectCondition(
names.OpenStackControlplaneName,
Expand All @@ -380,6 +409,8 @@ var _ = Describe("OpenStackOperator controller", func() {
crtmgr.GetIssuer(names.RootCAInternalName)
crtmgr.GetCert(names.RootCAOvnName)
crtmgr.GetIssuer(names.RootCAOvnName)
crtmgr.GetCert(names.RootCALibvirtName)
crtmgr.GetIssuer(names.RootCALibvirtName)

Eventually(func(g Gomega) {
th.GetSecret(names.RootCAPublicName)
Expand Down Expand Up @@ -549,6 +580,19 @@ var _ = Describe("OpenStackOperator controller", func() {
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCAOvnName.Name))
}, timeout, interval).Should(Succeed())
Eventually(func(g Gomega) {
// ca cert
cert := crtmgr.GetCert(names.RootCALibvirtName)
g.Expect(cert).Should(Not(BeNil()))
g.Expect(cert.Spec.CommonName).Should(Equal(names.RootCALibvirtName.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.RootCALibvirtName.Name))
// issuer
issuer := crtmgr.GetIssuer(names.RootCALibvirtName)
g.Expect(issuer).Should(Not(BeNil()))
g.Expect(issuer.Spec.CA.SecretName).Should(Equal(names.RootCALibvirtName.Name))
}, timeout, interval).Should(Succeed())

th.ExpectCondition(
names.OpenStackControlplaneName,
Expand Down
Loading

0 comments on commit 8d70a75

Please sign in to comment.