diff --git a/e2e/main_test.go b/e2e/main_test.go index 3d2648d..fbc9035 100644 --- a/e2e/main_test.go +++ b/e2e/main_test.go @@ -102,8 +102,8 @@ func TestMain(m *testing.M) { testenv.Setup(installVaultOperator) testenv.Finish(uninstallVaultOperator, envfuncs.DeleteNamespace("vault-operator")) - testenv.Setup(envfuncs.CreateNamespace("secrets-webhook"), installVaultSecretsWebhook) - testenv.Finish(uninstallVaultSecretsWebhook, envfuncs.DeleteNamespace("secrets-webhook")) + testenv.Setup(envfuncs.CreateNamespace("secrets-webhook"), installSecretsWebhook) + testenv.Finish(uninstallSecretsWebhook, envfuncs.DeleteNamespace("secrets-webhook")) // Set up test namespace // ns := envconf.RandomName("webhook-test", 16) @@ -158,7 +158,7 @@ func uninstallVaultOperator(ctx context.Context, cfg *envconf.Config) (context.C return ctx, nil } -func installVaultSecretsWebhook(ctx context.Context, cfg *envconf.Config) (context.Context, error) { +func installSecretsWebhook(ctx context.Context, cfg *envconf.Config) (context.Context, error) { manager := helm.New(cfg.KubeconfigFile()) version := "latest" @@ -186,7 +186,7 @@ func installVaultSecretsWebhook(ctx context.Context, cfg *envconf.Config) (conte return ctx, nil } -func uninstallVaultSecretsWebhook(ctx context.Context, cfg *envconf.Config) (context.Context, error) { +func uninstallSecretsWebhook(ctx context.Context, cfg *envconf.Config) (context.Context, error) { manager := helm.New(cfg.KubeconfigFile()) err := manager.RunUninstall( diff --git a/e2e/test/configmap.yaml b/e2e/test/configmap.yaml index 28a176a..d6d3382 100644 --- a/e2e/test/configmap.yaml +++ b/e2e/test/configmap.yaml @@ -3,7 +3,7 @@ kind: ConfigMap metadata: name: test-configmap annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" vault.security.banzaicloud.io/vault-addr: "https://vault.default.svc.cluster.local:8200" vault.security.banzaicloud.io/vault-role: "default" vault.security.banzaicloud.io/vault-tls-secret: vault-tls diff --git a/e2e/test/deployment-init-seccontext.yaml b/e2e/test/deployment-init-seccontext.yaml index aaee8f9..8246c0e 100644 --- a/e2e/test/deployment-init-seccontext.yaml +++ b/e2e/test/deployment-init-seccontext.yaml @@ -12,7 +12,7 @@ spec: labels: app.kubernetes.io/name: test-deployment-init-seccontext annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" secrets-webhook.security.banzaicloud.io/run-as-non-root: "true" secrets-webhook.security.banzaicloud.io/run-as-user: "1000" secrets-webhook.security.banzaicloud.io/run-as-group: "1000" diff --git a/e2e/test/deployment-seccontext.yaml b/e2e/test/deployment-seccontext.yaml index 33cb078..8dad319 100644 --- a/e2e/test/deployment-seccontext.yaml +++ b/e2e/test/deployment-seccontext.yaml @@ -12,7 +12,7 @@ spec: labels: app.kubernetes.io/name: test-deployment-seccontext annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" vault.security.banzaicloud.io/vault-addr: "https://vault.default.svc.cluster.local:8200" vault.security.banzaicloud.io/vault-role: "default" vault.security.banzaicloud.io/vault-tls-secret: vault-tls diff --git a/e2e/test/deployment-template.yaml b/e2e/test/deployment-template.yaml index 1f790da..0a5a22a 100644 --- a/e2e/test/deployment-template.yaml +++ b/e2e/test/deployment-template.yaml @@ -53,7 +53,7 @@ spec: labels: app.kubernetes.io/name: test-deployment-template annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" vault.security.banzaicloud.io/vault-addr: "https://vault:8200" # optional, the address of the Vault service, default values is https://vault:8200 vault.security.banzaicloud.io/vault-role: "default" # optional, the default value is the name of the ServiceAccount the Pod runs in, in case of Secrets and ConfigMaps it is "default" vault.security.banzaicloud.io/vault-skip-verify: "false" # optional, skip TLS verification of the Vault server certificate diff --git a/e2e/test/deployment.yaml b/e2e/test/deployment.yaml index 2b2a5f9..e8095c0 100644 --- a/e2e/test/deployment.yaml +++ b/e2e/test/deployment.yaml @@ -12,7 +12,7 @@ spec: labels: app.kubernetes.io/name: test-deployment annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" vault.security.banzaicloud.io/vault-addr: "https://vault.default.svc.cluster.local:8200" vault.security.banzaicloud.io/vault-role: "default" vault.security.banzaicloud.io/vault-tls-secret: vault-tls diff --git a/e2e/test/secret.yaml b/e2e/test/secret.yaml index 8131456..7c879b9 100644 --- a/e2e/test/secret.yaml +++ b/e2e/test/secret.yaml @@ -3,7 +3,7 @@ kind: Secret metadata: name: test-secret annotations: - secrets-webhook.security.banzaicloud.io/providers: "vault" + secrets-webhook.security.banzaicloud.io/provider: "vault" vault.security.banzaicloud.io/vault-addr: "https://vault.default.svc.cluster.local:8200" vault.security.banzaicloud.io/vault-role: "default" vault.security.banzaicloud.io/vault-tls-secret: vault-tls diff --git a/pkg/common/common.go b/pkg/common/common.go index 2a1ac7c..d6e9f44 100644 --- a/pkg/common/common.go +++ b/pkg/common/common.go @@ -31,7 +31,7 @@ const ( RegistrySkipVerifyAnnotation = "secrets-webhook.security.banzaicloud.io/registry-skip-verify" MutateAnnotation = "secrets-webhook.security.banzaicloud.io/mutate" MutateProbesAnnotation = "secrets-webhook.security.banzaicloud.io/mutate-probes" - ProvidersAnnotation = "secrets-webhook.security.banzaicloud.io/providers" + ProviderAnnotation = "secrets-webhook.security.banzaicloud.io/provider" // Secret-init annotations SecretInitDaemonAnnotation = "secrets-webhook.security.banzaicloud.io/secret-init-daemon" diff --git a/pkg/common/config.go b/pkg/common/config.go index 6aaa7a2..35c90d1 100644 --- a/pkg/common/config.go +++ b/pkg/common/config.go @@ -16,7 +16,6 @@ package common import ( "strconv" - "strings" "time" "github.com/spf13/viper" @@ -35,7 +34,7 @@ type Config struct { RegistrySkipVerify bool Mutate bool MutateProbes bool - Providers []string + Provider string } // SecretInitConfig represents the configuration for the secret-init container @@ -90,8 +89,8 @@ func ParseWebhookConfig(obj metav1.Object) Config { Config.MutateProbes, _ = strconv.ParseBool(val) } - if val, ok := annotations[ProvidersAnnotation]; ok { - Config.Providers = strings.Split(val, ",") + if val, ok := annotations[ProviderAnnotation]; ok { + Config.Provider = val } return Config diff --git a/pkg/webhook/configmap.go b/pkg/webhook/configmap.go index fdf3389..2f564bf 100644 --- a/pkg/webhook/configmap.go +++ b/pkg/webhook/configmap.go @@ -33,27 +33,25 @@ func (mw *MutatingWebhook) MutateConfigMap(configMap *corev1.ConfigMap) error { return nil } - for _, config := range mw.providerConfigs { - switch providerConfig := config.(type) { - case vault.Config: - currentlyUsedProvider = vault.ProviderName + switch providerConfig := mw.providerConfig.(type) { + case vault.Config: + currentlyUsedProvider = vault.ProviderName - err := mw.mutateConfigMapForVault(configMap, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } + err := mw.mutateConfigMapForVault(configMap, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") + } - case bao.Config: - currentlyUsedProvider = bao.ProviderName + case bao.Config: + currentlyUsedProvider = bao.ProviderName - err := mw.mutateConfigMapForBao(configMap, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } - - default: - return errors.Errorf("unknown provider config type: %T", config) + err := mw.mutateConfigMapForBao(configMap, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") } + + default: + return errors.Errorf("unknown provider config type: %T", mw.providerConfig) } return nil diff --git a/pkg/webhook/configmap_test.go b/pkg/webhook/configmap_test.go index a6dad2e..2d2c819 100644 --- a/pkg/webhook/configmap_test.go +++ b/pkg/webhook/configmap_test.go @@ -63,9 +63,9 @@ func TestMutateConfigMap_Vault(t *testing.T) { admissionReview := &model.AdmissionReview{} - providerConfigs, err := parseProviderConfigs(&configMap, admissionReview, []string{vaultprov.ProviderName}) + providerConfig, err := parseProviderConfig(&configMap, admissionReview, vaultprov.ProviderName) assert.NoError(t, err) - mw.providerConfigs = providerConfigs + mw.providerConfig = providerConfig err = mw.MutateConfigMap(&configMap) assert.NoError(t, err) diff --git a/pkg/webhook/object.go b/pkg/webhook/object.go index f21a9ea..5bb23e9 100644 --- a/pkg/webhook/object.go +++ b/pkg/webhook/object.go @@ -84,27 +84,25 @@ func sliceIterator(s []interface{}) iterator { func (mw *MutatingWebhook) MutateObject(object *unstructured.Unstructured) error { mw.logger.Debug(fmt.Sprintf("mutating object: %s.%s", object.GetNamespace(), object.GetName())) - for _, config := range mw.providerConfigs { - switch providerConfig := config.(type) { - case vault.Config: - currentlyUsedProvider = vault.ProviderName + switch providerConfig := mw.providerConfig.(type) { + case vault.Config: + currentlyUsedProvider = vault.ProviderName - err := mw.mutateObjectForVault(object, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } - - case bao.Config: - currentlyUsedProvider = bao.ProviderName + err := mw.mutateObjectForVault(object, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") + } - err := mw.mutateObjectForBao(object, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } + case bao.Config: + currentlyUsedProvider = bao.ProviderName - default: - return errors.Errorf("unknown provider config type: %T", config) + err := mw.mutateObjectForBao(object, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") } + + default: + return errors.Errorf("unknown provider config type: %T", mw.providerConfig) } return nil diff --git a/pkg/webhook/pod.go b/pkg/webhook/pod.go index 101d5ff..8a601c2 100644 --- a/pkg/webhook/pod.go +++ b/pkg/webhook/pod.go @@ -38,27 +38,25 @@ const SecretInitVolumeName = "secret-init" func (mw *MutatingWebhook) MutatePod(ctx context.Context, pod *corev1.Pod, webhookConfig common.Config, secretInitConfig common.SecretInitConfig, dryRun bool) error { mw.logger.Debug("Successfully connected to the API") - for _, config := range mw.providerConfigs { - switch providerConfig := config.(type) { - case vault.Config: - currentlyUsedProvider = vault.ProviderName - - err := mw.mutatePodForVault(ctx, pod, webhookConfig, secretInitConfig, providerConfig, dryRun) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } + switch providerConfig := mw.providerConfig.(type) { + case vault.Config: + currentlyUsedProvider = vault.ProviderName - case bao.Config: - currentlyUsedProvider = bao.ProviderName + err := mw.mutatePodForVault(ctx, pod, webhookConfig, secretInitConfig, providerConfig, dryRun) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") + } - err := mw.mutatePodForBao(ctx, pod, webhookConfig, secretInitConfig, providerConfig, dryRun) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } + case bao.Config: + currentlyUsedProvider = bao.ProviderName - default: - return errors.Errorf("unknown provider config type: %T", config) + err := mw.mutatePodForBao(ctx, pod, webhookConfig, secretInitConfig, providerConfig, dryRun) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") } + + default: + return errors.Errorf("unknown provider config type: %T", mw.providerConfig) } return nil @@ -74,6 +72,45 @@ func isPodAlreadyMutated(pod *corev1.Pod) bool { return false } +func isSecretInitAlreadyMounted(podSpec *corev1.PodSpec) bool { + if podSpec == nil { + return false + } + + for _, volume := range podSpec.Volumes { + if volume.Name == SecretInitVolumeName { + return true + } + } + + return false +} + +func isSecretInitContainerExists(containers []corev1.Container) bool { + for _, container := range containers { + if container.Name == "copy-secret-init" { + return true + } + } + return false +} + +func areProbesAlreadyMutated(container *corev1.Container) bool { + if container.LivenessProbe != nil && container.LivenessProbe.Exec != nil { + if len(container.LivenessProbe.Exec.Command) > 0 && container.LivenessProbe.Exec.Command[0] == "/bank-vaults/secret-init" { + return true + } + } + + if container.ReadinessProbe != nil && container.ReadinessProbe.Exec != nil { + if len(container.ReadinessProbe.Exec.Command) > 0 && container.ReadinessProbe.Exec.Command[0] == "/bank-vaults/secret-init" { + return true + } + } + + return false +} + func (mw *MutatingWebhook) mutateContainers(ctx context.Context, containers []corev1.Container, podSpec *corev1.PodSpec, webhookConfig common.Config, secretInitConfig common.SecretInitConfig, config interface{}, objectNamespace string, fromPath string) (bool, error) { mutated := false @@ -131,61 +168,66 @@ func (mw *MutatingWebhook) mutateContainers(ctx context.Context, containers []co args = append(args, container.Args...) - container.Command = []string{"/bank-vaults/secret-init"} - container.Args = args - // mutate probes if needed - if webhookConfig.MutateProbes { - // mutate LivenessProbe - if container.LivenessProbe != nil && container.LivenessProbe.Exec != nil { - lProbeCmd := container.LivenessProbe.Exec.Command - container.LivenessProbe.Exec.Command = []string{"/bank-vaults/secret-init"} - container.LivenessProbe.Exec.Command = append(container.LivenessProbe.Exec.Command, lProbeCmd...) - } + if !areProbesAlreadyMutated(&container) { + if webhookConfig.MutateProbes { + // mutate LivenessProbe + if container.LivenessProbe != nil && container.LivenessProbe.Exec != nil { + lProbeCmd := container.LivenessProbe.Exec.Command + container.LivenessProbe.Exec.Command = []string{"/bank-vaults/secret-init"} + container.LivenessProbe.Exec.Command = append(container.LivenessProbe.Exec.Command, lProbeCmd...) + } - // mutate LivenessProbe - if container.ReadinessProbe != nil && container.ReadinessProbe.Exec != nil { - rProbeCmd := container.ReadinessProbe.Exec.Command - container.ReadinessProbe.Exec.Command = []string{"/bank-vaults/secret-init"} - container.ReadinessProbe.Exec.Command = append(container.ReadinessProbe.Exec.Command, rProbeCmd...) + // mutate LivenessProbe + if container.ReadinessProbe != nil && container.ReadinessProbe.Exec != nil { + rProbeCmd := container.ReadinessProbe.Exec.Command + container.ReadinessProbe.Exec.Command = []string{"/bank-vaults/secret-init"} + container.ReadinessProbe.Exec.Command = append(container.ReadinessProbe.Exec.Command, rProbeCmd...) + } } - } - - container.VolumeMounts = append(container.VolumeMounts, []corev1.VolumeMount{ - { - Name: SecretInitVolumeName, - MountPath: "/bank-vaults/", - }, - }...) - - if secretInitConfig.Daemon { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "SECRET_INIT_DAEMON", - Value: "true", - }) - } - if secretInitConfig.Delay > 0 { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "SECRET_INIT_DELAY", - Value: secretInitConfig.Delay.String(), - }) } - if secretInitConfig.LogServer != "" { - container.Env = append(container.Env, corev1.EnvVar{ - Name: "SECRET_INIT_LOG_SERVER", - Value: secretInitConfig.LogServer, - }) - } + if !isSecretInitAlreadyMounted(podSpec) { + container.Command = []string{"/bank-vaults/secret-init"} + container.Args = args - if !isLogLevelSet(container.Env) && secretInitConfig.LogLevel != "" { - container.Env = append(container.Env, []corev1.EnvVar{ + container.VolumeMounts = append(container.VolumeMounts, []corev1.VolumeMount{ { - Name: "SECRET_INIT_LOG_LEVEL", - Value: secretInitConfig.LogLevel, + Name: SecretInitVolumeName, + MountPath: "/bank-vaults/", }, }...) + + if secretInitConfig.Daemon { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "SECRET_INIT_DAEMON", + Value: "true", + }) + } + + if secretInitConfig.Delay > 0 { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "SECRET_INIT_DELAY", + Value: secretInitConfig.Delay.String(), + }) + } + + if secretInitConfig.LogServer != "" { + container.Env = append(container.Env, corev1.EnvVar{ + Name: "SECRET_INIT_LOG_SERVER", + Value: secretInitConfig.LogServer, + }) + } + + if !isLogLevelSet(container.Env) && secretInitConfig.LogLevel != "" { + container.Env = append(container.Env, []corev1.EnvVar{ + { + Name: "SECRET_INIT_LOG_LEVEL", + Value: secretInitConfig.LogLevel, + }, + }...) + } } mw.setEnvVarsForProvider(&container, podSpec, secretInitConfig, config) @@ -463,7 +505,7 @@ func (mw *MutatingWebhook) addSecretsVolToContainers(containers []corev1.Contain container.VolumeMounts = append(container.VolumeMounts, []corev1.VolumeMount{ { - Name: "ct-secrets", + Name: "ct-secrets-" + currentlyUsedProvider, MountPath: configFilePath, }, }...) @@ -472,13 +514,39 @@ func (mw *MutatingWebhook) addSecretsVolToContainers(containers []corev1.Contain } } +func createCopySecretInitContainer(secretInitConfig common.SecretInitConfig, podSecurityContext *corev1.PodSecurityContext, webhookConfig common.Config) corev1.Container { + return corev1.Container{ + Name: "copy-secret-init", + Image: secretInitConfig.Image, + ImagePullPolicy: secretInitConfig.ImagePullPolicy, + Command: []string{"sh", "-c", "cp /usr/local/bin/secret-init /bank-vaults/"}, + VolumeMounts: []corev1.VolumeMount{ + { + Name: SecretInitVolumeName, + MountPath: "/bank-vaults/", + }, + }, + SecurityContext: getBaseSecurityContext(podSecurityContext, webhookConfig), + Resources: corev1.ResourceRequirements{ + Limits: corev1.ResourceList{ + corev1.ResourceCPU: secretInitConfig.CPULimit, + corev1.ResourceMemory: secretInitConfig.MemoryLimit, + }, + Requests: corev1.ResourceList{ + corev1.ResourceCPU: secretInitConfig.CPURequest, + corev1.ResourceMemory: secretInitConfig.MemoryRequest, + }, + }, + } +} + func (mw *MutatingWebhook) addAgentSecretsVolToContainers(containers []corev1.Container, configFilePath string) { for i, container := range containers { mw.logger.Debug(fmt.Sprintf("Add secrets VolumeMount to container %s", container.Name)) container.VolumeMounts = append(container.VolumeMounts, []corev1.VolumeMount{ { - Name: "agent-secrets", + Name: "agent-secrets-" + currentlyUsedProvider, MountPath: configFilePath, }, }...) @@ -583,12 +651,16 @@ func (mw *MutatingWebhook) mutatePodForVault(ctx context.Context, pod *corev1.Po }) } - containerVolMounts := []corev1.VolumeMount{ - { - Name: SecretInitVolumeName, - MountPath: "/bank-vaults/", - }, + containerVolMounts := []corev1.VolumeMount{} + if !isSecretInitAlreadyMounted(&pod.Spec) { + containerVolMounts = []corev1.VolumeMount{ + { + Name: SecretInitVolumeName, + MountPath: "/bank-vaults/", + }, + } } + if vaultConfig.TLSSecret != "" { mountPath := "/vault/tls/" volumeName := "vault-tls" @@ -716,13 +788,13 @@ func getContainersForVault(podSecurityContext *corev1.PodSecurityContext, webhoo } containerVolMounts = append(containerVolMounts, corev1.VolumeMount{ - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: vaultConfig.ConfigfilePath, }, corev1.VolumeMount{ Name: SecretInitVolumeName, - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-vault", }, corev1.VolumeMount{ - Name: "ct-configmap", + Name: "ct-configmap-vault", MountPath: "/vault/ct-config/config.hcl", ReadOnly: true, SubPath: "config.hcl", @@ -736,7 +808,7 @@ func getContainersForVault(podSecurityContext *corev1.PodSecurityContext, webhoo } containers = append(containers, corev1.Container{ - Name: "consul-template", + Name: "consul-template-vault", Image: vaultConfig.CtImage, Args: ctCommandString, ImagePullPolicy: vaultConfig.CtImagePullPolicy, @@ -853,31 +925,8 @@ func getInitContainersForVault(originalContainers []corev1.Container, podSecurit }) } - if initContainersMutated || containersMutated { - containers = append(containers, corev1.Container{ - Name: "copy-secret-init", - Image: secretInitConfig.Image, - ImagePullPolicy: secretInitConfig.ImagePullPolicy, - Command: []string{"sh", "-c", "cp /usr/local/bin/secret-init /bank-vaults/"}, - VolumeMounts: []corev1.VolumeMount{ - { - Name: SecretInitVolumeName, - MountPath: "/bank-vaults/", - }, - }, - - SecurityContext: getBaseSecurityContext(podSecurityContext, webhookConfig), - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: secretInitConfig.CPULimit, - corev1.ResourceMemory: secretInitConfig.MemoryLimit, - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: secretInitConfig.CPURequest, - corev1.ResourceMemory: secretInitConfig.MemoryRequest, - }, - }, - }) + if initContainersMutated || containersMutated && !isSecretInitContainerExists(originalContainers) { + containers = append(containers, createCopySecretInitContainer(secretInitConfig, podSecurityContext, webhookConfig)) } return containers @@ -944,7 +993,7 @@ func (mw *MutatingWebhook) getVolumesForVault(existingVolumes []corev1.Volume, a defaultMode := int32(420) volumes = append(volumes, corev1.Volume{ - Name: "ct-secrets", + Name: "ct-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -952,7 +1001,7 @@ func (mw *MutatingWebhook) getVolumesForVault(existingVolumes []corev1.Volume, a }, }, corev1.Volume{ - Name: "ct-configmap", + Name: "ct-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -976,7 +1025,7 @@ func (mw *MutatingWebhook) getVolumesForVault(existingVolumes []corev1.Volume, a defaultMode := int32(420) volumes = append(volumes, corev1.Volume{ - Name: "agent-secrets", + Name: "agent-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -984,7 +1033,7 @@ func (mw *MutatingWebhook) getVolumesForVault(existingVolumes []corev1.Volume, a }, }, corev1.Volume{ - Name: "agent-configmap", + Name: "agent-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1025,10 +1074,10 @@ func getAgentContainersForVault(originalContainers []corev1.Container, podSecuri serviceAccountMount := getServiceAccountMount(originalContainers, vaultConfig.ServiceAccountTokenVolumeName) containerVolMounts = append(containerVolMounts, serviceAccountMount, corev1.VolumeMount{ - Name: "agent-secrets", + Name: "agent-secrets-vault", MountPath: vaultConfig.ConfigfilePath, }, corev1.VolumeMount{ - Name: "agent-configmap", + Name: "agent-configmap-vault", MountPath: "/vault/config/config.hcl", ReadOnly: true, SubPath: "config.hcl", @@ -1121,12 +1170,16 @@ func (mw *MutatingWebhook) mutatePodForBao(ctx context.Context, pod *corev1.Pod, }) } - containerVolMounts := []corev1.VolumeMount{ - { - Name: SecretInitVolumeName, - MountPath: "/bank-vaults/", - }, + containerVolMounts := []corev1.VolumeMount{} + if !isSecretInitAlreadyMounted(&pod.Spec) { + containerVolMounts = []corev1.VolumeMount{ + { + Name: SecretInitVolumeName, + MountPath: "/bank-vaults/", + }, + } } + if baoConfig.TLSSecret != "" { mountPath := "/bao/tls/" volumeName := "bao-tls" @@ -1254,13 +1307,13 @@ func getContainersForBao(podSecurityContext *corev1.PodSecurityContext, webhookC } containerVolMounts = append(containerVolMounts, corev1.VolumeMount{ - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: baoConfig.ConfigfilePath, }, corev1.VolumeMount{ Name: SecretInitVolumeName, - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-bao", }, corev1.VolumeMount{ - Name: "ct-configmap", + Name: "ct-configmap-bao", MountPath: "/bao/ct-config/config.hcl", ReadOnly: true, SubPath: "config.hcl", @@ -1274,7 +1327,7 @@ func getContainersForBao(podSecurityContext *corev1.PodSecurityContext, webhookC } containers = append(containers, corev1.Container{ - Name: "consul-template", + Name: "consul-template-bao", Image: baoConfig.CtImage, Args: ctCommandString, ImagePullPolicy: baoConfig.CtImagePullPolicy, @@ -1391,31 +1444,8 @@ func getInitContainersForBao(originalContainers []corev1.Container, podSecurityC }) } - if initContainersMutated || containersMutated { - containers = append(containers, corev1.Container{ - Name: "copy-secret-init", - Image: secretInitConfig.Image, - ImagePullPolicy: secretInitConfig.ImagePullPolicy, - Command: []string{"sh", "-c", "cp /usr/local/bin/secret-init /bank-vaults/"}, - VolumeMounts: []corev1.VolumeMount{ - { - Name: SecretInitVolumeName, - MountPath: "/bank-vaults/", - }, - }, - - SecurityContext: getBaseSecurityContext(podSecurityContext, webhookConfig), - Resources: corev1.ResourceRequirements{ - Limits: corev1.ResourceList{ - corev1.ResourceCPU: secretInitConfig.CPULimit, - corev1.ResourceMemory: secretInitConfig.MemoryLimit, - }, - Requests: corev1.ResourceList{ - corev1.ResourceCPU: secretInitConfig.CPURequest, - corev1.ResourceMemory: secretInitConfig.MemoryRequest, - }, - }, - }) + if initContainersMutated || containersMutated && !isSecretInitContainerExists(originalContainers) { + containers = append(containers, createCopySecretInitContainer(secretInitConfig, podSecurityContext, webhookConfig)) } return containers @@ -1482,7 +1512,7 @@ func (mw *MutatingWebhook) getVolumesForBao(existingVolumes []corev1.Volume, age defaultMode := int32(420) volumes = append(volumes, corev1.Volume{ - Name: "ct-secrets", + Name: "ct-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -1490,7 +1520,7 @@ func (mw *MutatingWebhook) getVolumesForBao(existingVolumes []corev1.Volume, age }, }, corev1.Volume{ - Name: "ct-configmap", + Name: "ct-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1514,7 +1544,7 @@ func (mw *MutatingWebhook) getVolumesForBao(existingVolumes []corev1.Volume, age defaultMode := int32(420) volumes = append(volumes, corev1.Volume{ - Name: "agent-secrets", + Name: "agent-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -1522,7 +1552,7 @@ func (mw *MutatingWebhook) getVolumesForBao(existingVolumes []corev1.Volume, age }, }, corev1.Volume{ - Name: "agent-configmap", + Name: "agent-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1563,10 +1593,10 @@ func getAgentContainersForBao(originalContainers []corev1.Container, podSecurity serviceAccountMount := getServiceAccountMount(originalContainers, baoConfig.ServiceAccountTokenVolumeName) containerVolMounts = append(containerVolMounts, serviceAccountMount, corev1.VolumeMount{ - Name: "agent-secrets", + Name: "agent-secrets-bao", MountPath: baoConfig.ConfigfilePath, }, corev1.VolumeMount{ - Name: "agent-configmap", + Name: "agent-configmap-bao", MountPath: "/bao/config/config.hcl", ReadOnly: true, SubPath: "config.hcl", diff --git a/pkg/webhook/pod_test.go b/pkg/webhook/pod_test.go index 77ff194..55ffc16 100644 --- a/pkg/webhook/pod_test.go +++ b/pkg/webhook/pod_test.go @@ -77,7 +77,7 @@ func (r *MockRegistry) GetImageConfig(_ context.Context, _ kubernetes.Interface, return &r.Image, nil } -func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { +func Test_mutatingWebhook_mutateContainers(t *testing.T) { vaultConfigEnvFrom := providerConfigs[vault.ProviderName].(vault.Config) vaultConfigEnvFrom.FromPath = "secrets/application" baoConfigEnvFrom := providerConfigs[bao.ProviderName].(bao.Config) @@ -93,7 +93,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { podSpec *corev1.PodSpec webhookConfig common.Config SecretInitConfig common.SecretInitConfig - useConfig []interface{} + useConfig interface{} } tests := []struct { @@ -129,7 +129,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -180,7 +180,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -233,7 +233,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -293,7 +293,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { MutateProbes: true, }, SecretInitConfig: common.SecretInitConfig{}, - useConfig: []interface{}{vault.Config{}}, + useConfig: vault.Config{}, }, wantedContainers: []corev1.Container{ { @@ -353,7 +353,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -397,7 +397,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -434,7 +434,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{vaultConfigEnvFrom}, + useConfig: vaultConfigEnvFrom, }, wantedContainers: []corev1.Container{ { @@ -486,7 +486,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[vault.ProviderName]}, + useConfig: providerConfigs[vault.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -544,17 +544,16 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { JSONLog: "enableJSONLog", LogLevel: "debug", }, - useConfig: []interface{}{ - vault.Config{ - Addr: "addr", - SkipVerify: false, - Path: "path", - Role: "role", - AuthMethod: "jwt", - IgnoreMissingSecrets: "ignoreMissingSecrets", - Passthrough: "vaultPassthrough", - ClientTimeout: 10 * time.Second, - }}, + useConfig: vault.Config{ + Addr: "addr", + SkipVerify: false, + Path: "path", + Role: "role", + AuthMethod: "jwt", + IgnoreMissingSecrets: "ignoreMissingSecrets", + Passthrough: "vaultPassthrough", + ClientTimeout: 10 * time.Second, + }, }, wantedContainers: []corev1.Container{ { @@ -606,7 +605,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -657,7 +656,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -710,7 +709,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -770,7 +769,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { MutateProbes: true, }, SecretInitConfig: common.SecretInitConfig{}, - useConfig: []interface{}{bao.Config{}}, + useConfig: bao.Config{}, }, wantedContainers: []corev1.Container{ { @@ -830,7 +829,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -874,7 +873,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -911,7 +910,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{baoConfigEnvFrom}, + useConfig: baoConfigEnvFrom, }, wantedContainers: []corev1.Container{ { @@ -963,7 +962,7 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { }, webhookConfig: webhookConfig, SecretInitConfig: secretInitConfig, - useConfig: []interface{}{providerConfigs[bao.ProviderName]}, + useConfig: providerConfigs[bao.ProviderName], }, wantedContainers: []corev1.Container{ { @@ -1021,17 +1020,16 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { JSONLog: "enableJSONLog", LogLevel: "debug", }, - useConfig: []interface{}{ - bao.Config{ - Addr: "addr", - SkipVerify: false, - Path: "path", - Role: "role", - AuthMethod: "jwt", - IgnoreMissingSecrets: "ignoreMissingSecrets", - Passthrough: "baoPassthrough", - ClientTimeout: 10 * time.Second, - }}, + useConfig: bao.Config{ + Addr: "addr", + SkipVerify: false, + Path: "path", + Role: "role", + AuthMethod: "jwt", + IgnoreMissingSecrets: "ignoreMissingSecrets", + Passthrough: "baoPassthrough", + ClientTimeout: 10 * time.Second, + }, }, wantedContainers: []corev1.Container{ { @@ -1069,33 +1067,31 @@ func Test_mutatingWebhook_mutateContainers_Vault(t *testing.T) { logger: slog.Default(), } - for _, config := range ttp.args.useConfig { - switch providerConfig := config.(type) { - case vault.Config: - currentlyUsedProvider = vault.ProviderName + switch providerConfig := ttp.args.useConfig.(type) { + case vault.Config: + currentlyUsedProvider = vault.ProviderName - got, err := mw.mutateContainers(context.Background(), ttp.args.containers, ttp.args.podSpec, ttp.args.webhookConfig, ttp.args.SecretInitConfig, providerConfig, providerConfig.ObjectNamespace, providerConfig.FromPath) - if (err != nil) != ttp.wantErr { - t.Errorf("MutatingWebhook.mutateContainers() error = %v, wantErr %v", err, ttp.wantErr) - return - } + got, err := mw.mutateContainers(context.Background(), ttp.args.containers, ttp.args.podSpec, ttp.args.webhookConfig, ttp.args.SecretInitConfig, providerConfig, providerConfig.ObjectNamespace, providerConfig.FromPath) + if (err != nil) != ttp.wantErr { + t.Errorf("MutatingWebhook.mutateContainers() error = %v, wantErr %v", err, ttp.wantErr) + return + } - if got != ttp.mutated { - t.Errorf("MutatingWebhook.mutateContainers() = %v, want %v", got, ttp.mutated) - } + if got != ttp.mutated { + t.Errorf("MutatingWebhook.mutateContainers() = %v, want %v", got, ttp.mutated) + } - case bao.Config: - currentlyUsedProvider = bao.ProviderName + case bao.Config: + currentlyUsedProvider = bao.ProviderName - got, err := mw.mutateContainers(context.Background(), ttp.args.containers, ttp.args.podSpec, ttp.args.webhookConfig, ttp.args.SecretInitConfig, providerConfig, providerConfig.ObjectNamespace, providerConfig.FromPath) - if (err != nil) != ttp.wantErr { - t.Errorf("MutatingWebhook.mutateContainers() error = %v, wantErr %v", err, ttp.wantErr) - return - } + got, err := mw.mutateContainers(context.Background(), ttp.args.containers, ttp.args.podSpec, ttp.args.webhookConfig, ttp.args.SecretInitConfig, providerConfig, providerConfig.ObjectNamespace, providerConfig.FromPath) + if (err != nil) != ttp.wantErr { + t.Errorf("MutatingWebhook.mutateContainers() error = %v, wantErr %v", err, ttp.wantErr) + return + } - if got != ttp.mutated { - t.Errorf("MutatingWebhook.mutateContainers() = %v, want %v", got, ttp.mutated) - } + if got != ttp.mutated { + t.Errorf("MutatingWebhook.mutateContainers() = %v, want %v", got, ttp.mutated) } } @@ -1116,7 +1112,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { pod *corev1.Pod webhookConfig common.Config secretInitConfig common.SecretInitConfig - useConfig []string + useConfig string } defaultMode := int32(420) @@ -1233,7 +1229,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"vault"}, + useConfig: vault.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1294,7 +1290,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, Containers: []corev1.Container{ { - Name: "consul-template", + Name: "consul-template-vault", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/vault/ct-config/config.hcl"}, Resources: corev1.ResourceRequirements{ @@ -1321,15 +1317,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-vault", }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", ReadOnly: true, MountPath: "/vault/ct-config/config.hcl", SubPath: "config.hcl", @@ -1346,7 +1342,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, }, @@ -1372,7 +1368,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -1380,7 +1376,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1452,7 +1448,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"vault"}, + useConfig: vault.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1512,7 +1508,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "consul-template", + Name: "consul-template-vault", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/vault/ct-config/config.hcl", "-once"}, Resources: corev1.ResourceRequirements{ @@ -1539,15 +1535,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-vault", }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", ReadOnly: true, MountPath: "/vault/ct-config/config.hcl", SubPath: "config.hcl", @@ -1566,7 +1562,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, }, @@ -1592,7 +1588,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -1600,7 +1596,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1668,7 +1664,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { RunAsUser: int64(1000), RunAsGroup: int64(1000), }, - useConfig: []string{"vault"}, + useConfig: vault.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1729,11 +1725,11 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "agent-secrets", + Name: "agent-secrets-vault", MountPath: "/vault/secrets", }, { - Name: "agent-configmap", + Name: "agent-configmap-vault", ReadOnly: true, MountPath: "/vault/config/config.hcl", SubPath: "config.hcl", @@ -1750,7 +1746,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "agent-secrets", + Name: "agent-secrets-vault", MountPath: "/vault/secrets", }, }, @@ -1766,7 +1762,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "agent-secrets", + Name: "agent-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -1774,7 +1770,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "agent-configmap", + Name: "agent-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -1860,7 +1856,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"vault"}, + useConfig: vault.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -1921,7 +1917,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "consul-template", + Name: "consul-template-vault", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/vault/ct-config/config.hcl", "-once"}, Resources: corev1.ResourceRequirements{ @@ -1948,15 +1944,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-vault", }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", ReadOnly: true, MountPath: "/vault/ct-config/config.hcl", SubPath: "config.hcl", @@ -1972,7 +1968,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, - {Name: "ct-secrets", MountPath: "/vault/secrets"}, + {Name: "ct-secrets-vault", MountPath: "/vault/secrets"}, }, }, }, @@ -1987,7 +1983,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, }, @@ -2013,7 +2009,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -2021,7 +2017,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -2106,7 +2102,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"vault"}, + useConfig: vault.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2179,7 +2175,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, Containers: []corev1.Container{ { - Name: "consul-template", + Name: "consul-template-vault", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/vault/ct-config/config.hcl"}, Resources: corev1.ResourceRequirements{ @@ -2206,15 +2202,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-vault", }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", ReadOnly: true, MountPath: "/vault/ct-config/config.hcl", SubPath: "config.hcl", @@ -2231,7 +2227,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/vault", }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", MountPath: "/vault/secrets", }, }, @@ -2257,7 +2253,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-vault", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -2265,7 +2261,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-vault", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -2336,7 +2332,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"bao"}, + useConfig: bao.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2397,7 +2393,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, Containers: []corev1.Container{ { - Name: "consul-template", + Name: "consul-template-bao", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/bao/ct-config/config.hcl"}, Resources: corev1.ResourceRequirements{ @@ -2424,15 +2420,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-bao", }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", ReadOnly: true, MountPath: "/bao/ct-config/config.hcl", SubPath: "config.hcl", @@ -2449,7 +2445,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, }, @@ -2475,7 +2471,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -2483,7 +2479,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -2555,7 +2551,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"bao"}, + useConfig: bao.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2615,7 +2611,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "consul-template", + Name: "consul-template-bao", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/bao/ct-config/config.hcl", "-once"}, Resources: corev1.ResourceRequirements{ @@ -2642,15 +2638,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-bao", }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", ReadOnly: true, MountPath: "/bao/ct-config/config.hcl", SubPath: "config.hcl", @@ -2669,7 +2665,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, }, @@ -2695,7 +2691,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -2703,7 +2699,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -2771,7 +2767,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { RunAsUser: int64(1000), RunAsGroup: int64(1000), }, - useConfig: []string{"bao"}, + useConfig: bao.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -2832,11 +2828,11 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "agent-secrets", + Name: "agent-secrets-bao", MountPath: "/bao/secrets", }, { - Name: "agent-configmap", + Name: "agent-configmap-bao", ReadOnly: true, MountPath: "/bao/config/config.hcl", SubPath: "config.hcl", @@ -2853,7 +2849,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "agent-secrets", + Name: "agent-secrets-bao", MountPath: "/bao/secrets", }, }, @@ -2869,7 +2865,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "agent-secrets", + Name: "agent-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -2877,7 +2873,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "agent-configmap", + Name: "agent-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -2963,7 +2959,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"bao"}, + useConfig: bao.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -3024,7 +3020,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "consul-template", + Name: "consul-template-bao", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/bao/ct-config/config.hcl", "-once"}, Resources: corev1.ResourceRequirements{ @@ -3051,15 +3047,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-bao", }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", ReadOnly: true, MountPath: "/bao/ct-config/config.hcl", SubPath: "config.hcl", @@ -3075,7 +3071,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, - {Name: "ct-secrets", MountPath: "/bao/secrets"}, + {Name: "ct-secrets-bao", MountPath: "/bao/secrets"}, }, }, }, @@ -3090,7 +3086,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/kubernetes.io/serviceaccount", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, }, @@ -3116,7 +3112,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -3124,7 +3120,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -3209,7 +3205,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { CPULimit: resource.MustParse("250m"), MemoryLimit: resource.MustParse("64Mi"), }, - useConfig: []string{"bao"}, + useConfig: bao.ProviderName, }, wantedPod: &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ @@ -3282,7 +3278,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, Containers: []corev1.Container{ { - Name: "consul-template", + Name: "consul-template-bao", Image: "hashicorp/consul-template:0.32.0", Args: []string{"-config", "/bao/ct-config/config.hcl"}, Resources: corev1.ResourceRequirements{ @@ -3309,15 +3305,15 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/bank-vaults/", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, { Name: "secret-init", - MountPath: "/home/consul-template", + MountPath: "/home/consul-template-bao", }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", ReadOnly: true, MountPath: "/bao/ct-config/config.hcl", SubPath: "config.hcl", @@ -3334,7 +3330,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { MountPath: "/var/run/secrets/bao", }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", MountPath: "/bao/secrets", }, }, @@ -3360,7 +3356,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-secrets", + Name: "ct-secrets-bao", VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{ Medium: corev1.StorageMediumMemory, @@ -3368,7 +3364,7 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { }, }, { - Name: "ct-configmap", + Name: "ct-configmap-bao", VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ LocalObjectReference: corev1.LocalObjectReference{ @@ -3402,12 +3398,12 @@ func Test_mutatingWebhook_mutatePod(t *testing.T) { admissionReview := &model.AdmissionReview{} - providerConfigs, err := parseProviderConfigs(ttp.args.pod, admissionReview, ttp.args.useConfig) + providerConfig, err := parseProviderConfig(ttp.args.pod, admissionReview, ttp.args.useConfig) if (err != nil) != ttp.wantErr { t.Errorf("parseProviderConfigs() error = %v, wantErr %v", err, ttp.wantErr) return } - mw.providerConfigs = providerConfigs + mw.providerConfig = providerConfig err = mw.MutatePod(context.Background(), ttp.args.pod, ttp.args.webhookConfig, ttp.args.secretInitConfig, false) if (err != nil) != ttp.wantErr { diff --git a/pkg/webhook/secret.go b/pkg/webhook/secret.go index 5ae60f6..6c3535c 100644 --- a/pkg/webhook/secret.go +++ b/pkg/webhook/secret.go @@ -56,27 +56,25 @@ type dockerAuthConfig struct { } func (mw *MutatingWebhook) MutateSecret(secret *corev1.Secret) error { - for _, config := range mw.providerConfigs { - switch providerConfig := config.(type) { - case vault.Config: - currentlyUsedProvider = vault.ProviderName + switch providerConfig := mw.providerConfig.(type) { + case vault.Config: + currentlyUsedProvider = vault.ProviderName - err := mw.mutateSecretForVault(secret, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } + err := mw.mutateSecretForVault(secret, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") + } - case bao.Config: - currentlyUsedProvider = bao.ProviderName + case bao.Config: + currentlyUsedProvider = bao.ProviderName - err := mw.mutateSecretForBao(secret, providerConfig) - if err != nil { - return errors.Wrap(err, "failed to mutate secret") - } - - default: - return errors.Errorf("unknown provider config type: %T", config) + err := mw.mutateSecretForBao(secret, providerConfig) + if err != nil { + return errors.Wrap(err, "failed to mutate secret") } + + default: + return errors.Errorf("unknown provider config type: %T", mw.providerConfig) } return nil diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index 61ef2ea..6a0a745 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -51,26 +51,26 @@ import ( var currentlyUsedProvider string type MutatingWebhook struct { - k8sClient kubernetes.Interface - namespace string - registry ImageRegistry - logger *slog.Logger - providerConfigs []interface{} + k8sClient kubernetes.Interface + namespace string + registry ImageRegistry + logger *slog.Logger + providerConfig interface{} } func (mw *MutatingWebhook) SecretsMutator(ctx context.Context, ar *model.AdmissionReview, obj metav1.Object) (*mutating.MutatorResult, error) { webhookConfig := common.ParseWebhookConfig(obj) secretInitConfig := common.ParseSecretInitConfig(obj) - if webhookConfig.Mutate || len(webhookConfig.Providers) == 0 { + if webhookConfig.Mutate || webhookConfig.Provider == "" { return &mutating.MutatorResult{}, nil } - configs, err := parseProviderConfigs(obj, ar, webhookConfig.Providers) + config, err := parseProviderConfig(obj, ar, webhookConfig.Provider) if err != nil { return nil, fmt.Errorf("failed to parse provider configs: %w", err) } - mw.providerConfigs = configs + mw.providerConfig = config switch v := obj.(type) { case *corev1.Pod: @@ -244,31 +244,28 @@ func ErrorLoggerMutator(mutator mutating.MutatorFunc, logger log.Logger) mutatin } } -// parseProviderConfigs parses all provider configs that was declared in the webhook annotation -func parseProviderConfigs(obj metav1.Object, ar *model.AdmissionReview, providers []string) ([]interface{}, error) { - configs := make([]interface{}, 0, len(providers)) - for _, providerName := range providers { - switch providerName { - case vaultprov.ProviderName: - config, err := vaultprov.ParseConfig(obj, ar) - if err != nil { - return nil, errors.Wrap(err, "failed to parse vault config") - } - configs = append(configs, config) - - case baoprov.ProviderName: - config, err := baoprov.ParseConfig(obj, ar) - if err != nil { - return nil, errors.Wrap(err, "failed to parse bao config") - } - configs = append(configs, config) +// parseProviderConfig parses all provider configs that was declared in the webhook annotation +func parseProviderConfig(obj metav1.Object, ar *model.AdmissionReview, providerName string) (interface{}, error) { + var config interface{} + var err error + switch providerName { + case vaultprov.ProviderName: + config, err = vaultprov.ParseConfig(obj, ar) + if err != nil { + return nil, errors.Wrap(err, "failed to parse vault config") + } - default: - return nil, errors.Errorf("unknown provider: %s", providerName) + case baoprov.ProviderName: + config, err = baoprov.ParseConfig(obj, ar) + if err != nil { + return nil, errors.Wrap(err, "failed to parse bao config") } + + default: + return nil, errors.Errorf("unknown provider: %s", providerName) } - return configs, nil + return config, nil } func hasProviderPrefix(providerName string, value string, withInlineDelimiters bool) bool {