diff --git a/CHANGELOG.md b/CHANGELOG.md index ad3fc13b..ff14abd8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## Unreleased +Improvements: +* Add `NAMESPACE`, `HOST_IP`, and `POD_IP` environment variables to Agent container using downward API [GH-486](https://github.com/hashicorp/vault-k8s/pull/486) + Changes: * Dependency updates: * `github.com/cenkalti/backoff/v4` v4.2.0 -> v4.2.1 diff --git a/agent-inject/agent/container_env.go b/agent-inject/agent/container_env.go index 761da34c..7498bec2 100644 --- a/agent-inject/agent/container_env.go +++ b/agent-inject/agent/container_env.go @@ -10,10 +10,37 @@ import ( corev1 "k8s.io/api/core/v1" ) +var baseContainerEnvVars []corev1.EnvVar = []corev1.EnvVar{ + corev1.EnvVar{ + Name: "NAMESPACE", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "metadata.namespace", + }, + }, + }, + corev1.EnvVar{ + Name: "HOST_IP", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.hostIP", + }, + }, + }, + corev1.EnvVar{ + Name: "POD_IP", + ValueFrom: &corev1.EnvVarSource{ + FieldRef: &corev1.ObjectFieldSelector{ + FieldPath: "status.podIP", + }, + }, + }, +} + // ContainerEnvVars adds the applicable environment vars // for the Vault Agent sidecar. func (a *Agent) ContainerEnvVars(init bool) ([]corev1.EnvVar, error) { - var envs []corev1.EnvVar + envs := baseContainerEnvVars if a.Vault.GoMaxProcs != "" { envs = append(envs, corev1.EnvVar{ diff --git a/agent-inject/agent/container_env_test.go b/agent-inject/agent/container_env_test.go index e0e1dd19..bbb521eb 100644 --- a/agent-inject/agent/container_env_test.go +++ b/agent-inject/agent/container_env_test.go @@ -11,19 +11,21 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) +var baseEnvVars = []string{"NAMESPACE", "HOST_IP", "POD_IP"} + func TestContainerEnvs(t *testing.T) { tests := []struct { agent Agent expectedEnvs []string }{ - {Agent{}, []string{"VAULT_CONFIG"}}, - {Agent{Vault: Vault{Address: "http://localhost:8200"}, ConfigMapName: "foobar"}, []string{"VAULT_SKIP_VERIFY", "VAULT_ADDR"}}, - {Agent{Vault: Vault{ClientMaxRetries: "0"}}, []string{"VAULT_CONFIG", "VAULT_MAX_RETRIES"}}, - {Agent{Vault: Vault{ClientTimeout: "5s"}}, []string{"VAULT_CONFIG", "VAULT_CLIENT_TIMEOUT"}}, - {Agent{Vault: Vault{ClientMaxRetries: "0", ClientTimeout: "5s"}}, []string{"VAULT_CONFIG", "VAULT_MAX_RETRIES", "VAULT_CLIENT_TIMEOUT"}}, - {Agent{ConfigMapName: "foobar", Vault: Vault{Address: "http://localhost:8200", ClientMaxRetries: "0", ClientTimeout: "5s", LogLevel: "info", ProxyAddress: "http://proxy:3128"}}, []string{"VAULT_MAX_RETRIES", "VAULT_CLIENT_TIMEOUT", "VAULT_LOG_LEVEL", "HTTPS_PROXY", "VAULT_SKIP_VERIFY", "VAULT_ADDR"}}, - {Agent{Vault: Vault{GoMaxProcs: "1"}}, []string{"VAULT_CONFIG", "GOMAXPROCS"}}, + {Agent{}, append(baseEnvVars, "VAULT_CONFIG")}, + {Agent{Vault: Vault{Address: "http://localhost:8200"}, ConfigMapName: "foobar"}, append(baseEnvVars, "VAULT_SKIP_VERIFY", "VAULT_ADDR")}, + {Agent{Vault: Vault{ClientMaxRetries: "0"}}, append(baseEnvVars, "VAULT_CONFIG", "VAULT_MAX_RETRIES")}, + {Agent{Vault: Vault{ClientTimeout: "5s"}}, append(baseEnvVars, "VAULT_CONFIG", "VAULT_CLIENT_TIMEOUT")}, + {Agent{Vault: Vault{ClientMaxRetries: "0", ClientTimeout: "5s"}}, append(baseEnvVars, "VAULT_CONFIG", "VAULT_MAX_RETRIES", "VAULT_CLIENT_TIMEOUT")}, + {Agent{ConfigMapName: "foobar", Vault: Vault{Address: "http://localhost:8200", ClientMaxRetries: "0", ClientTimeout: "5s", LogLevel: "info", ProxyAddress: "http://proxy:3128"}}, append(baseEnvVars, "VAULT_MAX_RETRIES", "VAULT_CLIENT_TIMEOUT", "VAULT_LOG_LEVEL", "HTTPS_PROXY", "VAULT_SKIP_VERIFY", "VAULT_ADDR")}, + {Agent{Vault: Vault{GoMaxProcs: "1"}}, append(baseEnvVars, "VAULT_CONFIG", "GOMAXPROCS")}, } for _, tt := range tests { @@ -48,9 +50,9 @@ func TestContainerEnvsForIRSA(t *testing.T) { agent Agent expectedEnvs []string }{ - {Agent{Pod: testPodWithoutIRSA()}, []string{"VAULT_CONFIG"}}, + {Agent{Pod: testPodWithoutIRSA()}, append(baseEnvVars, "VAULT_CONFIG")}, {Agent{Pod: testPodWithIRSA(), Vault: Vault{AuthType: "aws"}}, - []string{"VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_DEFAULT_REGION", "AWS_REGION"}, + append(baseEnvVars, "VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_DEFAULT_REGION", "AWS_REGION"), }, } for _, tt := range envTests { @@ -70,10 +72,10 @@ func TestAwsRegionEnvForAwsAuthMethod(t *testing.T) { expectedEnvs []string }{ {Agent{Pod: testPodWithRegionInAuthConfig(), Vault: Vault{AuthType: "aws", AuthConfig: getRegionMap()}}, - []string{"VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_REGION"}, + append(baseEnvVars, "VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_REGION"), }, {Agent{Pod: testPodWithIRSA(), Vault: Vault{AuthType: "aws"}}, - []string{"VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_DEFAULT_REGION", "AWS_REGION"}, + append(baseEnvVars, "VAULT_CONFIG", "AWS_ROLE_ARN", "AWS_WEB_IDENTITY_TOKEN_FILE", "AWS_DEFAULT_REGION", "AWS_REGION"), }, } for _, item := range input { diff --git a/agent-inject/agent/container_sidecar_test.go b/agent-inject/agent/container_sidecar_test.go index 22f8e137..de9801b7 100644 --- a/agent-inject/agent/container_sidecar_test.go +++ b/agent-inject/agent/container_sidecar_test.go @@ -248,36 +248,36 @@ func TestContainerSidecar(t *testing.T) { t.Errorf("creating container sidecar failed, it shouldn't have: %s", err) } - expectedEnvs := 4 + expectedEnvs := 7 if len(container.Env) != expectedEnvs { t.Errorf("wrong number of env vars, got %d, should have been %d", len(container.Env), expectedEnvs) } - if container.Env[0].Name != "VAULT_LOG_LEVEL" { + if container.Env[3].Name != "VAULT_LOG_LEVEL" { t.Errorf("env name wrong, should have been %s, got %s", "VAULT_LOG_LEVEL", container.Env[0].Name) } - if container.Env[0].Value == "" { + if container.Env[3].Value == "" { t.Error("env value empty, it shouldn't be") } - if container.Env[1].Name != "VAULT_LOG_FORMAT" { + if container.Env[4].Name != "VAULT_LOG_FORMAT" { t.Errorf("env name wrong, should have been %s, got %s", "VAULT_LOG_FORMAT", container.Env[1].Name) } - if container.Env[2].Name != "HTTPS_PROXY" { + if container.Env[5].Name != "HTTPS_PROXY" { t.Errorf("env name wrong, should have been %s, got %s", "HTTPS_PROXY", container.Env[2].Name) } - if container.Env[1].Value == "" { + if container.Env[4].Value == "" { t.Error("env value empty, it shouldn't be") } - if container.Env[3].Name != "VAULT_CONFIG" { + if container.Env[6].Name != "VAULT_CONFIG" { t.Errorf("env name wrong, should have been %s, got %s", "VAULT_CONFIG", container.Env[3].Name) } - if container.Env[2].Value == "" { + if container.Env[5].Value == "" { t.Error("env value empty, it shouldn't be") } @@ -454,7 +454,7 @@ func TestContainerSidecarConfigMap(t *testing.T) { t.Errorf("creating container sidecar failed, it shouldn't have: %s", err) } - expectedEnvs := 9 + expectedEnvs := 12 if len(container.Env) != expectedEnvs { t.Errorf("wrong number of env vars, got %d, should have been %d", len(container.Env), expectedEnvs) } @@ -1285,11 +1285,12 @@ func TestAgentJsonPatch(t *testing.T) { Image: "foobar-image", Command: []string{"/bin/sh", "-ec"}, Args: []string{`echo ${VAULT_CONFIG?} | base64 -d > /home/vault/config.json && vault agent -config=/home/vault/config.json`}, - Env: []v1.EnvVar{ - {Name: "VAULT_LOG_LEVEL", Value: "info"}, - {Name: "VAULT_LOG_FORMAT", Value: "standard"}, - {Name: "VAULT_CONFIG", Value: "eyJhdXRvX2F1dGgiOnsibWV0aG9kIjp7InR5cGUiOiJrdWJlcm5ldGVzIiwibW91bnRfcGF0aCI6InRlc3QiLCJjb25maWciOnsicm9sZSI6InJvbGUiLCJ0b2tlbl9wYXRoIjoic2VydmljZWFjY291bnQvc29tZXdoZXJlL3Rva2VuIn19LCJzaW5rIjpbeyJ0eXBlIjoiZmlsZSIsImNvbmZpZyI6eyJwYXRoIjoiL2hvbWUvdmF1bHQvLnZhdWx0LXRva2VuIn19XX0sImV4aXRfYWZ0ZXJfYXV0aCI6ZmFsc2UsInBpZF9maWxlIjoiL2hvbWUvdmF1bHQvLnBpZCIsInZhdWx0Ijp7ImFkZHJlc3MiOiJodHRwOi8vZm9vYmFyOjEyMzQifSwidGVtcGxhdGVfY29uZmlnIjp7ImV4aXRfb25fcmV0cnlfZmFpbHVyZSI6dHJ1ZX19"}, - }, + Env: append( + baseContainerEnvVars, + corev1.EnvVar{Name: "VAULT_LOG_LEVEL", Value: "info"}, + corev1.EnvVar{Name: "VAULT_LOG_FORMAT", Value: "standard"}, + corev1.EnvVar{Name: "VAULT_CONFIG", Value: "eyJhdXRvX2F1dGgiOnsibWV0aG9kIjp7InR5cGUiOiJrdWJlcm5ldGVzIiwibW91bnRfcGF0aCI6InRlc3QiLCJjb25maWciOnsicm9sZSI6InJvbGUiLCJ0b2tlbl9wYXRoIjoic2VydmljZWFjY291bnQvc29tZXdoZXJlL3Rva2VuIn19LCJzaW5rIjpbeyJ0eXBlIjoiZmlsZSIsImNvbmZpZyI6eyJwYXRoIjoiL2hvbWUvdmF1bHQvLnZhdWx0LXRva2VuIn19XX0sImV4aXRfYWZ0ZXJfYXV0aCI6ZmFsc2UsInBpZF9maWxlIjoiL2hvbWUvdmF1bHQvLnBpZCIsInZhdWx0Ijp7ImFkZHJlc3MiOiJodHRwOi8vZm9vYmFyOjEyMzQifSwidGVtcGxhdGVfY29uZmlnIjp7ImV4aXRfb25fcmV0cnlfZmFpbHVyZSI6dHJ1ZX19"}, + ), Resources: v1.ResourceRequirements{ Limits: v1.ResourceList{"cpu": resource.MustParse("500m"), "memory": resource.MustParse("128Mi")}, Requests: v1.ResourceList{"cpu": resource.MustParse("250m"), "memory": resource.MustParse("64Mi")}, @@ -1320,11 +1321,12 @@ func TestAgentJsonPatch(t *testing.T) { baseInitContainer := baseContainer baseInitContainer.Name = "vault-agent-init" - baseInitContainer.Env = []v1.EnvVar{ - {Name: "VAULT_LOG_LEVEL", Value: "info"}, - {Name: "VAULT_LOG_FORMAT", Value: "standard"}, - {Name: "VAULT_CONFIG", Value: "eyJhdXRvX2F1dGgiOnsibWV0aG9kIjp7InR5cGUiOiJrdWJlcm5ldGVzIiwibW91bnRfcGF0aCI6InRlc3QiLCJjb25maWciOnsicm9sZSI6InJvbGUiLCJ0b2tlbl9wYXRoIjoic2VydmljZWFjY291bnQvc29tZXdoZXJlL3Rva2VuIn19LCJzaW5rIjpbeyJ0eXBlIjoiZmlsZSIsImNvbmZpZyI6eyJwYXRoIjoiL2hvbWUvdmF1bHQvLnZhdWx0LXRva2VuIn19XX0sImV4aXRfYWZ0ZXJfYXV0aCI6dHJ1ZSwicGlkX2ZpbGUiOiIvaG9tZS92YXVsdC8ucGlkIiwidmF1bHQiOnsiYWRkcmVzcyI6Imh0dHA6Ly9mb29iYXI6MTIzNCJ9LCJ0ZW1wbGF0ZV9jb25maWciOnsiZXhpdF9vbl9yZXRyeV9mYWlsdXJlIjp0cnVlfX0="}, - } + baseInitContainer.Env = append( + baseContainerEnvVars, + corev1.EnvVar{Name: "VAULT_LOG_LEVEL", Value: "info"}, + corev1.EnvVar{Name: "VAULT_LOG_FORMAT", Value: "standard"}, + corev1.EnvVar{Name: "VAULT_CONFIG", Value: "eyJhdXRvX2F1dGgiOnsibWV0aG9kIjp7InR5cGUiOiJrdWJlcm5ldGVzIiwibW91bnRfcGF0aCI6InRlc3QiLCJjb25maWciOnsicm9sZSI6InJvbGUiLCJ0b2tlbl9wYXRoIjoic2VydmljZWFjY291bnQvc29tZXdoZXJlL3Rva2VuIn19LCJzaW5rIjpbeyJ0eXBlIjoiZmlsZSIsImNvbmZpZyI6eyJwYXRoIjoiL2hvbWUvdmF1bHQvLnZhdWx0LXRva2VuIn19XX0sImV4aXRfYWZ0ZXJfYXV0aCI6dHJ1ZSwicGlkX2ZpbGUiOiIvaG9tZS92YXVsdC8ucGlkIiwidmF1bHQiOnsiYWRkcmVzcyI6Imh0dHA6Ly9mb29iYXI6MTIzNCJ9LCJ0ZW1wbGF0ZV9jb25maWciOnsiZXhpdF9vbl9yZXRyeV9mYWlsdXJlIjp0cnVlfX0="}, + ) baseInitContainer.VolumeMounts = []v1.VolumeMount{ {Name: "home-init", MountPath: "/home/vault"}, {Name: "foobar", ReadOnly: true, MountPath: "serviceaccount/somewhere"},