diff --git a/charts/cert-manager-webhook-hetzner/.helmignore b/charts/cert-manager-webhook-hetzner/.helmignore new file mode 100644 index 0000000..f0c1319 --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/.helmignore @@ -0,0 +1,21 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*~ +# Various IDEs +.project +.idea/ +*.tmproj diff --git a/charts/cert-manager-webhook-hetzner/Chart.yaml b/charts/cert-manager-webhook-hetzner/Chart.yaml new file mode 100644 index 0000000..245af5e --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/Chart.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +description: A Helm chart for the Hetzner DNS webhook for cert-manager +name: cert-manager-webhook-hetzner +version: 0.1.1 +appVersion: 0.1.1 +maintainers: + - name: mecodia GmbH + url: https://github.com/mecodia/cert-manager-webhook-hetzner diff --git a/charts/cert-manager-webhook-hetzner/templates/NOTES.txt b/charts/cert-manager-webhook-hetzner/templates/NOTES.txt new file mode 100644 index 0000000..e69de29 diff --git a/charts/cert-manager-webhook-hetzner/templates/_helpers.tpl b/charts/cert-manager-webhook-hetzner/templates/_helpers.tpl new file mode 100644 index 0000000..253a87a --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/_helpers.tpl @@ -0,0 +1,48 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "cert-manager-webhook-hetzner.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "cert-manager-webhook-hetzner.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "cert-manager-webhook-hetzner.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "cert-manager-webhook-hetzner.selfSignedIssuer" -}} +{{ printf "%s-selfsign" (include "cert-manager-webhook-hetzner.fullname" .) }} +{{- end -}} + +{{- define "cert-manager-webhook-hetzner.rootCAIssuer" -}} +{{ printf "%s-ca" (include "cert-manager-webhook-hetzner.fullname" .) }} +{{- end -}} + +{{- define "cert-manager-webhook-hetzner.rootCACertificate" -}} +{{ printf "%s-ca" (include "cert-manager-webhook-hetzner.fullname" .) }} +{{- end -}} + +{{- define "cert-manager-webhook-hetzner.servingCertificate" -}} +{{ printf "%s-webhook-tls" (include "cert-manager-webhook-hetzner.fullname" .) }} +{{- end -}} diff --git a/charts/cert-manager-webhook-hetzner/templates/apiservice.yaml b/charts/cert-manager-webhook-hetzner/templates/apiservice.yaml new file mode 100644 index 0000000..6c6a657 --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/apiservice.yaml @@ -0,0 +1,19 @@ +apiVersion: apiregistration.k8s.io/v1 +kind: APIService +metadata: + name: v1alpha1.{{ .Values.groupName }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} + annotations: + cert-manager.io/inject-ca-from: "{{ .Release.Namespace }}/{{ include "cert-manager-webhook-hetzner.servingCertificate" . }}" +spec: + group: {{ .Values.groupName }} + groupPriorityMinimum: 1000 + versionPriority: 15 + service: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} + version: v1alpha1 diff --git a/charts/cert-manager-webhook-hetzner/templates/deployment.yaml b/charts/cert-manager-webhook-hetzner/templates/deployment.yaml new file mode 100644 index 0000000..808428d --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/deployment.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + release: {{ .Release.Name }} + template: + metadata: + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + release: {{ .Release.Name }} + spec: + serviceAccountName: {{ include "cert-manager-webhook-hetzner.fullname" . }} + containers: + - name: {{ .Chart.Name }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + args: + - --tls-cert-file=/tls/tls.crt + - --tls-private-key-file=/tls/tls.key + - --secure-port=8443 + env: + - name: GROUP_NAME + value: {{ .Values.groupName | quote }} + ports: + - name: https + containerPort: 8443 + protocol: TCP + livenessProbe: + httpGet: + scheme: HTTPS + path: /healthz + port: 8443 + readinessProbe: + httpGet: + scheme: HTTPS + path: /healthz + port: 8443 + volumeMounts: + - name: certs + mountPath: /tls + readOnly: true + resources: +{{ toYaml .Values.resources | indent 12 }} + volumes: + - name: certs + secret: + secretName: {{ include "cert-manager-webhook-hetzner.servingCertificate" . }} + {{- with .Values.nodeSelector }} + nodeSelector: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.affinity }} + affinity: +{{ toYaml . | indent 8 }} + {{- end }} + {{- with .Values.tolerations }} + tolerations: +{{ toYaml . | indent 8 }} + {{- end }} diff --git a/charts/cert-manager-webhook-hetzner/templates/pki.yaml b/charts/cert-manager-webhook-hetzner/templates/pki.yaml new file mode 100644 index 0000000..366388e --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/pki.yaml @@ -0,0 +1,76 @@ +--- +# Create a selfsigned Issuer, in order to create a root CA certificate for +# signing webhook serving certificates +apiVersion: cert-manager.io/v1alpha3 +kind: Issuer +metadata: + name: {{ include "cert-manager-webhook-hetzner.selfSignedIssuer" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + selfSigned: {} + +--- + +# Generate a CA Certificate used to sign certificates for the webhook +apiVersion: cert-manager.io/v1alpha3 +kind: Certificate +metadata: + name: {{ include "cert-manager-webhook-hetzner.rootCACertificate" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + secretName: {{ include "cert-manager-webhook-hetzner.rootCACertificate" . }} + duration: 43800h # 5y + issuerRef: + name: {{ include "cert-manager-webhook-hetzner.selfSignedIssuer" . }} + commonName: "ca.cert-manager-webhook-hetzner.cert-manager" + isCA: true + +--- + +# Create an Issuer that uses the above generated CA certificate to issue certs +apiVersion: cert-manager.io/v1alpha3 +kind: Issuer +metadata: + name: {{ include "cert-manager-webhook-hetzner.rootCAIssuer" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + ca: + secretName: {{ include "cert-manager-webhook-hetzner.rootCACertificate" . }} + +--- + +# Finally, generate a serving certificate for the webhook to use +apiVersion: cert-manager.io/v1alpha3 +kind: Certificate +metadata: + name: {{ include "cert-manager-webhook-hetzner.servingCertificate" . }} + namespace: {{ .Release.Namespace | quote }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + secretName: {{ include "cert-manager-webhook-hetzner.servingCertificate" . }} + duration: 8760h # 1y + issuerRef: + name: {{ include "cert-manager-webhook-hetzner.rootCAIssuer" . }} + dnsNames: + - {{ include "cert-manager-webhook-hetzner.fullname" . }} + - {{ include "cert-manager-webhook-hetzner.fullname" . }}.{{ .Release.Namespace }} + - {{ include "cert-manager-webhook-hetzner.fullname" . }}.{{ .Release.Namespace }}.svc diff --git a/charts/cert-manager-webhook-hetzner/templates/rbac.yaml b/charts/cert-manager-webhook-hetzner/templates/rbac.yaml new file mode 100644 index 0000000..c942413 --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/rbac.yaml @@ -0,0 +1,91 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +--- +# Grant the webhook permission to read the ConfigMap containing the Kubernetes +# apiserver's requestheader-ca-certificate. +# This ConfigMap is automatically created by the Kubernetes apiserver. +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }}:webhook-authentication-reader + namespace: kube-system + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: extension-apiserver-authentication-reader +subjects: + - apiGroup: "" + kind: ServiceAccount + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} +--- +# apiserver gets the auth-delegator role to delegate auth decisions to +# the core apiserver +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }}:auth-delegator + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: system:auth-delegator +subjects: + - apiGroup: "" + kind: ServiceAccount + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} +--- +# Grant cert-manager permission to validate using our apiserver +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }}:domain-solver + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +rules: + - apiGroups: + - {{ .Values.groupName }} + resources: + - '*' + verbs: + - 'create' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }}:domain-solver + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "cert-manager-webhook-hetzner.fullname" . }}:domain-solver +subjects: + - apiGroup: "" + kind: ServiceAccount + name: {{ .Values.certManager.serviceAccountName }} + namespace: {{ .Release.Namespace }} diff --git a/charts/cert-manager-webhook-hetzner/templates/service.yaml b/charts/cert-manager-webhook-hetzner/templates/service.yaml new file mode 100644 index 0000000..f6604e0 --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "cert-manager-webhook-hetzner.fullname" . }} + namespace: {{ .Release.Namespace }} + labels: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + chart: {{ include "cert-manager-webhook-hetzner.chart" . }} + release: {{ .Release.Name }} + heritage: {{ .Release.Service }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: 8443 + protocol: TCP + name: https + selector: + app: {{ include "cert-manager-webhook-hetzner.name" . }} + release: {{ .Release.Name }} diff --git a/charts/cert-manager-webhook-hetzner/values.yaml b/charts/cert-manager-webhook-hetzner/values.yaml new file mode 100644 index 0000000..4f57511 --- /dev/null +++ b/charts/cert-manager-webhook-hetzner/values.yaml @@ -0,0 +1,45 @@ +# The GroupName here is used to identify your company or business unit that +# created this webhook. +# For hetzner, this may be "acme.mycompany.com". +# This name will need to be referenced in each Issuer's `webhook` stanza to +# inform cert-manager of where to send ChallengePayload resources in order to +# solve the DNS01 challenge. +# This group name should be **unique**, hence using your own company's domain +# here is recommended. +groupName: dns.hetzner.cloud + +certManager: + namespace: cert-manager + serviceAccountName: cert-manager + +image: + repository: mecodia/cert-manager-webhook-hetzner + tag: latest + pullPolicy: Always + +nameOverride: "webhook-hetzner" +fullnameOverride: "cert-manager-webhook-hetzner" + +replicaCount: 1 + +service: + type: ClusterIP + port: 443 + +resources: {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 128Mi + # requests: + # cpu: 100m + # memory: 128Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {}