parser.go 6.1 KB

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