This Operator is a tool for teams to integrate Bitwarden Secrets Manager into their Kubernetes workflows seamlessly.
[!NOTE]
This is a beta release and might be missing some functionality.***
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.
To get started developing, please install the following software. You do not have to install the recommendations, but it is advised for testing.
You will need a Kubernetes cluster to run against. We recommend KIND to get a local cluster for testing, or run against a remote cluster.
Note: Your controller will automatically use the current context in your kubeconfig file (i.e. whatever cluster kubectl cluster-info
shows).
Run make setup
to generate an example .env
file. If you are using the Dev Container, this step has already been completed for you.
A Visual Studio Code Dev Container is provided for development purposes, and handles the setup of all of these pre-requisites. It is strongly recommended that you use the Dev Container, especially on Mac and Windows. The only requirements for the Dev Container are:
You will need to open Visual Studio Code at the repository root to use the Dev Container.
For manual Linux setups:
Open the project in Visual Studio Code. Please develop in the DevContainer provided. Please note that the Visual Studio Code debugger for Go does not work correctly if you open your workspace via a symlink anywhere in the path. For debugging to work, you should open it from the full path of the repository.
This project aims to follow the Kubernetes Operator pattern.
It uses Controllers, which provide a reconcile function responsible for synchronizing resources until the desired state is reached on the cluster. The controller (internal/controller/bitwardensecret_controller.go) is where the main synchronization/reconciliation takes place. The types file (api/v1/bitwardensecret_types.go) specifies the structure of the Custom Resource Definition used throughout the controller, as well as the manifest structure.
The config directory contains the generated manifest definitions for deployment and testing of the operator into Kubernetes.
If you are editing the API definitions via api/v1/bitwardensecret_types.go, re-generate the manifests such as the Custom Resource Definition using:
make manifests
NOTE: Run make --help
for more information on all potential make
targets
More information can be found via the Kubebuilder Documentation
Install the Custom Resource Definition into the cluster using make install
or 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 run
at the command line to run without debugging.
NOTE: You can also run this in one step by running: make install run
A .env
file will be created under this workspace's root directory 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:
Our operator is designed to look for the creation of a custom resource called a BitwardenSecret. 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. The resulting Kubernetes secret will include all secrets that a specific machine account has access to. The sample manifest (config/samples/k8s_v1_bitwardensecret.yaml) gives the basic structure of the BitwardenSecret. The key settings that you will want to update are listed below:
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:
Note that the custom mapping is made available on the generated secret for informational purposes in the k8s.bitwarden.com/custom-map
annotation.
To test the operator, we will create a BitwardenSecret object. But first, we will need to 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>"
Next, create an instance of BitwardenSecret. An example can be found in config/samples/k8s_v1_bitwardensecret.yaml:
kubectl apply -n some-namespace -f config/samples/k8s_v1_bitwardensecret.yaml
To delete the CRDs from the cluster:
make uninstall
The following sections describe how to test the container image itself. Up to this point the operator has been tested outside of the cluster. These next steps will allow us to test the operator running inside of the cluster. Custom configuration of URLs, refresh interval, and state path is handled by updating the environment variables in config/manager/manager.yaml when working with the container.
Build and push your image directly to Kind by using the Visual Studio Code Command Palette. Open the palette 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".
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>"
Create an instances of BitwardenSecret. An example can be found in config/samples/k8s_v1_bitwardensecret.yaml: kubectl apply -n some-namespace -f config/samples/k8s_v1_bitwardensecret.yaml
Build and push your image to the registry location 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
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>"
Create an instance of BitwardenSecret. An example can be found in config/samples/k8s_v1_bitwardensecret.yaml: kubectl apply -n some-namespace -f config/samples/k8s_v1_bitwardensecret.yaml
To "UnDeploy" the controller from the cluster after testing, run:
make undeploy
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
from the root directory of this workspace. To debug the unit tests, click on 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. NOTE: Using the Visual Studio Code "Testing" tab does not currently work due to VS Code not linking the static binaries correctly.