client.go 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 impliec.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package doppler
  13. import (
  14. "context"
  15. "encoding/json"
  16. "fmt"
  17. "net/url"
  18. "strings"
  19. "time"
  20. corev1 "k8s.io/api/core/v1"
  21. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  22. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  23. "github.com/external-secrets/external-secrets/pkg/find"
  24. dClient "github.com/external-secrets/external-secrets/pkg/provider/doppler/client"
  25. "github.com/external-secrets/external-secrets/pkg/utils"
  26. "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
  27. )
  28. const (
  29. customBaseURLEnvVar = "DOPPLER_BASE_URL"
  30. verifyTLSOverrideEnvVar = "DOPPLER_VERIFY_TLS"
  31. errGetSecret = "could not get secret %s: %s"
  32. errGetSecrets = "could not get secrets %s"
  33. errUnmarshalSecretMap = "unable to unmarshal secret %s: %w"
  34. secretsDownloadFileKey = "DOPPLER_SECRETS_FILE"
  35. errDopplerTokenSecretName = "missing auth.secretRef.dopplerToken.name"
  36. errInvalidClusterStoreMissingDopplerTokenNamespace = "missing auth.secretRef.dopplerToken.namespace"
  37. )
  38. type Client struct {
  39. doppler SecretsClientInterface
  40. dopplerToken string
  41. project string
  42. config string
  43. nameTransformer string
  44. format string
  45. kube kclient.Client
  46. store *esv1beta1.DopplerProvider
  47. namespace string
  48. storeKind string
  49. }
  50. // SecretsClientInterface defines the required Doppler Client methods.
  51. type SecretsClientInterface interface {
  52. BaseURL() *url.URL
  53. Authenticate() error
  54. GetSecret(request dClient.SecretRequest) (*dClient.SecretResponse, error)
  55. GetSecrets(request dClient.SecretsRequest) (*dClient.SecretsResponse, error)
  56. }
  57. func (c *Client) setAuth(ctx context.Context) error {
  58. token, err := resolvers.SecretKeyRef(
  59. ctx,
  60. c.kube,
  61. c.storeKind,
  62. c.namespace,
  63. &c.store.Auth.SecretRef.DopplerToken)
  64. if err != nil {
  65. return err
  66. }
  67. c.dopplerToken = token
  68. return nil
  69. }
  70. func (c *Client) Validate() (esv1beta1.ValidationResult, error) {
  71. timeout := 15 * time.Second
  72. clientURL := c.doppler.BaseURL().String()
  73. if err := utils.NetworkValidate(clientURL, timeout); err != nil {
  74. return esv1beta1.ValidationResultError, err
  75. }
  76. if err := c.doppler.Authenticate(); err != nil {
  77. return esv1beta1.ValidationResultError, err
  78. }
  79. return esv1beta1.ValidationResultReady, nil
  80. }
  81. func (c *Client) DeleteSecret(_ context.Context, _ esv1beta1.PushSecretRemoteRef) error {
  82. return fmt.Errorf("not implemented")
  83. }
  84. func (c *Client) PushSecret(_ context.Context, _ *corev1.Secret, _ esv1beta1.PushSecretData) error {
  85. return fmt.Errorf("not implemented")
  86. }
  87. func (c *Client) GetSecret(_ context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  88. request := dClient.SecretRequest{
  89. Name: ref.Key,
  90. Project: c.project,
  91. Config: c.config,
  92. }
  93. secret, err := c.doppler.GetSecret(request)
  94. if err != nil {
  95. return nil, fmt.Errorf(errGetSecret, ref.Key, err)
  96. }
  97. return []byte(secret.Value), nil
  98. }
  99. func (c *Client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  100. data, err := c.GetSecret(ctx, ref)
  101. if err != nil {
  102. return nil, err
  103. }
  104. kv := make(map[string]json.RawMessage)
  105. err = json.Unmarshal(data, &kv)
  106. if err != nil {
  107. return nil, fmt.Errorf(errUnmarshalSecretMap, ref.Key, err)
  108. }
  109. secretData := make(map[string][]byte)
  110. for k, v := range kv {
  111. var strVal string
  112. err = json.Unmarshal(v, &strVal)
  113. if err == nil {
  114. secretData[k] = []byte(strVal)
  115. } else {
  116. secretData[k] = v
  117. }
  118. }
  119. return secretData, nil
  120. }
  121. func (c *Client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  122. secrets, err := c.getSecrets(ctx)
  123. selected := map[string][]byte{}
  124. if err != nil {
  125. return nil, err
  126. }
  127. if ref.Name == nil && ref.Path == nil {
  128. return secrets, nil
  129. }
  130. var matcher *find.Matcher
  131. if ref.Name != nil {
  132. m, err := find.New(*ref.Name)
  133. if err != nil {
  134. return nil, err
  135. }
  136. matcher = m
  137. }
  138. for key, value := range secrets {
  139. if (matcher != nil && !matcher.MatchName(key)) || (ref.Path != nil && !strings.HasPrefix(key, *ref.Path)) {
  140. continue
  141. }
  142. selected[key] = value
  143. }
  144. return selected, nil
  145. }
  146. func (c *Client) Close(_ context.Context) error {
  147. return nil
  148. }
  149. func (c *Client) getSecrets(_ context.Context) (map[string][]byte, error) {
  150. request := dClient.SecretsRequest{
  151. Project: c.project,
  152. Config: c.config,
  153. NameTransformer: c.nameTransformer,
  154. Format: c.format,
  155. }
  156. response, err := c.doppler.GetSecrets(request)
  157. if err != nil {
  158. return nil, fmt.Errorf(errGetSecrets, err)
  159. }
  160. if c.format != "" {
  161. return map[string][]byte{
  162. secretsDownloadFileKey: response.Body,
  163. }, nil
  164. }
  165. return externalSecretsFormat(response.Secrets), nil
  166. }
  167. func externalSecretsFormat(secrets dClient.Secrets) map[string][]byte {
  168. converted := make(map[string][]byte, len(secrets))
  169. for key, value := range secrets {
  170. converted[key] = []byte(value)
  171. }
  172. return converted
  173. }