From 972cdbe75b892e975c1534ec62deef68ca7e6458 Mon Sep 17 00:00:00 2001 From: James Petersen Date: Tue, 10 Dec 2024 16:56:21 -0700 Subject: [PATCH] feat: add chart ci (#1) * feat: add chart ci Signed-off-by: James Petersen * chore: bump chart version Signed-off-by: James Petersen * feat: add chart maintainers Signed-off-by: James Petersen * chore: update chart docs Signed-off-by: James Petersen * chore: prepare testing environment Signed-off-by: James Petersen * chore: update chart docs Signed-off-by: James Petersen * chore: create namespace Signed-off-by: James Petersen * chore: set default object selector Signed-off-by: James Petersen * feat: add docs Signed-off-by: James Petersen * chore: fix values Signed-off-by: James Petersen * chore: test self signed Signed-off-by: James Petersen * chore: test self signed more Signed-off-by: James Petersen --------- Signed-off-by: James Petersen --- .github/workflows/helm-test.yaml | 17 ++++++- README.md | 26 +++++++++++ Taskfile.yaml | 27 +++++++++-- charts/protect-webhook/Chart.yaml | 23 ++-------- charts/protect-webhook/README.md | 42 +++++++++++++++++ .../ci/self-signed-values.yaml | 12 +++++ .../templates/tests/test-connection.yaml | 15 ------ charts/protect-webhook/templates/webhook.yaml | 2 +- charts/protect-webhook/values.yaml | 34 ++++++++++---- examples/self-signed-certs/README.md | 22 +++++++++ .../self-signed-certs/self-signed-certs.yaml | 46 +++++++++++++++++++ examples/self-signed-certs/values.yaml | 1 + 12 files changed, 219 insertions(+), 48 deletions(-) create mode 100644 README.md create mode 100644 charts/protect-webhook/README.md create mode 100644 charts/protect-webhook/ci/self-signed-values.yaml delete mode 100644 charts/protect-webhook/templates/tests/test-connection.yaml create mode 100644 examples/self-signed-certs/README.md create mode 100644 examples/self-signed-certs/self-signed-certs.yaml create mode 120000 examples/self-signed-certs/values.yaml diff --git a/.github/workflows/helm-test.yaml b/.github/workflows/helm-test.yaml index 70f0499..cae0afa 100644 --- a/.github/workflows/helm-test.yaml +++ b/.github/workflows/helm-test.yaml @@ -61,9 +61,24 @@ jobs: if: steps.list-changed.outputs.changed == 'true' uses: helm/kind-action@v1.10.0 + - name: Prepare cluster for tests + if: steps.list-changed.outputs.changed == 'true' + run: | + helm repo add jetstack https://charts.jetstack.io + helm repo update + helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --set installCRDs=true + kubectl create namespace edera-system + kubectl apply -f ./examples/self-signed-certs/self-signed-certs.yaml \ + --namespace edera-system + - name: Run chart-testing (install) if: steps.list-changed.outputs.changed == 'true' run: | - ct install --target-branch ${DEFAULT_BRANCH} + ct install \ + --namespace edera-system \ + --target-branch ${DEFAULT_BRANCH} env: DEFAULT_BRANCH: ${{ github.event.repository.default_branch }} diff --git a/README.md b/README.md new file mode 100644 index 0000000..eb2d4d1 --- /dev/null +++ b/README.md @@ -0,0 +1,26 @@ +# Edera Protect Runtime Class Injector + +This repo contains a mutating webhook to inject the `edera` runtime class into a kubernetes manifest. + +### Why would I want this? + +Edera Protect provides strong isolation for kubernetes workloads (see [edera.dev](https://edera.dev) +for more details). It does so by utilizing a runtime class name to specify whichworkloads should be +isolated. Some upstream projects don't have a way to specify a runtime class name so you can make +use of this webhook to inject it into the manifest upon creation. You also might not want to edit +every manifest you've ever created. Instead you can just use this mutating webhook to set a runtime +class name for manifests without ever touching their yaml. + +### Quickstart + +You can get started quickly by setting up self-signed certificates and then deploying the helm chart. +It deploys a mutating webhook which needs certs to communicate with the API Server. You can find an +example using self signed certs in the [examples/self-signed-certs](./examples/self-signed-certs/) +directory. Once the certificates are in place, install the mutating webhook and accompanying server + +```bash +helm upgrade --install mutate oci://ghcr.io/edera-dev/charts/protect-webhook \ + --namespace edera-system \ + --create-namespace \ + --values ./examples/self-signed-certs/values.yaml +``` diff --git a/Taskfile.yaml b/Taskfile.yaml index 4d206a4..0b6f3fd 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -1,13 +1,34 @@ version: '3' vars: - REGISTRY: 'ttl.sh/beet' + REGISTRY: 'ttl.sh/protect' tasks: - build-*: + build-image: vars: - IMAGE: '{{index .MATCH 0}}' + IMAGE: 'protect-webhook' cmds: - docker buildx build --platform linux/amd64 -t {{ .REGISTRY }}/{{ .IMAGE }}:latest . - echo "Built {{ .REGISTRY }}/{{ .IMAGE }}:latest" - docker push {{ .REGISTRY }}/{{ .IMAGE }}:latest + + install-cert-manager: + cmds: + - helm repo add jetstack https://charts.jetstack.io + - helm repo update + - | + helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --set installCRDs=true + + install-self-signed-certs: + preconditions: + - test -f ./examples/self-signed-certs/self-signed-certs.yaml + cmds: + - kubectl create namespace edera-system + - kubectl apply -f ./examples/self-signed-certs/self-signed-certs.yaml -n edera-system + + chart-test: + cmds: + - ct install --target-branch main --namespace edera-system diff --git a/charts/protect-webhook/Chart.yaml b/charts/protect-webhook/Chart.yaml index ee66aec..51aad53 100644 --- a/charts/protect-webhook/Chart.yaml +++ b/charts/protect-webhook/Chart.yaml @@ -1,24 +1,9 @@ apiVersion: v2 name: protect-webhook description: A Helm chart for the Edera Protect Mutating Webhook - -# 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. +version: 0.1.1 appVersion: "0.1.0" +maintainers: + - name: "Edera" + url: "https://github.com/edera-dev" diff --git a/charts/protect-webhook/README.md b/charts/protect-webhook/README.md new file mode 100644 index 0000000..55695cc --- /dev/null +++ b/charts/protect-webhook/README.md @@ -0,0 +1,42 @@ +# protect-webhook + +![Version: 0.1.1](https://img.shields.io/badge/Version-0.1.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 0.1.0](https://img.shields.io/badge/AppVersion-0.1.0-informational?style=flat-square) + +A Helm chart for the Edera Protect Mutating Webhook + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| Edera | | | + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| affinity | object | `{}` | Webhook server affinity | +| fullnameOverride | string | `""` | | +| image.pullPolicy | string | `"IfNotPresent"` | This sets the pull policy for images | +| image.repository | string | `"ghcr.io/edera-dev/protect-webhook"` | | +| image.tag | string | `"latest"` | Overrides the image tag whose default is the chart appVersion | +| imagePullSecrets | list | `[]` | This is for the secretes for pulling an image from a private repository | +| livenessProbe | object | `{"tcpSocket":{"port":8443}}` | Webhook server liveness probe | +| logLevel | string | `"info"` | Webhook server log level | +| nameOverride | string | `""` | This is to override the chart name | +| nodeSelector | object | `{}` | Webhook server node selector | +| podAnnotations | object | `{}` | Webhook server pod annotations | +| podLabels | object | `{}` | Webhook server pod labels | +| podSecurityContext | object | `{}` | Webhook server pod security context | +| readinessProbe | object | `{"tcpSocket":{"port":8443}}` | Webhook server readiness probe | +| replicaCount | int | `1` | Webhook server replica count | +| resources | object | `{}` | Webhook server resources | +| securityContext | object | `{}` | Webhook server security context | +| service | object | `{"port":443,"type":"ClusterIP"}` | Webhook server service definition | +| tolerations | list | `[]` | Webhook server tolerations | +| volumeMounts | list | `[]` | Webhook server additional volume mounts | +| volumes | list | `[]` | Webhook server additional volumes | +| webhook | object | `{"objectSelector":{"matchLabels":{"dev.edera/inject-runtime":"true"}}}` | Mutating webhook configuration | +| webhook.objectSelector | object | `{"matchLabels":{"dev.edera/inject-runtime":"true"}}` | This object selector lets you customize which labels you would like to filter on to inject the edera runtime class | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/charts/protect-webhook/ci/self-signed-values.yaml b/charts/protect-webhook/ci/self-signed-values.yaml new file mode 100644 index 0000000..3a0fade --- /dev/null +++ b/charts/protect-webhook/ci/self-signed-values.yaml @@ -0,0 +1,12 @@ +podAnnotations: + cert-manager.io/inject-ca-from: edera-system/webhook-ca + +volumes: + - name: webhook-tls + secret: + secretName: webhook-server-tls + +volumeMounts: + - name: webhook-tls + mountPath: /certs + readOnly: true diff --git a/charts/protect-webhook/templates/tests/test-connection.yaml b/charts/protect-webhook/templates/tests/test-connection.yaml deleted file mode 100644 index d08c67d..0000000 --- a/charts/protect-webhook/templates/tests/test-connection.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: "{{ include "protect-webhook.fullname" . }}-test-connection" - labels: - {{- include "protect-webhook.labels" . | nindent 4 }} - annotations: - "helm.sh/hook": test -spec: - containers: - - name: wget - image: busybox - command: ['wget'] - args: ['{{ include "protect-webhook.fullname" . }}:{{ .Values.service.port }}'] - restartPolicy: Never diff --git a/charts/protect-webhook/templates/webhook.yaml b/charts/protect-webhook/templates/webhook.yaml index 763b75b..0212de1 100644 --- a/charts/protect-webhook/templates/webhook.yaml +++ b/charts/protect-webhook/templates/webhook.yaml @@ -13,7 +13,7 @@ webhooks: clientConfig: service: name: {{ include "protect-webhook.fullname" . }} - namespace: {{ .Values.webhook.serviceNamespace | default "default" }} + namespace: {{ .Values.webhook.serviceNamespace | default .Release.Namespace }} path: /mutate {{- if .Values.webhook }} {{- if .Values.webhook.objectSelector }} diff --git a/charts/protect-webhook/values.yaml b/charts/protect-webhook/values.yaml index 3dfa6dd..ad74a31 100644 --- a/charts/protect-webhook/values.yaml +++ b/charts/protect-webhook/values.yaml @@ -1,56 +1,72 @@ # Default values for protect-webhook. +# -- Webhook server replica count replicaCount: 1 image: repository: ghcr.io/edera-dev/protect-webhook - # This sets the pull policy for images. + # -- This sets the pull policy for images pullPolicy: IfNotPresent - # Overrides the image tag whose default is the chart appVersion. + # -- Overrides the image tag whose default is the chart appVersion tag: "latest" -# This is for the secretes for pulling an image from a private repository more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ +# -- This is for the secretes for pulling an image from a private repository imagePullSecrets: [] -# This is to override the chart name. +# -- This is to override the chart name nameOverride: "" fullnameOverride: "" +# -- Webhook server pod annotations podAnnotations: {} +# -- Webhook server pod labels podLabels: {} +# -- Webhook server pod security context podSecurityContext: {} +# -- Webhook server security context securityContext: {} +# -- Webhook server log level logLevel: info -# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +# -- Webhook server service definition service: type: ClusterIP port: 443 +# -- Webhook server resources resources: {} -# This is to setup the liveness and readiness probes more information can be found here: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ +# -- Webhook server liveness probe livenessProbe: tcpSocket: port: 8443 + +# -- Webhook server readiness probe readinessProbe: tcpSocket: port: 8443 -# Additional volumes on the output Deployment definition. +# -- Webhook server additional volumes volumes: [] -# Additional volumeMounts on the output Deployment definition. +# -- Webhook server additional volume mounts volumeMounts: [] +# -- Webhook server node selector nodeSelector: {} +# -- Webhook server tolerations tolerations: [] +# -- Webhook server affinity affinity: {} +# -- Mutating webhook configuration webhook: - serviceNamespace: edera-system + # -- This object selector lets you customize which labels you would like to filter on to inject the edera runtime class + objectSelector: + matchLabels: + dev.edera/inject-runtime: "true" diff --git a/examples/self-signed-certs/README.md b/examples/self-signed-certs/README.md new file mode 100644 index 0000000..89e63f6 --- /dev/null +++ b/examples/self-signed-certs/README.md @@ -0,0 +1,22 @@ +# Using Cert Manager to generate self-signed certs + +Start by installing cert-manager + +```bash +helm repo add jetstack https://charts.jetstack.io +helm repo update +helm install cert-manager jetstack/cert-manager \ + --namespace cert-manager \ + --create-namespace \ + --set installCRDs=true +``` + +Next apply the manifest in the `edera-system` namespace + +**NOTE:** you may need to create the `edera-system` namespace with `kubectl create namespace edera-system` + +```bash +kubectl apply -f ./self-signed-certs.yaml --namespace edera-system +``` + +This should configure all the certificates and secrets you need to configure the mutating webhook. diff --git a/examples/self-signed-certs/self-signed-certs.yaml b/examples/self-signed-certs/self-signed-certs.yaml new file mode 100644 index 0000000..3132f36 --- /dev/null +++ b/examples/self-signed-certs/self-signed-certs.yaml @@ -0,0 +1,46 @@ +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: self-signed +spec: + selfSigned: {} + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: webhook-ca +spec: + isCA: true + duration: 8760h # 1 year + secretName: webhook-ca-secret + commonName: webhook-ca + issuerRef: + name: self-signed + kind: Issuer + +--- +apiVersion: cert-manager.io/v1 +kind: Issuer +metadata: + name: webhook-ca-issuer +spec: + ca: + secretName: webhook-ca-secret + +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: webhook-server-cert +spec: + duration: 8760h # 1 year + secretName: webhook-server-tls + commonName: webhook-service.default.svc + dnsNames: + - mutate-protect-webhook.edera-system.svc + - mutate-protect-webhook.edera-system.svc.cluster.local + issuerRef: + name: webhook-ca-issuer + kind: Issuer diff --git a/examples/self-signed-certs/values.yaml b/examples/self-signed-certs/values.yaml new file mode 120000 index 0000000..07af366 --- /dev/null +++ b/examples/self-signed-certs/values.yaml @@ -0,0 +1 @@ +../../charts/protect-webhook/ci/self-signed-values.yaml \ No newline at end of file