externalsecret_controller_template.go 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. Licensed under the Apache License, Version 2.0 (the "License");
  3. you may not use this file except in compliance with the License.
  4. You may obtain a copy of the License at
  5. http://www.apache.org/licenses/LICENSE-2.0
  6. Unless required by applicable law or agreed to in writing, software
  7. distributed under the License is distributed on an "AS IS" BASIS,
  8. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package externalsecret
  13. import (
  14. "context"
  15. "fmt"
  16. v1 "k8s.io/api/core/v1"
  17. "k8s.io/apimachinery/pkg/types"
  18. "sigs.k8s.io/controller-runtime/pkg/client"
  19. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  20. // Loading registered providers.
  21. _ "github.com/external-secrets/external-secrets/pkg/provider/register"
  22. "github.com/external-secrets/external-secrets/pkg/template"
  23. utils "github.com/external-secrets/external-secrets/pkg/utils"
  24. )
  25. // merge template in the following order:
  26. // * template.Data (highest precedence)
  27. // * template.templateFrom
  28. // * secret via es.data or es.dataFrom.
  29. func (r *Reconciler) applyTemplate(ctx context.Context, es *esv1alpha1.ExternalSecret, secret *v1.Secret, dataMap map[string][]byte) error {
  30. mergeMetadata(secret, es)
  31. // no template: copy data and return
  32. if es.Spec.Target.Template == nil {
  33. secret.Data = dataMap
  34. secret.Annotations[esv1alpha1.AnnotationDataHash] = utils.ObjectHash(secret.Data)
  35. return nil
  36. }
  37. // fetch templates defined in template.templateFrom
  38. tplMap, err := r.getTemplateData(ctx, es)
  39. if err != nil {
  40. return fmt.Errorf(errFetchTplFrom, err)
  41. }
  42. // explicitly defined template.Data takes precedence over templateFrom
  43. for k, v := range es.Spec.Target.Template.Data {
  44. tplMap[k] = []byte(v)
  45. }
  46. r.Log.V(1).Info("found template data", "tpl_data", tplMap)
  47. err = template.Execute(tplMap, dataMap, secret)
  48. if err != nil {
  49. return fmt.Errorf(errExecTpl, err)
  50. }
  51. // if no data was provided by template fallback
  52. // to value from the provider
  53. if len(es.Spec.Target.Template.Data) == 0 {
  54. for k, v := range dataMap {
  55. secret.Data[k] = v
  56. }
  57. }
  58. secret.Annotations[esv1alpha1.AnnotationDataHash] = utils.ObjectHash(secret.Data)
  59. return nil
  60. }
  61. // we do not want to force-override the label/annotations
  62. // and only copy the necessary key/value pairs.
  63. func mergeMetadata(secret *v1.Secret, externalSecret *esv1alpha1.ExternalSecret) {
  64. if secret.ObjectMeta.Labels == nil {
  65. secret.ObjectMeta.Labels = make(map[string]string)
  66. }
  67. if secret.ObjectMeta.Annotations == nil {
  68. secret.ObjectMeta.Annotations = make(map[string]string)
  69. }
  70. if externalSecret.Spec.Target.Template == nil {
  71. utils.MergeStringMap(secret.ObjectMeta.Labels, externalSecret.ObjectMeta.Labels)
  72. utils.MergeStringMap(secret.ObjectMeta.Annotations, externalSecret.ObjectMeta.Annotations)
  73. return
  74. }
  75. // if template is defined: use those labels/annotations
  76. secret.Type = externalSecret.Spec.Target.Template.Type
  77. utils.MergeStringMap(secret.ObjectMeta.Labels, externalSecret.Spec.Target.Template.Metadata.Labels)
  78. utils.MergeStringMap(secret.ObjectMeta.Annotations, externalSecret.Spec.Target.Template.Metadata.Annotations)
  79. }
  80. func (r *Reconciler) getTemplateData(ctx context.Context, externalSecret *esv1alpha1.ExternalSecret) (map[string][]byte, error) {
  81. out := make(map[string][]byte)
  82. if externalSecret.Spec.Target.Template == nil {
  83. return out, nil
  84. }
  85. for _, tpl := range externalSecret.Spec.Target.Template.TemplateFrom {
  86. err := mergeConfigMap(ctx, r.Client, externalSecret, tpl, out)
  87. if err != nil {
  88. return nil, err
  89. }
  90. err = mergeSecret(ctx, r.Client, externalSecret, tpl, out)
  91. if err != nil {
  92. return nil, err
  93. }
  94. }
  95. return out, nil
  96. }
  97. func mergeConfigMap(ctx context.Context, k8sClient client.Client, es *esv1alpha1.ExternalSecret, tpl esv1alpha1.TemplateFrom, out map[string][]byte) error {
  98. if tpl.ConfigMap == nil {
  99. return nil
  100. }
  101. var cm v1.ConfigMap
  102. err := k8sClient.Get(ctx, types.NamespacedName{
  103. Name: tpl.ConfigMap.Name,
  104. Namespace: es.Namespace,
  105. }, &cm)
  106. if err != nil {
  107. return err
  108. }
  109. for _, k := range tpl.ConfigMap.Items {
  110. val, ok := cm.Data[k.Key]
  111. if !ok {
  112. return fmt.Errorf(errTplCMMissingKey, tpl.ConfigMap.Name, k.Key)
  113. }
  114. out[k.Key] = []byte(val)
  115. }
  116. return nil
  117. }
  118. func mergeSecret(ctx context.Context, k8sClient client.Client, es *esv1alpha1.ExternalSecret, tpl esv1alpha1.TemplateFrom, out map[string][]byte) error {
  119. if tpl.Secret == nil {
  120. return nil
  121. }
  122. var sec v1.Secret
  123. err := k8sClient.Get(ctx, types.NamespacedName{
  124. Name: tpl.Secret.Name,
  125. Namespace: es.Namespace,
  126. }, &sec)
  127. if err != nil {
  128. return err
  129. }
  130. for _, k := range tpl.Secret.Items {
  131. val, ok := sec.Data[k.Key]
  132. if !ok {
  133. return fmt.Errorf(errTplSecMissingKey, tpl.Secret.Name, k.Key)
  134. }
  135. out[k.Key] = val
  136. }
  137. return nil
  138. }