Skip to content

Commit

Permalink
feat(webhook): add webhook to validate kepler resource
Browse files Browse the repository at this point in the history
Previously, when user created kepler with name other `kepler`, k8s API
server would accept the resource and create it. The operator then
updates the status of the resource to be `invalid`. This is now changed
by adding Validating webhook that rejects the resource if the name does
not match `kepler`.

Signed-off-by: Sunil Thaha <sthaha@redhat.com>
  • Loading branch information
sthaha committed Feb 22, 2024
1 parent d3bce3d commit 0dc7a28
Show file tree
Hide file tree
Showing 21 changed files with 442 additions and 24 deletions.
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ else
GOBIN=$(shell go env GOBIN)
endif

# WEBHOOKS
ENABLE_WEBHOOKS ?= true # enable webhooks by default

# Setting GOENV
GOOS := $(shell go env GOOS)
GOARCH := $(shell go env GOARCH)
Expand Down
5 changes: 4 additions & 1 deletion PROJECT
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@ repo: github.com/sustainable.computing.io/kepler-operator
resources:
- api:
crdVersion: v1
namespaced: true
controller: true
domain: sustainable.computing.io
group: kepler.system
kind: Kepler
path: github.com/sustainable.computing.io/kepler-operator/api/v1alpha1
version: v1alpha1
webhooks:
defaulting: true
validation: true
webhookVersion: v1
version: "3"
23 changes: 23 additions & 0 deletions bundle/manifests/kepler-operator-webhook-service_v1_service.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
apiVersion: v1
kind: Service
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/component: webhook
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/instance: webhook-service
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: service
app.kubernetes.io/part-of: kepler-operator
name: kepler-operator-webhook-service
spec:
ports:
- port: 443
protocol: TCP
targetPort: 9443
selector:
app.kubernetes.io/component: manager
app.kubernetes.io/instance: controller-manager
app.kubernetes.io/part-of: kepler-operator
status:
loadBalancer: {}
61 changes: 60 additions & 1 deletion bundle/manifests/kepler-operator.clusterserviceversion.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ metadata:
capabilities: Basic Install
categories: Monitoring
containerImage: quay.io/sustainable_computing_io/kepler-operator:0.10.0
createdAt: "2024-01-16T09:18:34Z"
createdAt: "2024-02-15T04:47:16Z"
description: 'Deploys and Manages Kepler on Kubernetes '
operators.operatorframework.io/builder: operator-sdk-v1.27.0
operators.operatorframework.io/internal-objects: |-
Expand Down Expand Up @@ -270,6 +270,9 @@ spec:
periodSeconds: 20
name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
- containerPort: 8080
name: metrics
protocol: TCP
Expand All @@ -291,6 +294,10 @@ spec:
capabilities:
drop:
- ALL
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
securityContext:
runAsNonRoot: true
serviceAccountName: kepler-operator-controller-manager
Expand Down Expand Up @@ -366,3 +373,55 @@ spec:
name: kepler
replaces: kepler-operator.v0.9.2
version: 0.10.0
webhookdefinitions:
- admissionReviewVersions:
- v1
containerPort: 443
conversionCRDs:
- keplers.kepler.system.sustainable.computing.io
deploymentName: kepler-operator-controller
generateName: ckeplers.kb.io
sideEffects: None
targetPort: 9443
type: ConversionWebhook
webhookPath: /convert
- admissionReviewVersions:
- v1
containerPort: 443
deploymentName: kepler-operator-controller
failurePolicy: Fail
generateName: mkepler.kb.io
rules:
- apiGroups:
- kepler.system.sustainable.computing.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- keplers
sideEffects: None
targetPort: 9443
type: MutatingAdmissionWebhook
webhookPath: /mutate-kepler-system-sustainable-computing-io-v1alpha1-kepler
- admissionReviewVersions:
- v1
containerPort: 443
deploymentName: kepler-operator-controller
failurePolicy: Fail
generateName: vkepler.kb.io
rules:
- apiGroups:
- kepler.system.sustainable.computing.io
apiVersions:
- v1alpha1
operations:
- CREATE
- UPDATE
resources:
- keplers
sideEffects: None
targetPort: 9443
type: ValidatingAdmissionWebhook
webhookPath: /validate-kepler-system-sustainable-computing-io-v1alpha1-kepler
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ metadata:
creationTimestamp: null
name: keplers.kepler.system.sustainable.computing.io
spec:
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
name: kepler-operator-webhook-service
namespace: kepler-operator-system
path: /convert
conversionReviewVersions:
- v1
group: kepler.system.sustainable.computing.io
names:
kind: Kepler
Expand Down
17 changes: 17 additions & 0 deletions cmd/manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package main

import (
"flag"
"fmt"
"os"
"strings"

Expand Down Expand Up @@ -169,6 +170,15 @@ func main() {
setupLog.Error(err, "unable to create controller", "controller", "kepler-internal")
os.Exit(1)
}

// Setup webhooks
if os.Getenv("ENABLE_WEBHOOKS") != "false" {
if err = setupWebhooks(mgr); err != nil {
setupLog.Error(err, "unable to create webhook")
os.Exit(1)
}
}

//+kubebuilder:scaffold:builder

if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
Expand All @@ -186,3 +196,10 @@ func main() {
os.Exit(1)
}
}

func setupWebhooks(mgr ctrl.Manager) error {
if err := (&keplersystemv1alpha1.Kepler{}).SetupWebhookWithManager(mgr); err != nil {
return fmt.Errorf("unable to create webhook: %v", err)
}
return nil
}
39 changes: 39 additions & 0 deletions config/certmanager/certificate.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# The following manifests contain a self-signed issuer CR and a certificate CR.
# More document can be found at https://docs.cert-manager.io
# WARNING: Targets CertManager v1.0. Check https://cert-manager.io/docs/installation/upgrading/ for breaking changes.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
labels:
app.kubernetes.io/name: issuer
app.kubernetes.io/instance: selfsigned-issuer
app.kubernetes.io/component: certificate
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/part-of: kepler-operator
app.kubernetes.io/managed-by: kustomize
name: selfsigned-issuer
namespace: system
spec:
selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
labels:
app.kubernetes.io/name: certificate
app.kubernetes.io/instance: serving-cert
app.kubernetes.io/component: certificate
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/part-of: kepler-operator
app.kubernetes.io/managed-by: kustomize
name: serving-cert # this name should match the one appeared in kustomizeconfig.yaml
namespace: system
spec:
# $(SERVICE_NAME) and $(SERVICE_NAMESPACE) will be substituted by kustomize
dnsNames:
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc
- $(SERVICE_NAME).$(SERVICE_NAMESPACE).svc.cluster.local
issuerRef:
kind: Issuer
name: selfsigned-issuer
secretName: webhook-server-cert # this secret will not be prefixed, since it's not managed by kustomize
5 changes: 5 additions & 0 deletions config/certmanager/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resources:
- certificate.yaml

configurations:
- kustomizeconfig.yaml
16 changes: 16 additions & 0 deletions config/certmanager/kustomizeconfig.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# This configuration is for teaching kustomize how to update name ref and var substitution
nameReference:
- kind: Issuer
group: cert-manager.io
fieldSpecs:
- kind: Certificate
group: cert-manager.io
path: spec/issuerRef/name

varReference:
- kind: Certificate
group: cert-manager.io
path: spec/commonName
- kind: Certificate
group: cert-manager.io
path: spec/dnsNames
2 changes: 1 addition & 1 deletion config/crd/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ resources:
patchesStrategicMerge:
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix.
# patches here are for enabling the conversion webhook for each CRD
#- patches/webhook_in_keplers.yaml
- patches/webhook_in_keplers.yaml
#+kubebuilder:scaffold:crdkustomizewebhookpatch

# [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
Expand Down
4 changes: 2 additions & 2 deletions config/default/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ bases:
- ../manager
# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- ../webhook
- ../webhook
# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'. 'WEBHOOK' components are required.
#- ../certmanager
# [PROMETHEUS] To enable prometheus monitor, uncomment all sections with 'PROMETHEUS'.
Expand All @@ -34,7 +34,7 @@ patchesStrategicMerge:

# [WEBHOOK] To enable webhook, uncomment all the sections with [WEBHOOK] prefix including the one in
# crd/kustomization.yaml
#- manager_webhook_patch.yaml
- manager_webhook_patch.yaml

# [CERTMANAGER] To enable cert-manager, uncomment all sections with 'CERTMANAGER'.
# Uncomment 'CERTMANAGER' sections in crd/kustomization.yaml to enable the CA injection in the admission webhooks.
Expand Down
25 changes: 25 additions & 0 deletions config/default/manager_webhook_patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: controller
namespace: system
spec:
template:
spec:
containers:
- name: manager
ports:
- containerPort: 9443
name: webhook-server
protocol: TCP
volumeMounts:
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
# NOTE: this will be removed by the manager kustomization.yaml
# since OLM will add the volume
volumes:
- name: cert
secret:
defaultMode: 420
secretName: webhook-server-cert
29 changes: 29 additions & 0 deletions config/default/webhookcainjection_patch.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This patch add annotation to admission webhook config and
# the variables $(CERTIFICATE_NAMESPACE) and $(CERTIFICATE_NAME) will be substituted by kustomize.
apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/name: mutatingwebhookconfiguration
app.kubernetes.io/instance: mutating-webhook-configuration
app.kubernetes.io/component: webhook
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/part-of: kepler-operator
app.kubernetes.io/managed-by: kustomize
name: mutating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
---
apiVersion: admissionregistration.k8s.io/v1
kind: ValidatingWebhookConfiguration
metadata:
labels:
app.kubernetes.io/name: validatingwebhookconfiguration
app.kubernetes.io/instance: validating-webhook-configuration
app.kubernetes.io/component: webhook
app.kubernetes.io/created-by: kepler-operator
app.kubernetes.io/part-of: kepler-operator
app.kubernetes.io/managed-by: kustomize
name: validating-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
32 changes: 16 additions & 16 deletions config/manifests/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,19 @@ resources:
# [WEBHOOK] To enable webhooks, uncomment all the sections with [WEBHOOK] prefix.
# Do NOT uncomment sections with prefix [CERTMANAGER], as OLM does not support cert-manager.
# These patches remove the unnecessary "cert" volume and its manager container volumeMount.
#patchesJson6902:
#- target:
# group: apps
# version: v1
# kind: Deployment
# name: controller-manager
# namespace: system
# patch: |-
# # Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs.
# # Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.
# - op: remove
# path: /spec/template/spec/containers/1/volumeMounts/0
# # Remove the "cert" volume, since OLM will create and mount a set of certs.
# # Update the indices in this path if adding or removing volumes in the manager's Deployment.
# - op: remove
# path: /spec/template/spec/volumes/0
patchesJson6902:
- target:
group: apps
version: v1
kind: Deployment
name: controller-manager
namespace: system
patch: |-
# Remove the manager container's "cert" volumeMount, since OLM will create and mount a set of certs.
# Update the indices in this path if adding or removing containers/volumeMounts in the manager's Deployment.
- op: remove
path: /spec/template/spec/containers/0/volumeMounts/0
# Remove the "cert" volume, since OLM will create and mount a set of certs.
# Update the indices in this path if adding or removing volumes in the manager's Deployment.
- op: remove
path: /spec/template/spec/volumes/0
6 changes: 6 additions & 0 deletions config/webhook/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resources:
- manifests.yaml
- service.yaml

configurations:
- kustomizeconfig.yaml
Loading

0 comments on commit 0dc7a28

Please sign in to comment.