Skip to content

Commit

Permalink
Support vault cacert bytes env for injected containers (#507)
Browse files Browse the repository at this point in the history
  • Loading branch information
tomhjp authored Oct 24, 2023
1 parent d3a0e58 commit 599c50f
Show file tree
Hide file tree
Showing 12 changed files with 93 additions and 16 deletions.
14 changes: 12 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,11 @@ jobs:
- run: pip install yq
shell: bash

# Checkout this repo.
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
path: "vault-k8s"

# Checkout vault-helm for acceptance test code.
- uses: actions/checkout@8ade135a41bc03ea155e62e844d188df1ea18608 # v4.1.0
with:
Expand All @@ -75,7 +80,12 @@ jobs:
docker image load --input vault-k8s-image.docker.tar
kind load docker-image hashicorp/vault-k8s:0.0.0-dev
- name: Makefile tests
working-directory: vault-k8s
run: make deploy exercise teardown

- name: bats tests
working-directory: vault-helm
run: |
yq --in-place --yaml-roundtrip '.injector.image.tag |= "0.0.0-dev"' ./vault-helm/values.yaml
bats ./vault-helm/test/acceptance -t --filter injector
yq --in-place --yaml-roundtrip '.injector.image.tag |= "0.0.0-dev"' ./values.yaml
bats ./test/acceptance -t --filter injector
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@

# Output directory for binaries built in CircleCI
/pkg
/dist/
/dist/
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ Changes:
* `github.com/hashicorp/vault/sdk` v0.9.2 => v0.10.2
* `github.com/prometheus/client_golang` v1.16.0 => v1.17.0

Improvements:
* Injector can set CA certificate for injected pods via `AGENT_INJECT_VAULT_CACERT_BYTES` env var or `-vault-cacert-bytes` flag [GH-507](https://github.com/hashicorp/vault-k8s/pull/507)

## 1.3.0 (August 16, 2023)

Improvements:
Expand Down
22 changes: 12 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,11 @@ PKG=github.com/hashicorp/vault-k8s/version
LDFLAGS?="-X '$(PKG).Version=v$(VERSION)'"
TESTARGS ?= '-test.v'

HELM_CHART_VERSION ?= 0.25.0
VAULT_HELM_CHART_VERSION ?= 0.25.0
VAULT_HELM_FLAGS?=--repo https://helm.releases.hashicorp.com --version=$(VAULT_HELM_CHART_VERSION) \
--wait --timeout=5m \
--values=test/vault/dev.values.yaml \
--set 'injector.image.tag=$(VERSION)'

.PHONY: all test build image clean version deploy exercise teardown
all: build
Expand All @@ -33,16 +37,14 @@ image: build

# Deploys Vault dev server and a locally built Agent Injector.
# Run multiple times to deploy new builds of the injector.
deploy: image
deploy:
kind load docker-image hashicorp/vault-k8s:$(VERSION)
helm upgrade --install vault vault --repo https://helm.releases.hashicorp.com --version=$(HELM_CHART_VERSION) \
--wait --timeout=5m \
--set 'server.dev.enabled=true' \
--set 'server.logLevel=debug' \
--set 'injector.image.tag=$(VERSION)' \
--set 'injector.image.pullPolicy=Never' \
--set 'injector.affinity=null' \
--set 'injector.annotations.deployed=unix-$(shell date +%s)'
helm upgrade --install vault vault $(VAULT_HELM_FLAGS) \
--set "injector.enabled=false"
kubectl delete pod -l "app.kubernetes.io/instance=vault"
kubectl wait --for=condition=Ready --timeout=5m pod -l "app.kubernetes.io/instance=vault"
helm upgrade --install vault vault $(VAULT_HELM_FLAGS) \
--set "injector.extraEnvironmentVars.AGENT_INJECT_VAULT_CACERT_BYTES=$$(kubectl exec vault-0 -- cat /tmp/vault-ca.pem | base64)"

# Populates the Vault dev server with a secret, configures kubernetes auth, and
# deploys an nginx pod with annotations to have the secret injected.
Expand Down
8 changes: 7 additions & 1 deletion agent-inject/agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,9 +249,15 @@ type Vault struct {
AuthConfig map[string]interface{}

// CACert is the name of the Certificate Authority certificate
// to use when validating Vault's server certificates.
// to use when validating Vault's server certificates. It takes
// precedence over CACertBytes.
CACert string

// CACertBytes is the contents of the CA certificate to trust
// for TLS with Vault as a PEM-encoded certificate or bundle.
// Can also be base64 encoded PEM contents.
CACertBytes string

// CAKey is the name of the Certificate Authority key
// to use when validating Vault's server certificates.
CAKey string
Expand Down
16 changes: 16 additions & 0 deletions agent-inject/agent/container_env.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,13 @@ func (a *Agent) ContainerEnvVars(init bool) ([]corev1.EnvVar, error) {
}
}

if a.Vault.CACertBytes != "" {
envs = append(envs, corev1.EnvVar{
Name: "VAULT_CACERT_BYTES",
Value: decodeIfBase64(a.Vault.CACertBytes),
})
}

// Add IRSA AWS Env variables for vault containers
if a.Vault.AuthType == "aws" {
envMap := a.getAwsEnvsFromContainer(a.Pod)
Expand All @@ -160,3 +167,12 @@ func (a *Agent) ContainerEnvVars(init bool) ([]corev1.EnvVar, error) {

return envs, nil
}

func decodeIfBase64(s string) string {
decoded, err := base64.StdEncoding.DecodeString(s)
if err == nil {
return string(decoded)
}

return s
}
2 changes: 1 addition & 1 deletion agent-inject/agent/container_init_sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"encoding/json"
"fmt"

"github.com/evanphx/json-patch"
jsonpatch "github.com/evanphx/json-patch"
corev1 "k8s.io/api/core/v1"
)

Expand Down
2 changes: 2 additions & 0 deletions agent-inject/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ type Handler struct {
// If this is false, injection is default.
RequireAnnotation bool
VaultAddress string
VaultCACertBytes string
VaultAuthType string
VaultAuthPath string
VaultNamespace string
Expand Down Expand Up @@ -226,6 +227,7 @@ func (h *Handler) Mutate(req *admissionv1.AdmissionRequest) *admissionv1.Admissi
err := fmt.Errorf("error creating new agent sidecar: %s", err)
return admissionError(req.UID, err)
}
agentSidecar.Vault.CACertBytes = h.VaultCACertBytes

h.Log.Debug("validating agent configuration..")
err = agentSidecar.Validate()
Expand Down
3 changes: 2 additions & 1 deletion subcommand/injector/command.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ type Command struct {
flagAutoName string // MutatingWebhookConfiguration for updating
flagAutoHosts string // SANs for the auto-generated TLS cert.
flagVaultService string // Name of the Vault service
flagVaultCACertBytes string // CA Cert to trust for TLS with Vault.
flagProxyAddress string // HTTP proxy address used to talk to the Vault service
flagVaultImage string // Name of the Vault Image to use
flagVaultAuthType string // Type of Vault Auth Method to use
Expand Down Expand Up @@ -87,7 +88,6 @@ type Command struct {
cert atomic.Value
}

// TODO Add flag for Vault TLS
func (c *Command) Run(args []string) int {
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
Expand Down Expand Up @@ -194,6 +194,7 @@ func (c *Command) Run(args []string) int {
// Build the HTTP handler and server
injector := agentInject.Handler{
VaultAddress: c.flagVaultService,
VaultCACertBytes: c.flagVaultCACertBytes,
VaultAuthType: c.flagVaultAuthType,
VaultAuthPath: c.flagVaultAuthPath,
VaultNamespace: c.flagVaultNamespace,
Expand Down
12 changes: 12 additions & 0 deletions subcommand/injector/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ type Specification struct {
// VaultAddr is the AGENT_INJECT_VAULT_ADDR environment variable.
VaultAddr string `split_words:"true"`

// VaultCACertBytes is the AGENT_INJECT_VAULT_CACERT_BYTES environment variable.
// Specifies the CA cert to trust for TLS with Vault as a PEM-encoded
// certificate or bundle. The multi-line PEM contents may optionally be base64
// encoded to avoid line breaks.
VaultCACertBytes string `envconfig:"AGENT_INJECT_VAULT_CACERT_BYTES"`

// ProxyAddr is the AGENT_INJECT_PROXY_ADDR environment variable.
ProxyAddr string `split_words:"true"`

Expand Down Expand Up @@ -159,6 +165,9 @@ func (c *Command) init() {
fmt.Sprintf("Docker image for Vault. Defaults to %q.", agent.DefaultVaultImage))
c.flagSet.StringVar(&c.flagVaultService, "vault-address", "",
"Address of the Vault server.")
c.flagSet.StringVar(&c.flagVaultCACertBytes, "vault-cacert-bytes", "",
"CA certificate to trust for TLS with Vault, specified as a PEM-encoded certificate or bundle. "+
"The multi-line PEM contents may optionally be base64 encoded to avoid line breaks.")
c.flagSet.StringVar(&c.flagProxyAddress, "proxy-address", "",
"HTTP proxy address used to talk to the Vault service.")
c.flagSet.StringVar(&c.flagVaultAuthType, "vault-auth-type", agent.DefaultVaultAuthType,
Expand Down Expand Up @@ -295,6 +304,9 @@ func (c *Command) parseEnvs() error {
if envs.VaultAddr != "" {
c.flagVaultService = envs.VaultAddr
}
if envs.VaultCACertBytes != "" {
c.flagVaultCACertBytes = envs.VaultCACertBytes
}

if envs.ProxyAddr != "" {
c.flagProxyAddress = envs.ProxyAddr
Expand Down
1 change: 1 addition & 0 deletions subcommand/injector/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@ func TestCommandEnvs(t *testing.T) {
}{
{env: "AGENT_INJECT_LISTEN", value: ":8080", cmdPtr: &cmd.flagListen},
{env: "AGENT_INJECT_VAULT_ADDR", value: "http://vault:8200", cmdPtr: &cmd.flagVaultService},
{env: "AGENT_INJECT_VAULT_CACERT_BYTES", value: "foo", cmdPtr: &cmd.flagVaultCACertBytes},
{env: "AGENT_INJECT_PROXY_ADDR", value: "http://proxy:3128", cmdPtr: &cmd.flagProxyAddress},
{env: "AGENT_INJECT_VAULT_AUTH_PATH", value: "auth-path-test", cmdPtr: &cmd.flagVaultAuthPath},
{env: "AGENT_INJECT_VAULT_IMAGE", value: "hashicorp/vault:1.14.1", cmdPtr: &cmd.flagVaultImage},
Expand Down
24 changes: 24 additions & 0 deletions test/vault/dev.values.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
global:
tlsDisable: false
injector:
image:
pullPolicy: Never
affinity: null
agentImage:
tag: 1.15.0
server:
image:
tag: 1.15.0
dev:
enabled: true
logLevel: debug
# >- to convert to a single line with no line breaks.
extraArgs: >-
-dev-tls
-dev-tls-cert-dir=/tmp
-dev-tls-san=vault.default.svc.cluster.local
-dev-tls-san=vault.default.svc
-dev-tls-san=vault.default
-dev-tls-san=vault
extraEnvironmentVars:
VAULT_CACERT: /tmp/vault-ca.pem

0 comments on commit 599c50f

Please sign in to comment.