Skip to content

Commit

Permalink
use OpenShift certs & CA
Browse files Browse the repository at this point in the history
Signed-off-by: Zbynek Roubalik <zroubalik@gmail.com>
  • Loading branch information
zroubalik committed May 30, 2023
1 parent 5f1d299 commit 32d8da1
Show file tree
Hide file tree
Showing 10 changed files with 829 additions and 223 deletions.
54 changes: 26 additions & 28 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ GOBIN=$(shell go env GOBIN)
endif

# ENVTEST_K8S_VERSION refers to the version of kubebuilder assets to be downloaded by envtest binary.
ENVTEST_K8S_VERSION = 1.23
ENVTEST_K8S_VERSION = 1.26

# Setting SHELL to bash allows bash commands to be executed by recipes.
# This is a requirement for 'setup-envtest.sh' in the test target.
Expand Down Expand Up @@ -73,7 +73,7 @@ build: generate fmt vet ## Build manager binary.
-o bin/manager main.go

run: manifests generate fmt vet ## Run a controller from your host.
go run ./main.go
WATCH_NAMESPACE="keda" go run ./main.go

docker-build: ## Build docker image with the manager.
docker build . -t ${IMAGE_CONTROLLER} --build-arg BUILD_VERSION=${VERSION} --build-arg GIT_VERSION=${GIT_VERSION} --build-arg GIT_COMMIT=${GIT_COMMIT}
Expand Down Expand Up @@ -104,32 +104,30 @@ deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in
undeploy: ## Undeploy controller from the K8s cluster specified in ~/.kube/config.
$(KUSTOMIZE) build config/default | kubectl delete -f -


CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
controller-gen: ## Download controller-gen locally if necessary.
$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.10.0)

KUSTOMIZE = $(shell pwd)/bin/kustomize
kustomize: ## Download kustomize locally if necessary.
$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v4@v4.5.5)

ENVTEST = $(shell pwd)/bin/setup-envtest
envtest: ## Download envtest-setup locally if necessary.
$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)

# go-get-tool will 'go get' any package $2 and install it to $1.
PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
define go-get-tool
@[ -f $(1) ] || { \
set -e ;\
TMP_DIR=$$(mktemp -d) ;\
cd $$TMP_DIR ;\
go mod init tmp ;\
echo "Downloading $(2)" ;\
GOBIN=$(PROJECT_DIR)/bin go install $(2) ;\
rm -rf $$TMP_DIR ;\
}
endef
## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN):
mkdir -p $(LOCALBIN)

## Tool Binaries
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest

.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Install controller-gen from vendor dir if necessary.
$(CONTROLLER_GEN): $(LOCALBIN)
test -s $(LOCALBIN)/controller-gen || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen

.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Install kustomize from vendor dir if necessary.
$(KUSTOMIZE): $(LOCALBIN)
test -s $(LOCALBIN)/kustomize || GOBIN=$(LOCALBIN) go install sigs.k8s.io/kustomize/kustomize/v4

.PHONY: envtest
envtest: $(ENVTEST) ## Install envtest-setup from vendor dir if necessary.
$(ENVTEST): $(LOCALBIN)
test -s $(LOCALBIN)/setup-envtest || GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest

# Run golangci against code
.PHONY: golangci
Expand Down
2 changes: 1 addition & 1 deletion apis/keda/v1alpha1/kedacontroller_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ type KedaControllerStatus struct {
// +optional
Version string `json:"version,omitempty"`
// +optional
ConfigMapDataSum string `json:"configmadatasum,omitempty"`
ConfigMapDataSum string `json:"configmapdatasum,omitempty"`
// +optional
SecretDataSum string `json:"secretdatasum,omitempty"`

Expand Down
2 changes: 1 addition & 1 deletion apis/keda/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions config/crd/bases/keda.sh_kedacontrollers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.10.0
controller-gen.kubebuilder.io/version: v0.11.3
creationTimestamp: null
name: kedacontrollers.keda.sh
spec:
Expand Down Expand Up @@ -3251,7 +3251,7 @@ spec:
status:
description: KedaControllerStatus defines the observed state of KedaController
properties:
configmadatasum:
configmapdatasum:
type: string
phase:
type: string
Expand Down
64 changes: 38 additions & 26 deletions controllers/keda/kedacontroller_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,12 @@ const (

installationNamespace = "keda"

grpcCertSecretName = "kedaorg-certs"
metricsServerServiceName = "keda-metrics-apiserver"
metricsServerConfigMapName = "keda-metrics-apiserver"
injectCABundleAnnotation = "service.beta.openshift.io/inject-cabundle"
injectCABundleAnnotationValue = "true"
injectservingCertAnnotation = "service.beta.openshift.io/serving-cert-secret-name"
injectservingCertAnnotationValue = "keda-metrics-apiserver"
roleBindingName = "keda-auth-reader"
roleBindingNamespace = "kube-system"
caBundleConfigMapName = "keda-ocp-cabundle"
injectCABundleAnnotation = "service.beta.openshift.io/inject-cabundle"
injectCABundleAnnotationValue = "true"
servingCertsAnnotation = "service.beta.openshift.io/serving-cert-secret-name"
roleBindingName = "keda-auth-reader"
roleBindingNamespace = "kube-system"

auditlogPolicyConfigMap = "keda-metrics-server-audit-policy"
auditlogPolicyMountPath = "/var/audit-policy"
Expand Down Expand Up @@ -203,7 +200,7 @@ func (r *KedaControllerReconciler) Reconcile(ctx context.Context, req ctrl.Reque
return ctrl.Result{}, err
}

if err := r.installAdmissionWebhooks(logger, instance); err != nil {
if err := r.installAdmissionWebhooks(ctx, logger, instance); err != nil {
status.MarkInstallFailed("Not able to install KEDA Admission Webhooks")
if statusErr := util.UpdateKedaControllerStatus(ctx, r.Client, instance, status); statusErr != nil {
err = fmt.Errorf("got error: %s and then another: %s", err, statusErr)
Expand Down Expand Up @@ -352,7 +349,7 @@ func (r *KedaControllerReconciler) installController(ctx context.Context, logger

if util.RunningOnOpenshift(ctx, logger, r.Client) {
transforms = append(transforms,
transform.EnsureCertInjectionForOperatorDeployment(metricsServerConfigMapName, r.Scheme),
transform.EnsureOpenshiftCABundleForOperatorDeployment(caBundleConfigMapName, r.Scheme),
)
}

Expand Down Expand Up @@ -464,22 +461,25 @@ func (r *KedaControllerReconciler) installMetricsServer(ctx context.Context, log

// certificates rotation works only on Openshift due to openshift/service-ca-operator
if util.RunningOnOpenshift(ctx, logger, r.Client) {
if err := r.ensureMetricsServerConfigMap(ctx, logger, instance); err != nil {
logger.Error(err, "Unable to check Metrics Server ConfigMap is present")
if err := r.ensureOpenshiftCABundleConfigMap(ctx, logger, instance); err != nil {
logger.Error(err, "Unable to check OpenShift CA Bundle ConfigMap is present")
return err
}

argsPrefixes := []transform.Prefix{transform.ClientCAFile, transform.TLSCertFile, transform.TLSPrivateKeyFile, transform.GRPCCertsDir}
newArgs := []string{"/cabundle/service-ca.crt", "/certs/tls.crt", "/certs/tls.key", "/grpc-certs"}
argsPrefixes := []transform.Prefix{transform.ClientCAFile, transform.TLSCertFile, transform.TLSPrivateKeyFile}
newArgs := []string{"/certs/ocp-ca.crt", "/certs/ocp-tls.crt", "/certs/ocp-tls.key"}

serviceName := "keda-metrics-apiserver"
certsSecretName := serviceName + "-certs"

transforms = append(transforms,
transform.EnsureCertInjectionForAPIService(injectCABundleAnnotation, injectCABundleAnnotationValue, r.Scheme),
transform.EnsureCertInjectionForService(metricsServerServiceName, injectservingCertAnnotation, injectservingCertAnnotationValue),
transform.EnsureCertInjectionForDeployment(metricsServerConfigMapName, metricsServerServiceName, grpcCertSecretName, r.Scheme),
transform.EnsureCABundleInjectionForAPIService(injectCABundleAnnotation, injectCABundleAnnotationValue, r.Scheme),
transform.EnsureCertInjectionForService(serviceName, servingCertsAnnotation, certsSecretName),
transform.MetricsServerEnsureCertificatesVolume(caBundleConfigMapName, certsSecretName, r.Scheme),
)
transforms = append(transforms, transform.EnsurePathsToCertsInDeployment(newArgs, argsPrefixes, r.Scheme, logger)...)
} else {
logger.Info("Not running on OpenShift -> using generated self-signed cert for KEDA Metrics Server")
logger.Info("Not running on OpenShift -> using only KEDA Operator generated self-signed cert for KEDA Metrics Server")
}

// Audit logging validation - configMap exists, logOutVolumeClaim validation
Expand Down Expand Up @@ -596,14 +596,14 @@ func (r *KedaControllerReconciler) installMetricsServer(ctx context.Context, log
return nil
}

func (r *KedaControllerReconciler) ensureMetricsServerConfigMap(ctx context.Context, logger logr.Logger, instance *kedav1alpha1.KedaController) error {
logger.Info("Ensure ConfigMap for Metrics Server CA bundle exists")
func (r *KedaControllerReconciler) ensureOpenshiftCABundleConfigMap(ctx context.Context, logger logr.Logger, instance *kedav1alpha1.KedaController) error {
logger.Info("Ensure ConfigMap for OpenShift CA bundle exists")

configMap := &corev1.ConfigMap{}
err := r.Client.Get(ctx, types.NamespacedName{Name: metricsServerConfigMapName, Namespace: instance.Namespace}, configMap)
err := r.Client.Get(ctx, types.NamespacedName{Name: caBundleConfigMapName, Namespace: instance.Namespace}, configMap)
if err != nil {
if errors.IsNotFound(err) {
configMap.Name = metricsServerConfigMapName
configMap.Name = caBundleConfigMapName
configMap.Namespace = instance.Namespace
metav1.SetMetaDataAnnotation(&configMap.ObjectMeta, injectCABundleAnnotation, injectCABundleAnnotationValue)

Expand All @@ -614,7 +614,7 @@ func (r *KedaControllerReconciler) ensureMetricsServerConfigMap(ctx context.Cont

err = r.Client.Create(ctx, configMap)
if err != nil {
logger.Error(err, "Failed to create new ConfigMap in cluster", "ConfigMap.Namespace", instance.Namespace, "ConfigMap.Name", metricsServerConfigMapName)
logger.Error(err, "Failed to create new ConfigMap in cluster", "ConfigMap.Namespace", instance.Namespace, "ConfigMap.Name", caBundleConfigMapName)
return err
}

Expand Down Expand Up @@ -645,7 +645,7 @@ func (r *KedaControllerReconciler) ensureMetricsServerConfigMap(ctx context.Cont
if configMapUpdate {
err = r.Client.Update(ctx, configMap)
if err != nil {
logger.Error(err, "Failed to update ConfigMap in cluster", "ConfigMap.Namespace", instance.Namespace, "ConfigMap.Name", metricsServerConfigMapName)
logger.Error(err, "Failed to update ConfigMap in cluster", "ConfigMap.Namespace", instance.Namespace, "ConfigMap.Name", caBundleConfigMapName)
return err
}
}
Expand Down Expand Up @@ -718,13 +718,25 @@ func (r *KedaControllerReconciler) ensureMetricsServerAuditLogPolicyConfigMap(ct
return nil
}

func (r *KedaControllerReconciler) installAdmissionWebhooks(logger logr.Logger, instance *kedav1alpha1.KedaController) error {
func (r *KedaControllerReconciler) installAdmissionWebhooks(ctx context.Context, logger logr.Logger, instance *kedav1alpha1.KedaController) error {
logger.Info("Reconciling KEDA Admission Webhooks deployment")
transforms := []mf.Transformer{
mf.InjectOwner(instance),
transform.ReplaceWatchNamespace(instance.Spec.WatchNamespace, "keda-admission-webhooks", r.Scheme, logger),
}

// certificates rotation works only on Openshift due to openshift/service-ca-operator
if util.RunningOnOpenshift(ctx, logger, r.Client) {
serviceName := "keda-admission-webhooks"
certsSecretName := serviceName + "-certs"

transforms = append(
transforms, transform.EnsureCABundleInjectionForValidatingWebhookConfiguration(injectCABundleAnnotation, injectCABundleAnnotationValue, r.Scheme),
transform.EnsureCertInjectionForService(serviceName, servingCertsAnnotation, certsSecretName),
transform.AdmissionWebhooksEnsureCertificatesVolume(caBundleConfigMapName, certsSecretName, r.Scheme),
)
}

// Use alternate image spec if env var set
if controllerImage := os.Getenv("KEDA_ADMISSION_WEBHOOKS_IMAGE"); len(controllerImage) > 0 {
transforms = append(transforms, transform.ReplaceAdmissionWebhooksImage(controllerImage, r.Scheme))
Expand Down

0 comments on commit 32d8da1

Please sign in to comment.