Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

use OpenShift certs & CA #189

Merged
merged 1 commit into from
May 30, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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