push_secret.go 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  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 secretmanager
  13. import (
  14. "bytes"
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
  19. "github.com/tidwall/sjson"
  20. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  21. )
  22. type Metadata struct {
  23. Annotations map[string]string `json:"annotations"`
  24. Labels map[string]string `json:"labels"`
  25. Topics []string `json:"topics,omitempty"`
  26. }
  27. func newPushSecretBuilder(payload []byte, data esv1beta1.PushSecretData) (pushSecretBuilder, error) {
  28. if data.GetProperty() == "" {
  29. return &psBuilder{
  30. payload: payload,
  31. pushSecretData: data,
  32. }, nil
  33. }
  34. if data.GetMetadata() != nil {
  35. return nil, errors.New("cannot specify metadata and property at the same time")
  36. }
  37. return &propertyPSBuilder{
  38. payload: payload,
  39. pushSecretData: data,
  40. }, nil
  41. }
  42. type pushSecretBuilder interface {
  43. buildMetadata(annotations, labels map[string]string, topics []*secretmanagerpb.Topic) (map[string]string, map[string]string, []string, error)
  44. needUpdate(original []byte) bool
  45. buildData(original []byte) ([]byte, error)
  46. }
  47. type psBuilder struct {
  48. payload []byte
  49. pushSecretData esv1beta1.PushSecretData
  50. }
  51. func (b *psBuilder) buildMetadata(_, labels map[string]string, _ []*secretmanagerpb.Topic) (map[string]string, map[string]string, []string, error) {
  52. if manager, ok := labels[managedByKey]; !ok || manager != managedByValue {
  53. return nil, nil, nil, fmt.Errorf("secret %v is not managed by external secrets", b.pushSecretData.GetRemoteKey())
  54. }
  55. var metadata Metadata
  56. if b.pushSecretData.GetMetadata() != nil {
  57. decoder := json.NewDecoder(bytes.NewReader(b.pushSecretData.GetMetadata().Raw))
  58. // Want to return an error if unknown fields exist
  59. decoder.DisallowUnknownFields()
  60. if err := decoder.Decode(&metadata); err != nil {
  61. return nil, nil, nil, fmt.Errorf("failed to decode PushSecret metadata: %w", err)
  62. }
  63. }
  64. newLabels := map[string]string{}
  65. if metadata.Labels != nil {
  66. newLabels = metadata.Labels
  67. }
  68. newLabels[managedByKey] = managedByValue
  69. return metadata.Annotations, newLabels, metadata.Topics, nil
  70. }
  71. func (b *psBuilder) needUpdate(original []byte) bool {
  72. if original == nil {
  73. return true
  74. }
  75. return !bytes.Equal(b.payload, original)
  76. }
  77. func (b *psBuilder) buildData(_ []byte) ([]byte, error) {
  78. return b.payload, nil
  79. }
  80. type propertyPSBuilder struct {
  81. payload []byte
  82. pushSecretData esv1beta1.PushSecretData
  83. }
  84. func (b *propertyPSBuilder) buildMetadata(annotations, labels map[string]string, topics []*secretmanagerpb.Topic) (map[string]string, map[string]string, []string, error) {
  85. newAnnotations := map[string]string{}
  86. newLabels := map[string]string{}
  87. if annotations != nil {
  88. newAnnotations = annotations
  89. }
  90. if labels != nil {
  91. newLabels = labels
  92. }
  93. newLabels[managedByKey] = managedByValue
  94. result := make([]string, 0, len(topics))
  95. for _, t := range topics {
  96. result = append(result, t.Name)
  97. }
  98. return newAnnotations, newLabels, result, nil
  99. }
  100. func (b *propertyPSBuilder) needUpdate(original []byte) bool {
  101. if original == nil {
  102. return true
  103. }
  104. val := getDataByProperty(original, b.pushSecretData.GetProperty())
  105. return !val.Exists() || val.String() != string(b.payload)
  106. }
  107. func (b *propertyPSBuilder) buildData(original []byte) ([]byte, error) {
  108. var base []byte
  109. if original != nil {
  110. base = original
  111. }
  112. return sjson.SetBytes(base, b.pushSecretData.GetProperty(), b.payload)
  113. }