Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Vault proxy mode #13

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
# Changelog for Vault Sidecar Injector

## Release v5.0.0 - 2019-12-06

- [VSI #13](https://github.com/Talend/vault-sidecar-injector/pull/13) - New [Proxy](https://github.com/Talend/vault-sidecar-injector/blob/master/doc/Discovering-Vault-Sidecar-Injector-Proxy.md) mode. Injected Vault Agent sidecar can act as a local proxy forwarding application requests to Vault server.

## Release v4.1.0 - 2019-11-24

- [VSI #12](https://github.com/Talend/vault-sidecar-injector/pull/12) - Image based on CentOS `7.7` and run as non-root, chart available on Helm Hub

## Release v4.0.0 - 2019-11-15

- [VSI #9](https://github.com/Talend/vault-sidecar-injector/pull/9) - Remove Consul Template sidecar and use Vault 1.3.0 new agent template feature to fetch secrets. See announcement [here](doc/Leveraging-Vault-Agent-Template.md).
- [VSI #9](https://github.com/Talend/vault-sidecar-injector/pull/9) - Remove Consul Template sidecar and use Vault 1.3.0 new agent template feature to fetch secrets. See announcement [here](https://github.com/Talend/vault-sidecar-injector/blob/master/doc/Leveraging-Vault-Agent-Template.md).
- [VSI #10](https://github.com/Talend/vault-sidecar-injector/pull/10) - Helm chart is now part of the released artifacts.

## Release v3.0.0 - 2019-10-11
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION:=4.1.0
VERSION:=5.0.0

OWNER:=Talend
REPO:=vault-sidecar-injector
Expand Down
212 changes: 164 additions & 48 deletions README.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions deploy/helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v1
name: vault-sidecar-injector
description: A Helm chart for Talend Vault Sidecar Injector (OSS)
version: 2.1.0
version: 3.0.0
icon: https://www.talend.com/wp-content/uploads/talend-logo.svg
keywords:
- Talend
Expand All @@ -14,4 +14,4 @@ sources:
maintainers:
- name: Talend
email: support@talend.com
appVersion: 4.1.0
appVersion: 5.0.0
36 changes: 28 additions & 8 deletions deploy/helm/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,15 @@ data:
{{`{{ with secret "<APPSVC_VAULT_SECRETS_PATH>" }}{{ range \$k, \$v := .Data }}
{{ \$k }}={{ \$v }}
{{ end }}{{ end }}`}}
proxyconfig.hcl: |
cache {
use_auto_auth_token = true
}

listener "tcp" {
address = "127.0.0.1:<APPSVC_PROXY_PORT>"
tls_disable = true
}
sidecarconfig.yaml: |
{{- if .Values.injectconfig.securityContext }}
securityContext:
Expand Down Expand Up @@ -61,14 +70,15 @@ data:
cntStatus=$(curl -s -X GET -H "Authorization: Bearer $jwt_sa_token" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/$pod_ns/pods/$POD_NAME?pretty=false | jq -c --raw-output '.status.containerStatuses[] | select(.name == "<APP_JOB_CNT_NAME>").state | keys[0]')
if [ $cntStatus = "terminated" ]; then
echo "=> job container terminated: send signal"
touch /home/vault/vault-sidecars-signal-terminate
touch /opt/talend/tvsi/vault-sidecars-signal-terminate
exit 0
fi
sleep 2
done
volumeMounts:
- name: vault-token
mountPath: /home/vault
# Mount path used by injected sidecars to share data
- name: tvsi-shared
mountPath: /opt/talend/tvsi
# The name's value will be overridden by the webhook
- name: K8S_SA_SECRETS_VOL_NAME
mountPath: /var/run/secrets/kubernetes.io/serviceaccount
Expand Down Expand Up @@ -110,6 +120,8 @@ data:
}
}

<APPSVC_PROXY_CONFIG>

<APPSVC_TEMPLATES>
EOF
elif [ $vault_auth_method = "approle" ]; then
Expand All @@ -132,6 +144,8 @@ data:
}
}

<APPSVC_PROXY_CONFIG>

<APPSVC_TEMPLATES>
EOF
else
Expand All @@ -142,7 +156,7 @@ data:
if [ $workload_is_job = "true" ]; then
docker-entrypoint.sh agent -config=vault-agent-config.hcl {{ include "talend-vault-sidecar-injector.vault.cert.skip.verify" .Values }} -log-level={{- .Values.injectconfig.vault.loglevel }} &
while true; do
if [ -f "/home/vault/vault-sidecars-signal-terminate" ]; then
if [ -f "/opt/talend/tvsi/vault-sidecars-signal-terminate" ]; then
echo "=> exit (signal received)"
export VAULT_TOKEN=$(cat /home/vault/.vault-token);
vault token revoke {{ include "talend-vault-sidecar-injector.vault.cert.skip.verify" .Values }} -self;
Expand All @@ -163,9 +177,11 @@ data:
export VAULT_TOKEN=$(cat /home/vault/.vault-token);
vault token revoke {{ include "talend-vault-sidecar-injector.vault.cert.skip.verify" .Values }} -self;
volumeMounts:
- name: vault-token
mountPath: /home/vault
# This volume must be defined in application's manifest (used to share the secrets file(s))
# Mount path used by injected sidecars to share data
- name: tvsi-shared
mountPath: /opt/talend/tvsi
# Mount path used to share secrets. The associated volume is expected to be defined in application's manifest but in case it is not,
# a default 'secrets' volume will be injected in the requesting pod (see definition below) so that mutation process does not fail.
- name: secrets
mountPath: /opt/talend/secrets
# The name's value will be overridden by the webhook to point to container's service account volume to use for Vault authentication.
Expand All @@ -177,6 +193,10 @@ data:
{{ toYaml .Values.injectconfig.vault.resources | indent 10 }}
{{- end }}
volumes:
- name: vault-token
- name: tvsi-shared
emptyDir:
medium: Memory
# Note: if 'secrets' volume is defined in pod's manifest then it will be considered instead of the default definition below
- name: secrets
emptyDir:
medium: Memory
1 change: 1 addition & 0 deletions deploy/helm/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ spec:
- -appLabelKey={{ .Values.mutatingwebhook.annotations.appLabelKey }}
- -appServiceLabelKey={{ .Values.mutatingwebhook.annotations.appServiceLabelKey }}
- -sidecarcfgfile=/opt/talend/webhook/config/sidecarconfig.yaml
- -proxycfgfile=/opt/talend/webhook/config/proxyconfig.hcl
- -tmplblockfile=/opt/talend/webhook/config/templateblock.hcl
- -tmpldefaultfile=/opt/talend/webhook/config/templatedefault.tmpl
- -podlchooksfile=/opt/talend/webhook/config/podlifecyclehooks.yaml
Expand Down
2 changes: 1 addition & 1 deletion deploy/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ revisionHistoryLimit: 3 # revision history limit in tiller / helm / k8s

image:
path: "talend/vault-sidecar-injector" # Docker image path
tag: "4.1.0" # Version/tag of the docker image
tag: "5.0.0" # Version/tag of the docker image
pullPolicy: IfNotPresent # Pull policy for docker images: IfNotPresent or Always
port: 8443 # service main port exposed by the docker image
metricsPort: 9000 # metricsPort defines the port exposed by the docker image for metrics collection
Expand Down
80 changes: 80 additions & 0 deletions deploy/samples/test-app-job-proxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: job-sa
namespace: default
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: job-pod-status
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: job-pod-status
subjects:
- kind: ServiceAccount
name: job-sa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: job-pod-status
---
apiVersion: batch/v1
kind: Job
metadata:
name: test-app-job-proxy
namespace: default
spec:
backoffLimit: 1
template:
metadata:
annotations:
sidecar.vault.talend.org/inject: "true"
sidecar.vault.talend.org/mode: "proxy" # Enable only 'proxy' mode
# Vault Sidecar Injector receive the pod spec: don't know whether it is a job or a deployment. Need annotation below.
sidecar.vault.talend.org/workload: "job"
labels:
com.talend.application: test
spec:
restartPolicy: Never
# custom serviceAccountName with role allowing to perform GET on pods (needed to poll for job's pod status)
serviceAccountName: job-sa
containers:
- name: test-app-job-proxy-container
image: everpeace/curl-jq
command:
- "sh"
- "-c"
- |
set -e
echo "Wait a while to make sure Vault Agent is started and authenticated..."
sleep 10
echo "Job started"
echo "Now using Vault Agent as a proxy to leverage Encryption as a Service feature"
echo "Advantage: you do not need to deal with any Vault tokens and you just have to send requests to the local Vault Agent sidecar (available at 127.0.0.1) that will then forward everything to Vault server."
echo

plaintext="Secret data to protect"
echo "Data that is going to be ciphered and deciphered: $plaintext"
echo
b64Plaintext=$(echo "$plaintext" | base64)

ciphertext=$(curl -s -X POST --data "{\"plaintext\": \"$b64Plaintext\"}" http://127.0.0.1:8200/v1/transit/encrypt/test-key | jq --raw-output .data.ciphertext)
echo "Ciphertext"
echo "=========="
echo "$ciphertext"
echo

cleartext=$(curl -s -X POST --data "{\"ciphertext\": \"$ciphertext\"}" http://127.0.0.1:8200/v1/transit/decrypt/test-key | jq --raw-output .data.plaintext)
echo "Cleartext"
echo "=========="
echo "$cleartext" | base64 -d
echo
echo "Job stopped"
# Note in this sample we do not add 'secrets' volume definition as we only asked for the 'proxy' mode.
94 changes: 94 additions & 0 deletions deploy/samples/test-app-job-secrets-proxy.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
apiVersion: v1
kind: ServiceAccount
metadata:
name: job-sa
namespace: default
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: job-pod-status
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: job-pod-status
subjects:
- kind: ServiceAccount
name: job-sa
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: job-pod-status
---
apiVersion: batch/v1
kind: Job
metadata:
name: test-app-job-secrets-proxy
namespace: default
spec:
backoffLimit: 1
template:
metadata:
annotations:
sidecar.vault.talend.org/inject: "true"
sidecar.vault.talend.org/mode: "secrets,proxy" # Enable both 'secrets' and 'proxy' modes
sidecar.vault.talend.org/proxy-port: "9999" # Override default proxy port value (8200)
# Vault Sidecar Injector receive the pod spec: don't know whether it is a job or a deployment. Need annotation below.
sidecar.vault.talend.org/workload: "job"
labels:
com.talend.application: test
com.talend.service: test-app-svc
spec:
restartPolicy: Never
# custom serviceAccountName with role allowing to perform GET on pods (needed to poll for job's pod status)
serviceAccountName: job-sa
containers:
- name: test-app-job-secrets-proxy-container
image: everpeace/curl-jq
command:
- "sh"
- "-c"
- |
set -e
while true; do
echo "Wait for secrets file before running job..."
if [ -f "/opt/talend/secrets/secrets.properties" ]; then
echo "Secrets available"
break
fi
sleep 2
done
echo "Job started"
echo "Now using Vault Agent as a proxy to leverage Encryption as a Service feature (will encrypt and decrypt our secrets here)"
echo "Advantage: you do not need to deal with any Vault tokens and you just have to send requests to the local Vault Agent sidecar (available at 127.0.0.1) that will then forward everything to Vault server."
echo

plaintext=$(cat /opt/talend/secrets/secrets.properties | grep SECRET1)
echo "Data that is going to be ciphered and deciphered: $plaintext"
echo
b64Plaintext=$(echo "$plaintext" | base64)

ciphertext=$(curl -s -X POST --data "{\"plaintext\": \"$b64Plaintext\"}" http://127.0.0.1:9999/v1/transit/encrypt/test-key | jq --raw-output .data.ciphertext)
echo "Ciphertext"
echo "=========="
echo "$ciphertext"
echo

cleartext=$(curl -s -X POST --data "{\"ciphertext\": \"$ciphertext\"}" http://127.0.0.1:9999/v1/transit/decrypt/test-key | jq --raw-output .data.plaintext)
echo "Cleartext"
echo "=========="
echo "$cleartext" | base64 -d
echo
echo "Job stopped"
volumeMounts:
- name: secrets
mountPath: /opt/talend/secrets
volumes:
- name: secrets
emptyDir:
medium: Memory
2 changes: 1 addition & 1 deletion deploy/samples/test-app-job.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ spec:
while true; do
echo "Wait for secrets file before running job..."
if [ -f "/opt/talend/secrets/secrets.properties" ]; then
echo "secrets available"
echo "Secrets available"
break
fi
sleep 2
Expand Down
16 changes: 15 additions & 1 deletion deploy/vault/init-dev-vault-server.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,14 @@ VAULT_POD="kubectl exec -i vault-0 -- sh -c"
cat vault-server-policy-test.hcl | ${VAULT_POD} "VAULT_TOKEN=root vault policy write test_pol -"
cat vault-server-policy-test2.hcl | ${VAULT_POD} "VAULT_TOKEN=root vault policy write test_pol2 -"

# Enable KV v1 (K/ v2 is enabled with Vault server in dev mode whereas KV v1 is enabled in prod mode: https://www.vaultproject.io/docs/secrets/kv/kv-v2.html#setup)
# Enable KV v1 (KV v2 is enabled with Vault server in dev mode whereas KV v1 is enabled in prod mode: https://www.vaultproject.io/docs/secrets/kv/kv-v2.html#setup)
${VAULT_POD} "VAULT_TOKEN=root vault secrets disable secret/"
${VAULT_POD} "VAULT_TOKEN=root vault secrets enable -version=1 -path=secret kv"

# Enable Transit Secrets Engine and create a test key
${VAULT_POD} "VAULT_TOKEN=root vault secrets enable transit" || true
${VAULT_POD} "VAULT_TOKEN=root vault write -f transit/keys/test-key"

# Enable Vault K8S Auth Method
echo "-> Enable & set up Vault Kubernetes Auth Method"
${VAULT_POD} "VAULT_TOKEN=root vault auth enable kubernetes" || true
Expand All @@ -38,3 +42,13 @@ ${VAULT_POD} "VAULT_TOKEN=root vault write auth/approle/role/test2 secret_id_ttl
# Add some secrets
${VAULT_POD} "VAULT_TOKEN=root vault kv put secret/test/test-app-svc ttl=10s SECRET1=Batman SECRET2=BruceWayne"
${VAULT_POD} "VAULT_TOKEN=root vault kv put secret/test2/test-app2-svc ttl=5s SECRET1=my SECRET2=name SECRET3=is SECRET4=James"

# List Auth Methods and Secrets Engines
echo
echo "Auth Methods"
echo "============"
${VAULT_POD} "VAULT_TOKEN=root vault auth list -detailed"
echo
echo "Secrets Engines"
echo "==============="
${VAULT_POD} "VAULT_TOKEN=root vault secrets list -detailed"
7 changes: 7 additions & 0 deletions deploy/vault/vault-server-policy-test.hcl
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
# To read secrets
path "secret/test/test-app-svc" {
capabilities = ["read"]
}

# To list secrets
path "secret/test/test-app-svc/" {
capabilities = ["list"]
}

# Manage the transit secrets engine
path "transit/*" {
capabilities = [ "create", "read", "update", "delete", "list" ]
}
2 changes: 2 additions & 0 deletions deploy/vault/vault-server-policy-test2.hcl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# To read secrets
path "secret/test2/test-app2-svc" {
capabilities = ["read"]
}

# To list secrets
path "secret/test2/test-app2-svc/" {
capabilities = ["list"]
}
Loading