Skip to content

Commit

Permalink
redpanda: Convert certs.yaml to go
Browse files Browse the repository at this point in the history
This commit converts the certs.yaml helm template into equivalent go
code and adds the appropriate bridge to render the output as a
multi-document YAML file.

Fixes #1111
  • Loading branch information
chrisseto committed Apr 11, 2024
1 parent f137f32 commit 6cc66bc
Show file tree
Hide file tree
Showing 8 changed files with 280 additions and 155 deletions.
130 changes: 130 additions & 0 deletions charts/redpanda/certs.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// +gotohelm:filename=certs.go.tpl
package redpanda

import (
"fmt"
"strings"

certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
"github.com/redpanda-data/helm-charts/pkg/gotohelm/helmette"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

func ClientCerts(dot *helmette.Dot) []certmanagerv1.Certificate {
if !TLSEnabled(dot) {
return []certmanagerv1.Certificate{}
}

values := helmette.Unwrap[Values](dot.Values)

fullname := Fullname(dot)
service := ServiceName(dot)
ns := dot.Release.Namespace
domain := strings.TrimSuffix(values.ClusterDomain, ".")

certs := []certmanagerv1.Certificate{}
for name, data := range values.TLS.Certs {
if helmette.Empty(data.SecretRef) {
continue
}

names := []string{}
if data.IssuerRef == nil {
names = append(names, fmt.Sprintf("%s-cluster.%s.%s.svc.%s", fullname, service, ns, domain))
names = append(names, fmt.Sprintf("%s-cluster.%s.%s.svc", fullname, service, ns))
names = append(names, fmt.Sprintf("%s-cluster.%s.%s", fullname, service, ns))
names = append(names, fmt.Sprintf("*.%s-cluster.%s.%s.svc.%s", fullname, service, ns, domain))
names = append(names, fmt.Sprintf("*.%s-cluster.%s.%s.svc", fullname, service, ns))
names = append(names, fmt.Sprintf("*.%s-cluster.%s.%s", fullname, service, ns))
names = append(names, fmt.Sprintf("%s.%s.svc.%s", service, ns, domain))
names = append(names, fmt.Sprintf("%s.%s.svc", service, ns))
names = append(names, fmt.Sprintf("%s.%s", service, ns))
names = append(names, fmt.Sprintf("*.%s.%s.svc.%s", service, ns, domain))
names = append(names, fmt.Sprintf("*.%s.%s.svc", service, ns))
names = append(names, fmt.Sprintf("*.%s.%s", service, ns))
}

if values.External.Domain != nil {
names = append(names, helmette.Tpl(*values.External.Domain, dot))
names = append(names, helmette.Tpl(fmt.Sprintf("*.%s", *values.External.Domain), dot))
}

issuerRef := cmmeta.ObjectReference{
Kind: "Issuer",
Group: "cert-manager.io",
Name: fmt.Sprintf("%s-%s-root-issuer", fullname, name),
}

if data.IssuerRef != nil {
issuerRef = *data.IssuerRef
}

duration := helmette.Default("43800h", data.Duration).(string)

certs = append(certs, certmanagerv1.Certificate{
TypeMeta: metav1.TypeMeta{
APIVersion: "cert-manager.io/v1",
Kind: "Certificate",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-%s-cert", fullname, name),
Labels: FullLabels(dot),
Namespace: dot.Release.Namespace,
},
Spec: certmanagerv1.CertificateSpec{
DNSNames: names,
Duration: helmette.MustDuration(duration),
IsCA: false,
IssuerRef: issuerRef,
SecretName: fmt.Sprintf("%s-%s-cert", fullname, name),
PrivateKey: &certmanagerv1.CertificatePrivateKey{
Algorithm: "ECDSA",
Size: 256,
},
},
})
}

name := values.Listeners.Kafka.TLS.Cert

data, ok := values.TLS.Certs[name]
if !ok || !ClientAuthRequired(dot) {
return certs
}

issuerRef := cmmeta.ObjectReference{
Group: "cert-manager.io",
Kind: "Issuer",
Name: fmt.Sprintf("%s-%s-root-issuer", fullname, name),
}

if data.IssuerRef != nil {
issuerRef = *data.IssuerRef
issuerRef.Group = "cert-manager.io"
}

duration := helmette.Default("43800h", data.Duration).(string)

return append(certs, certmanagerv1.Certificate{
TypeMeta: metav1.TypeMeta{
APIVersion: "cert-manager.io/v1",
Kind: "Certificate",
},
ObjectMeta: metav1.ObjectMeta{
Name: fmt.Sprintf("%s-client", fullname),
Labels: FullLabels(dot),
},
Spec: certmanagerv1.CertificateSpec{
CommonName: fmt.Sprintf("%s-client", fullname),
Duration: helmette.MustDuration(duration),
IsCA: false,
SecretName: fmt.Sprintf("%s-client", fullname),
PrivateKey: &certmanagerv1.CertificatePrivateKey{
Algorithm: "ECDSA",
Size: 256,
},
IssuerRef: issuerRef,
},
})
}
64 changes: 64 additions & 0 deletions charts/redpanda/templates/certs.go.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
{{- /* Generated from "certs.go" */ -}}

{{- define "redpanda.ClientCerts" -}}
{{- $dot := (index .a 0) -}}
{{- range $_ := (list 1) -}}
{{- if (not (get (fromJson (include "redpanda.TLSEnabled" (dict "a" (list $dot) ))) "r")) -}}
{{- (dict "r" (list )) | toJson -}}
{{- break -}}
{{- end -}}
{{- $values := $dot.Values.AsMap -}}
{{- $fullname := (get (fromJson (include "redpanda.Fullname" (dict "a" (list $dot) ))) "r") -}}
{{- $service := (get (fromJson (include "redpanda.ServiceName" (dict "a" (list $dot) ))) "r") -}}
{{- $ns := $dot.Release.Namespace -}}
{{- $domain := (trimSuffix "." $values.clusterDomain) -}}
{{- $certs := (list ) -}}
{{- range $name, $data := $values.tls.certs -}}
{{- if (empty $data.secretRef) -}}
{{- continue -}}
{{- end -}}
{{- $names := (list ) -}}
{{- if (eq $data.issuerRef nil) -}}
{{- $names = (mustAppend $names (printf "%s-cluster.%s.%s.svc.%s" $fullname $service $ns $domain)) -}}
{{- $names = (mustAppend $names (printf "%s-cluster.%s.%s.svc" $fullname $service $ns)) -}}
{{- $names = (mustAppend $names (printf "%s-cluster.%s.%s" $fullname $service $ns)) -}}
{{- $names = (mustAppend $names (printf "*.%s-cluster.%s.%s.svc.%s" $fullname $service $ns $domain)) -}}
{{- $names = (mustAppend $names (printf "*.%s-cluster.%s.%s.svc" $fullname $service $ns)) -}}
{{- $names = (mustAppend $names (printf "*.%s-cluster.%s.%s" $fullname $service $ns)) -}}
{{- $names = (mustAppend $names (printf "%s.%s.svc.%s" $service $ns $domain)) -}}
{{- $names = (mustAppend $names (printf "%s.%s.svc" $service $ns)) -}}
{{- $names = (mustAppend $names (printf "%s.%s" $service $ns)) -}}
{{- $names = (mustAppend $names (printf "*.%s.%s.svc.%s" $service $ns $domain)) -}}
{{- $names = (mustAppend $names (printf "*.%s.%s.svc" $service $ns)) -}}
{{- $names = (mustAppend $names (printf "*.%s.%s" $service $ns)) -}}
{{- end -}}
{{- if (ne $values.external.domain nil) -}}
{{- $names = (mustAppend $names (tpl $values.external.domain $dot)) -}}
{{- $names = (mustAppend $names (tpl (printf "*.%s" $values.external.domain) $dot)) -}}
{{- end -}}
{{- $issuerRef := (mustMergeOverwrite (dict "name" "" ) (dict "kind" "Issuer" "group" "cert-manager.io" "name" (printf "%s-%s-root-issuer" $fullname $name) )) -}}
{{- if (ne $data.issuerRef nil) -}}
{{- $issuerRef = $data.issuerRef -}}
{{- end -}}
{{- $duration := (default "43800h" $data.duration) -}}
{{- $certs = (mustAppend $certs (mustMergeOverwrite (mustMergeOverwrite (dict ) (dict "metadata" (dict "creationTimestamp" (fromJson "null") ) "spec" (dict "secretName" "" "issuerRef" (dict "name" "" ) ) "status" (dict ) )) (mustMergeOverwrite (dict ) (dict "apiVersion" "cert-manager.io/v1" "kind" "Certificate" )) (dict "metadata" (mustMergeOverwrite (dict "creationTimestamp" (fromJson "null") ) (dict "name" (printf "%s-%s-cert" $fullname $name) "labels" (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $dot) ))) "r") "namespace" $dot.Release.Namespace )) "spec" (mustMergeOverwrite (dict "secretName" "" "issuerRef" (dict "name" "" ) ) (dict "dnsNames" $names "duration" $duration "isCA" false "issuerRef" $issuerRef "secretName" (printf "%s-%s-cert" $fullname $name) "privateKey" (mustMergeOverwrite (dict ) (dict "algorithm" "ECDSA" "size" 256 )) )) ))) -}}
{{- end -}}
{{- $name := $values.listeners.kafka.tls.cert -}}
{{- $tmp_tuple_1 := (get (fromJson (include "_shims.compact" (dict "a" (list (get (fromJson (include "_shims.dicttest" (dict "a" (list $values.tls.certs $name) ))) "r")) ))) "r") -}}
{{- $ok := $tmp_tuple_1.T2 -}}
{{- $data := $tmp_tuple_1.T1 -}}
{{- if (or (not $ok) (not (get (fromJson (include "redpanda.ClientAuthRequired" (dict "a" (list $dot) ))) "r"))) -}}
{{- (dict "r" $certs) | toJson -}}
{{- break -}}
{{- end -}}
{{- $issuerRef := (mustMergeOverwrite (dict "name" "" ) (dict "group" "cert-manager.io" "kind" "Issuer" "name" (printf "%s-%s-root-issuer" $fullname $name) )) -}}
{{- if (ne $data.issuerRef nil) -}}
{{- $issuerRef = $data.issuerRef -}}
{{- $_ := (set $issuerRef "group" "cert-manager.io") -}}
{{- end -}}
{{- $duration := (default "43800h" $data.duration) -}}
{{- (dict "r" (mustAppend $certs (mustMergeOverwrite (mustMergeOverwrite (dict ) (dict "metadata" (dict "creationTimestamp" (fromJson "null") ) "spec" (dict "secretName" "" "issuerRef" (dict "name" "" ) ) "status" (dict ) )) (mustMergeOverwrite (dict ) (dict "apiVersion" "cert-manager.io/v1" "kind" "Certificate" )) (dict "metadata" (mustMergeOverwrite (dict "creationTimestamp" (fromJson "null") ) (dict "name" (printf "%s-client" $fullname) "labels" (get (fromJson (include "redpanda.FullLabels" (dict "a" (list $dot) ))) "r") )) "spec" (mustMergeOverwrite (dict "secretName" "" "issuerRef" (dict "name" "" ) ) (dict "commonName" (printf "%s-client" $fullname) "duration" $duration "isCA" false "secretName" (printf "%s-client" $fullname) "privateKey" (mustMergeOverwrite (dict ) (dict "algorithm" "ECDSA" "size" 256 )) "issuerRef" $issuerRef )) )))) | toJson -}}
{{- break -}}
{{- end -}}
{{- end -}}

91 changes: 3 additions & 88 deletions charts/redpanda/templates/certs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,93 +14,8 @@ 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.
*/}}
{{- if (include "tls-enabled" . | fromJson).bool }}
{{- $root := deepCopy . }}
{{- $service := include "redpanda.servicename" . }}
{{- $ns := .Release.Namespace }}
{{- $domain := .Values.clusterDomain | trimSuffix "." }}
{{- $listeners := .Values.listeners }}
{{- $values := .Values }}
{{- range $name, $data := .Values.tls.certs }}
{{- if (empty $data.secretRef ) }}
{{- $d := $data.duration }}

---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ template "redpanda.fullname" $ }}-{{ $name }}-cert
namespace: {{ $ns | quote }}
{{- with include "full.labels" $root }}
labels:
{{- . | nindent 4 }}
{{- end }}
spec:
dnsNames:
{{- if (empty $data.issuerRef) }}
- {{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s.svc.%s" $service $ns $domain }}
- {{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s.svc" $service $ns }}
- {{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s" $service $ns }}
- "*.{{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s.svc.%s" $service $ns $domain }}"
- "*.{{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s.svc" $service $ns }}"
- "*.{{ template "redpanda.fullname" $ }}-cluster.{{ printf "%s.%s" $service $ns }}"
- {{ printf "%s.%s.svc.%s" $service $ns $domain }}
- {{ printf "%s.%s.svc" $service $ns }}
- {{ printf "%s.%s" $service $ns }}
- {{ printf "*.%s.%s.svc.%s" $service $ns $domain | quote }}
- {{ printf "*.%s.%s.svc" $service $ns | quote }}
- {{ printf "*.%s.%s" $service $ns | quote }}
{{- end }}
{{- if (tpl ($values.external.domain | default "") $) }}
- "{{ tpl $values.external.domain $ }}"
- "*.{{ tpl $values.external.domain $ }}"
{{- end }}
duration: {{ $d | default "43800h" }}
isCA: false
secretName: {{ template "redpanda.fullname" $ }}-{{ $name }}-cert
privateKey:
algorithm: ECDSA
size: 256
{{- if not (empty $data.issuerRef) }}
issuerRef:
{{- toYaml $data.issuerRef | nindent 4 }}
group: cert-manager.io
{{- else }}
issuerRef:
name: {{ template "redpanda.fullname" $ }}-{{ $name }}-root-issuer
kind: Issuer
group: cert-manager.io
{{- end }}
{{- end }}
{{- end }}
{{- $docs := (get ((include "redpanda.ClientCerts" (dict "a" (list .))) | fromJson) "r") }}
{{- range $_, $doc := $docs }}
---
{{- $name := .Values.listeners.kafka.tls.cert }}
{{- $data := get .Values.tls.certs $name }}
{{- if and (empty $data.secretRef) (include "client-auth-required" . | fromJson).bool }}
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ template "redpanda.fullname" $ }}-client
namespace: {{ $ns | quote }}
{{- with include "full.labels" $root }}
labels: {{- . | nindent 4 }}
{{- end }}
spec:
commonName: {{ template "redpanda.fullname" $ }}-client
duration: {{ $data.duration | default "43800h" }}
isCA: false
secretName: {{ template "redpanda.fullname" $ }}-client
privateKey:
algorithm: ECDSA
size: 256
{{- if not (empty $data.issuerRef) }}
issuerRef: {{- toYaml $data.issuerRef | nindent 4 }}
group: cert-manager.io
{{- else }}
issuerRef:
name: {{ template "redpanda.fullname" $ }}-{{ $name }}-root-issuer
kind: Issuer
group: cert-manager.io
{{- end }}
{{- end }}
{{ toYaml $doc }}
{{- end }}
28 changes: 19 additions & 9 deletions charts/redpanda/values.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
package redpanda

import (
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
"github.com/invopop/jsonschema"
orderedmap "github.com/wk8/go-ordered-map/v2"
)
Expand Down Expand Up @@ -121,14 +123,14 @@ type Auth struct {
}

type TLS struct {
Enabled *bool `json:"enabled" jsonschema:"required"`
Certs *TLSCertMap `json:"certs"`
Enabled *bool `json:"enabled" jsonschema:"required"`
Certs TLSCertMap `json:"certs"`
}

type ExternalConfig struct {
Addresses []string `json:"addresses"`
Annotations map[string]string `json:"annotations"`
Domain string `json:"domain"`
Domain *string `json:"domain"`
Enabled bool `json:"enabled" jsonschema:"required"`
Type string `json:"type" jsonschema:"pattern=^(LoadBalancer|NodePort)$"`
PrefixTemplate string `json:"prefixTemplate"`
Expand Down Expand Up @@ -411,17 +413,25 @@ type PandaProxyClient struct {

type TLSCert struct {
// Enabled bool `json:"enabled"`
CAEnabled bool `json:"caEnabled" jsonschema:"required"`
Duration string `json:"duration" jsonschema:"pattern=.*[smh]$"`
IssuerRef struct {
Name string `json:"name"`
Kind IssuerRefKind `json:"kind"`
} `json:"issuerRef"`
CAEnabled bool `json:"caEnabled" jsonschema:"required"`
Duration string `json:"duration" jsonschema:"pattern=.*[smh]$"`
IssuerRef *cmmeta.ObjectReference `json:"issuerRef"`
SecretRef struct {
Name string `json:"name"`
} `json:"secretRef"`
}

func (TLSCert) JSONSchemaExtend(schema *jsonschema.Schema) {
// An object reference could allow anything but we want to require that the
// reference is to either a ClusterIssuer or Issuer.
ref, _ := schema.Properties.Get("issuerRef")
refKind, _ := ref.Properties.Get("kind")
refKind.Enum = []any{
certmanagerv1.ClusterIssuerKind,
certmanagerv1.IssuerKind,
}
}

type TLSCertMap map[string]TLSCert

func (TLSCertMap) JSONSchemaExtend(schema *jsonschema.Schema) {
Expand Down
3 changes: 3 additions & 0 deletions charts/redpanda/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1714,6 +1714,9 @@
},
"issuerRef": {
"properties": {
"group": {
"type": "string"
},
"kind": {
"enum": [
"ClusterIssuer",
Expand Down
13 changes: 7 additions & 6 deletions charts/redpanda/values_partial.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
//+gotohelm:ignore=true
package redpanda

import (
cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1"
)

type PartialValues struct {
NameOverride *string `json:"nameOverride,omitempty"`
FullnameOverride *string `json:"fullnameOverride,omitempty"`
Expand Down Expand Up @@ -355,12 +359,9 @@ type PartialPandaProxyClient struct {
}

type PartialTLSCert struct {
CAEnabled *bool `json:"caEnabled,omitempty" jsonschema:"required"`
Duration *string `json:"duration,omitempty" jsonschema:"pattern=.*[smh]$"`
IssuerRef struct {
Name *string `json:"name,omitempty"`
Kind *IssuerRefKind `json:"kind,omitempty"`
} `json:"issuerRef,omitempty"`
CAEnabled *bool `json:"caEnabled,omitempty" jsonschema:"required"`
Duration *string `json:"duration,omitempty" jsonschema:"pattern=.*[smh]$"`
IssuerRef *cmmeta.ObjectReference `json:"issuerRef,omitempty"`
SecretRef struct {
Name *string `json:"name,omitempty"`
} `json:"secretRef,omitempty"`
Expand Down
Loading

0 comments on commit 6cc66bc

Please sign in to comment.