Skip to content

Latest commit

 

History

History
170 lines (101 loc) · 11.4 KB

README.md

File metadata and controls

170 lines (101 loc) · 11.4 KB

Bitwarden Secrets Manager Kubernetes Operator

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.***

Description

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.

Getting Started

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.

Pre-requisites

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:

Recommended

Development

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.

How it works

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.

Modifying the API definitions

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

Debugging

  1. 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.

  2. 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

Configuration settings

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:

  • 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.

BitwardenSecret

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:

  • 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.

Creating a BitwardenSecret object

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

Uninstall Custom Resource Definition

To delete the CRDs from the cluster:

make uninstall

Testing the container

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.

Running on Kind cluster

  1. 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".

  2. 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".

  3. 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>"

  4. 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

Alternative: Running on a cluster using a registry

  1. Build and push your image to the registry location specified by IMG: make docker-build docker-push IMG=<some-registry>/sm-operator:tag

  2. Deploy the controller to the cluster with the image specified by IMG: make deploy IMG=<some-registry>/sm-operator:tag

  3. 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>"

  4. 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

Undeploy controller

To "UnDeploy" the controller from the cluster after testing, run:

make undeploy

Unit test

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.