From 93c34290cd828bbaae4280eadc693ffa368daa54 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Fri, 8 Nov 2024 12:20:59 +0000 Subject: [PATCH] openstack: Add support for storing ca bundle If a CA bundle is required to talk to your OpenStack then obviously all services that talk to the cloud need to have both credentials and said bundle. Currently, these users can get their credentials via cloud credential operator, but they need to source their CA bundle from elsewhere (typically by extracting it from the cloud controller manager's configuration). This makes configuration of services more complicated than necessary. Begin the resolution of the issue by allowing users (i.e. the Installer) to store the CA bundle in their root secret and dole this out to anyone who asks for it via a CredentialsRequest. Follow-up changes will be needed in places like the Installer and csi-operator to start setting/consuming this. Signed-off-by: Stephen Finucane --- README.md | 1 + pkg/openstack/actuator.go | 12 ++++++--- pkg/openstack/utils.go | 27 +++++++++++-------- .../secretannotator/openstack/reconciler.go | 4 +-- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index c98cba3df..ee9973594 100644 --- a/README.md +++ b/README.md @@ -119,6 +119,7 @@ metadata: data: clouds.yaml: Base64encodeCloudCreds clouds.conf: Base64encodeCloudCredsINI + cabundle.pem: Base64encodeCABundle ``` ### Ovirt diff --git a/pkg/openstack/actuator.go b/pkg/openstack/actuator.go index 34104304a..e5f58b1f2 100644 --- a/pkg/openstack/actuator.go +++ b/pkg/openstack/actuator.go @@ -96,7 +96,7 @@ func (a *OpenStackActuator) sync(ctx context.Context, cr *minterv1.CredentialsRe return err } - clouds, err := GetRootCloudCredentialsSecretData(credentialsRootSecret, logger) + clouds, cabundle, err := GetRootCloudCredentialsSecretData(credentialsRootSecret, logger) if err != nil { logger.WithError(err).Error("issue with cloud credentials secret") return &actuatoriface.ActuatorError{ @@ -106,7 +106,7 @@ func (a *OpenStackActuator) sync(ctx context.Context, cr *minterv1.CredentialsRe } logger.Debugf("provisioning secret") - err = a.syncCredentialSecret(ctx, cr, clouds, logger) + err = a.syncCredentialSecret(ctx, cr, clouds, cabundle, logger) if err != nil { msg := "error creating/updating secret" logger.WithError(err).Error(msg) @@ -119,7 +119,7 @@ func (a *OpenStackActuator) sync(ctx context.Context, cr *minterv1.CredentialsRe return nil } -func (a *OpenStackActuator) syncCredentialSecret(ctx context.Context, cr *minterv1.CredentialsRequest, clouds string, logger log.FieldLogger) error { +func (a *OpenStackActuator) syncCredentialSecret(ctx context.Context, cr *minterv1.CredentialsRequest, clouds, cabundle string, logger log.FieldLogger) error { sLog := logger.WithFields(log.Fields{ "targetSecret": fmt.Sprintf("%s/%s", cr.Spec.SecretRef.Namespace, cr.Spec.SecretRef.Name), "cr": fmt.Sprintf("%s/%s", cr.Namespace, cr.Name), @@ -145,6 +145,12 @@ func (a *OpenStackActuator) syncCredentialSecret(ctx context.Context, cr *minter secret.Data = map[string][]byte{} } secret.Data[RootOpenStackCredsSecretKey] = []byte(clouds) + + // This means we only write cabundle.pem if clouds.yaml is present. That's okay, since + // the former is useless without the latter. + if cabundle != "" { + secret.Data[RootOpenStackCAFileSecretKey] = []byte(cabundle) + } } return nil }) diff --git a/pkg/openstack/utils.go b/pkg/openstack/utils.go index 5ad06a215..ef3c13867 100644 --- a/pkg/openstack/utils.go +++ b/pkg/openstack/utils.go @@ -23,29 +23,34 @@ import ( ) const ( - RootOpenStackCredsSecretKey = "clouds.yaml" - OpenStackCloudName = "openstack" - CACertFile = "/etc/kubernetes/static-pod-resources/configmaps/cloud-config/ca-bundle.pem" + RootOpenStackCredsSecretKey = "clouds.yaml" + RootOpenStackCAFileSecretKey = "ca-bundle.pem" + OpenStackCloudName = "openstack" + CACertFile = "/etc/kubernetes/static-pod-resources/configmaps/cloud-config/ca-bundle.pem" ) -func GetRootCloudCredentialsSecretData(cloudCredSecret *corev1.Secret, logger log.FieldLogger) (string, error) { - var clouds string - - keyBytes, ok := cloudCredSecret.Data[RootOpenStackCredsSecretKey] +func GetRootCloudCredentialsSecretData(cloudCredSecret *corev1.Secret, logger log.FieldLogger) (string, string, error) { + creds, ok := cloudCredSecret.Data[RootOpenStackCredsSecretKey] if !ok { - return "", fmt.Errorf("secret did not have expected key: %v", RootOpenStackCredsSecretKey) + return "", "", fmt.Errorf("secret did not have expected key: %v", RootOpenStackCredsSecretKey) } - clouds = string(keyBytes) + // cacert is optional, so it's okay if it's not present + cabundle, _ := cloudCredSecret.Data[RootOpenStackCAFileSecretKey] + logger.Debug("found clouds.yaml in target secret") - return clouds, nil + return string(creds), string(cabundle), nil } -func SetRootCloudCredentialsSecretData(cloudCredSecret *corev1.Secret, clouds string) { +func SetRootCloudCredentialsSecretData(cloudCredSecret *corev1.Secret, clouds, cafile string) { if cloudCredSecret.Data == nil { cloudCredSecret.Data = make(map[string][]byte) } cloudCredSecret.Data[RootOpenStackCredsSecretKey] = []byte(clouds) + + if len(cafile) > 0 { + cloudCredSecret.Data[RootOpenStackCAFileSecretKey] = []byte(cafile) + } } diff --git a/pkg/operator/secretannotator/openstack/reconciler.go b/pkg/operator/secretannotator/openstack/reconciler.go index 020b6ea75..d51ec955f 100644 --- a/pkg/operator/secretannotator/openstack/reconciler.go +++ b/pkg/operator/secretannotator/openstack/reconciler.go @@ -156,7 +156,7 @@ func (r *ReconcileCloudCredSecret) Reconcile(ctx context.Context, request reconc return reconcile.Result{}, err } - clouds, err := openstack.GetRootCloudCredentialsSecretData(secret, r.Logger) + clouds, cabundle, err := openstack.GetRootCloudCredentialsSecretData(secret, r.Logger) if err != nil { r.Logger.WithError(err).Error("errored getting clouds.yaml from secret") return reconcile.Result{}, err @@ -169,7 +169,7 @@ func (r *ReconcileCloudCredSecret) Reconcile(ctx context.Context, request reconc } if cloudsUpdated { - openstack.SetRootCloudCredentialsSecretData(secret, clouds) + openstack.SetRootCloudCredentialsSecretData(secret, clouds, cabundle) err := r.RootCredClient.Update(context.TODO(), secret) if err != nil { r.Logger.WithError(err).Error("error writing updated root secret")