externalsecret_controller_template.go 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293
  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. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  20. // Loading registered providers.
  21. _ "github.com/external-secrets/external-secrets/pkg/provider/register"
  22. "github.com/external-secrets/external-secrets/pkg/template"
  23. "github.com/external-secrets/external-secrets/pkg/utils"
  24. )
  25. type Parser struct {
  26. exec template.ExecFunc
  27. dataMap map[string][]byte
  28. client client.Client
  29. targetSecret *v1.Secret
  30. }
  31. func (p *Parser) MergeConfigMap(ctx context.Context, namespace string, tpl esv1beta1.TemplateFrom) error {
  32. if tpl.ConfigMap == nil {
  33. return nil
  34. }
  35. var cm v1.ConfigMap
  36. err := p.client.Get(ctx, types.NamespacedName{
  37. Name: tpl.ConfigMap.Name,
  38. Namespace: namespace,
  39. }, &cm)
  40. if err != nil {
  41. return err
  42. }
  43. for _, k := range tpl.ConfigMap.Items {
  44. val, ok := cm.Data[k.Key]
  45. out := make(map[string][]byte)
  46. if !ok {
  47. return fmt.Errorf(errTplCMMissingKey, tpl.ConfigMap.Name, k.Key)
  48. }
  49. switch k.TemplateAs {
  50. case esv1beta1.TemplateScopeValues:
  51. out[k.Key] = []byte(val)
  52. case esv1beta1.TemplateScopeKeysAndValues:
  53. out[val] = []byte(val)
  54. }
  55. err = p.exec(out, p.dataMap, k.TemplateAs, tpl.Target, p.targetSecret)
  56. if err != nil {
  57. return err
  58. }
  59. }
  60. return nil
  61. }
  62. func (p *Parser) MergeSecret(ctx context.Context, namespace string, tpl esv1beta1.TemplateFrom) error {
  63. if tpl.Secret == nil {
  64. return nil
  65. }
  66. var sec v1.Secret
  67. err := p.client.Get(ctx, types.NamespacedName{
  68. Name: tpl.Secret.Name,
  69. Namespace: namespace,
  70. }, &sec)
  71. if err != nil {
  72. return err
  73. }
  74. for _, k := range tpl.Secret.Items {
  75. val, ok := sec.Data[k.Key]
  76. if !ok {
  77. return fmt.Errorf(errTplSecMissingKey, tpl.Secret.Name, k.Key)
  78. }
  79. out := make(map[string][]byte)
  80. switch k.TemplateAs {
  81. case esv1beta1.TemplateScopeValues:
  82. out[k.Key] = val
  83. case esv1beta1.TemplateScopeKeysAndValues:
  84. out[string(val)] = val
  85. }
  86. err = p.exec(out, p.dataMap, k.TemplateAs, tpl.Target, p.targetSecret)
  87. if err != nil {
  88. return err
  89. }
  90. }
  91. return nil
  92. }
  93. func (p *Parser) MergeLiteral(_ context.Context, tpl esv1beta1.TemplateFrom) error {
  94. if tpl.Literal == nil {
  95. return nil
  96. }
  97. out := make(map[string][]byte)
  98. out[*tpl.Literal] = []byte(*tpl.Literal)
  99. return p.exec(out, p.dataMap, esv1beta1.TemplateScopeKeysAndValues, tpl.Target, p.targetSecret)
  100. }
  101. func (p *Parser) MergeTemplateFrom(ctx context.Context, es *esv1beta1.ExternalSecret) error {
  102. if es.Spec.Target.Template == nil {
  103. return nil
  104. }
  105. for _, tpl := range es.Spec.Target.Template.TemplateFrom {
  106. err := p.MergeConfigMap(ctx, es.Namespace, tpl)
  107. if err != nil {
  108. return err
  109. }
  110. err = p.MergeSecret(ctx, es.Namespace, tpl)
  111. if err != nil {
  112. return err
  113. }
  114. err = p.MergeLiteral(ctx, tpl)
  115. if err != nil {
  116. return err
  117. }
  118. }
  119. return nil
  120. }
  121. func (p *Parser) MergeMap(tplMap map[string]string, target esv1beta1.TemplateTarget) error {
  122. byteMap := make(map[string][]byte)
  123. for k, v := range tplMap {
  124. byteMap[k] = []byte(v)
  125. }
  126. err := p.exec(byteMap, p.dataMap, esv1beta1.TemplateScopeValues, target, p.targetSecret)
  127. if err != nil {
  128. return fmt.Errorf(errExecTpl, err)
  129. }
  130. return nil
  131. }
  132. // merge template in the following order:
  133. // * template.Data (highest precedence)
  134. // * template.templateFrom
  135. // * secret via es.data or es.dataFrom.
  136. func (r *Reconciler) applyTemplate(ctx context.Context, es *esv1beta1.ExternalSecret, secret *v1.Secret, dataMap map[string][]byte) error {
  137. if err := setMetadata(secret, es); err != nil {
  138. return err
  139. }
  140. // no template: copy data and return
  141. if es.Spec.Target.Template == nil {
  142. secret.Data = dataMap
  143. return nil
  144. }
  145. // Merge Policy should merge secrets
  146. if es.Spec.Target.Template.MergePolicy == esv1beta1.MergePolicyMerge {
  147. for k, v := range dataMap {
  148. secret.Data[k] = v
  149. }
  150. }
  151. execute, err := template.EngineForVersion(es.Spec.Target.Template.EngineVersion)
  152. if err != nil {
  153. return err
  154. }
  155. p := Parser{
  156. client: r.Client,
  157. targetSecret: secret,
  158. dataMap: dataMap,
  159. exec: execute,
  160. }
  161. // apply templates defined in template.templateFrom
  162. err = p.MergeTemplateFrom(ctx, es)
  163. if err != nil {
  164. return fmt.Errorf(errFetchTplFrom, err)
  165. }
  166. // explicitly defined template.Data takes precedence over templateFrom
  167. err = p.MergeMap(es.Spec.Target.Template.Data, esv1beta1.TemplateTargetData)
  168. if err != nil {
  169. return fmt.Errorf(errExecTpl, err)
  170. }
  171. // get template data for labels
  172. err = p.MergeMap(es.Spec.Target.Template.Metadata.Labels, esv1beta1.TemplateTargetLabels)
  173. if err != nil {
  174. return fmt.Errorf(errExecTpl, err)
  175. }
  176. // get template data for annotations
  177. err = p.MergeMap(es.Spec.Target.Template.Metadata.Annotations, esv1beta1.TemplateTargetAnnotations)
  178. if err != nil {
  179. return fmt.Errorf(errExecTpl, err)
  180. }
  181. // if no data was provided by template fallback
  182. // to value from the provider
  183. if len(es.Spec.Target.Template.Data) == 0 && len(es.Spec.Target.Template.TemplateFrom) == 0 {
  184. secret.Data = dataMap
  185. }
  186. return nil
  187. }
  188. // setMetadata sets Labels and Annotations to the given secret.
  189. func setMetadata(secret *v1.Secret, es *esv1beta1.ExternalSecret) error {
  190. if secret.Labels == nil {
  191. secret.Labels = make(map[string]string)
  192. }
  193. if secret.Annotations == nil {
  194. secret.Annotations = make(map[string]string)
  195. }
  196. // Clean up Labels and Annotations added by the operator
  197. // so that it won't leave outdated ones
  198. labelKeys, err := getManagedLabelKeys(secret, es.Name)
  199. if err != nil {
  200. return err
  201. }
  202. for _, key := range labelKeys {
  203. delete(secret.ObjectMeta.Labels, key)
  204. }
  205. annotationKeys, err := getManagedAnnotationKeys(secret, es.Name)
  206. if err != nil {
  207. return err
  208. }
  209. for _, key := range annotationKeys {
  210. delete(secret.ObjectMeta.Annotations, key)
  211. }
  212. if es.Spec.Target.Template == nil {
  213. utils.MergeStringMap(secret.ObjectMeta.Labels, es.ObjectMeta.Labels)
  214. utils.MergeStringMap(secret.ObjectMeta.Annotations, es.ObjectMeta.Annotations)
  215. return nil
  216. }
  217. secret.Type = es.Spec.Target.Template.Type
  218. utils.MergeStringMap(secret.ObjectMeta.Labels, es.Spec.Target.Template.Metadata.Labels)
  219. utils.MergeStringMap(secret.ObjectMeta.Annotations, es.Spec.Target.Template.Metadata.Annotations)
  220. return nil
  221. }
  222. func getManagedAnnotationKeys(secret *v1.Secret, fieldOwner string) ([]string, error) {
  223. return getManagedFieldKeys(secret, fieldOwner, func(fields map[string]interface{}) []string {
  224. metadataFields, exists := fields["f:metadata"]
  225. if !exists {
  226. return nil
  227. }
  228. mf, ok := metadataFields.(map[string]interface{})
  229. if !ok {
  230. return nil
  231. }
  232. annotationFields, exists := mf["f:annotations"]
  233. if !exists {
  234. return nil
  235. }
  236. af, ok := annotationFields.(map[string]interface{})
  237. if !ok {
  238. return nil
  239. }
  240. var keys []string
  241. for k := range af {
  242. keys = append(keys, k)
  243. }
  244. return keys
  245. })
  246. }
  247. func getManagedLabelKeys(secret *v1.Secret, fieldOwner string) ([]string, error) {
  248. return getManagedFieldKeys(secret, fieldOwner, func(fields map[string]interface{}) []string {
  249. metadataFields, exists := fields["f:metadata"]
  250. if !exists {
  251. return nil
  252. }
  253. mf, ok := metadataFields.(map[string]interface{})
  254. if !ok {
  255. return nil
  256. }
  257. labelFields, exists := mf["f:labels"]
  258. if !exists {
  259. return nil
  260. }
  261. lf, ok := labelFields.(map[string]interface{})
  262. if !ok {
  263. return nil
  264. }
  265. var keys []string
  266. for k := range lf {
  267. keys = append(keys, k)
  268. }
  269. return keys
  270. })
  271. }