Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!--
Thank you for sending a pull request! Here are some tips for contributors:

1. Fill the description template below.
2. Include appropriate tests (if necessary). Make sure that all CI checks passed.
3. If the Pull Request is a work in progress, make use of GitHub's "Draft PR" feature and mark it as such.
-->

## Overview

<!--
Please include a summary of the changes and the related issue.
Please also include relevant motivation and context.
List any dependencies that are required for this change.
-->

Fixes #(issue)

## Notes for reviewer

<!-- Anything the reviewer should know? -->
16 changes: 16 additions & 0 deletions .github/renovate.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"schedule:earlyMondays",
":disableDependencyDashboard"
],
"enabledManagers": [
"nix"
],
"nix": {
"enabled": true
},
"lockFileMaintenance": {
"enabled": true
}
}
6 changes: 6 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,12 @@ jobs:
- name: Lint
run: nix develop --impure .#ci -c make lint -j

- name: Pre-commit hooks
run: nix develop --impure .#ci -c pre-commit run -a

- name: Check commit messages
run: nix develop --impure .#ci -c pre-commit run --hook-stage manual

license-check:
name: License check
runs-on: ubuntu-latest
Expand Down
1 change: 1 addition & 0 deletions .hadolint.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
failure-threshold: error
54 changes: 34 additions & 20 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ lint-helm: # Run helm lint check

.PHONY: lint-docker
lint-docker: # Run Dockerfile lint check
$(HADOLINT) --failure-threshold error Dockerfile
$(HADOLINT) Dockerfile

.PHONY: lint
lint: lint-go lint-helm lint-docker ## Run lint checks
Expand Down Expand Up @@ -73,21 +73,20 @@ run: ## Run manager from your host
up: ## Start kind development environment
$(KIND) create cluster --name $(TEST_KIND_CLUSTER)
sleep 10
helm upgrade --install vault-operator oci://ghcr.io/bank-vaults/helm-charts/vault-operator \
$(HELM) upgrade --install vault-operator oci://ghcr.io/bank-vaults/helm-charts/vault-operator \
--set image.tag=latest \
--set image.bankVaultsTag=latest \
--wait
kubectl create namespace bank-vaults-infra --dry-run=client -o yaml | kubectl apply -f -
kubectl apply -f $(shell pwd)/e2e/deploy/vault/
$(KUBECTL) create namespace bank-vaults-infra --dry-run=client -o yaml | $(KUBECTL) apply -f -
$(KUBECTL) apply -f $(shell pwd)/e2e/deploy/vault/
sleep 60
helm upgrade --install vault-secrets-webhook oci://ghcr.io/bank-vaults/helm-charts/vault-secrets-webhook \
$(HELM) upgrade --install vault-secrets-webhook oci://ghcr.io/bank-vaults/helm-charts/vault-secrets-webhook \
--set replicaCount=1 \
--set image.tag=latest \
--set image.pullPolicy=IfNotPresent \
--set podsFailurePolicy=Fail \
--set vaultEnv.tag=latest \
--namespace bank-vaults-infra
kind load docker-image ghcr.io/bank-vaults/vault-secrets-reloader:dev --name $(TEST_KIND_CLUSTER)

.PHONY: down
down: ## Destroy kind development environment
Expand Down Expand Up @@ -124,14 +123,21 @@ generate: gen-helm-docs ## Generate manifests, code, and docs resources
##@ Deployment

.PHONY: deploy
deploy: ## Deploy manager resources to the K8s cluster
kubectl create namespace bank-vaults-infra --dry-run=client -o yaml | kubectl apply -f -
deploy: ## Deploy Reloader controller resources to the K8s cluster
$(KUBECTL) create namespace bank-vaults-infra --dry-run=client -o yaml | $(KUBECTL) apply -f -
$(HELM) upgrade --install vault-secrets-reloader deploy/charts/vault-secrets-reloader \
--set image.tag=dev \
--set collectorSyncPeriod=30s \
--set reloaderRunPeriod=1m \
--namespace bank-vaults-infra

.PHONY: upload-kind
upload-kind:
$(KIND) load docker-image $(IMG) --name $(TEST_KIND_CLUSTER) ## Load docker image to kind cluster

.PHONY: deploy-kind
deploy-kind: upload-kind deploy ## Deploy Reloder controller resources to the kind cluster

.PHONY: undeploy
undeploy: ## Clean manager resources from the K8s cluster.
$(HELM) uninstall vault-secrets-reloader --namespace bank-vaults-infra
Expand All @@ -142,6 +148,7 @@ undeploy: ## Clean manager resources from the K8s cluster.
GOLANGCI_VERSION = 1.53.3
LICENSEI_VERSION = 0.8.0
KIND_VERSION = 0.20.0
KUBECTL_VERSION = 1.28.3
HELM_DOCS_VERSION = 1.11.0

## Location to install dependencies to
Expand All @@ -157,17 +164,6 @@ GOLANGCI_LINT ?= $(or $(shell which golangci-lint),$(LOCALBIN)/golangci-lint)
$(GOLANGCI_LINT): $(LOCALBIN)
test -s $(LOCALBIN)/golangci-lint || curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash -s -- v${GOLANGCI_VERSION}

LICENSEI ?= $(or $(shell which licensei),$(LOCALBIN)/licensei)
$(LICENSEI): $(LOCALBIN)
test -s $(LOCALBIN)/licensei || curl -sfL https://raw.githubusercontent.com/goph/licensei/master/install.sh | bash -s -- v${LICENSEI_VERSION}

KIND ?= $(or $(shell which kind),$(LOCALBIN)/kind)
$(KIND): $(LOCALBIN)
@if [ ! -s "$(LOCALBIN)/kind" ]; then \
curl -Lo $(LOCALBIN)/kind https://kind.sigs.k8s.io/dl/v${KIND_VERSION}/kind-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed -e "s/aarch64/arm64/; s/x86_64/amd64/"); \
chmod +x $(LOCALBIN)/kind; \
fi

HELM ?= $(or $(shell which helm),$(LOCALBIN)/helm)
$(HELM): $(LOCALBIN)
test -s $(LOCALBIN)/helm || curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | USE_SUDO=false HELM_INSTALL_DIR=$(LOCALBIN) bash
Expand All @@ -179,9 +175,27 @@ $(HELM_DOCS): $(LOCALBIN)
chmod +x $(LOCALBIN)/helm-docs; \
fi

KIND ?= $(or $(shell which kind),$(LOCALBIN)/kind)
$(KIND): $(LOCALBIN)
@if [ ! -s "$(LOCALBIN)/kind" ]; then \
curl -Lo $(LOCALBIN)/kind https://kind.sigs.k8s.io/dl/v${KIND_VERSION}/kind-$(shell uname -s | tr '[:upper:]' '[:lower:]')-$(shell uname -m | sed -e "s/aarch64/arm64/; s/x86_64/amd64/"); \
chmod +x $(LOCALBIN)/kind; \
fi

KUBECTL ?= $(or $(shell which kubectl),$(LOCALBIN)/kubectl)
$(KUBECTL): $(LOCALBIN)
@if [ ! -s "$(LOCALBIN)/kubectl" ]; then \
curl -Lo $(LOCALBIN)/kubectl https://dl.k8s.io/release/v${KUBECTL_VERSION}/bin/$(shell uname -s | tr '[:upper:]' '[:lower:]')/$(shell uname -m | sed -e "s/aarch64/arm64/; s/x86_64/amd64/")/kubectl; \
chmod +x $(LOCALBIN)/kubectl; \
fi

LICENSEI ?= $(or $(shell which licensei),$(LOCALBIN)/licensei)
$(LICENSEI): $(LOCALBIN)
test -s $(LOCALBIN)/licensei || curl -sfL https://raw.githubusercontent.com/goph/licensei/master/install.sh | bash -s -- v${LICENSEI_VERSION}

# TODO: add support for hadolint and yamllint dependencies
HADOLINT ?= hadolint
YAMLLINT ?= yamllint

.PHONY: deps
deps: $(HELM) $(HELM_DOCS) $(ENVTEST) $(GOLANGCI_LINT) $(LICENSEI) $(KIND) ## Download and install dependencies
deps: $(ENVTEST) $(GOLANGCI_LINT) $(HELM) $(HELM_DOCS) $(KIND) $(KUBECTL) $(LICENSEI) ## Download and install dependencies
29 changes: 27 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,31 @@ are supported yet.
- Data collected by the `reloader` is only stored in-memory (secret version updates during the controller is being
recreated will not be acted upon, as it will rebuild its data store from scratch on start).

## Configuration

Reloader needs to access the Vault instance on its own, so make sure you set the correct environment variables through
the Helm chart (you can check the list of environmental variables accepted for creating a Vault client
[here](https://developer.hashicorp.com/vault/docs/commands#environment-variables)). Furthermore, configure the workload
data collection and reloading periods (using Go Duration format) that work best for your requirements and use-cases. For
example:

```shell
helm upgrade --install vault-secrets-reloader oci://ghcr.io/bank-vaults/vault-secrets-reloader \
--set collectorSyncPeriod=2h \
--set reloaderRunPeriod=4h \
--set env.VAULT_ADDR=[URL for Vault]
--set env.VAULT_PATH=[Auth path]
--set env.VAULT_ROLE=[Auth role]
--set env.VAULT_AUTH_METHOD=[Auth method]
# other environmental variables needed for the auth method of your choice
--namespace bank-vaults-infra --create-namespace
```

Vault also needs to be configured with an auth method for the Reloader to use. Additionally, it is advised to create a
role and policy that allows the Reloader to `read` and `list` secrets from Vault. An example can be found in the
[example Bank-Vaults Operator CR
file](https://github.com/bank-vaults/vault-secrets-reloader/blob/main/e2e/deploy/vault/vault.yaml#L102).

## Trying out Vault Secrets Reloader locally

Make sure Docker is installed with Compose and Buildx.
Expand All @@ -74,10 +99,10 @@ make up
make container-image

# deploy Vault Secrets Reloader
make deploy
make deploy-kind
```

The last command will install the Reloader Helm chart with the following settings:
The last command will install the Reloader Helm chart with the following configuration:

```shell
helm upgrade --install vault-secrets-reloader deploy/charts/vault-secrets-reloader \
Expand Down
39 changes: 17 additions & 22 deletions deploy/charts/vault-secrets-reloader/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,24 +1,19 @@
apiVersion: v2
name: vault-secrets-reloader
description: A Kubernetes Controller that reloads workloads on a referenced secret change in HashiCorp Vault

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "0.1.0"
name: vault-secrets-reloader
version: 0.0.0
appVersion: latest
description: A Kubernetes Controller that reloads workloads on a referenced secret change in HashiCorp Vault.
keywords:
- vault
- hashicorp
- secret
- webhook
- reloader
home: https://bank-vaults.dev
sources:
- https://github.com/hashicorp/vault
- https://github.com/bank-vaults/vault-secrets-reloader
maintainers:
- name: Bank Vaults Maintainers
email: team@bank-vaults.dev
97 changes: 97 additions & 0 deletions deploy/charts/vault-secrets-reloader/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# vault-secrets-reloader

This chart will install Vault Secrets Reloader Controller, that reloads workloads on a referenced secret change in HashiCorp Vault.

Reloader will collect (unversioned) secrets injected by the Webhook from watched workloads, periodically checks if their version has been updated in Vault and if so, "reloads" the workload with an annotation update, triggering a new rollout so the Webhook can inject the new version of the secret into the pod.

## Before you start

Reloader works in conjunction with the [Vault Secrets Webhook](https://github.com/bank-vaults/vault-secrets-webhook), therefore the prerequisites to start using it would be a Hashicorp Vault instance, and a working Webhook.

You will need to add the following annotations to the pod template spec of the workloads (i.e. Deployments, DaemonSets and StatefulSets) that you wish to reload:

```yaml
alpha.vault.security.banzaicloud.io/reload-on-secret-change: "true"
```

## Installing the Chart

**Prepare Kubernetes namespace**

You can prepare a separate namespace for Vault Secrets Reloader beforehand, create it automatically if not yet exist with appending `--create-namespace` to the installation Helm command, or just use the one already created for Vault Secrets Webhook.

**Install the chart**

```shell
helm upgrade --install vault-secrets-reloader oci://ghcr.io/bank-vaults/vault-secrets-reloader --namespace bank-vaults-infra --create-namespace
```

## Values

The following table lists the configurable parameters of the Helm chart.

| Parameter | Type | Default | Description |
| --- | ---- | ------- | ----------- |
| `affinity` | object | `{}` | Node affinity settings for the pods. Check: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/ |
| `autoscaling.enabled` | bool | `false` | Enable Reloader horizontal pod autoscaling |
| `autoscaling.maxReplicas` | int | `100` | Maximum number of replicas |
| `autoscaling.minReplicas` | int | `1` | Minimum number of replicas |
| `collectorSyncPeriod` | string | `"30m"` | Time interval for the collector worker to run in Go Duration format |
| `env` | object | `{"VAULT_ADDR":"https://vault.default.svc.cluster.local:8200","VAULT_ROLE":"reloader","VAULT_TLS_SECRET":"vault-tls","VAULT_TLS_SECRET_NS":"bank-vaults-infra"}` | Custom environment variables available to Reloader Define environment variables for Vault authentication here |
| `fullnameOverride` | string | `""` | Override app full name |
| `image.pullPolicy` | string | `"IfNotPresent"` | Container image pull policy |
| `image.repository` | string | `"ghcr.io/bank-vaults/vault-secrets-reloader"` | Container image repo that contains the Reloader Controller |
| `image.tag` | string | `""` | Container image tag |
| `imagePullSecrets` | list | `[]` | Container image pull secrets for private repositories |
| `ingress.annotations` | object | `{}` | Reloader ingress annotations |
| `ingress.className` | string | `""` | Reloader IngressClass name |
| `ingress.enabled` | bool | `false` | Enable Reloader ingress |
| `ingress.hosts` | list | `[{"host":"chart-example.local","paths":[{"path":"/","pathType":"ImplementationSpecific"}]}]` | Reloader ingress hosts |
| `ingress.tls` | list | `[]` | Reloader ingress tls |
| `logLevel` | string | `"info"` | Log level |
| `nameOverride` | string | `""` | Override app name |
| `nodeSelector` | object | `{}` | Node labels for pod assignment. Check: https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/#nodeselector |
| `podAnnotations` | object | `{}` | Extra annotations to add to pod metadata |
| `podSecurityContext` | object | `{}` | Pod security context for Reloader deployment |
| `reloaderRunPeriod` | string | `"1h"` | Time interval for the reloader worker to run in Go Duration format |
| `replicaCount` | int | `1` | Number of replicas |
| `resources` | object | `{}` | Resources to request for the deployment and pods |
| `securityContext` | object | `{}` | Pod security context for Reloader containers |
| `service.annotations` | object | `{}` | Reloader service annotations, e.g. if type is AWS LoadBalancer and you want to add security groups |
| `service.externalPort` | int | `443` | Reloader service external port |
| `service.internalPort` | int | `8443` | Reloader service internal port |
| `service.name` | string | `"vault-secrets-reloader"` | Reloader service name |
| `service.type` | string | `"ClusterIP"` | Reloader service type |
| `serviceAccount.annotations` | object | `{}` | Annotations to add to the service account |
| `serviceAccount.create` | bool | `true` | Specifies whether a service account should be created |
| `serviceAccount.name` | string | `""` | The name of the service account to use. If not set and create is true, a name is generated using the fullname template |
| `tolerations` | list | `[]` | List of node tolerations for the pods. Check: https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ |
| `volumeMounts` | list | `[]` | Extra volume mounts for Reloader deployment |
| `volumes` | list | `[]` | Extra volume definitions for Reloader deployment |

Specify each parameter using the `--set key=value[,key=value]` argument to `helm install`.

### Time periods

Configure the time for periodic runs of the `collector` and `reloader` workers with a value in Go Duration format:

```yaml
collectorSyncPeriod: 30m
reloaderRunPeriod: 1h
```

### Vault credentials

Reloader needs to be supplied with Vault credentials to be able to connect to Vault in order to get the secrets. You can check the list of environmental variables accepted for creating a Vault client [here](https://developer.hashicorp.com/vault/docs/commands#environment-variables). For example:

```yaml
env:
# define env vars for Vault used for authentication
VAULT_ROLE: "reloader"
VAULT_ADDR: "https://vault.default.svc.cluster.local:8200"
VAULT_NAMESPACE: "default"
VAULT_TLS_SECRET: "vault-tls"
VAULT_TLS_SECRET_NS: "bank-vaults-infra"
```

In addition to that, make sure to add the `read` and `list` capabilities for secrets to the Vault auth role the Reloader will use. An example can be found in the [example Bank-Vaults Operator CR file](https://github.com/bank-vaults/vault-secrets-reloader/blob/main/e2e/deploy/vault/vault.yaml#L102).
Loading