[COMMON] Fix genericKV cache generation
[oom.git] / kubernetes / common / common / templates / _secret.tpl
1 {{/*
2 # Copyright © 2019 AT&T, Samsung Electronics
3 #
4 # Licensed under the Apache License, Version 2.0 (the "License");
5 # you may not use this file except in compliance with the License.
6 # You may obtain a copy of the License at
7 #
8 #       http://www.apache.org/licenses/LICENSE-2.0
9 #
10 # Unless required by applicable law or agreed to in writing, software
11 # distributed under the License is distributed on an "AS IS" BASIS,
12 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 # See the License for the specific language governing permissions and
14 # limitations under the License.
15 */}}
16
17 {{/*
18   For internal use only!
19
20   Generates a secret header with given name and desired labels.
21
22   The template takes two arguments:
23     - .global: environment (.)
24     - .name: name of the secret
25     - .annotations: annotations which should be used
26
27   Example call:
28     {{ include "common.secret._header" (dict "global" . "name" "myFancyName") }}
29 */}}
30 {{- define "common.secret._header" -}}
31 {{- $global := .global }}
32 {{- $name := .name }}
33 apiVersion: v1
34 kind: Secret
35 metadata:
36   name: {{ $name }}
37   namespace: {{ include "common.namespace" $global }}
38   labels:
39     app: {{ include "common.name" $global }}
40     chart: {{ $global.Chart.Name }}-{{ $global.Chart.Version | replace "+" "_" }}
41     release: {{ include "common.release" $global }}
42     heritage: {{ $global.Release.Service }}
43 {{- if .annotations }}
44   annotations: {{- include "common.tplValue" (dict "value" .annotations "context" $global) | nindent 4 }}
45 {{- end }}
46 type: Opaque
47 {{- end -}}
48
49 {{/*
50   For internal use only!
51
52   Pick a value based on "user input" and generation policy.
53
54   The template takes below arguments:
55     - .global: environment (.)
56     - .secretName: name of the secret where the value will be placed
57     - .secretEnv: map of values which configures this secret. This can contain below keys:
58         - value: Value of secret key provided by user (can be a template inside a string)
59         - policy: What to do if value is missing or empty. Possible options are:
60             - generate: Generate a new password deriving it from master password
61             - required: Fail the deployment if value has not been provided
62           Defaults to generate.
63         - name: Name of the key to which this value should be assigned
64 */}}
65 {{- define "common.secret._value" -}}
66   {{- $global := .global }}
67   {{- $name := .secretName }}
68   {{- $secretEnv := .secretEnv }}
69   {{- $value := tpl $secretEnv.value $global }}
70   {{- $policy := default "generate" $secretEnv.policy }}
71
72   {{- if $value }}
73     {{- $value | quote }}
74   {{- else if eq $policy "generate" }}
75     {{- include "common.createPassword" (dict "dot" $global "uid" $name) | quote }}
76   {{- else }}
77     {{- fail (printf "Value for %s secret %s key not provided" $name $secretEnv.name) }}
78   {{- end }}
79 {{- end -}}
80
81 {{/*
82   For internal use only!
83
84   Pick a value based on "user input" and generation policy.
85
86   The template takes below arguments:
87     - .global: environment (.)
88     - .secretName: name of the secret where the value will be placed
89     - .secretEnv: map of values which configures this secret. This can contain below keys:
90         - value: Value of secret key provided by user (can be a template inside a string)
91         - policy: What to do if value is missing or empty. Possible options are:
92             - generate: Generate a new password deriving it from master password
93             - required: Fail the deployment if value has not been provided
94           Defaults to generate.
95         - name: Name of the key to which this value should be assigned
96 */}}
97 {{- define "common.secret._valueFast" -}}
98   {{- $global := .global }}
99   {{- $name := .secretName }}
100   {{- $secretEnv := .secretEnv }}
101   {{- $value := $secretEnv.value }}
102   {{- $policy := default "generate" $secretEnv.policy }}
103
104   {{- if $value }}
105     {{- $value | quote }}
106   {{- else if eq $policy "generate" }}
107     {{- include "common.createPassword" (dict "dot" $global "uid" $name) | quote }}
108   {{- else }}
109     {{- fail (printf "Value for %s secret %s key not provided" $name $secretEnv.name) }}
110   {{- end }}
111 {{- end -}}
112
113
114 {{/*
115   Generate a secret name based on provided name or UID.
116   If UID is provided then the name is generated by appending this UID right after
117   the chart name. If name is provided, it overrides the name generation algorith
118   and is used right away. Both name and uid strings may contain a template to be
119   resolved.
120
121   The template takes below arguments:
122     - .global: environment (.)
123     - .uid: string that uniquely identifies this secret within a helm chart
124     - .name: string that can be used to override default name generation algorithm
125         and provide a custom name for the secret
126 */}}
127 {{- define "common.secret.genName" -}}
128   {{- $global := .global }}
129   {{- $uid := tpl (default "" .uid) $global }}
130   {{- $name := tpl (default "" .name) $global }}
131   {{- $fullname := ne (default "" .chartName) "" | ternary (include "common.fullnameExplicit" (dict "dot" $global "chartName" .chartName)) (include "common.fullname" $global) }}
132   {{- default (printf "%s-%s" $fullname $uid) $name }}
133 {{- end -}}
134
135 {{- define "common.secret.genNameFast" -}}
136   {{- $global := .global }}
137   {{- $uid := (default "" .uid) }}
138   {{- $name := (default "" .name) }}
139   {{- $fullname := ne (default "" .chartName) "" | ternary (include "common.fullnameExplicit" (dict "dot" $global "chartName" .chartName)) (include "common.fullname" $global) }}
140   {{- if eq "test-release" $global.Release.Name -}}
141   {{/* Special case for chart liniting in helm3. DON"T NAME YOUR PRODUCTION RELEASE test-release */}}
142   {{- $uid = lower $uid -}}
143   {{- end -}}
144   {{- default (printf "%s-%s" $fullname $uid) $name }}
145 {{- end -}}
146
147 {{/*
148   Get the real secret name by UID or name, based on the configuration provided by user.
149   User may decide to not create a new secret but reuse existing one for this deployment
150   (aka externalSecret). In this case the real name of secret to be used is different
151   than the one declared in secret definition. This easily retrieve current secret real
152   name based on declared name or UID even if it has been overrided by the user using
153   externalSecret option. You should use this template always when you need to reference
154   a secret created using common.secret template by name.
155
156   The template takes below arguments:
157     - .global: environment (.)
158     - .uid: string that uniquely identifies this secret within a helm chart
159         (can be omitted if name has been provided)
160     - .name: name which was used to declare a secret
161         (can be omitted if uid has been provided)
162 */}}
163 {{- define "common.secret.getSecretName" -}}
164   {{- $global := .global }}
165   {{- $name := tpl (default "" .name) $global }}
166   {{- $uid := tpl (default "" .uid) $global }}
167   {{- $targetName := default (include "common.secret.genName" (dict "global" $global "uid" $uid "name" .name)) $name}}
168   {{- range $secret := $global.Values.secrets }}
169     {{- $currUID := tpl (default "" $secret.uid) $global }}
170     {{- $givenName := tpl (default "" $secret.name) $global }}
171     {{- $currName := default (include "common.secret.genName" (dict "global" $global "uid" $currUID "name" $secret.name)) $givenName }}
172     {{- if or (eq $uid $currUID) (eq $currName $targetName) }}
173       {{- $externalSecret := tpl (default "" $secret.externalSecret) $global }}
174       {{- default $currName $externalSecret }}
175     {{- end }}
176   {{- end }}
177 {{- end -}}
178
179 {{- define "common.secret.getSecretNameFast" -}}
180   {{- $global := .global }}
181   {{- include "common.secret.buildCache" $global }}
182   {{- $secretsCache := $global.Values._secretsCache }}
183   {{- $uid := tpl .uid $global }}
184   {{- $secret := index $secretsCache $uid }}
185   {{- $secret.realName }}
186 {{- end -}}
187
188 {{- define "common.secret.buildCache" -}}
189   {{- $global := . }}
190   {{- if not $global.Values._secretsCache }}
191     {{- $secretCache := dict }}
192     {{- range $secret := .Values.secrets }}
193       {{- $entry := dict }}
194       {{- $uid := tpl (default "" $secret.uid) $global }}
195       {{- $keys := keys $secret }}
196       {{- range $key := (without $keys "annotations" "filePaths" "envs" )}}
197         {{- $_ := set $entry $key (tpl (index $secret $key) $global) }}
198       {{- end }}
199       {{- if $secret.annotations }}
200         {{- $_ := set $entry "annotations" $secret.annotations }}
201       {{- end }}
202       {{- if $secret.filePaths }}
203         {{- if kindIs "string" $secret.filePaths }}
204           {{- $evaluated := tpl (default "" $secret.filePaths) $global }}
205           {{- if and $evaluated (ne $evaluated "\"\"") }}
206             {{- $fstr := printf "val:\n%s" ($evaluated | indent 2) }}
207             {{- $flist := (index (tpl $fstr $global | fromYaml) "val") }}
208             {{- $_ := set $entry "filePaths" $flist }}
209           {{- else }}
210             {{- $_ := set $entry "filePaths" (list) }}
211           {{- end }}
212         {{- else }}
213           {{- $_ := set $entry "filePaths" $secret.filePaths }}
214         {{- end }}
215       {{- end }}
216       {{- if $secret.envs }}
217         {{- $envsCache := (list) }}
218         {{- range $env := $secret.envs }}
219           {{- $tplValue := tpl (default "" $env.value) $global }}
220           {{- $envsCache = append $envsCache (dict "name" $env.name "policy" $env.policy "value" $tplValue) }}
221         {{- end }}
222         {{- $_ := set $entry "envs" $envsCache }}
223       {{- end }}
224       {{- $realName := default (include "common.secret.genNameFast" (dict "global" $global "uid" $uid "name" $entry.name) ) $entry.externalSecret }}
225       {{- $_ := set $entry "realName" $realName }}
226       {{- $_ := set $secretCache $uid $entry }}
227     {{- end }}
228     {{- $_ := set $global.Values "_secretsCache" $secretCache }}
229   {{- end }}
230
231 {{- end -}}
232
233 {{/*
234   Convenience template which can be used to easily set the value of environment variable
235   to the value of a key in a secret.
236
237   It takes care of all name mangling, usage of external secrets etc.
238
239   The template takes below arguments:
240     - .global: environment (.)
241     - .uid: string that uniquely identifies this secret within a helm chart
242         (can be omitted if name has been provided)
243     - .name: name which was used to declare a secret
244         (can be omitted if uid has been provided)
245     - .key: Key within this secret which value should be assigned to this variable
246
247   Example usage:
248   env:
249     - name: SECRET_PASSWORD
250       {{- include "common.secret.envFromSecret" (dict "global" . "uid" "secret" "key" "password") | indent 8}}
251 */}}
252 {{- define "common.secret.envFromSecret" -}}
253   {{- $key := .key }}
254 valueFrom:
255   secretKeyRef:
256     name: {{ include "common.secret.getSecretName" . }}
257     key: {{ $key }}
258 {{- end -}}
259
260 {{- define "common.secret.envFromSecretFast" -}}
261   {{- $key := .key }}
262 valueFrom:
263   secretKeyRef:
264     name: {{ include "common.secret.getSecretNameFast" . }}
265     key: {{ $key }}
266 {{- end -}}
267
268 {{/*
269   Define secrets to be used by chart.
270   Every secret has a type which is one of:
271     - generic:
272         Generic secret template that allows to input some raw data (from files).
273         File Input can be passed as list of files (filePaths) or as a single string
274         (filePath)
275     - genericKV:
276         Type of secret which allows you to define a list of key value pairs.
277         The list is assiged to envs value. Every item may define below items:
278           - name:
279               Identifier of this value within secret
280           - value:
281               String that defines a value associated with given key.
282               This can be a simple string or a template.
283           - policy:
284               Defines what to do if value is not provided by the user.
285               Available options are:
286                 - generate:
287                     Generate a value by derriving it from master password
288                 - required:
289                     Fail the deployment
290     - password:
291         Type of secret that holds only the password.
292         Only two items can be defined for this type:
293           - password:
294               Equivalent of value field from genericKV
295           - policy:
296               The same meaning as for genericKV policy field
297     - basicAuth:
298         Type of secret that holds both username and password.
299         Below fields are available:
300           - login:
301               The value for login key.
302               This can be a simple string or a template.
303               Providing a value for login is always required.
304           - password:
305               The value for password key.
306               This can be a simple string or a template.
307           - passwordPolicy:
308               The same meaning as the policy field in genericKV.
309               Only the policy for password can be set.
310
311   Every secret can be identified using:
312     - uid:
313         A string to be appended to the chart fullname to generate a secret name.
314     - name:
315         Overrides default secret name generation and allows to set immutable
316         and globaly unique name
317     - annotations:
318         List of annotations to be used while defining a secret
319
320   To allow sharing a secret between the components and allow to pre-deploy secrets
321   before ONAP deployment it is possible to use already existing secret instead of
322   creating a new one. For this purpose externalSecret field can be used. If value of
323   this field is evaluated to true no new secret is created, only the name of the
324   secret is aliased to the external one.
325
326   Example usage:
327     secrets.yaml:
328       {{ include "common.secret" . }}
329
330     values.yaml:
331       mysqlLogin: "root"
332
333       mysqlExternalSecret: "some-other-secret-name"
334
335       secrets:
336         - uid: "mysql"
337           externalSecret: '{{ tpl .Values.passExternalSecret . }}'
338           type: basicAuth
339           login: '{{ .Values.mysqlLogin }}'
340           mysqlPassword: '{{ .Values.mysqlPassword }}'
341           passwordPolicy: generate
342
343     In the above example new secret is not going to be created.
344     Already existing one (some-other-secret-name) is going to be used.
345     To force creating a new one, just make sure that mysqlExternalSecret
346     is not set.
347
348 */}}
349 {{- define "common.secret" -}}
350   {{- $global := . }}
351   {{- range $secret := .Values.secrets }}
352     {{- $uid := tpl (default "" $secret.uid) $global }}
353     {{- $name := include "common.secret.genName" (dict "global" $global "uid" $uid "name" $secret.name) }}
354     {{- $annotations := default "" $secret.annotations }}
355     {{- $type := default "generic" $secret.type }}
356     {{- $externalSecret := tpl (default "" $secret.externalSecret) $global }}
357     {{- if not $externalSecret }}
358 ---
359       {{ include "common.secret._header" (dict "global" $global "name" $name "annotations" $annotations) }}
360
361       {{- if eq $type "generic" }}
362 data:
363         {{- range $curFilePath := $secret.filePaths }}
364           {{ tpl ($global.Files.Glob $curFilePath).AsSecrets $global | indent 2 }}
365         {{- end }}
366         {{- if $secret.filePath }}
367           {{ tpl ($global.Files.Glob $secret.filePath).AsSecrets $global | indent 2 }}
368         {{- end }}
369       {{- else if eq $type "genericKV" }}
370 stringData:
371         {{- if $secret.envs }}
372           {{- range $secretEnv := $secret.envs }}
373             {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
374     {{ $secretEnv.name }}: {{ include "common.secret._value" $valueDesc }}
375           {{- end }}
376         {{- end }}
377       {{- else if eq $type "password" }}
378         {{- $secretEnv := (dict "policy" (default "generate" $secret.policy) "name" "password" "value" $secret.password) }}
379         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
380 stringData:
381   password: {{ include "common.secret._value" $valueDesc }}
382       {{- else if eq $type "basicAuth" }}
383 stringData:
384         {{- $secretEnv := (dict "policy" "required" "name" "login" "value" $secret.login) }}
385         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
386   login: {{ include "common.secret._value" $valueDesc }}
387         {{- $secretEnv := (dict "policy" (default "generate" $secret.passwordPolicy) "name" "password" "value" $secret.password) }}
388         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
389   password: {{ include "common.secret._value" $valueDesc }}
390       {{- end }}
391     {{- end }}
392   {{- end }}
393 {{- end -}}
394
395 {{/*
396   Define secrets to be used by chart.
397   Every secret has a type which is one of:
398     - generic:
399         Generic secret template that allows to input some raw data (from files).
400         File Input can be passed as list of files (filePaths) or as a single string
401         (filePath)
402     - genericKV:
403         Type of secret which allows you to define a list of key value pairs.
404         The list is assiged to envs value. Every item may define below items:
405           - name:
406               Identifier of this value within secret
407           - value:
408               String that defines a value associated with given key.
409               This can be a simple string or a template.
410           - policy:
411               Defines what to do if value is not provided by the user.
412               Available options are:
413                 - generate:
414                     Generate a value by derriving it from master password
415                 - required:
416                     Fail the deployment
417     - password:
418         Type of secret that holds only the password.
419         Only two items can be defined for this type:
420           - password:
421               Equivalent of value field from genericKV
422           - policy:
423               The same meaning as for genericKV policy field
424     - basicAuth:
425         Type of secret that holds both username and password.
426         Below fields are available:
427           - login:
428               The value for login key.
429               This can be a simple string or a template.
430               Providing a value for login is always required.
431           - password:
432               The value for password key.
433               This can be a simple string or a template.
434           - passwordPolicy:
435               The same meaning as the policy field in genericKV.
436               Only the policy for password can be set.
437
438   Every secret can be identified using:
439     - uid:
440         A string to be appended to the chart fullname to generate a secret name.
441     - name:
442         Overrides default secret name generation and allows to set immutable
443         and globaly unique name
444     - annotations:
445         List of annotations to be used while defining a secret
446
447   To allow sharing a secret between the components and allow to pre-deploy secrets
448   before ONAP deployment it is possible to use already existing secret instead of
449   creating a new one. For this purpose externalSecret field can be used. If value of
450   this field is evaluated to true no new secret is created, only the name of the
451   secret is aliased to the external one.
452
453   Example usage:
454     secrets.yaml:
455       {{ include "common.secretFast" . }}
456
457     values.yaml:
458       mysqlLogin: "root"
459
460       mysqlExternalSecret: "some-other-secret-name"
461
462       secrets:
463         - uid: "mysql"
464           externalSecret: '{{ tpl .Values.passExternalSecret . }}'
465           type: basicAuth
466           login: '{{ .Values.mysqlLogin }}'
467           mysqlPassword: '{{ .Values.mysqlPassword }}'
468           passwordPolicy: generate
469
470     In the above example new secret is not going to be created.
471     Already existing one (some-other-secret-name) is going to be used.
472     To force creating a new one, just make sure that mysqlExternalSecret
473     is not set.
474
475 */}}
476 {{- define "common.secretFast" -}}
477   {{- $global := . }}
478   {{- include "common.secret.buildCache" $global }}
479   {{- range $secret := .Values._secretsCache }}
480     {{- $uid := $secret.uid }}
481     {{- $externalSecret := $secret.externalSecret }}
482     {{- if not $externalSecret }}
483       {{- $name := $secret.realName }}
484       {{- $annotations := default "" $secret.annotations }}
485       {{- $type := default "generic" $secret.type }}
486 ---
487       {{ include "common.secret._header" (dict "global" $global "name" $name "annotations" $annotations) }}
488
489       {{- if eq $type "generic" }}
490 data:
491         {{- range $curFilePath := $secret.filePaths }}
492           {{ tpl ($global.Files.Glob $curFilePath).AsSecrets $global | indent 2 }}
493         {{- end }}
494         {{- if $secret.filePath }}
495           {{ tpl ($global.Files.Glob $secret.filePath).AsSecrets $global | indent 2 }}
496         {{- end }}
497       {{- else if eq $type "genericKV" }}
498 stringData:
499         {{- if $secret.envs }}
500           {{- range $secretEnv := $secret.envs }}
501             {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
502     {{ $secretEnv.name }}: {{ include "common.secret._valueFast" $valueDesc }}
503           {{- end }}
504         {{- end }}
505       {{- else if eq $type "password" }}
506         {{- $secretEnv := (dict "policy" (default "generate" $secret.policy) "name" "password" "value" $secret.password) }}
507         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
508 stringData:
509   password: {{ include "common.secret._valueFast" $valueDesc }}
510       {{- else if eq $type "basicAuth" }}
511 stringData:
512         {{- $secretEnv := (dict "policy" "required" "name" "login" "value" $secret.login) }}
513         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
514   login: {{ include "common.secret._valueFast" $valueDesc }}
515         {{- $secretEnv := (dict "policy" (default "generate" $secret.passwordPolicy) "name" "password" "value" $secret.password) }}
516         {{- $valueDesc := (dict "global" $global "secretName" $name "secretEnv" $secretEnv) }}
517   password: {{ include "common.secret._valueFast" $valueDesc }}
518       {{- end }}
519     {{- end }}
520   {{- end }}
521 {{- end -}}