mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-23 15:41:07 +02:00
419 lines
13 KiB
Plaintext
419 lines
13 KiB
Plaintext
---
|
|
layout: docs
|
|
page_title: Vault Agent Injector examples
|
|
description: Configuration examples of using the Vault Agent Injector.
|
|
---
|
|
|
|
# Vault Agent Injector examples
|
|
|
|
The following are different configuration examples to support a variety of
|
|
deployment models.
|
|
|
|
~> A common mistake is to set the annotation on the Deployment or other resource.
|
|
Ensure that the injector annotations are specified on the pod specification when
|
|
using higher level constructs such as deployments, jobs or statefulsets.
|
|
|
|
## Before using the Vault Agent injector
|
|
|
|
Before applying Vault Agent injection annotations to pods, the following requirements
|
|
should be satisfied.
|
|
|
|
### Connectivity
|
|
|
|
- the Kubernetes API can connect to the Vault Agent injector service on port `443`, and
|
|
the injector can connect to the Kubernetes API,
|
|
- Vault can connect to the Kubernetes API,
|
|
- Pods in the Kubernetes cluster can connect to Vault.
|
|
|
|
~> Note: The Kubernetes API typically runs on the master nodes, and the Vault Agent injector
|
|
on a worker node in a Kubernetes cluster. <br/><br/>
|
|
On Kubernetes clusters that have aggregator routing enabled (ex. [GKE private
|
|
clusters](https://cloud.google.com/kubernetes-engine/docs/how-to/private-clusters#add_firewall_rules)),
|
|
the Kubernetes API will connect directly to the injector service endpoint,
|
|
which is on port `8080`.
|
|
|
|
### Kubernetes and Vault configuration
|
|
|
|
- Kubernetes auth method should be configured and enabled in Vault,
|
|
- Pod should have a service account,
|
|
- desired secrets exist within Vault,
|
|
- the service account should be bound to a Vault role with a policy enabling access to desired secrets.
|
|
|
|
For more information on configuring the Vault Kubernetes auth method,
|
|
[see the official documentation](/vault/docs/auth/kubernetes#configuration).
|
|
|
|
## Debugging
|
|
|
|
If an error occurs with a mutation request, Kubernetes will attach the error to the
|
|
owner of the pod. Check the following for errors:
|
|
|
|
- If the pod was created by a deployment or statefulset, check for errors in the `replicaset`
|
|
that owns the pod.
|
|
- If the pod was created by a job, check the `job` for errors.
|
|
|
|
## Patching existing pods
|
|
|
|
To patch existing pods, a Kubernetes patch can be applied to add the required annotations
|
|
to pods. When applying a patch, the pods will be rescheduled.
|
|
|
|
First, create the patch:
|
|
|
|
```bash
|
|
cat <<EOF >> ./patch.yaml
|
|
spec:
|
|
template:
|
|
metadata:
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: "true"
|
|
vault.hashicorp.com/agent-inject-status: "update"
|
|
vault.hashicorp.com/agent-inject-secret-db-creds: "database/creds/db-app"
|
|
vault.hashicorp.com/agent-inject-template-db-creds: |
|
|
{{- with secret "database/creds/db-app" -}}
|
|
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/appdb?sslmode=disable
|
|
{{- end }}
|
|
vault.hashicorp.com/role: "db-app"
|
|
vault.hashicorp.com/ca-cert: "/vault/tls/ca.crt"
|
|
vault.hashicorp.com/client-cert: "/vault/tls/client.crt"
|
|
vault.hashicorp.com/client-key: "/vault/tls/client.key"
|
|
vault.hashicorp.com/tls-secret: "vault-tls-client"
|
|
EOF
|
|
```
|
|
|
|
Next, apply the patch:
|
|
|
|
```bash
|
|
kubectl patch deployment <MY DEPLOYMENT> --patch "$(cat patch.yaml)"
|
|
```
|
|
|
|
The pod should now be rescheduled with additional containers. The pod can be inspected
|
|
using the `kubectl describe` command:
|
|
|
|
```bash
|
|
kubectl describe pod <name of pod>
|
|
```
|
|
|
|
## Deployments, StatefulSets, etc.
|
|
|
|
The annotations for configuring Vault Agent injection must be on the pod
|
|
specification. Since higher level resources such as Deployments wrap pod
|
|
specification templates, Vault Agent Injector can be used with all of these
|
|
higher level constructs, too.
|
|
|
|
An example Deployment below shows how to enable Vault Agent injection:
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
name: app-example
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: app-example-deployment
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: app-example
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: app-example
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: 'true'
|
|
vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/db-app'
|
|
vault.hashicorp.com/agent-inject-template-db-creds: |
|
|
{{- with secret "database/creds/db-app" -}}
|
|
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/appdb?sslmode=disable
|
|
{{- end }}
|
|
vault.hashicorp.com/role: 'db-app'
|
|
vault.hashicorp.com/ca-cert: '/vault/tls/ca.crt'
|
|
vault.hashicorp.com/client-cert: '/vault/tls/client.crt'
|
|
vault.hashicorp.com/client-key: '/vault/tls/client.key'
|
|
vault.hashicorp.com/tls-secret: 'vault-tls-client'
|
|
spec:
|
|
containers:
|
|
- name: app
|
|
image: 'app:1.0.0'
|
|
serviceAccountName: app-example
|
|
```
|
|
|
|
## ConfigMap example
|
|
|
|
The following example creates a deployment that mounts a Kubernetes ConfigMap
|
|
containing Vault Agent configuration files. For a complete list of the Vault
|
|
Agent configuration settings, [see the Agent documentation](/vault/docs/agent-and-proxy/agent/template#vault-agent-templates).
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: v1
|
|
kind: ServiceAccount
|
|
metadata:
|
|
name: app-example
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: app-example-deployment
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: app-example
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: app-example
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: 'true'
|
|
vault.hashicorp.com/agent-configmap: 'my-configmap'
|
|
vault.hashicorp.com/tls-secret: 'vault-tls-client'
|
|
spec:
|
|
containers:
|
|
- name: app
|
|
image: 'app:1.0.0'
|
|
serviceAccountName: app-example
|
|
---
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: my-configmap
|
|
data:
|
|
config.hcl: |
|
|
"auto_auth" = {
|
|
"method" = {
|
|
"config" = {
|
|
"role" = "db-app"
|
|
}
|
|
"type" = "kubernetes"
|
|
}
|
|
|
|
"sink" = {
|
|
"config" = {
|
|
"path" = "/home/vault/.token"
|
|
}
|
|
|
|
"type" = "file"
|
|
}
|
|
}
|
|
|
|
"exit_after_auth" = false
|
|
"pid_file" = "/home/vault/.pid"
|
|
|
|
"template" = {
|
|
"contents" = "{{- with secret \"database/creds/db-app\" -}}postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable{{- end }}"
|
|
"destination" = "/vault/secrets/db-creds"
|
|
}
|
|
|
|
"vault" = {
|
|
"address" = "https://vault.demo.svc.cluster.local:8200"
|
|
"ca_cert" = "/vault/tls/ca.crt"
|
|
"client_cert" = "/vault/tls/client.crt"
|
|
"client_key" = "/vault/tls/client.key"
|
|
}
|
|
config-init.hcl: |
|
|
"auto_auth" = {
|
|
"method" = {
|
|
"config" = {
|
|
"role" = "db-app"
|
|
}
|
|
"type" = "kubernetes"
|
|
}
|
|
|
|
"sink" = {
|
|
"config" = {
|
|
"path" = "/home/vault/.token"
|
|
}
|
|
|
|
"type" = "file"
|
|
}
|
|
}
|
|
|
|
"exit_after_auth" = true
|
|
"pid_file" = "/home/vault/.pid"
|
|
|
|
"template" = {
|
|
"contents" = "{{- with secret \"database/creds/db-app\" -}}postgres://{{ .Data.username }}:{{ .Data.password }}@postgres:5432/mydb?sslmode=disable{{- end }}"
|
|
"destination" = "/vault/secrets/db-creds"
|
|
}
|
|
|
|
"vault" = {
|
|
"address" = "https://vault.demo.svc.cluster.local:8200"
|
|
"ca_cert" = "/vault/tls/ca.crt"
|
|
"client_cert" = "/vault/tls/client.crt"
|
|
"client_key" = "/vault/tls/client.key"
|
|
}
|
|
```
|
|
|
|
## Environment variable example
|
|
|
|
The following example demonstrates how templates can be used to create environment
|
|
variables. A template should be created that exports a Vault secret as an environment
|
|
variable and the application container should source those files during startup.
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: web-deployment
|
|
labels:
|
|
app: web
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: web
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: web
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: 'true'
|
|
vault.hashicorp.com/role: 'web'
|
|
vault.hashicorp.com/agent-inject-secret-config: 'secret/data/web'
|
|
# Environment variable export template
|
|
vault.hashicorp.com/agent-inject-template-config: |
|
|
{{- with secret "secret/data/web" -}}
|
|
export api_key="{{ .Data.data.payments_api_key }}"
|
|
{{- end }}
|
|
spec:
|
|
serviceAccountName: web
|
|
containers:
|
|
- name: web
|
|
image: alpine:latest
|
|
command:
|
|
['sh', '-c']
|
|
args:
|
|
['source /vault/secrets/config && <entrypoint script>']
|
|
ports:
|
|
- containerPort: 9090
|
|
```
|
|
|
|
## AppRole authentication
|
|
|
|
The following example demonstrates how the AppRole authentication method can be used by
|
|
Vault Agent for retrieving secrets. A Kubernetes secret containing the AppRole secret ID
|
|
and role ID should be created first.
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: web-deployment
|
|
labels:
|
|
app: web
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: web
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: web
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: 'true'
|
|
vault.hashicorp.com/agent-extra-secret: 'approle-example'
|
|
vault.hashicorp.com/auth-type: 'approle'
|
|
vault.hashicorp.com/auth-path: 'auth/approle'
|
|
vault.hashicorp.com/auth-config-role-id-file-path: '/vault/custom/role-id'
|
|
vault.hashicorp.com/auth-config-secret-id-file-path: '/vault/custom/secret-id'
|
|
vault.hashicorp.com/agent-inject-secret-db-creds: 'database/creds/db-app'
|
|
vault.hashicorp.com/agent-inject-template-db-creds: |
|
|
{{- with secret "database/creds/db-app" -}}
|
|
postgres://{{ .Data.username }}:{{ .Data.password }}@postgres.postgres.svc:5432/wizard?sslmode=disable
|
|
{{- end }}
|
|
vault.hashicorp.com/role: 'my-role'
|
|
vault.hashicorp.com/tls-secret: 'vault-tls'
|
|
vault.hashicorp.com/ca-cert: '/vault/tls/ca.crt'
|
|
spec:
|
|
serviceAccountName: web
|
|
containers:
|
|
- name: web
|
|
image: alpine:latest
|
|
args:
|
|
['sh', '-c', 'source /vault/secrets/config && <entrypoint script>']
|
|
ports:
|
|
- containerPort: 9090
|
|
```
|
|
|
|
## PKI cert example
|
|
|
|
The following example demonstrates how to use the [`pkiCert` function][pkiCert] and
|
|
[`writeToFile` function][writeToFile] from consul-template to create two files
|
|
from a template: one for the certificate and CA (`cert.pem`) and one for the key
|
|
(`cert.key`) generated by [Vault's PKI Secrets Engine](/vault/docs/secrets/pki).
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: web-deployment
|
|
labels:
|
|
app: web
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: web
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: web
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: 'true'
|
|
vault.hashicorp.com/role: 'web'
|
|
vault.hashicorp.com/agent-inject-secret-certs: 'pki/issue/cert'
|
|
vault.hashicorp.com/agent-inject-template-certs: |
|
|
{{- with pkiCert "pki/issue/cert" "common_name=test.example.com" "ttl=2h" -}}
|
|
{{ .Cert }}{{ .CA }}{{ .Key }}
|
|
{{ .Key | writeToFile "/vault/secrets/cert.key" "vault" "vault" "0644" }}
|
|
{{ .CA | writeToFile "/vault/secrets/cert.pem" "vault" "vault" "0644" }}
|
|
{{ .Cert | writeToFile "/vault/secrets/cert.pem" "vault" "vault" "0644" "append" }}
|
|
{{- end -}}
|
|
spec:
|
|
serviceAccountName: web
|
|
containers:
|
|
- name: web
|
|
image: nginx
|
|
```
|
|
|
|
[pkiCert]: https://github.com/hashicorp/consul-template/blob/main/docs/templating-language.md#pkicert
|
|
[writeToFile]: https://github.com/hashicorp/consul-template/blob/main/docs/templating-language.md#writeToFile
|
|
|
|
## Cross namespace secret sharing ((#cross-namespace))
|
|
|
|
1. [Configure Vault for secret sharing across namespaces][cross-namespace].
|
|
1. Use the following Pod annotations to authenticate to the Kubernetes method in
|
|
the `us-west-org` namespace and render secrets from the `us-east-org`
|
|
namespace into the file `/vault/secrets/marketing`
|
|
|
|
```yaml
|
|
---
|
|
apiVersion: v1
|
|
kind: Pod
|
|
metadata:
|
|
name: cross-namespace
|
|
namespace: client-nicecorp
|
|
annotations:
|
|
vault.hashicorp.com/agent-inject: "true"
|
|
vault.hashicorp.com/role: "cross-namespace-demo"
|
|
vault.hashicorp.com/auth-path: "us-west-org/auth/kubernetes"
|
|
vault.hashicorp.com/agent-inject-template-marketing: |
|
|
{{- with secret "us-east-org/kv-marketing/campaign" -}}
|
|
{{ range $k, $v := .Data.data }}{{ $k }}: {{ $v }}
|
|
{{ end }}{{- end -}}
|
|
spec:
|
|
serviceAccountName: mega-app
|
|
containers:
|
|
- name: campaign
|
|
image: nginx
|
|
```
|
|
|
|
[cross-namespace]: https://support.hashicorp.com/hc/en-us/articles/27093291534995-How-to-configure-cross-namespace-access-in-Vault-Enterprise
|