查询helm模板中的值



我正在尝试为Helm图表中的所有入口资源生成TLS证书。我的掌舵图包含一个应用程序与多个后端,所以我的值。Yaml的结构如下:

backend1:
ingress:
host: testing.app.com
tls:
- secretName: my-tls-cert
hosts:
- testing.app.com
backend2:
ingress:
host: testing.app.com
tls:
- secretName: idp-cts-cert
hosts:
- idp-cts
db
creds: ""
serviceName: ""

注意这里混合了映射和字符串值。我的目标是使用我编写的实用程序模板来调用genSignedCert并生成一个TLS证书,该证书将主机列为CN或替代名称:

{{/*
Return a self-signed TLS certificate
{{ include "common.certs.ingress-tls" .hosts  }}
*/}}
{{- define "common.certs.gen-cert" -}}
{{- $hostlist := toStrings . -}}
{{- $cn := (first $hostlist) -}}
{{- $altnames := uniq (rest $hostlist) -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}} 

我已经尝试过迭代的值,但我不能提出可行的代码来做到这一点。

Edit1:我知道使用自签名证书的安全含义。坏的价值观。Yaml结构继承自这样一个事实,即这是一个伞形图,每个背面也是它自己的图表。可能需要重构图表结构,但我想首先用尽所有选项。

考虑在Helm外部生成TLS证书,并通过值注入它(或直接将其组件存储在Secret中)。这避免了一些复杂的代码。但是,有一个更严重的问题:每次调用genCAgenSignedCert时,它都会创建一个新证书,因此每次升级都会获得不同的证书,因此,如果每个入口对象调用此模板一次,则每个都将拥有不同的证书。


稍微重组values.yaml有助于解决这个问题。代码很难分辨出backend1是后端规范,但serviceName不是。如果你只有一个backends的列表,这就容易多了:

backends:
- ingress:
host: testing.app.com
...
- ingress:
host: testing.app.com
...

然后,您将遇到Helm模板作为全功能编程语言的几个限制。模板只返回字符串,所以你不能编写一个返回列表的模板。您不能将函数作为参数传递给模板,因此您不能编写通用的map(在有限的情况下,您可以传递模板名称并将其include)。

你能做的是编写一个递归函数,将部分列表传递给下一次迭代,然后在迭代完成时调用最终生成器。在Python中,我们可以这样写:

def generateCertificate(backends, tls, hosts):
# If `tls` is non-empty, take the first item from it and add its
# hosts to the `hosts` list; then recurse with the same backend
# list, the remaining `tls` items, and the updated `hosts`:
if len(tls) > 0:
return generateCertificate(backends, tls[1:], hosts + tls[0].hosts)
# If `tls` is empty but `backends` is non-empty, take the first
# backend, and recurse with the remaining `backends`, the `tls` items
# from the selected backend, and the same `hosts`:
else if len(backends) > 0:
return generateCertificate(backends[1:], backends[0].tls, hosts)
# If `tls` and `backends` are both empty, we're done
else:
return buildTheCertificate(hosts)
certificate = generateCertificate(values.backends, [], [])

我们可以把这个逻辑转换成Go模板:

{{/* Emit a TLS certificate given the list of backends.  The
parameter is a dictionary with keys `backends`, `tls`, and `hosts`. */}}
{{- define "common.certs.gen-cert" -}}
{{- if .tls -}}
{{- include "common.certs.gen-cert" (dict "backends" .backend "tls" (last .tls) "hosts" (concat .hosts (head .tls).hosts)) -}}
{{- else if .backends -}}
{{- include "common.certs.gen-cert" (dict "backends" (tail .backends) "tls" (head .backends).tls "hosts" .hosts) -}}
{{- else -}}
{{- include "common.certs.gen-cert-hosts" .hosts -}}
{{- end -}}
{{- end -}}
{{/* Actually generate a TLS certificate from a list of host names.
Note, the certificate will be regenerated on every call.  The
single parameter is a list of names. */}}
{{- define "common.certs.gen-cert-hosts" -}}
{{- $cn := first . -}}
{{- $altnames := rest . | uniq -}}
{{- $ca := genCA "idp-ca" 365 -}}
{{- $cert := genSignedCert $cn nil $altnames 365 $ca -}}
tls.crt: {{ $cert.Cert | b64enc }}
tls.key: {{ $cert.Key | b64enc }}
{{- end -}}
{{- include "common.certs.gen-cert" (dict "backends" .Values.backends) -}}

这是足够复杂的代码,可能值得进行单元测试。设置这个是一个练习;Helm在这里没有任何原生支持。

最新更新