diff --git a/agent-inject/agent/agent.go b/agent-inject/agent/agent.go index b3b2758b..11e72cc7 100644 --- a/agent-inject/agent/agent.go +++ b/agent-inject/agent/agent.go @@ -123,6 +123,10 @@ type Agent struct { // SetSecurityContext controls whether the injected containers have a // SecurityContext set. SetSecurityContext bool + + // ExtraSecret is the Kubernetes secret to mount as a volume in the Vault agent container + // which can be referenced by the Agent config for secrets. Mounted at /vault/custom/ + ExtraSecret string } type Secret struct { @@ -228,6 +232,7 @@ func New(pod *corev1.Pod, patches []*jsonpatch.JsonPatchOperation) (*Agent, erro ServiceAccountName: saName, ServiceAccountPath: saPath, Status: pod.Annotations[AnnotationAgentStatus], + ExtraSecret: pod.Annotations[AnnotationAgentExtraSecret], Vault: Vault{ Address: pod.Annotations[AnnotationVaultService], AuthPath: pod.Annotations[AnnotationVaultAuthPath], @@ -375,6 +380,14 @@ func (a *Agent) Patch() ([]byte, error) { "/spec/volumes")...) } + // Add ExtraSecret if one was provided + if a.ExtraSecret != "" { + a.Patches = append(a.Patches, addVolumes( + a.Pod.Spec.Volumes, + []corev1.Volume{a.ContainerExtraSecretVolume()}, + "/spec/volumes")...) + } + // Add TLS Secret if one was provided if a.Vault.TLSSecret != "" { a.Patches = append(a.Patches, addVolumes( diff --git a/agent-inject/agent/annotations.go b/agent-inject/agent/annotations.go index 93dac90e..d510e3fc 100644 --- a/agent-inject/agent/annotations.go +++ b/agent-inject/agent/annotations.go @@ -81,6 +81,10 @@ const ( // configuration file and templates can be found. AnnotationAgentConfigMap = "vault.hashicorp.com/agent-configmap" + // AnnotationAgentExtraSecret is the name of a Kubernetes secret that will be mounted + // into the Vault agent container so that the agent config can reference secrets. + AnnotationAgentExtraSecret = "vault.hashicorp.com/agent-extra-secret" + // AnnotationAgentLimitsCPU sets the CPU limit on the Vault Agent containers. AnnotationAgentLimitsCPU = "vault.hashicorp.com/agent-limits-cpu" diff --git a/agent-inject/agent/container_init_sidecar.go b/agent-inject/agent/container_init_sidecar.go index c68fdec6..ca5c4ff9 100644 --- a/agent-inject/agent/container_init_sidecar.go +++ b/agent-inject/agent/container_init_sidecar.go @@ -26,6 +26,14 @@ func (a *Agent) ContainerInitSidecar() (corev1.Container, error) { } volumeMounts = append(volumeMounts, a.ContainerVolumeMounts()...) + if a.ExtraSecret != "" { + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: extraSecretVolumeName, + MountPath: extraSecretVolumePath, + ReadOnly: true, + }) + } + arg := DefaultContainerArg if a.ConfigMapName != "" { diff --git a/agent-inject/agent/container_sidecar.go b/agent-inject/agent/container_sidecar.go index 119ea080..f03a55eb 100644 --- a/agent-inject/agent/container_sidecar.go +++ b/agent-inject/agent/container_sidecar.go @@ -37,6 +37,14 @@ func (a *Agent) ContainerSidecar() (corev1.Container, error) { } volumeMounts = append(volumeMounts, a.ContainerVolumeMounts()...) + if a.ExtraSecret != "" { + volumeMounts = append(volumeMounts, corev1.VolumeMount{ + Name: extraSecretVolumeName, + MountPath: extraSecretVolumePath, + ReadOnly: true, + }) + } + arg := DefaultContainerArg if a.ConfigMapName != "" { diff --git a/agent-inject/agent/container_sidecar_test.go b/agent-inject/agent/container_sidecar_test.go index a12984f1..7e700ae2 100644 --- a/agent-inject/agent/container_sidecar_test.go +++ b/agent-inject/agent/container_sidecar_test.go @@ -28,6 +28,9 @@ func TestContainerSidecarVolume(t *testing.T) { AnnotationVaultSecretVolumePath: "/etc/default_path", fmt.Sprintf("%s-%s", AnnotationAgentInjectSecret, "secret3"): "secret/secret3", + + // Test adding an extra secret from Kube secrets for reference by Agent config + fmt.Sprintf("%s", AnnotationAgentExtraSecret): "extrasecret", } pod := testPod(annotations) @@ -46,7 +49,7 @@ func TestContainerSidecarVolume(t *testing.T) { container, err := agent.ContainerSidecar() // One token volume mount, one config volume mount and two secrets volume mounts - require.Equal(t, 4, len(container.VolumeMounts)) + require.Equal(t, 5, len(container.VolumeMounts)) require.Equal( t, @@ -71,6 +74,11 @@ func TestContainerSidecarVolume(t *testing.T) { MountPath: "/etc/container_environment", ReadOnly: false, }, + corev1.VolumeMount{ + Name: extraSecretVolumeName, + MountPath: extraSecretVolumePath, + ReadOnly: true, + }, }, container.VolumeMounts, ) diff --git a/agent-inject/agent/container_volume.go b/agent-inject/agent/container_volume.go index 95565f50..a40be94d 100644 --- a/agent-inject/agent/container_volume.go +++ b/agent-inject/agent/container_volume.go @@ -17,6 +17,8 @@ const ( tlsSecretVolumeName = "vault-tls-secrets" tlsSecretVolumePath = "/vault/tls" secretVolumePath = "/vault/secrets" + extraSecretVolumeName = "extra-secrets" + extraSecretVolumePath = "/vault/custom" ) func (a *Agent) getUniqueMountPaths() []string { @@ -104,6 +106,19 @@ func (a *Agent) ContainerConfigMapVolume() corev1.Volume { } } +// ContainerExtraSecretVolume returns a volume to mount a Kube secret +// if the user supplied one. +func (a *Agent) ContainerExtraSecretVolume() corev1.Volume { + return corev1.Volume{ + Name: extraSecretVolumeName, + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: a.ExtraSecret, + }, + }, + } +} + // ContainerTLSSecretVolume returns a volume to mount TLS secrets // if the user supplied any. func (a *Agent) ContainerTLSSecretVolume() corev1.Volume {