Kubernetes
The Bitwarden Secrets Manager Kubernetes Operator (sm-operator) is a tool for teams to integrate
Bitwarden Secrets Manager into their Kubernetes workflows seamlessly.
The sm-operator uses a controller to synchronize Bitwarden Secrets into Kubernetes secrets. It does so by registering a Custom Resource Definition of BitwardenSecret into the cluster. It will listen for new BitwardenSecrets registered on the cluster and then synchronize on a configurable interval.
Requirements
- Visual Studio Code
- Visual Studio Code Go Extension
- Go version 1.21
- musl-gcc
- Make
- kubectl
- Docker or Podman or another container engine
- A Kind Cluster or other Kubernetes cluster with Kubectl pointed to it as the current context for local development.
You will also need:
- A Bitwarden organization with Secrets Manager. You will need the organization ID GUID for your organization.
- An access token for a Secrets Manager machine account (previously known as service account) tied to the projects you want to pull.
Setup and configuration
Clone the repository:
git clone https://github.com/bitwarden/sm-kubernetes.gitOpen Visual Studio Code at the repository root.
Dev Container setup is automated. This will create a Kind cluster and setup all necessary software.
- Open the command palette (using
Cmd/Ctrl+Shift+PorF1depending on user settings) - Start typing
Dev Containers: Reopen in Container
- Install all requirements listed in the Direct Setup requirements
- Create a Kind cluster using
kind create cluster - Run
make setupto create a default .env file.
Configuration settings
A .env file will be created in the repository root once the Dev Container is created or
make setup has been run. The following environment variable settings can be updated to change the
behavior of the operator:
- BW_API_URL - Sets the Bitwarden API URL that the Secrets Manager SDK uses. This is useful for self-host scenarios, as well as hitting European servers.
- BW_IDENTITY_API_URL - Sets the Bitwarden Identity service URL that the Secrets Manager SDK uses. This is useful for self-host scenarios, as well as hitting European servers.
- BW_SECRETS_MANAGER_STATE_PATH - Sets the base path where Secrets Manager SDK stores its state files.
- BW_SECRETS_MANAGER_REFRESH_INTERVAL - Specifies the refresh interval in seconds for syncing secrets between Secrets Manager and K8s secrets. The minimum value is 180.
Running and debugging
-
Install the Custom Resource Definition into the cluster using
make installor by using the Visual Studio Task called “apply-crd” from the “Tasks: Run Task” in the command palette. -
To debug the code, just hit F5. You can also use
make runat the command line to run without debugging.
Uninstall Custom Resource Definition
To delete the CRDs from the cluster:
make uninstallCreate a BitwardenSecret to test
With the debugger running, we now will create a BitwardenSecret object to synchronize Secret Manager secrets into a K8s secret:
- Create a secret to house the Secrets Manager authentication token in the namespace where you will
be creating your BitwardenSecret object:
kubectl create secret generic bw-auth-token -n <some-namespace> --from-literal=token="<Auth-Token-Here>"
-
Install an instance of BitwardenSecret. An example can be found in config/samples/k8s_v1_bitwardensecret.yaml. You will want to copy this example and update it for your own needs. Then apply it like so:
kubectl apply -n <some-namespace> -f k8s_v1_bitwardensecret.yaml -
In the Debug Console window, you should see messages stating that the secret started and completed synchronization.
-
Run the following to view if the secret was created:
kubectl get secrets -n <some-namespace> -
Run the following to view the structure and data of the synchronized secret:
kubectl get secret -n <some-namespace> <secret-name> -o yaml
BitwardenSecret manifest
Think of the BitwardenSecret object as the synchronization settings that will be used by the operator to create and synchronize a Kubernetes secret. This Kubernetes secret will live inside of a namespace and will be injected with the data available to a Secrets Manager machine account (previously known as service account). The resulting Kubernetes secret will include all secrets that a specific machine account has access to. The sample file (config/samples/k8s_v1_bitwardensecret.yaml) provides the basic structure of a BitwardenSecret manifest. The key settings that you will want to update are listed below:
- metadata.name: The name of the BitwardenSecret object you are deploying
- spec.organizationId: The Bitwarden organization ID you are pulling Secrets Manager data from
- spec.secretName: The name of the Kubernetes secret that will be created and injected with Secrets Manager data.
- spec.authToken: The name of a secret inside of the Kubernetes namespace that the BitwardenSecrets object is being deployed into that contains the Secrets Manager machine account authorization token being used to access secrets.
Secrets Manager does not guarantee unique secret names across projects, so by default secrets will be created with the Secrets Manager secret UUID used as the key. To make your generated secret easier to use, you can create a map of Bitwarden Secret IDs to Kubernetes secret keys. The generated secret will replace the Bitwarden Secret IDs with the mapped friendly name you provide. Below are the map settings available:
- bwSecretId: This is the UUID of the secret in Secrets Manager. This can found under the secret name in the Secrets Manager web portal or by using the Bitwarden Secrets Manager CLI.
- secretKeyName: The resulting key inside the Kubernetes secret that replaces the UUID
Note that the custom mapping is made available on the generated secret for informational purposes in
the k8s.bitwarden.com/custom-map annotation.
Testing the Docker image
Kind on Windows has a difficult time pulling from a local registry, so we have provided two different routes for deploying the image.
-
Build and push your image to a registry location (local or otherwise) specified by
IMG:make docker-build docker-push IMG={some-registry}/sm-operator:tag -
Deploy the controller to the cluster with the image specified by
IMG:make deploy IMG={some-registry}/sm-operator:tag
-
Build and push your image directly to Kind by using the Visual Studio Code Command Palette. Open the palette (F1) and select Tasks: Run Task and select “docker-build” followed by “kind-push”.
-
Deploy the Kubernetes objects to Kind by using the Visual Studio Code Command Palette. Open the palette (F1) and select Tasks: Run Task and select “deploy”.
After install, create your K8s authorization token secret and a BitwardenSecret as described earlier in this document to test.
Viewing pod logs
To view the logs of an operator deployed via the steps above:
-
Run
kubectl get pods -n sm-operator-system. This will retrieve the name of the installed operator pod. -
Run
kubectl logs -n sm-operator-system <name-of-pod-from-previous-step>
Undeploy controller
To remove the controller pod installed to the cluster, run:
make undeployUnit testing
Unit tests are currently found in the following files:
-
internal/controller/suite_test.go
-
cmd/suite_test.go
To run the unit tests, run make test. To debug the unit tests, open the file you would like to
debug. In the Run and Debug tab in Visual Studio Code, change the launch configuration from
“Debug” to “Test current file”, and then press F5.
Modifying the API definitions
If you are editing the API definitions via api/v1/bitwardensecret_types.go, re-generate the manifests using:
make manifestsMore information can be found via the Kubebuilder Documentation