Skip to content
This repository has been archived by the owner on Dec 19, 2023. It is now read-only.
/ keyvault2kube Public archive

Simple container to copy keyvault secrets to kube

License

Notifications You must be signed in to change notification settings

terricain/keyvault2kube

Repository files navigation

CI status Docker Pulls Docker Image Size (latest by date) Docker Image Version (latest semver)

Copies secrets from KeyVault into Kubernetes

Deployment

Flux Deployment

Deployment via Flux can be achieved with a kustomization similar to the below.

bases:
- github.com/terrycain/keyvault2kube/deploy?ref=2.1.0

patches:
  - target:
      kind: Deployment
    patch: |-
      - op: replace
        path: /spec/template/spec/containers/0/env
        value:
          - name: KEY_VAULT_URLS
            value: https://bink-uksouth-dev-inf.vault.azure.net/
  - target:
      kind: AzureIdentity
    patch: |-
      - op: replace
        path: /spec/resourceID
        value: /subscriptions/abc123ab-abc1-def2-ghi3-abc123ab1231/resourceGroups/foogroup/providers/Microsoft.ManagedIdentity/userAssignedIdentities/bar
  - target:
      kind: AzureIdentity
    patch: |-
      - op: replace
        path: /spec/clientID
        value: a4e207e6-9d04-4a47-937d-a2bc32a18c00

Manual Deployment

Ideally the container should get KeyVault credentials from a managed service identity using something like the aad-pod-identity project but it will also respect the env vars of AZURE_CLIENT_ID, AZURE_CLIENT_SECRET and AZURE_TENANT_ID.

To configure which KeyVaults to scan, an env var of KEY_VAULT_URLS with a comma separated list of Key Vault URL's is all thats needed.

Deployment: Download https://raw.githubusercontent.com/terrycain/keyvault2kube/master/deployment.yaml, replace the keyvault env var, aad-pod-identity resource and client id's, then apply.

Example deployment.yaml mounting a config map to be used as a template (this example is missing the RBAC roles so check deployment.yaml for those):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: keyvault2kube
  namespace: kube-system
  labels:
    app: keyvault2kube
spec:
  replicas: 1
  selector:
    matchLabels:
      app: keyvault2kube
  template:
    metadata:
      labels:
        app: keyvault2kube
    spec:
      containers:
        - name: keyvault2kube
          image: terrycain/keyvault2kube:latest
          volumeMounts:
            - name: config-volume
              mountPath: /app/templates/
      volumes:
        - name: config-volume
          configMap:
            name: keyvault2kube-template
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: keyvault2kube-template
  namespace: kube-system
data:
  template1.yaml: |
    test1: "hello {{data}}"
    test2: "{{data2}} world"

Secret Configuration

Keyvault Secret tags control how and what secrets are copied into keyvault:

k8s_secret_name | required | Name of the secret in Kubernetes 
k8s_secret_key  | optional | Name of the key to store the value against. If the secret content type is not `application/json` or `text/x-yaml` then this is required
k8s_namespaces  | optional | Comma separated list of namespaces to apply the secret to, otherwise default is used
k8s_type        | optional | Either Opaque or `kubernetes.io/dockerconfigjson`
k8s_convert     | optional | Look below

If the k8s_secret_name is applied to multiple KeyVault secrets and the k8s_namespaces are the same and the k8s_secret_key tags are different, the secret will be combined into 1 Kubernetes secret with multiple keys.

k8s_namespaces can either be a list of comma separated namespaces or *

If a content type is applied to the secret and is application/json or text/x-yaml, the value will be decoded and used as the content for the secret. E.g. if a secret contained {"a": "1", "b": "2"} then the Kubernetes secret would have 2 keys, "a" and "b".

If k8s_convert is added to a secret with a value of dockerconfigjson, a content type of application/json, and a json value with the fields "registry", "email", "username", "password" are provided then it'll convert that json into the dockerconfigjson format and secret type.

If k8s_convert has a value like file:/app/templates/template1.yaml (must end with .yaml), the secret value is a json document and has a content type of application/json, then the yaml file will be read in, will be templated with Jinja2 which should result in valid YAML, and then the yaml document is loaded and used as the secret data. E.g. a secret value of {"data": "world", "data2": "hello"}

test1: "hello {{data}}"
test2: "{{data2}} world"

would result in:

data:
  test1: hello world
  test2: hello world