Skip to content

Commit

Permalink
External Secret: Implementation to skip the creation of the default u… (
Browse files Browse the repository at this point in the history
rabbitmq#1199)

* External Secret: Implementation to skip the creation of the default user credential secret and give the possibility to use an external one

* replacing externalSecret type from string to LocalObjectReference
  • Loading branch information
DanielePalaia authored Dec 12, 2022
1 parent 91730ea commit 9e50b90
Show file tree
Hide file tree
Showing 8 changed files with 59 additions and 9 deletions.
8 changes: 7 additions & 1 deletion api/v1beta1/rabbitmqcluster_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
appsv1 "k8s.io/api/apps/v1"

corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
k8sresource "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -104,7 +105,8 @@ type RabbitmqClusterSpec struct {
// Future secret backends could be Secrets Store CSI Driver.
// If not configured, K8s Secrets will be used.
type SecretBackend struct {
Vault *VaultSpec `json:"vault,omitempty"`
Vault *VaultSpec `json:"vault,omitempty"`
ExternalSecret v1.LocalObjectReference `json:"externalSecret,omitempty"`
}

// VaultSpec will add Vault annotations (see https://www.vaultproject.io/docs/platform/k8s/injector/annotations)
Expand Down Expand Up @@ -443,6 +445,10 @@ func (cluster *RabbitmqCluster) VaultEnabled() bool {
return cluster.Spec.SecretBackend.Vault != nil
}

func (cluster *RabbitmqCluster) ExternalSecretEnabled() bool {
return cluster.Spec.SecretBackend.ExternalSecret.Name != ""
}

func (cluster *RabbitmqCluster) UsesDefaultUserUpdaterImage() bool {
return cluster.VaultEnabled() && cluster.Spec.SecretBackend.Vault.DefaultUserUpdaterImage == nil
}
Expand Down
1 change: 1 addition & 0 deletions api/v1beta1/zz_generated.deepcopy.go

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

8 changes: 8 additions & 0 deletions config/crd/bases/rabbitmq.com_rabbitmqclusters.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4022,6 +4022,14 @@ spec:
secretBackend:
description: Secret backend configuration for the RabbitmqCluster. Enables to fetch default user credentials and certificates from K8s external secret stores.
properties:
externalSecret:
description: LocalObjectReference contains enough information to let you locate the referenced object inside the same namespace.
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
vault:
description: VaultSpec will add Vault annotations (see https://www.vaultproject.io/docs/platform/k8s/injector/annotations) to RabbitMQ Pods. It requires a Vault Agent Sidecar Injector (https://www.vaultproject.io/docs/platform/k8s/injector) to be installed in the K8s cluster. The injector is a K8s Mutation Webhook Controller that alters RabbitMQ Pod specifications (based on the added Vault annotations) to include Vault Agent containers that render Vault secrets to the volume.
properties:
Expand Down
14 changes: 11 additions & 3 deletions controllers/reconcile_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ package controllers

import (
"context"
"reflect"

rabbitmqv1beta1 "github.com/rabbitmq/cluster-operator/api/v1beta1"
"github.com/rabbitmq/cluster-operator/internal/resource"
corev1 "k8s.io/api/core/v1"
"reflect"
)

// reconcileStatus sets status.defaultUser (secret and service reference) and status.binding.
Expand Down Expand Up @@ -34,8 +35,15 @@ func (r *RabbitmqClusterReconciler) reconcileStatus(ctx context.Context, rmq *ra
"password": "password",
},
}
binding = &corev1.LocalObjectReference{
Name: rmq.ChildResourceName(resource.DefaultUserSecretName),
if !rmq.ExternalSecretEnabled() {
binding = &corev1.LocalObjectReference{
Name: rmq.ChildResourceName(resource.DefaultUserSecretName),
}
} else {
binding = &corev1.LocalObjectReference{
Name: rmq.Spec.SecretBackend.ExternalSecret.Name,
}

}
}

Expand Down
1 change: 1 addition & 0 deletions docs/api/rabbitmq.com.ref.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ SecretBackend configures a single secret backend. Today, only Vault exists as su
|===
| Field | Description
| *`vault`* __xref:{anchor_prefix}-github-com-rabbitmq-cluster-operator-api-v1beta1-vaultspec[$$VaultSpec$$]__ |
| *`externalSecret`* __link:https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#localobjectreference-v1-core[$$LocalObjectReference$$]__ |
|===


Expand Down
2 changes: 1 addition & 1 deletion internal/resource/rabbitmq_resource_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (builder *RabbitmqResourceBuilder) ResourceBuilders() []ResourceBuilder {
builder.RoleBinding(),
builder.StatefulSet(),
}
if builder.Instance.VaultDefaultUserSecretEnabled() {
if builder.Instance.VaultDefaultUserSecretEnabled() || builder.Instance.ExternalSecretEnabled() {
// do not create default-user K8s Secret
builders = append(builders[:3], builders[3+1:]...)
}
Expand Down
15 changes: 11 additions & 4 deletions internal/resource/statefulset.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,8 +419,10 @@ func (builder *StatefulSetBuilder) podTemplateSpec(previousPodAnnotations map[st
},
}

if !builder.Instance.VaultDefaultUserSecretEnabled() {
appendDefaultUserSecretVolumeProjection(volumes, builder.Instance)
if !builder.Instance.VaultDefaultUserSecretEnabled() && !builder.Instance.ExternalSecretEnabled() {
appendDefaultUserSecretVolumeProjection(volumes, builder.Instance, "")
} else if builder.Instance.ExternalSecretEnabled() {
appendDefaultUserSecretVolumeProjection(volumes, builder.Instance, builder.Instance.Spec.SecretBackend.ExternalSecret.Name)
}

if builder.Instance.Spec.Rabbitmq.AdvancedConfig != "" || builder.Instance.Spec.Rabbitmq.EnvConfig != "" {
Expand Down Expand Up @@ -779,14 +781,19 @@ func setupContainer(instance *rabbitmqv1beta1.RabbitmqCluster) corev1.Container
return setupContainer
}

func appendDefaultUserSecretVolumeProjection(volumes []corev1.Volume, instance *rabbitmqv1beta1.RabbitmqCluster) {
func appendDefaultUserSecretVolumeProjection(volumes []corev1.Volume, instance *rabbitmqv1beta1.RabbitmqCluster, secretName string) {

if secretName == "" {
secretName = instance.ChildResourceName(DefaultUserSecretName)
}

for _, value := range volumes {
if value.Name == "rabbitmq-confd" {
value.VolumeSource.Projected.Sources = append(value.VolumeSource.Projected.Sources,
corev1.VolumeProjection{
Secret: &corev1.SecretProjection{
LocalObjectReference: corev1.LocalObjectReference{
Name: instance.ChildResourceName(DefaultUserSecretName),
Name: secretName,
},
Items: []corev1.KeyToPath{
{
Expand Down
19 changes: 19 additions & 0 deletions internal/resource/statefulset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -869,6 +869,25 @@ var _ = Describe("StatefulSet", func() {
Expect(container.Env).To(ConsistOf(requiredEnvVariables))
})

Context("ExternalSecret", func() {
When("SecretBackend.ExternalSecret is set", func() {
JustBeforeEach(func() {
Expect(stsBuilder.Update(statefulSet)).To(Succeed())
})
BeforeEach(func() {
instance.Spec.SecretBackend.ExternalSecret.Name = "my-secret"
})

It("does not project default user secret to rabbitmq-confd volume", func() {
rabbitmqConfdVolume := extractVolume(statefulSet.Spec.Template.Spec.Volumes, "rabbitmq-confd")
defaultUserSecret := extractProjectedSecret(rabbitmqConfdVolume, "foo-default-user")
Expect(defaultUserSecret.Secret).To(BeNil())
})

})

})

Context("Vault", func() {
BeforeEach(func() {
instance.Spec.SecretBackend.Vault = &rabbitmqv1beta1.VaultSpec{
Expand Down

0 comments on commit 9e50b90

Please sign in to comment.