feat: add goddady webhook for cluster_issuer (#942)

diff --git a/charts/cert-manager-webhook-godaddy/.helmignore b/charts/cert-manager-webhook-godaddy/.helmignore
new file mode 100644
index 0000000..50af031
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/.helmignore
@@ -0,0 +1,22 @@
+# 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
+.vscode/
diff --git a/charts/cert-manager-webhook-godaddy/Chart.yaml b/charts/cert-manager-webhook-godaddy/Chart.yaml
new file mode 100644
index 0000000..7a4de81
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/Chart.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+appVersion: 0.3.0
+description: Cert Manager godaddy webhook Helm chart
+name: godaddy-webhook
+version: 0.3.0
diff --git a/charts/cert-manager-webhook-godaddy/templates/NOTES.txt b/charts/cert-manager-webhook-godaddy/templates/NOTES.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/NOTES.txt
diff --git a/charts/cert-manager-webhook-godaddy/templates/_helpers.tpl b/charts/cert-manager-webhook-godaddy/templates/_helpers.tpl
new file mode 100644
index 0000000..fe851b1
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/_helpers.tpl
@@ -0,0 +1,64 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "godaddy-webhook.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 "godaddy-webhook.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 "godaddy-webhook.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "godaddy-webhook.labels" -}}
+app.kubernetes.io/name: {{ include "godaddy-webhook.name" . }}
+helm.sh/chart: {{ include "godaddy-webhook.chart" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+PKI
+*/}}
+{{- define "godaddy-webhook.selfSignedIssuer" -}}
+{{ printf "%s-selfsign" (include "godaddy-webhook.fullname" .) }}
+{{- end -}}
+
+{{- define "godaddy-webhook.rootCAIssuer" -}}
+{{ printf "%s-ca" (include "godaddy-webhook.fullname" .) }}
+{{- end -}}
+
+{{- define "godaddy-webhook.rootCACertificate" -}}
+{{ printf "%s-ca" (include "godaddy-webhook.fullname" .) }}
+{{- end -}}
+
+{{- define "godaddy-webhook.servingCertificate" -}}
+{{ printf "%s-webhook-tls" (include "godaddy-webhook.fullname" .) }}
+{{- end -}}
diff --git a/charts/cert-manager-webhook-godaddy/templates/apiservice.yaml b/charts/cert-manager-webhook-godaddy/templates/apiservice.yaml
new file mode 100644
index 0000000..6289aad
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/apiservice.yaml
@@ -0,0 +1,16 @@
+apiVersion: apiregistration.k8s.io/v1
+kind: APIService
+metadata:
+  name: v1alpha1.{{ .Values.groupName }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+  annotations:
+    cert-manager.io/inject-ca-from: "{{ .Release.Namespace }}/{{ include "godaddy-webhook.servingCertificate" . }}"
+spec:
+  group: {{ .Values.groupName }}
+  groupPriorityMinimum: 1000
+  versionPriority: 15
+  service:
+    name: {{ include "godaddy-webhook.fullname" . }}
+    namespace: {{ .Release.Namespace }}
+  version: v1alpha1
diff --git a/charts/cert-manager-webhook-godaddy/templates/deployment.yaml b/charts/cert-manager-webhook-godaddy/templates/deployment.yaml
new file mode 100644
index 0000000..debfdb5
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/deployment.yaml
@@ -0,0 +1,76 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: {{ include "godaddy-webhook.name" . }}
+      app.kubernetes.io/instance: {{ .Release.Name }}
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: {{ include "godaddy-webhook.name" . }}
+        app.kubernetes.io/instance: {{ .Release.Name }}
+    spec:
+      serviceAccountName: {{ include "godaddy-webhook.fullname" . }}
+    {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+      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={{ default 443 .Values.pod.securePort }}
+          env:
+            - name: GROUP_NAME
+              value: {{ .Values.groupName | quote }}
+            - name: LOGGING_LEVEL
+              value: {{ .Values.logging.level }}
+            - name: LOGGING_FORMAT
+              value: {{ .Values.logging.format }}
+            - name: LOGGING_TIMESTAMP
+              value: {{ .Values.logging.timestamp | quote }}
+          ports:
+            - name: https
+              containerPort: {{ default 443 .Values.pod.securePort }}
+              protocol: TCP
+          livenessProbe:
+            httpGet:
+              scheme: HTTPS
+              path: /healthz
+              port: https
+          readinessProbe:
+            httpGet:
+              scheme: HTTPS
+              path: /healthz
+              port: https
+          volumeMounts:
+            - name: certs
+              mountPath: /tls
+              readOnly: true
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+      volumes:
+        - name: certs
+          secret:
+            secretName: {{ include "godaddy-webhook.servingCertificate" . }}
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+    {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
diff --git a/charts/cert-manager-webhook-godaddy/templates/pki.yaml b/charts/cert-manager-webhook-godaddy/templates/pki.yaml
new file mode 100644
index 0000000..3e68b29
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/pki.yaml
@@ -0,0 +1,64 @@
+---
+# Create a selfsigned Issuer, in order to create a root CA certificate for
+# signing webhook serving certificates
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+  name: {{ include "godaddy-webhook.selfSignedIssuer" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  selfSigned: {}
+
+---
+
+# Generate a CA Certificate used to sign certificates for the webhook
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: {{ include "godaddy-webhook.rootCACertificate" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  secretName: {{ include "godaddy-webhook.rootCACertificate" . }}
+  duration: 43800h # 5y
+  issuerRef:
+    name: {{ include "godaddy-webhook.selfSignedIssuer" . }}
+  commonName: "ca.godaddy-webhook.cert-manager"
+  isCA: true
+
+---
+
+# Create an Issuer that uses the above generated CA certificate to issue certs
+apiVersion: cert-manager.io/v1
+kind: Issuer
+metadata:
+  name: {{ include "godaddy-webhook.rootCAIssuer" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  ca:
+    secretName: {{ include "godaddy-webhook.rootCACertificate" . }}
+
+---
+
+# Finally, generate a serving certificate for the webhook to use
+apiVersion: cert-manager.io/v1
+kind: Certificate
+metadata:
+  name: {{ include "godaddy-webhook.servingCertificate" . }}
+  namespace: {{ .Release.Namespace | quote }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  secretName: {{ include "godaddy-webhook.servingCertificate" . }}
+  duration: 8760h # 1y
+  issuerRef:
+    name: {{ include "godaddy-webhook.rootCAIssuer" . }}
+  dnsNames:
+  - {{ include "godaddy-webhook.fullname" . }}
+  - {{ include "godaddy-webhook.fullname" . }}.{{ .Release.Namespace }}
+  - {{ include "godaddy-webhook.fullname" . }}.{{ .Release.Namespace }}.svc
diff --git a/charts/cert-manager-webhook-godaddy/templates/rbac.yaml b/charts/cert-manager-webhook-godaddy/templates/rbac.yaml
new file mode 100644
index 0000000..69b9315
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/rbac.yaml
@@ -0,0 +1,140 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+---
+# 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 "godaddy-webhook.fullname" . }}:webhook-authentication-reader
+  namespace: kube-system
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: Role
+  name: extension-apiserver-authentication-reader
+subjects:
+  - apiGroup: ""
+    kind: ServiceAccount
+    name: {{ include "godaddy-webhook.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 "godaddy-webhook.fullname" . }}:auth-delegator
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: system:auth-delegator
+subjects:
+  - apiGroup: ""
+    kind: ServiceAccount
+    name: {{ include "godaddy-webhook.fullname" . }}
+    namespace: {{ .Release.Namespace }}
+---
+# Grant cert-manager permission to validate using our apiserver
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}:domain-solver
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+rules:
+  - apiGroups:
+      - {{ .Values.groupName }}
+    resources:
+      - '*'
+    verbs:
+      - 'create'
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}:domain-solver
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: {{ include "godaddy-webhook.fullname" . }}:domain-solver
+subjects:
+  - apiGroup: ""
+    kind: ServiceAccount
+    name: {{ .Values.certManager.serviceAccountName }}
+    namespace: {{ .Values.certManager.namespace }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: {{ include "godaddy-webhook.fullname" . }}
+subjects:
+  - apiGroup: ""
+    kind: ServiceAccount
+    name: {{ include "godaddy-webhook.fullname" . }}
+    namespace: {{ .Release.Namespace }}
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+rules:
+  - apiGroups:
+      - ''
+    resources:
+      - 'secrets'
+    verbs:
+      - 'get'
+---
+# Grant cert-manager-webhook-gandi permission to read the flow control mechanism (APF)
+# API Priority and Fairness is enabled by default in Kubernetes 1.20
+# https://kubernetes.io/docs/concepts/cluster-administration/flow-control/
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}:flowcontrol-solver
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+rules:
+  - apiGroups:
+      - "flowcontrol.apiserver.k8s.io"
+    resources:
+      - "prioritylevelconfigurations"
+      - "flowschemas"
+    verbs:
+      - "list"
+      - "watch"
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}:flowcontrol-solver
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+roleRef:
+  apiGroup: rbac.authorization.k8s.io
+  kind: ClusterRole
+  name: {{ include "godaddy-webhook.fullname" . }}:flowcontrol-solver
+subjects:
+  - apiGroup: ""
+    kind: ServiceAccount
+    name: {{ include "godaddy-webhook.fullname" . }}
+    namespace: {{ .Release.Namespace }}
diff --git a/charts/cert-manager-webhook-godaddy/templates/service.yaml b/charts/cert-manager-webhook-godaddy/templates/service.yaml
new file mode 100644
index 0000000..5c376b8
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/templates/service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "godaddy-webhook.fullname" . }}
+  labels:
+{{ include "godaddy-webhook.labels" . | indent 4 }}
+spec:
+  type: {{ .Values.service.type }}
+  ports:
+    - port: {{ .Values.service.port }}
+      targetPort: https
+      protocol: TCP
+      name: https
+  selector:
+    app.kubernetes.io/name: {{ include "godaddy-webhook.name" . }}
+    app.kubernetes.io/instance: {{ .Release.Name }}
diff --git a/charts/cert-manager-webhook-godaddy/values.yaml b/charts/cert-manager-webhook-godaddy/values.yaml
new file mode 100644
index 0000000..03aa5a8
--- /dev/null
+++ b/charts/cert-manager-webhook-godaddy/values.yaml
@@ -0,0 +1,29 @@
+# Default values for godaddy-webhook.
+# This is a YAML-formatted file.
+# Declare variables to be passed into your templates.
+
+replicaCount: 1
+image:
+  repository: quay.io/snowdrop/cert-manager-webhook-godaddy
+  tag: 0.3.0
+  pullPolicy: IfNotPresent
+pod:
+  securePort:
+logging:
+  level: info # Log level (trace, debug, info, warn, error, fatal, panic)
+  format: color # Log format (text, color, json)
+  timestamp: false # Timestamp in log output: true/false
+groupName: acme.mycompany.com
+certManager:
+  namespace: cert-manager
+  serviceAccountName: cert-manager
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+service:
+  type: ClusterIP
+  port: 443
+resources: {}
+nodeSelector: {}
+tolerations: []
+affinity: {}
diff --git a/roles/cluster_issuer/README.md b/roles/cluster_issuer/README.md
index 6ec4821..68839d0 100644
--- a/roles/cluster_issuer/README.md
+++ b/roles/cluster_issuer/README.md
@@ -64,6 +64,19 @@
    You'll need to make sure that your AWS credentials have the correct
    permissions to update the Route53 zone.
 
+#### Godaddy
+
+If you're using Godaddy for the DNS of your domain, you can use the following
+configuration which depends on
+`cert-manager-webhook-godaddy`[https://github.com/snowdrop/godaddy-webhook].
+
+```yaml
+cluster_issuer_acme_email: user@example.com
+cluster_issuer_acme_solver: godaddy
+cluster_issuer_acme_godaddy_api_key: <GODADDY_API_KEY>
+cluster_issuer_acme_godaddy_secret_key: <GODADDY_SECRET_KEY>
+```
+
 #### Infoblox
 
 If you're using Infoblox for the DNS of your domain, you can use the following
diff --git a/roles/cluster_issuer/defaults/main.yml b/roles/cluster_issuer/defaults/main.yml
index d301015..f877cda 100644
--- a/roles/cluster_issuer/defaults/main.yml
+++ b/roles/cluster_issuer/defaults/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023 VEXXHOST, Inc.
+# Copyright (c) 2024 VEXXHOST, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -35,6 +35,22 @@
 # cluster_issuer_acme_route53_access_key_id: <AWS_ACCESS_KEY_ID>
 # cluster_issuer_acme_route53_secret_access_key: <AWS_SECRET_ACCESS_KEY>
 
+cluster_issuer_acme_godaddy_helm_release_name: cert-manager-webhook-godaddy
+cluster_issuer_acme_godaddy_helm_chart_path: "../../charts/cert-manager-webhook-godaddy/"
+cluster_issuer_acme_godaddy_helm_chart_ref: /usr/local/src/cert-manager-webhook-godaddy
+cluster_issuer_acme_godaddy_helm_release_namespace: cert-manager
+cluster_issuer_acme_godaddy_helm_values: {}
+
+cluster_issuer_acme_godaddy_group_name: godaddy.cert-manager.atmosphere.dev
+cluster_issuer_acme_godaddy_secret_name: godaddy-api-key
+cluster_issuer_acme_godaddy_role_name: webhook-godaddy:secret-reader
+cluster_issuer_acme_godaddy_role_binding_name: "{{ cluster_issuer_acme_godaddy_role_name }}"
+cluster_issuer_acme_godaddy_service_account_name: "{{ cluster_issuer_acme_godaddy_helm_release_name }}"
+cluster_issuer_acme_godaddy_is_production: true
+cluster_issuer_acme_godaddy_ttl: 600
+# cluster_issuer_acme_godaddy_api_key: <GODADDY_API_KEY>
+# cluster_issuer_acme_godaddy_secret_key: <GODADDY_SECRET_KEY>
+
 cluster_issuer_acme_infoblox_helm_release_name: cert-manager-webhook-infoblox-wapi
 cluster_issuer_acme_infoblox_helm_chart_path: "../../charts/cert-manager-webhook-infoblox-wapi/"
 cluster_issuer_acme_infoblox_helm_chart_ref: /usr/local/src/cert-manager-webhook-infoblox-wapi
diff --git a/roles/cluster_issuer/handlers/main.yml b/roles/cluster_issuer/handlers/main.yml
index ce91b4f..84670bd 100644
--- a/roles/cluster_issuer/handlers/main.yml
+++ b/roles/cluster_issuer/handlers/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023 VEXXHOST, Inc.
+# Copyright (c) 2024 VEXXHOST, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -15,4 +15,4 @@
 - name: Update CA certificates on host
   changed_when: true
   ansible.builtin.command:
-    cmd: update-ca-certificates
+    cmd: "{{ 'update-ca-certificates' if ansible_facts['os_family'] in ['Debian'] else 'update-ca-trust' }}"
diff --git a/roles/cluster_issuer/tasks/main.yml b/roles/cluster_issuer/tasks/main.yml
index aab9fcb..8516771 100644
--- a/roles/cluster_issuer/tasks/main.yml
+++ b/roles/cluster_issuer/tasks/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023 VEXXHOST, Inc.
+# Copyright (c) 2024 VEXXHOST, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -43,7 +43,7 @@
     - name: Copy CA certificate on host
       ansible.builtin.copy:
         content: "{{ _cluster_issuer_ca_secret.resources[0].data['tls.crt'] | b64decode }}"
-        dest: /usr/local/share/ca-certificates/atmosphere.crt
+        dest: "{{ '/usr/local/share/ca-certificates' if ansible_facts['os_family'] in ['Debian'] else '/etc/pki/ca-trust/source/anchors' }}/atmosphere.crt"
         mode: "0644"
       notify:
         - Update CA certificates on host
diff --git a/roles/cluster_issuer/tasks/type/acme/solver/godaddy.yml b/roles/cluster_issuer/tasks/type/acme/solver/godaddy.yml
new file mode 100644
index 0000000..80ba793
--- /dev/null
+++ b/roles/cluster_issuer/tasks/type/acme/solver/godaddy.yml
@@ -0,0 +1,92 @@
+# Copyright (c) 2024 VEXXHOST, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+- name: Upload Helm chart
+  run_once: true
+  ansible.builtin.import_role:
+    name: vexxhost.kubernetes.upload_helm_chart
+  vars:
+    upload_helm_chart_src: "{{ cluster_issuer_acme_godaddy_helm_chart_path }}"
+    upload_helm_chart_dest: "{{ cluster_issuer_acme_godaddy_helm_chart_ref }}"
+
+- name: Deploy Helm chart
+  run_once: true
+  kubernetes.core.helm:
+    name: "{{ cluster_issuer_acme_godaddy_helm_release_name }}"
+    chart_ref: "{{ cluster_issuer_acme_godaddy_helm_chart_ref }}"
+    release_namespace: "{{ cluster_issuer_acme_godaddy_helm_release_namespace }}"
+    create_namespace: true
+    kubeconfig: /etc/kubernetes/admin.conf
+    values: "{{ _cluster_issuer_acme_godaddy_helm_values | combine(cluster_issuer_acme_godaddy_helm_values, recursive=True) }}"
+
+- name: Apply manifests for Godaddy integration
+  run_once: true
+  kubernetes.core.k8s:
+    state: present
+    definition:
+      - apiVersion: v1
+        kind: Secret
+        metadata:
+          name: "{{ cluster_issuer_acme_godaddy_secret_name }}"
+          namespace: "{{ cluster_issuer_acme_godaddy_helm_release_namespace }}"
+        type: Opaque
+        stringData:
+          token: "{{ cluster_issuer_acme_godaddy_api_key }}:{{ cluster_issuer_acme_godaddy_secret_key }}"
+
+      - apiVersion: rbac.authorization.k8s.io/v1
+        kind: Role
+        metadata:
+          name: "{{ cluster_issuer_acme_godaddy_role_name }}"
+          namespace: "{{ cluster_issuer_acme_godaddy_helm_release_namespace }}"
+        rules:
+          - apiGroups: [""]
+            resources: ["secrets"]
+            verbs: ["get", "watch"]
+            resourceNames: ["{{ cluster_issuer_acme_godaddy_secret_name }}"]
+
+      - apiVersion: rbac.authorization.k8s.io/v1
+        kind: RoleBinding
+        metadata:
+          name: "{{ cluster_issuer_acme_godaddy_role_binding_name }}"
+          namespace: "{{ cluster_issuer_acme_godaddy_helm_release_namespace }}"
+        roleRef:
+          apiGroup: rbac.authorization.k8s.io
+          kind: Role
+          name: "{{ cluster_issuer_acme_godaddy_role_name }}"
+        subjects:
+          - kind: ServiceAccount
+            name: "{{ cluster_issuer_acme_godaddy_service_account_name }}"
+            namespace: "{{ cluster_issuer_acme_godaddy_helm_release_namespace }}"
+
+      - apiVersion: cert-manager.io/v1
+        kind: ClusterIssuer
+        metadata:
+          name: "{{ cluster_issuer_name }}"
+        spec:
+          acme:
+            email: "{{ cluster_issuer_acme_email }}"
+            server: "{{ cluster_issuer_acme_server }}"
+            privateKeySecretRef:
+              name: "{{ cluster_issuer_acme_private_key_secret_name }}"
+            solvers:
+              - dns01:
+                  webhook:
+                    groupName: "{{ cluster_issuer_acme_godaddy_group_name }}"
+                    solverName: godaddy
+                    config:
+                      apiKeySecretRef:
+                        name: "{{ cluster_issuer_acme_godaddy_secret_name }}"
+                        key: token
+                      production: "{{ cluster_issuer_acme_godaddy_is_production }}"
+                      ttl: "{{ cluster_issuer_acme_godaddy_ttl }}"
diff --git a/roles/cluster_issuer/vars/main.yml b/roles/cluster_issuer/vars/main.yml
index 278e189..d7886b4 100644
--- a/roles/cluster_issuer/vars/main.yml
+++ b/roles/cluster_issuer/vars/main.yml
@@ -1,4 +1,4 @@
-# Copyright (c) 2023 VEXXHOST, Inc.
+# Copyright (c) 2024 VEXXHOST, Inc.
 #
 # Licensed under the Apache License, Version 2.0 (the "License"); you may
 # not use this file except in compliance with the License. You may obtain
@@ -14,3 +14,6 @@
 
 _cluster_issuer_acme_infoblox_helm_values:
   groupName: "{{ cluster_issuer_acme_infoblox_group_name }}"
+
+_cluster_issuer_acme_godaddy_helm_values:
+  groupName: "{{ cluster_issuer_acme_godaddy_group_name }}"
diff --git a/vendir.lock.yml b/vendir.lock.yml
index de1fb17..44cbc89 100644
--- a/vendir.lock.yml
+++ b/vendir.lock.yml
@@ -14,6 +14,10 @@
       version: 0.1.8
     path: ceph-provisioners
   - helmChart:
+      appVersion: 0.3.0
+      version: 0.3.0
+    path: cert-manager-webhook-godaddy
+  - helmChart:
       appVersion: 1.5.0
       version: 1.5.2
     path: cert-manager-webhook-infoblox-wapi
diff --git a/vendir.yml b/vendir.yml
index aa1e0b7..9e33ae0 100644
--- a/vendir.yml
+++ b/vendir.yml
@@ -21,6 +21,12 @@
           version: 0.1.8
           repository:
             url: https://tarballs.openstack.org/openstack-helm-infra
+      - path: cert-manager-webhook-godaddy
+        helmChart:
+          name: godaddy-webhook
+          version: 0.3.0
+          repository:
+            url: https://snowdrop.github.io/godaddy-webhook
       - path: cert-manager-webhook-infoblox-wapi
         helmChart:
           name: cert-manager-webhook-infoblox-wapi