From 17dee94a0140bafd3672b4fa90f38fb711f0c913 Mon Sep 17 00:00:00 2001 From: Tom Weininger Date: Wed, 25 Oct 2023 10:10:33 -0400 Subject: [PATCH 1/3] Amphora certificate management WIP --- ...enstack.org_octaviaamphoracontrollers.yaml | 11 +- api/bases/octavia.openstack.org_octavias.yaml | 33 ++- api/v1beta1/amphoracontroller_types.go | 7 +- ...enstack.org_octaviaamphoracontrollers.yaml | 11 +- .../bases/octavia.openstack.org_octavias.yaml | 33 ++- config/samples/octavia_v1beta1_octavia.yaml | 6 +- controllers/amphoracontroller_controller.go | 29 ++- pkg/amphoracontrollers/amphora_certs.go | 217 ++++++++++++++++++ pkg/amphoracontrollers/deployment.go | 6 +- pkg/amphoracontrollers/volumes.go | 55 +++++ .../config/octavia.conf | 7 + 11 files changed, 392 insertions(+), 23 deletions(-) create mode 100644 pkg/amphoracontrollers/amphora_certs.go create mode 100644 pkg/amphoracontrollers/volumes.go diff --git a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index 189e424a..fecf2e16 100644 --- a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -50,9 +50,15 @@ spec: description: OctaviaAmphoraControllerSpec defines common state for all Octavia Amphora Controllers properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret containing + passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing certs - for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts - + Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image URL @@ -214,6 +220,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/api/bases/octavia.openstack.org_octavias.yaml b/api/bases/octavia.openstack.org_octavias.yaml index fa729a1b..ee31de72 100644 --- a/api/bases/octavia.openstack.org_octavias.yaml +++ b/api/bases/octavia.openstack.org_octavias.yaml @@ -456,9 +456,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -622,6 +628,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role @@ -632,9 +639,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -798,6 +811,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role @@ -808,9 +822,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -974,6 +994,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/api/v1beta1/amphoracontroller_types.go b/api/v1beta1/amphoracontroller_types.go index b68dbcdf..3b8f1332 100644 --- a/api/v1beta1/amphoracontroller_types.go +++ b/api/v1beta1/amphoracontroller_types.go @@ -78,9 +78,14 @@ type OctaviaAmphoraControllerSpec struct { Secret string `json:"secret"` // *kubebuilder:validation:Required - // Secret containing certs for securing communication with amphora based Load Balancers + // LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers LoadBalancerCerts string `json:"certssecret"` + // *kubebuilder:validation:Optional + // +kubebuilder:default=octavia-ca-passphrase + // Name of secret containing passphrase for the CA private keys + CAKeyPassphraseSecret string `json:"certspassphrasesecret"` + // +kubebuilder:validation:Optional // +kubebuilder:default={database: OctaviaDatabasePassword, service: OctaviaPassword} // PasswordSelectors - Selectors to identify the DB and AdminUser password from the Secret diff --git a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index 189e424a..fecf2e16 100644 --- a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -50,9 +50,15 @@ spec: description: OctaviaAmphoraControllerSpec defines common state for all Octavia Amphora Controllers properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret containing + passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing certs - for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts - + Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image URL @@ -214,6 +220,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/config/crd/bases/octavia.openstack.org_octavias.yaml b/config/crd/bases/octavia.openstack.org_octavias.yaml index fa729a1b..ee31de72 100644 --- a/config/crd/bases/octavia.openstack.org_octavias.yaml +++ b/config/crd/bases/octavia.openstack.org_octavias.yaml @@ -456,9 +456,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -622,6 +628,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role @@ -632,9 +639,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -798,6 +811,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role @@ -808,9 +822,15 @@ spec: description: OctaviaHousekeeping - Spec definition for the Octavia Housekeeping agent for the Octavia deployment properties: + certspassphrasesecret: + default: octavia-ca-passphrase + description: '*kubebuilder:validation:Optional Name of secret + containing passphrase for the CA private keys' + type: string certssecret: - description: '*kubebuilder:validation:Required Secret containing - certs for securing communication with amphora based Load Balancers' + description: '*kubebuilder:validation:Required LoadBalancerCerts + - Secret containing certs for securing communication with amphora + based Load Balancers' type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -974,6 +994,7 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: + - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/config/samples/octavia_v1beta1_octavia.yaml b/config/samples/octavia_v1beta1_octavia.yaml index 93125cd3..3ac72e32 100644 --- a/config/samples/octavia_v1beta1_octavia.yaml +++ b/config/samples/octavia_v1beta1_octavia.yaml @@ -21,7 +21,7 @@ spec: serviceUser: octavia serviceAccount: octavia role: housekeeping - certssecret: todo + certssecret: octavia-amp-cert-data secret: osp-secret preserveJobs: false customServiceConfig: | @@ -33,7 +33,7 @@ spec: serviceUser: octavia serviceAccount: octavia role: healthmanager - certssecret: todo + certssecret: octavia-amp-cert-data secret: osp-secret preserveJobs: false customServiceConfig: | @@ -45,7 +45,7 @@ spec: serviceUser: octavia serviceAccount: octavia role: worker - certssecret: todo + certssecret: octavia-amp-cert-data secret: osp-secret preserveJobs: false customServiceConfig: | diff --git a/controllers/amphoracontroller_controller.go b/controllers/amphoracontroller_controller.go index 74df6159..69ab0ca3 100644 --- a/controllers/amphoracontroller_controller.go +++ b/controllers/amphoracontroller_controller.go @@ -31,6 +31,7 @@ import ( "github.com/openstack-k8s-operators/lib-common/modules/common/helper" "github.com/openstack-k8s-operators/lib-common/modules/common/labels" nad "github.com/openstack-k8s-operators/lib-common/modules/common/networkattachment" + "github.com/openstack-k8s-operators/lib-common/modules/common/secret" "github.com/openstack-k8s-operators/lib-common/modules/common/util" keystonev1 "github.com/openstack-k8s-operators/keystone-operator/api/v1beta1" @@ -254,6 +255,17 @@ func (r *OctaviaAmphoraControllerReconciler) reconcileNormal(ctx context.Context return ctrl.Result{}, err } + err = amphoracontrollers.EnsureAmphoraCerts(ctx, instance, helper, &Log) + if err != nil { + instance.Status.Conditions.Set(condition.FalseCondition( + condition.ServiceConfigReadyCondition, + condition.ErrorReason, + condition.SeverityWarning, + condition.ServiceConfigReadyErrorMessage, + err.Error())) + return ctrl.Result{}, err + } + instance.Status.Conditions.MarkTrue(condition.InputReadyCondition, condition.InputReadyMessage) // @@ -418,12 +430,25 @@ func (r *OctaviaAmphoraControllerReconciler) generateServiceConfigMaps( if err != nil { return err } - templateParameters["ServiceUser"] = instance.Spec.ServiceUser + caPassSecret, _, err := secret.GetSecret( + ctx, helper, instance.Spec.CAKeyPassphraseSecret, instance.Namespace) + if err != nil { + return err + } + spec := instance.Spec + templateParameters["ServiceUser"] = spec.ServiceUser templateParameters["KeystoneInternalURL"] = keystoneInternalURL templateParameters["KeystonePublicURL"] = keystonePublicURL - templateParameters["ServiceRoleName"] = instance.Spec.Role + templateParameters["ServiceRoleName"] = spec.Role templateParameters["LbMgmtNetworkId"] = templateVars.LbMgmtNetworkID templateParameters["AmpFlavorId"] = templateVars.AmphoraDefaultFlavorID + serverCAPassphrase := caPassSecret.Data["server-ca-passphrase"] + if serverCAPassphrase != nil { + templateParameters["ServerCAKeyPassphrase"] = string(serverCAPassphrase) + } else { + // Can't do string(nil) + templateParameters["ServerCAKeyPassphrase"] = "" + } // TODO(beagles): populate the template parameters cms := []util.Template{ diff --git a/pkg/amphoracontrollers/amphora_certs.go b/pkg/amphoracontrollers/amphora_certs.go new file mode 100644 index 00000000..c70d6770 --- /dev/null +++ b/pkg/amphoracontrollers/amphora_certs.go @@ -0,0 +1,217 @@ +package amphoracontrollers + +import ( + "bytes" + "context" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "fmt" + "math/big" + "time" + + "github.com/go-logr/logr" + "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/secret" + octaviav1 "github.com/openstack-k8s-operators/octavia-operator/api/v1beta1" + corev1 "k8s.io/api/core/v1" + k8serrors "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" +) + +var ( + subjectDefault = pkix.Name{ + Organization: []string{"Dis"}, + Country: []string{"US"}, + Province: []string{"Oregon"}, + Locality: []string{"Springfield"}, + StreetAddress: []string{"Denial"}, + PostalCode: []string{""}, + CommonName: "www.example.com", + } +) + +// generateKey generates a PEM encoded private RSA key and applies PEM +// encryption if given passphrase is not an empty string. +func generateKey(passphrase []byte) (*rsa.PrivateKey, []byte, error) { + priv, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return nil, nil, err + } + + var pemBlock *pem.Block + if passphrase != nil { + pemBlock, err = x509.EncryptPEMBlock( //nolint:staticcheck + rand.Reader, + "RSA PRIVATE KEY", + x509.MarshalPKCS1PrivateKey(priv), + passphrase, + x509.PEMCipherAES128) + if err != nil { + fmt.Println("Error encrypting private CA key:", err) + return priv, nil, err + } + } else { + privBytes := x509.MarshalPKCS1PrivateKey(priv) + pemBlock = &pem.Block{Type: "PRIVATE KEY", Bytes: privBytes} + } + + privPEM := new(bytes.Buffer) + err = pem.Encode(privPEM, pemBlock) + if err != nil { + return priv, nil, err + } + + return priv, privPEM.Bytes(), nil +} + +func generateCACert(caPrivKey *rsa.PrivateKey, commonName string) ([]byte, error) { + caTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(2019), + Subject: subjectDefault, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(10, 0, 0), + IsCA: true, + BasicConstraintsValid: true, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageCRLSign | x509.KeyUsageCertSign, + } + caTemplate.Subject.CommonName = commonName + + caBytes, err := x509.CreateCertificate( + rand.Reader, caTemplate, caTemplate, &caPrivKey.PublicKey, caPrivKey) + if err != nil { + return nil, err + } + caCertPEM := new(bytes.Buffer) + err = pem.Encode(caCertPEM, &pem.Block{ + Type: "CERTIFICATE", + Bytes: caBytes, + }) + if err != nil { + return nil, err + } + return caCertPEM.Bytes(), nil +} + +// Create a certificate and key for the client and sign it with the CA +// TODO: Change signature to take PEM encoded CA key as []byte so it can be +// used directly with data from secret store +func generateClientCert(caCertPEM []byte, caPrivKey *rsa.PrivateKey) ([]byte, error) { + + certTemplate := &x509.Certificate{ + SerialNumber: big.NewInt(2019), + Subject: subjectDefault, + NotBefore: time.Now(), + NotAfter: time.Now().AddDate(0, 1, 0), + IsCA: false, + BasicConstraintsValid: false, + KeyUsage: x509.KeyUsageDigitalSignature | x509.KeyUsageKeyEncipherment, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageClientAuth, x509.ExtKeyUsageEmailProtection}, + } + + certBytes, err := x509.CreateCertificate( + rand.Reader, certTemplate, certTemplate, &caPrivKey.PublicKey, caPrivKey) + if err != nil { + return nil, err + } + + certPEM := new(bytes.Buffer) + err = pem.Encode(certPEM, &pem.Block{ + Type: "CERTIFICATE", + Bytes: certBytes, + }) + if err != nil { + return nil, err + } + + return certPEM.Bytes(), nil +} + +// EnsureAmphoraCerts ensures Amphora certificates exist in the secret store +func EnsureAmphoraCerts(ctx context.Context, instance *octaviav1.OctaviaAmphoraController, h *helper.Helper, log *logr.Logger) error { + var oAmpSecret *corev1.Secret + var serverCAPass []byte = nil + + _, _, err := secret.GetSecret(ctx, h, instance.Spec.LoadBalancerCerts, instance.Namespace) + if err != nil { + if !k8serrors.IsNotFound(err) { + err = fmt.Errorf("Error retrieving secret %s - %w", instance.Spec.LoadBalancerCerts, err) + return err + } + + cAPassSecret, _, err := secret.GetSecret( + ctx, h, instance.Spec.CAKeyPassphraseSecret, instance.Namespace) + if err != nil { + log.Info("Could not read server CA passphrase. No encryption will be applied to the generated key.") + } else { + serverCAPass = cAPassSecret.Data["server-ca-passphrase"] + } + + serverCAKey, serverCAKeyPEM, err := generateKey(serverCAPass) + if err != nil { + err = fmt.Errorf("Error while generating server CA key: %w", err) + return err + } + serverCACert, err := generateCACert(serverCAKey, "Octavia server CA") + if err != nil { + err = fmt.Errorf("Error while generating server CA certificate: %w", err) + return err + } + + clientCAKey, _, err := generateKey(nil) + if err != nil { + err = fmt.Errorf("Error while generating client CA key: %w", err) + return err + } + clientCACert, err := generateCACert(clientCAKey, "Octavia client CA") + if err != nil { + err = fmt.Errorf("Error while generating amphora client CA certificate: %w", err) + return err + } + + clientKey, clientKeyPEM, err := generateKey(nil) + if err != nil { + err = fmt.Errorf("Error while generating amphora client key: %w", err) + return err + } + clientCert, err := generateClientCert(clientCACert, clientKey) + if err != nil { + err = fmt.Errorf("Error while generating amphora client certificate: %w", err) + return err + } + clientKeyAndCert := append(clientKeyPEM, clientCert...) + + oAmpSecret = &corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: instance.Spec.LoadBalancerCerts, + Namespace: instance.Namespace, + }, + + // note: the client CA key seem to be needed only for generating the + // client CA cert and should not get mounted to the pods + Data: map[string][]byte{ + "server_ca.key.pem": serverCAKeyPEM, + "server_ca.cert.pem": serverCACert, + "client_ca.cert.pem": clientCACert, + // Unencrypted client key and cert + "client.cert-and-key.pem": clientKeyAndCert, + }, + } + + // err = h.GetClient().Create(ctx, oAmpSecret) + _, result, err := secret.CreateOrPatchSecret(ctx, h, instance, oAmpSecret) + + if err != nil { + err = fmt.Errorf("Error creating certs secret %s - %w", + instance.Spec.LoadBalancerCerts, err) + return err + } else if result != controllerutil.OperationResultNone { + return nil + } + } + + return nil +} diff --git a/pkg/amphoracontrollers/deployment.go b/pkg/amphoracontrollers/deployment.go index 8b060c45..06d7d544 100644 --- a/pkg/amphoracontrollers/deployment.go +++ b/pkg/amphoracontrollers/deployment.go @@ -41,6 +41,10 @@ func Deployment( // The API pod has an extra volume so the API and the provider agent can // communicate with each other. volumes := octavia.GetVolumes(instance.Name) + volumes = append(volumes, GetCertVolume(instance.Spec.LoadBalancerCerts)...) + + volumeMounts := octavia.GetVolumeMounts(serviceName) + volumeMounts = append(volumeMounts, GetCertVolumeMount()...) // TODO(beagles): service debugging @@ -100,7 +104,7 @@ func Deployment( Name: serviceName, Image: instance.Spec.ContainerImage, Env: env.MergeEnvs([]corev1.EnvVar{}, envVars), - VolumeMounts: octavia.GetVolumeMounts(serviceName), + VolumeMounts: volumeMounts, Resources: instance.Spec.Resources, ReadinessProbe: readinessProbe, LivenessProbe: livenessProbe, diff --git a/pkg/amphoracontrollers/volumes.go b/pkg/amphoracontrollers/volumes.go new file mode 100644 index 00000000..1f72f42f --- /dev/null +++ b/pkg/amphoracontrollers/volumes.go @@ -0,0 +1,55 @@ +/* + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package amphoracontrollers + +import ( + corev1 "k8s.io/api/core/v1" +) + +const ( + configVolume = "amphora-certs" +) + +var ( + // Files get mounted as root:root, but process is running as octavia + configMode int32 = 0644 +) + +// GetCertVolume - service volumes +func GetCertVolume(certSecretName string) []corev1.Volume { + return []corev1.Volume{ + { + Name: configVolume, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + DefaultMode: &configMode, + SecretName: certSecretName, + }, + }, + }, + } +} + +// GetCertVolumeMount - certificate VolumeMount +func GetCertVolumeMount() []corev1.VolumeMount { + return []corev1.VolumeMount{ + { + Name: configVolume, + MountPath: "/etc/octavia/certs", + ReadOnly: true, + }, + } +} diff --git a/templates/octaviaamphoracontroller/config/octavia.conf b/templates/octaviaamphoracontroller/config/octavia.conf index 915fc0cc..5ef02ae8 100644 --- a/templates/octaviaamphoracontroller/config/octavia.conf +++ b/templates/octaviaamphoracontroller/config/octavia.conf @@ -22,13 +22,20 @@ auth_type=password # region_name=regionOne interface=internal [certificates] +cert_generator = local_cert_generator +ca_certificate = /etc/octavia/certs/server_ca.cert.pem +ca_private_key = /etc/octavia/certs/server_ca.key.pem +ca_private_key_passphrase = {{ .ServerCAKeyPassphrase }} [compute] [networking] port_detach_timeout=300 [haproxy_amphora] +client_cert = /etc/octavia/certs/client.cert-and-key.pem +server_ca = /etc/octavia/certs/server_ca.cert.pem [controller_worker] amp_boot_network_list={{ .LbMgmtNetworkId }} amp_flavor_id={{ .AmpFlavorId }} +client_ca = /etc/octavia/certs/client_ca.cert.pem [task_flow] [oslo_messaging] # topic=octavia-rpc From 920df38fbdc091f5ab2434783ba034a03cd9edcc Mon Sep 17 00:00:00 2001 From: Tom Weininger Date: Wed, 29 Nov 2023 05:17:17 -0500 Subject: [PATCH 2/3] Set default for certssecret --- api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml | 1 + api/bases/octavia.openstack.org_octavias.yaml | 3 +++ api/v1beta1/amphoracontroller_types.go | 1 + .../bases/octavia.openstack.org_octaviaamphoracontrollers.yaml | 1 + config/crd/bases/octavia.openstack.org_octavias.yaml | 3 +++ pkg/amphoracontrollers/amphora_certs.go | 2 -- 6 files changed, 9 insertions(+), 2 deletions(-) diff --git a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index fecf2e16..564fa7af 100644 --- a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -56,6 +56,7 @@ spec: passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' diff --git a/api/bases/octavia.openstack.org_octavias.yaml b/api/bases/octavia.openstack.org_octavias.yaml index ee31de72..523a24b8 100644 --- a/api/bases/octavia.openstack.org_octavias.yaml +++ b/api/bases/octavia.openstack.org_octavias.yaml @@ -462,6 +462,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' @@ -645,6 +646,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' @@ -828,6 +830,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' diff --git a/api/v1beta1/amphoracontroller_types.go b/api/v1beta1/amphoracontroller_types.go index 3b8f1332..dddf5396 100644 --- a/api/v1beta1/amphoracontroller_types.go +++ b/api/v1beta1/amphoracontroller_types.go @@ -78,6 +78,7 @@ type OctaviaAmphoraControllerSpec struct { Secret string `json:"secret"` // *kubebuilder:validation:Required + // +kubebuilder:default=octavia-certs-secret // LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers LoadBalancerCerts string `json:"certssecret"` diff --git a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index fecf2e16..564fa7af 100644 --- a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -56,6 +56,7 @@ spec: passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' diff --git a/config/crd/bases/octavia.openstack.org_octavias.yaml b/config/crd/bases/octavia.openstack.org_octavias.yaml index ee31de72..523a24b8 100644 --- a/config/crd/bases/octavia.openstack.org_octavias.yaml +++ b/config/crd/bases/octavia.openstack.org_octavias.yaml @@ -462,6 +462,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' @@ -645,6 +646,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' @@ -828,6 +830,7 @@ spec: containing passphrase for the CA private keys' type: string certssecret: + default: octavia-certs-secret description: '*kubebuilder:validation:Required LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers' diff --git a/pkg/amphoracontrollers/amphora_certs.go b/pkg/amphoracontrollers/amphora_certs.go index c70d6770..6c10acb1 100644 --- a/pkg/amphoracontrollers/amphora_certs.go +++ b/pkg/amphoracontrollers/amphora_certs.go @@ -97,8 +97,6 @@ func generateCACert(caPrivKey *rsa.PrivateKey, commonName string) ([]byte, error } // Create a certificate and key for the client and sign it with the CA -// TODO: Change signature to take PEM encoded CA key as []byte so it can be -// used directly with data from secret store func generateClientCert(caCertPEM []byte, caPrivKey *rsa.PrivateKey) ([]byte, error) { certTemplate := &x509.Certificate{ From 34f4a114c07d9f22ce64939843125032cae6320c Mon Sep 17 00:00:00 2001 From: Tom Weininger Date: Wed, 29 Nov 2023 06:21:10 -0500 Subject: [PATCH 3/3] Fix typo in kubebuilder comment --- ...enstack.org_octaviaamphoracontrollers.yaml | 10 +++---- api/bases/octavia.openstack.org_octavias.yaml | 30 ++++++++----------- api/v1beta1/amphoracontroller_types.go | 4 +-- ...enstack.org_octaviaamphoracontrollers.yaml | 10 +++---- .../bases/octavia.openstack.org_octavias.yaml | 30 ++++++++----------- 5 files changed, 34 insertions(+), 50 deletions(-) diff --git a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index 564fa7af..8267d0fb 100644 --- a/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/api/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -52,14 +52,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret containing - passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image URL @@ -221,7 +220,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/api/bases/octavia.openstack.org_octavias.yaml b/api/bases/octavia.openstack.org_octavias.yaml index 523a24b8..9df71518 100644 --- a/api/bases/octavia.openstack.org_octavias.yaml +++ b/api/bases/octavia.openstack.org_octavias.yaml @@ -458,14 +458,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -629,7 +628,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role @@ -642,14 +640,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -813,7 +810,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role @@ -826,14 +822,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -997,7 +992,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/api/v1beta1/amphoracontroller_types.go b/api/v1beta1/amphoracontroller_types.go index dddf5396..60878844 100644 --- a/api/v1beta1/amphoracontroller_types.go +++ b/api/v1beta1/amphoracontroller_types.go @@ -77,12 +77,12 @@ type OctaviaAmphoraControllerSpec struct { // Secret containing OpenStack password information for octavia OctaviaDatabasePassword, AdminPassword Secret string `json:"secret"` - // *kubebuilder:validation:Required + // +kubebuilder:validation:Required // +kubebuilder:default=octavia-certs-secret // LoadBalancerCerts - Secret containing certs for securing communication with amphora based Load Balancers LoadBalancerCerts string `json:"certssecret"` - // *kubebuilder:validation:Optional + // +kubebuilder:validation:Optional // +kubebuilder:default=octavia-ca-passphrase // Name of secret containing passphrase for the CA private keys CAKeyPassphraseSecret string `json:"certspassphrasesecret"` diff --git a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml index 564fa7af..8267d0fb 100644 --- a/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml +++ b/config/crd/bases/octavia.openstack.org_octaviaamphoracontrollers.yaml @@ -52,14 +52,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret containing - passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image URL @@ -221,7 +220,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role diff --git a/config/crd/bases/octavia.openstack.org_octavias.yaml b/config/crd/bases/octavia.openstack.org_octavias.yaml index 523a24b8..9df71518 100644 --- a/config/crd/bases/octavia.openstack.org_octavias.yaml +++ b/config/crd/bases/octavia.openstack.org_octavias.yaml @@ -458,14 +458,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -629,7 +628,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role @@ -642,14 +640,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -813,7 +810,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role @@ -826,14 +822,13 @@ spec: properties: certspassphrasesecret: default: octavia-ca-passphrase - description: '*kubebuilder:validation:Optional Name of secret - containing passphrase for the CA private keys' + description: Name of secret containing passphrase for the CA private + keys type: string certssecret: default: octavia-certs-secret - description: '*kubebuilder:validation:Required LoadBalancerCerts - - Secret containing certs for securing communication with amphora - based Load Balancers' + description: LoadBalancerCerts - Secret containing certs for securing + communication with amphora based Load Balancers type: string containerImage: description: ContainerImage - Amphora Controller Container Image @@ -997,7 +992,6 @@ spec: description: TransportURLSecret - Secret containing RabbitMQ transportURL type: string required: - - certspassphrasesecret - certssecret - databaseInstance - role