bitwarden-eso-provider

Bitwarden External Secrets Operator Provider Helm Chart

Deploy a Bitwarden Provider for the External Secrets Operator so you can use ExternalSecrets from Bitwarden to create Kubernetes Secrets 🎉 This project is neither directly affiliated with the External Secrets Operator, nor the official Bitwarden®️ at this time.

Usage

For helm, see the README for full details of the allowed values in values.yaml, but, provided you already installed the Externeral secrets operator, this is the gist:

helm repo add bitwarden-eso-provider https://small-hack.github.io/bitwarden-eso-provider

helm install my-release bitwarden-eso-provider/bitwarden-eso-provider \
  --set bitwarden_eso_provider.auth.password=my-secure-bitwarden-password \
  --set bitwarden_eso_provider.auth.clientID=my-bitwarden-clientID \
  --set bitwarden_eso_provider.auth.clientSecret=my-bitwarden-clientSecret

[!Note] kind cant pull the container for some reason so we are using a pre-pull and side-load workaround in our CI steps. Ref: thread.

Disable ClusterSecretStore Deployment

If you don’t want to deploy any ClusterSecretStores, use the following arg to helm:

helm install my-release bitwarden-eso-provider/bitwarden-eso-provider \
  --set bitwarden_eso_provider.create_cluster_secret_store=false

or set it via the values:

bitwarden_eso_provider:
  create_cluster_secret_store: false

Use an existing Secret for Bitwarden credentials

You can pass in credentials plain text to this helm chart, and we’ll create the values as a Kubernetes Secret, but it’s recommended to instead provide an existing Secret so that the values are never plain text anywhere. You can do that by passing in the following in your values.yaml:

bitwarden_eso_provider:
  auth:
    # -- use an existing Kubernetes Secret for bitwarden credentials
    existingSecret: "my-cool-secert"
    # -- Keys in the existing Kubernetes Secret to use for each sensitive value
    secretKeys:
      # -- secret key for Bitwarden password key
      password: "BW_PASSWORD"
      # -- secret key for Bitwarden client Secret to use to grabs secrets in the pod
      clientSecret: "BW_CLIENTSECRET"
      # -- secret key for Bitwarden client ID to use to grabs secrets in the pod
      clientID: "BW_CLIENTID"
      # -- secret key for Bitwarden hostname to use to grab secrets in the pod
      host: "BW_HOST"

Or setting it via the helm cli:

helm install my-release bitwarden-eso-provider/bitwarden-eso-provider --set bitwarden_eso_provider.auth.existingSecret="my-cool-secret"

Example ExternalSecret

By default we will create two ClusterSecretStores for you that can then be accessed when you create a secret like this, but also printed below here:

---
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  # name of the ExternalSecret itself
  name: beatiful-external-secret
  namespace: coolapp4dogs
spec:
  target:
    # name of the secret to create in Kubernetes
    name: beautiful-k8s-secret
    deletionPolicy: Delete
    template:
      type: Opaque
      data:
        # key in the Kubernetes secret to create
        password: |-
          
  data:
    # value to pass to the Kubernetes secret, go-templated as  above
    - secretKey: password
      sourceRef:
        storeRef:
          # Use the bitwarden-login store to get password values from a Bitwarden item
          # does *not* contain custom fields. Use bitwarden-fields for Bitwarden items with custom fields
          name: bitwarden-login
          kind: ClusterSecretStore
      remoteRef:
        # This is the `name` of your Bitwarden item (not the id)
        key: my-beautiful-login-item-in-bitwarden
        # This is the property of the Bitwarden item that we want e.g. password
        property: password

Testing

Searching for items has to be done using JSONpath, you will need to install a utility for that, we use bashtools/JSONPath.sh.

To query the endpoint you will need to deploy a maintenance container into the external-secrets namespace.

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: maintenance
  namespace: external-secrets
  annotations:
    # set to "true" to include in future backups
    k8up.io/backup: "false"
  # Optional:
  #labels:
  #  app: multi-file-writer
spec:
  # Optional:
  storageClassName: local-path
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      # Must be sufficient to hold your data
      storage: 16Gi
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: maintenance
  namespace: external-secrets
  annotations:
    # set to "true" to include in future backups
    k8up.io/backup: "false"
  # Optional:
  #labels:
  #  app: multi-file-writer
spec:
  # Optional:
  storageClassName: local-path
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      # Must be sufficient to hold your data
      storage: 16Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: maintenance
  namespace: external-secrets
spec:
  selector:
    matchLabels:
      app: onboardme
  template:
    metadata:
      labels:
        app: onboardme
    spec:
      restartPolicy: Always
      containers:
        - name: onboardme
          image: jessebot/onboardme:debian12
          command:
            - /bin/sleep
            - 3650d
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80
              name: "http"
            - containerPort: 443
              name: "https"
            - containerPort: 22
              name: "ssh"
            - containerPort: 5900
              name: "vnc"
          volumeMounts:
          - mountPath: /tmp
            name: maintenance
      volumes:
      - name: maintenance
        persistentVolumeClaim:
          claimName: maintenance

Status

Actively maintained mostly by @jessebot and @cloudymax, but we’d love to have your help if you’d like to make improvements (bugs or feature fixes). We mostly test on k3s. Feel free to submit a GitHub issue to this repo (not the Bitwarden repos) if you need help. You’re also welcome to submit PRs to this repo, and we’d love to review them 💙 Star the repo if you find it helpful <3

Acknowledgements

We followed the example over at the ESO docs to create this helm chart :)