A Kubernetes operator that bridges Hardware Security Module (HSM) data storage with Kubernetes Secrets, providing true secret portability th
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 441 lines 19 kB view raw
1# VERSION defines the project version for the bundle. 2# Update this value when you upgrade the version of your project. 3# To re-generate a bundle for another specific version without changing the standard setup, you can: 4# - use the VERSION as arg of the bundle target (e.g make bundle VERSION=0.0.2) 5# - use environment variables to overwrite this value (e.g export VERSION=0.0.2) 6VERSION ?= 0.8.0 7 8# CHANNELS define the bundle channels used in the bundle. 9# Add a new line here if you would like to change its default config. (E.g CHANNELS = "candidate,fast,stable") 10# To re-generate a bundle for other specific channels without changing the standard setup, you can: 11# - use the CHANNELS as arg of the bundle target (e.g make bundle CHANNELS=candidate,fast,stable) 12# - use environment variables to overwrite this value (e.g export CHANNELS="candidate,fast,stable") 13ifneq ($(origin CHANNELS), undefined) 14BUNDLE_CHANNELS := --channels=$(CHANNELS) 15endif 16 17# DEFAULT_CHANNEL defines the default channel used in the bundle. 18# Add a new line here if you would like to change its default config. (E.g DEFAULT_CHANNEL = "stable") 19# To re-generate a bundle for any other default channel without changing the default setup, you can: 20# - use the DEFAULT_CHANNEL as arg of the bundle target (e.g make bundle DEFAULT_CHANNEL=stable) 21# - use environment variables to overwrite this value (e.g export DEFAULT_CHANNEL="stable") 22ifneq ($(origin DEFAULT_CHANNEL), undefined) 23BUNDLE_DEFAULT_CHANNEL := --default-channel=$(DEFAULT_CHANNEL) 24endif 25BUNDLE_METADATA_OPTS ?= $(BUNDLE_CHANNELS) $(BUNDLE_DEFAULT_CHANNEL) 26 27# IMAGE_TAG_BASE defines the docker.io namespace and part of the image name for remote images. 28# This variable is used to construct full image tags for bundle and catalog images. 29# 30# For example, running 'make bundle-build bundle-push catalog-build catalog-push' will build and push both 31# j5t.io/hsm-secrets-operator-bundle:$VERSION and j5t.io/hsm-secrets-operator-catalog:$VERSION. 32IMAGE_TAG_BASE ?= j5t.io/hsm-secrets-operator 33 34# BUNDLE_IMG defines the image:tag used for the bundle. 35# You can use it as an arg. (E.g make bundle-build BUNDLE_IMG=<some-registry>/<project-name-bundle>:<tag>) 36BUNDLE_IMG ?= $(IMAGE_TAG_BASE)-bundle:v$(VERSION) 37 38# BUNDLE_GEN_FLAGS are the flags passed to the operator-sdk generate bundle command 39BUNDLE_GEN_FLAGS ?= -q --overwrite --version $(VERSION) $(BUNDLE_METADATA_OPTS) 40 41# USE_IMAGE_DIGESTS defines if images are resolved via tags or digests 42# You can enable this value if you would like to use SHA Based Digests 43# To enable set flag to true 44USE_IMAGE_DIGESTS ?= false 45ifeq ($(USE_IMAGE_DIGESTS), true) 46 BUNDLE_GEN_FLAGS += --use-image-digests 47endif 48 49# Set the Operator SDK version to use. By default, what is installed on the system is used. 50# This is useful for CI or a project to utilize a specific version of the operator-sdk toolkit. 51OPERATOR_SDK_VERSION ?= v1.41.1 52# Image URL to use all building/pushing image targets 53IMG ?= controller:latest 54 55# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set) 56ifeq (,$(shell go env GOBIN)) 57GOBIN=$(shell go env GOPATH)/bin 58else 59GOBIN=$(shell go env GOBIN) 60endif 61 62# CONTAINER_TOOL defines the container tool to be used for building images. 63# Be aware that the target commands are only tested with Docker which is 64# scaffolded by default. However, you might want to replace it to use other 65# tools. (i.e. podman) 66CONTAINER_TOOL ?= docker 67 68# Setting SHELL to bash allows bash commands to be executed by recipes. 69# Options are set to exit when a recipe line exits non-zero or a piped command fails. 70SHELL = /usr/bin/env bash -o pipefail 71.SHELLFLAGS = -ec 72 73.PHONY: all 74all: build 75 76##@ General 77 78# The help target prints out all targets with their descriptions organized 79# beneath their categories. The categories are represented by '##@' and the 80# target descriptions by '##'. The awk command is responsible for reading the 81# entire set of makefiles included in this invocation, looking for lines of the 82# file as xyz: ## something, and then pretty-format the target and help. Then, 83# if there's a line with ##@ something, that gets pretty-printed as a category. 84# More info on the usage of ANSI control characters for terminal formatting: 85# https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters 86# More info on the awk command: 87# http://linuxcommand.org/lc3_adv_awk.php 88 89.PHONY: help 90help: ## Display this help. 91 @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) 92 93##@ Version Management 94 95.PHONY: version-show 96version-show: ## Show current version 97 @echo "Current version: $(VERSION)" 98 99.PHONY: version-sync 100version-sync: ## Sync Chart.yaml versions with Makefile VERSION 101 @echo "Syncing Chart.yaml with VERSION=$(VERSION)..." 102 @sed -i 's/^version: .*/version: $(VERSION)/' helm/hsm-secrets-operator/Chart.yaml 103 @sed -i 's/^appVersion: .*/appVersion: v$(VERSION)/' helm/hsm-secrets-operator/Chart.yaml 104 @echo "✅ Chart.yaml synced with version $(VERSION)" 105 106.PHONY: version-patch 107version-patch: ## Increment patch version (x.y.Z+1) 108 $(call increment-version,patch) 109 110.PHONY: version-minor 111version-minor: ## Increment minor version (x.Y+1.0) 112 $(call increment-version,minor) 113 114.PHONY: version-major 115version-major: ## Increment major version (X+1.0.0) 116 $(call increment-version,major) 117 118# Helper function to increment version 119define increment-version 120$(eval NEW_VERSION := $(shell echo "$(VERSION)" | awk -F. -v component=$(1) '{ \ 121 if (component == "major") { print ($$1+1) ".0.0" } \ 122 else if (component == "minor") { print $$1 "." ($$2+1) ".0" } \ 123 else if (component == "patch") { print $$1 "." $$2 "." ($$3+1) } \ 124}')) 125@echo "Incrementing $(1): $(VERSION)$(NEW_VERSION)" 126@sed -i 's/^VERSION ?= .*/VERSION ?= $(NEW_VERSION)/' Makefile 127@$(MAKE) version-sync VERSION=$(NEW_VERSION) 128@echo "✅ Version updated to $(NEW_VERSION)" 129@echo "" 130@echo "Next steps:" 131@echo "git commit -am 'chore: bump version to $(NEW_VERSION)'" 132@echo "git tag v$(NEW_VERSION) && git push origin v$(NEW_VERSION)" 133endef 134 135##@ Development 136 137.PHONY: manifests 138manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects. 139 $(CONTROLLER_GEN) rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases 140 141.PHONY: helm-sync 142helm-sync: manifests ## Sync generated CRDs from config/ to helm/crds/ 143 @echo "Syncing CRDs from config/crd/bases/ to helm/hsm-secrets-operator/crds/" 144 cp config/crd/bases/*.yaml helm/hsm-secrets-operator/crds/ 145 @echo "✅ CRDs synced successfully" 146 @echo "⚠️ RBAC sync: Please manually verify helm/hsm-secrets-operator/templates/rbac/role.yaml matches config/rbac/role.yaml" 147 148.PHONY: generate 149generate: controller-gen ## Generate code containing DeepCopy, DeepCopyInto, and DeepCopyObject method implementations. 150 $(CONTROLLER_GEN) object:headerFile="hack/boilerplate.go.txt" paths="./..." 151 152.PHONY: fmt 153fmt: ## Run go fmt against code. 154 go fmt ./... 155 156.PHONY: vet 157vet: ## Run go vet against code. 158 go vet ./... 159 160.PHONY: test 161test: manifests generate fmt vet setup-envtest ## Run tests. 162 KUBEBUILDER_ASSETS="$(shell $(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path)" go test $$(go list ./... | grep -v -E '/(e2e|test/utils)') -coverprofile cover.out 163 164# TODO(user): To use a different vendor for e2e tests, modify the setup under 'tests/e2e'. 165# The default setup assumes Kind is pre-installed and builds/loads the Manager Docker image locally. 166# CertManager is installed by default; skip with: 167# - CERT_MANAGER_INSTALL_SKIP=true 168KIND_CLUSTER ?= hsm-secrets-operator-test-e2e 169 170.PHONY: setup-test-e2e 171setup-test-e2e: ## Set up a Kind cluster for e2e tests if it does not exist 172 @command -v $(KIND) >/dev/null 2>&1 || { \ 173 echo "Kind is not installed. Please install Kind manually."; \ 174 exit 1; \ 175 } 176 @case "$$($(KIND) get clusters)" in \ 177 *"$(KIND_CLUSTER)"*) \ 178 echo "Kind cluster '$(KIND_CLUSTER)' already exists. Skipping creation." ;; \ 179 *) \ 180 echo "Creating Kind cluster '$(KIND_CLUSTER)'..."; \ 181 $(KIND) create cluster --name $(KIND_CLUSTER) ;; \ 182 esac 183 @echo "Setting kubectl context to kind-$(KIND_CLUSTER)" 184 @kubectl config use-context kind-$(KIND_CLUSTER) 185 186.PHONY: test-e2e 187test-e2e: setup-test-e2e manifests generate fmt vet ## Run the e2e tests. Expected an isolated environment using Kind. 188 KIND_CLUSTER=$(KIND_CLUSTER) go test ./test/e2e/ -v -ginkgo.v 189 $(MAKE) cleanup-test-e2e 190 191.PHONY: cleanup-test-e2e 192cleanup-test-e2e: ## Tear down the Kind cluster used for e2e tests 193 @$(KIND) delete cluster --name $(KIND_CLUSTER) 194 195.PHONY: lint 196lint: golangci-lint ## Run golangci-lint linter 197 $(GOLANGCI_LINT) run ./... 198 199.PHONY: lint-fix 200lint-fix: golangci-lint ## Run golangci-lint linter and perform fixes 201 $(GOLANGCI_LINT) run --fix ./... 202 203.PHONY: lint-config 204lint-config: golangci-lint ## Verify golangci-lint linter configuration 205 $(GOLANGCI_LINT) config verify 206 207.PHONY: quality 208quality: fmt vet lint ## Run full code quality check (format, vet, lint) 209 @echo "✅ All code quality checks passed!" 210 211##@ Build 212 213.PHONY: build 214build: manifests generate fmt vet ## Build unified hsm-operator binary. 215 go build -o bin/hsm-operator cmd/hsm-operator/main.go 216 217# Legacy build targets for individual binaries (now creates symlinks to unified binary) 218.PHONY: build-legacy 219build-legacy: build ## Build legacy binary names as symlinks to unified binary. 220 ln -sf hsm-operator bin/manager 221 ln -sf hsm-operator bin/discovery 222 ln -sf hsm-operator bin/agent 223 224.PHONY: run 225run: manifests generate fmt vet ## Run manager mode from your host. 226 go run ./cmd/hsm-operator/main.go --mode=manager 227 228.PHONY: run-agent 229run-agent: ## Run agent mode from your host (requires HSM device). 230 go run ./cmd/hsm-operator/main.go --mode=agent 231 232.PHONY: run-discovery 233run-discovery: ## Run discovery mode from your host. 234 go run ./cmd/hsm-operator/main.go --mode=discovery 235 236# If you wish to build the manager image targeting other platforms you can use the --platform flag. 237# (i.e. docker build --platform linux/arm64). However, you must enable docker buildKit for it. 238# More info: https://docs.docker.com/develop/develop-images/build_enhancements/ 239.PHONY: docker-build 240docker-build: ## Build debug distroless image (root + busybox shell) - default for testing. 241 $(CONTAINER_TOOL) build -t ${IMG} . 242 243.PHONY: docker-build-production 244docker-build-production: ## Build production distroless image (root + no shell). 245 $(CONTAINER_TOOL) build --target production -t ${IMG}-production . 246 247.PHONY: docker-build-alpine 248docker-build-alpine: ## Build Alpine-based image (fallback option). 249 $(CONTAINER_TOOL) build -f Dockerfile.alpine -t ${IMG}-alpine . 250 251.PHONY: docker-push 252docker-push: ## Push docker image with the manager. 253 $(CONTAINER_TOOL) push ${IMG} 254 255.PHONY: docker-build-multiarch 256docker-build-multiarch: ## Build docker image for multiple architectures and push. 257 $(CONTAINER_TOOL) buildx build --platform linux/amd64,linux/arm64 --push -t ${IMG} . 258 259# PLATFORMS defines the target platforms for the manager image be built to provide support to multiple 260# architectures. (i.e. make docker-buildx IMG=myregistry/mypoperator:0.0.1). To use this option you need to: 261# - be able to use docker buildx. More info: https://docs.docker.com/build/buildx/ 262# - have enabled BuildKit. More info: https://docs.docker.com/develop/develop-images/build_enhancements/ 263# - be able to push the image to your registry (i.e. if you do not set a valid value via IMG=<myregistry/image:<tag>> then the export will fail) 264# To adequately provide solutions that are compatible with multiple platforms, you should consider using this option. 265PLATFORMS ?= linux/arm64,linux/amd64,linux/s390x,linux/ppc64le 266.PHONY: docker-buildx 267docker-buildx: ## Build and push docker image for cross-platform support (linux/amd64,linux/arm64) 268 - $(CONTAINER_TOOL) buildx create --name hsm-secrets-operator-builder 269 $(CONTAINER_TOOL) buildx use hsm-secrets-operator-builder 270 - $(CONTAINER_TOOL) buildx build --push --platform=$(PLATFORMS) --tag ${IMG} . 271 - $(CONTAINER_TOOL) buildx rm hsm-secrets-operator-builder 272 273.PHONY: build-installer 274build-installer: manifests generate kustomize ## Generate a consolidated YAML with CRDs and deployment. 275 mkdir -p dist 276 cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 277 $(KUSTOMIZE) build config/default > dist/install.yaml 278 279##@ Deployment 280 281ifndef ignore-not-found 282 ignore-not-found = false 283endif 284 285.PHONY: install 286install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config. 287 $(KUSTOMIZE) build config/crd | $(KUBECTL) apply -f - 288 289.PHONY: uninstall 290uninstall: manifests kustomize ## Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 291 $(KUSTOMIZE) build config/crd | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - 292 293.PHONY: deploy 294deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config. 295 cd config/manager && $(KUSTOMIZE) edit set image controller=${IMG} 296 $(KUSTOMIZE) build config/default | $(KUBECTL) apply -f - 297 298.PHONY: undeploy 299undeploy: kustomize ## Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion. 300 $(KUSTOMIZE) build config/default | $(KUBECTL) delete --ignore-not-found=$(ignore-not-found) -f - 301 302##@ Dependencies 303 304## Location to install dependencies to 305LOCALBIN ?= $(shell pwd)/bin 306$(LOCALBIN): 307 mkdir -p $(LOCALBIN) 308 309## Tool Binaries 310KUBECTL ?= kubectl 311KIND ?= kind 312KUSTOMIZE ?= $(LOCALBIN)/kustomize 313CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen 314ENVTEST ?= $(LOCALBIN)/setup-envtest 315GOLANGCI_LINT = $(LOCALBIN)/golangci-lint 316 317## Tool Versions 318KUSTOMIZE_VERSION ?= v5.6.0 319CONTROLLER_TOOLS_VERSION ?= v0.18.0 320#ENVTEST_VERSION is the version of controller-runtime release branch to fetch the envtest setup script (i.e. release-0.20) 321ENVTEST_VERSION ?= $(shell go list -m -f "{{ .Version }}" sigs.k8s.io/controller-runtime | awk -F'[v.]' '{printf "release-%d.%d", $$2, $$3}') 322#ENVTEST_K8S_VERSION is the version of Kubernetes to use for setting up ENVTEST binaries (i.e. 1.31) 323ENVTEST_K8S_VERSION ?= $(shell go list -m -f "{{ .Version }}" k8s.io/api | awk -F'[v.]' '{printf "1.%d", $$3}') 324GOLANGCI_LINT_VERSION ?= v2.5.0 325 326.PHONY: kustomize 327kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary. 328$(KUSTOMIZE): $(LOCALBIN) 329 $(call go-install-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v5,$(KUSTOMIZE_VERSION)) 330 331.PHONY: controller-gen 332controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary. 333$(CONTROLLER_GEN): $(LOCALBIN) 334 $(call go-install-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen,$(CONTROLLER_TOOLS_VERSION)) 335 336.PHONY: setup-envtest 337setup-envtest: envtest ## Download the binaries required for ENVTEST in the local bin directory. 338 @echo "Setting up envtest binaries for Kubernetes version $(ENVTEST_K8S_VERSION)..." 339 @$(ENVTEST) use $(ENVTEST_K8S_VERSION) --bin-dir $(LOCALBIN) -p path || { \ 340 echo "Error: Failed to set up envtest binaries for version $(ENVTEST_K8S_VERSION)."; \ 341 exit 1; \ 342 } 343 344.PHONY: envtest 345envtest: $(ENVTEST) ## Download setup-envtest locally if necessary. 346$(ENVTEST): $(LOCALBIN) 347 $(call go-install-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest,$(ENVTEST_VERSION)) 348 349.PHONY: golangci-lint 350golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. 351$(GOLANGCI_LINT): $(LOCALBIN) 352 $(call go-install-tool,$(GOLANGCI_LINT),github.com/golangci/golangci-lint/v2/cmd/golangci-lint,$(GOLANGCI_LINT_VERSION)) 353 354# go-install-tool will 'go install' any package with custom target and name of binary, if it doesn't exist 355# $1 - target path with name of binary 356# $2 - package url which can be installed 357# $3 - specific version of package 358define go-install-tool 359@[ -f "$(1)-$(3)" ] || { \ 360set -e; \ 361package=$(2)@$(3) ;\ 362echo "Downloading $${package}" ;\ 363rm -f $(1) || true ;\ 364GOBIN=$(LOCALBIN) go install $${package} ;\ 365mv $(1) $(1)-$(3) ;\ 366} ;\ 367ln -sf $(1)-$(3) $(1) 368endef 369 370.PHONY: operator-sdk 371OPERATOR_SDK ?= $(LOCALBIN)/operator-sdk 372operator-sdk: ## Download operator-sdk locally if necessary. 373ifeq (,$(wildcard $(OPERATOR_SDK))) 374ifeq (, $(shell which operator-sdk 2>/dev/null)) 375 @{ \ 376 set -e ;\ 377 mkdir -p $(dir $(OPERATOR_SDK)) ;\ 378 OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ 379 curl -sSLo $(OPERATOR_SDK) https://github.com/operator-framework/operator-sdk/releases/download/$(OPERATOR_SDK_VERSION)/operator-sdk_$${OS}_$${ARCH} ;\ 380 chmod +x $(OPERATOR_SDK) ;\ 381 } 382else 383OPERATOR_SDK = $(shell which operator-sdk) 384endif 385endif 386 387.PHONY: bundle 388bundle: manifests kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. 389 $(OPERATOR_SDK) generate kustomize manifests -q 390 cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) 391 $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) 392 $(OPERATOR_SDK) bundle validate ./bundle 393 394.PHONY: bundle-build 395bundle-build: ## Build the bundle image. 396 $(CONTAINER_TOOL) build -f bundle.Dockerfile -t $(BUNDLE_IMG) . 397 398.PHONY: bundle-push 399bundle-push: ## Push the bundle image. 400 $(MAKE) docker-push IMG=$(BUNDLE_IMG) 401 402.PHONY: opm 403OPM = $(LOCALBIN)/opm 404opm: ## Download opm locally if necessary. 405ifeq (,$(wildcard $(OPM))) 406ifeq (,$(shell which opm 2>/dev/null)) 407 @{ \ 408 set -e ;\ 409 mkdir -p $(dir $(OPM)) ;\ 410 OS=$(shell go env GOOS) && ARCH=$(shell go env GOARCH) && \ 411 curl -sSLo $(OPM) https://github.com/operator-framework/operator-registry/releases/download/v1.55.0/$${OS}-$${ARCH}-opm ;\ 412 chmod +x $(OPM) ;\ 413 } 414else 415OPM = $(shell which opm) 416endif 417endif 418 419# A comma-separated list of bundle images (e.g. make catalog-build BUNDLE_IMGS=example.com/operator-bundle:v0.1.0,example.com/operator-bundle:v0.2.0). 420# These images MUST exist in a registry and be pull-able. 421BUNDLE_IMGS ?= $(BUNDLE_IMG) 422 423# The image tag given to the resulting catalog image (e.g. make catalog-build CATALOG_IMG=example.com/operator-catalog:v0.2.0). 424CATALOG_IMG ?= $(IMAGE_TAG_BASE)-catalog:v$(VERSION) 425 426# Set CATALOG_BASE_IMG to an existing catalog image tag to add $BUNDLE_IMGS to that image. 427ifneq ($(origin CATALOG_BASE_IMG), undefined) 428FROM_INDEX_OPT := --from-index $(CATALOG_BASE_IMG) 429endif 430 431# Build a catalog image by adding bundle images to an empty catalog using the operator package manager tool, 'opm'. 432# This recipe invokes 'opm' in 'semver' bundle add mode. For more information on add modes, see: 433# https://github.com/operator-framework/community-operators/blob/7f1438c/docs/packaging-operator.md#updating-your-existing-operator 434.PHONY: catalog-build 435catalog-build: opm ## Build a catalog image. 436 $(OPM) index add --container-tool $(CONTAINER_TOOL) --mode semver --tag $(CATALOG_IMG) --bundles $(BUNDLE_IMGS) $(FROM_INDEX_OPT) 437 438# Push the catalog image. 439.PHONY: catalog-push 440catalog-push: ## Push a catalog image. 441 $(MAKE) docker-push IMG=$(CATALOG_IMG)