parser.go 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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 templating
  13. import (
  14. "context"
  15. "encoding/json"
  16. "fmt"
  17. "strings"
  18. v1 "k8s.io/api/core/v1"
  19. "k8s.io/apimachinery/pkg/types"
  20. "sigs.k8s.io/controller-runtime/pkg/client"
  21. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  22. "github.com/external-secrets/external-secrets/pkg/template"
  23. )
  24. const fieldOwnerTemplate = "externalsecrets.external-secrets.io/%v"
  25. var (
  26. errTplCMMissingKey = "error in configmap %s: missing key %s"
  27. errTplSecMissingKey = "error in secret %s: missing key %s"
  28. errExecTpl = "could not execute template: %w"
  29. )
  30. type Parser struct {
  31. Exec template.ExecFunc
  32. DataMap map[string][]byte
  33. Client client.Client
  34. TargetSecret *v1.Secret
  35. TemplateFromConfigMap *v1.ConfigMap
  36. TemplateFromSecret *v1.Secret
  37. }
  38. func (p *Parser) MergeConfigMap(ctx context.Context, namespace string, tpl esv1beta1.TemplateFrom) error {
  39. if tpl.ConfigMap == nil {
  40. return nil
  41. }
  42. var cm v1.ConfigMap
  43. if p.TemplateFromConfigMap != nil {
  44. cm = *p.TemplateFromConfigMap
  45. } else {
  46. err := p.Client.Get(ctx, types.NamespacedName{
  47. Name: tpl.ConfigMap.Name,
  48. Namespace: namespace,
  49. }, &cm)
  50. if err != nil {
  51. return err
  52. }
  53. }
  54. for _, k := range tpl.ConfigMap.Items {
  55. val, ok := cm.Data[k.Key]
  56. out := make(map[string][]byte)
  57. if !ok {
  58. return fmt.Errorf(errTplCMMissingKey, tpl.ConfigMap.Name, k.Key)
  59. }
  60. switch k.TemplateAs {
  61. case esv1beta1.TemplateScopeValues:
  62. out[k.Key] = []byte(val)
  63. case esv1beta1.TemplateScopeKeysAndValues:
  64. out[val] = []byte(val)
  65. }
  66. err := p.Exec(out, p.DataMap, k.TemplateAs, tpl.Target, p.TargetSecret)
  67. if err != nil {
  68. return err
  69. }
  70. }
  71. return nil
  72. }
  73. func (p *Parser) MergeSecret(ctx context.Context, namespace string, tpl esv1beta1.TemplateFrom) error {
  74. if tpl.Secret == nil {
  75. return nil
  76. }
  77. var sec v1.Secret
  78. if p.TemplateFromSecret != nil {
  79. sec = *p.TemplateFromSecret
  80. } else {
  81. err := p.Client.Get(ctx, types.NamespacedName{
  82. Name: tpl.Secret.Name,
  83. Namespace: namespace,
  84. }, &sec)
  85. if err != nil {
  86. return err
  87. }
  88. }
  89. for _, k := range tpl.Secret.Items {
  90. val, ok := sec.Data[k.Key]
  91. if !ok {
  92. return fmt.Errorf(errTplSecMissingKey, tpl.Secret.Name, k.Key)
  93. }
  94. out := make(map[string][]byte)
  95. switch k.TemplateAs {
  96. case esv1beta1.TemplateScopeValues:
  97. out[k.Key] = val
  98. case esv1beta1.TemplateScopeKeysAndValues:
  99. out[string(val)] = val
  100. }
  101. err := p.Exec(out, p.DataMap, k.TemplateAs, tpl.Target, p.TargetSecret)
  102. if err != nil {
  103. return err
  104. }
  105. }
  106. return nil
  107. }
  108. func (p *Parser) MergeLiteral(_ context.Context, tpl esv1beta1.TemplateFrom) error {
  109. if tpl.Literal == nil {
  110. return nil
  111. }
  112. out := make(map[string][]byte)
  113. out[*tpl.Literal] = []byte(*tpl.Literal)
  114. return p.Exec(out, p.DataMap, esv1beta1.TemplateScopeKeysAndValues, tpl.Target, p.TargetSecret)
  115. }
  116. func (p *Parser) MergeTemplateFrom(ctx context.Context, namespace string, template *esv1beta1.ExternalSecretTemplate) error {
  117. if template == nil {
  118. return nil
  119. }
  120. for _, tpl := range template.TemplateFrom {
  121. err := p.MergeConfigMap(ctx, namespace, tpl)
  122. if err != nil {
  123. return err
  124. }
  125. err = p.MergeSecret(ctx, namespace, tpl)
  126. if err != nil {
  127. return err
  128. }
  129. err = p.MergeLiteral(ctx, tpl)
  130. if err != nil {
  131. return err
  132. }
  133. }
  134. return nil
  135. }
  136. func (p *Parser) MergeMap(tplMap map[string]string, target esv1beta1.TemplateTarget) error {
  137. byteMap := make(map[string][]byte)
  138. for k, v := range tplMap {
  139. byteMap[k] = []byte(v)
  140. }
  141. err := p.Exec(byteMap, p.DataMap, esv1beta1.TemplateScopeValues, target, p.TargetSecret)
  142. if err != nil {
  143. return fmt.Errorf(errExecTpl, err)
  144. }
  145. return nil
  146. }
  147. func GetManagedAnnotationKeys(secret *v1.Secret, fieldOwner string) ([]string, error) {
  148. return getManagedFieldKeys(secret, fieldOwner, func(fields map[string]any) []string {
  149. metadataFields, exists := fields["f:metadata"]
  150. if !exists {
  151. return nil
  152. }
  153. mf, ok := metadataFields.(map[string]any)
  154. if !ok {
  155. return nil
  156. }
  157. annotationFields, exists := mf["f:annotations"]
  158. if !exists {
  159. return nil
  160. }
  161. af, ok := annotationFields.(map[string]any)
  162. if !ok {
  163. return nil
  164. }
  165. var keys []string
  166. for k := range af {
  167. keys = append(keys, k)
  168. }
  169. return keys
  170. })
  171. }
  172. func GetManagedLabelKeys(secret *v1.Secret, fieldOwner string) ([]string, error) {
  173. return getManagedFieldKeys(secret, fieldOwner, func(fields map[string]any) []string {
  174. metadataFields, exists := fields["f:metadata"]
  175. if !exists {
  176. return nil
  177. }
  178. mf, ok := metadataFields.(map[string]any)
  179. if !ok {
  180. return nil
  181. }
  182. labelFields, exists := mf["f:labels"]
  183. if !exists {
  184. return nil
  185. }
  186. lf, ok := labelFields.(map[string]any)
  187. if !ok {
  188. return nil
  189. }
  190. var keys []string
  191. for k := range lf {
  192. keys = append(keys, k)
  193. }
  194. return keys
  195. })
  196. }
  197. func getManagedFieldKeys(
  198. secret *v1.Secret,
  199. fieldOwner string,
  200. process func(fields map[string]any) []string,
  201. ) ([]string, error) {
  202. fqdn := fmt.Sprintf(fieldOwnerTemplate, fieldOwner)
  203. var keys []string
  204. for _, v := range secret.ObjectMeta.ManagedFields {
  205. if v.Manager != fqdn {
  206. continue
  207. }
  208. fields := make(map[string]any)
  209. err := json.Unmarshal(v.FieldsV1.Raw, &fields)
  210. if err != nil {
  211. return nil, fmt.Errorf("error unmarshaling managed fields: %w", err)
  212. }
  213. for _, key := range process(fields) {
  214. if key == "." {
  215. continue
  216. }
  217. keys = append(keys, strings.TrimPrefix(key, "f:"))
  218. }
  219. }
  220. return keys, nil
  221. }