client.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170
  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 infisical
  13. import (
  14. "context"
  15. "encoding/json"
  16. "errors"
  17. "fmt"
  18. "strings"
  19. "github.com/tidwall/gjson"
  20. corev1 "k8s.io/api/core/v1"
  21. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  22. "github.com/external-secrets/external-secrets/pkg/find"
  23. "github.com/external-secrets/external-secrets/pkg/provider/infisical/api"
  24. )
  25. var (
  26. errNotImplemented = errors.New("not implemented")
  27. errPropertyNotFound = "property %s does not exist in secret %s"
  28. errTagsNotImplemented = errors.New("find by tags not supported")
  29. )
  30. func getPropertyValue(jsonData, propertyName, keyName string) ([]byte, error) {
  31. result := gjson.Get(jsonData, propertyName)
  32. if !result.Exists() {
  33. return nil, fmt.Errorf(errPropertyNotFound, propertyName, keyName)
  34. }
  35. return []byte(result.Str), nil
  36. }
  37. // if GetSecret returns an error with type NoSecretError.
  38. // then the secret entry will be deleted depending on the deletionPolicy.
  39. func (p *Provider) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  40. secret, err := p.apiClient.GetSecretByKeyV3(api.GetSecretByKeyV3Request{
  41. EnvironmentSlug: p.apiScope.EnvironmentSlug,
  42. ProjectSlug: p.apiScope.ProjectSlug,
  43. SecretPath: p.apiScope.SecretPath,
  44. SecretKey: ref.Key,
  45. })
  46. if err != nil {
  47. return nil, err
  48. }
  49. if ref.Property != "" {
  50. propertyValue, err := getPropertyValue(secret, ref.Property, ref.Key)
  51. if err != nil {
  52. return nil, err
  53. }
  54. return propertyValue, nil
  55. }
  56. return []byte(secret), nil
  57. }
  58. // GetSecretMap returns multiple k/v pairs from the provider.
  59. func (p *Provider) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  60. secret, err := p.GetSecret(ctx, ref)
  61. if err != nil {
  62. return nil, err
  63. }
  64. kv := make(map[string]json.RawMessage)
  65. err = json.Unmarshal(secret, &kv)
  66. if err != nil {
  67. return nil, fmt.Errorf("unable to unmarshal secret %s: %w", ref.Key, err)
  68. }
  69. secretData := make(map[string][]byte)
  70. for k, v := range kv {
  71. var strVal string
  72. err = json.Unmarshal(v, &strVal)
  73. if err == nil {
  74. secretData[k] = []byte(strVal)
  75. } else {
  76. secretData[k] = v
  77. }
  78. }
  79. return secretData, nil
  80. }
  81. // GetAllSecrets returns multiple k/v pairs from the provider.
  82. func (p *Provider) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  83. if ref.Tags != nil {
  84. return nil, errTagsNotImplemented
  85. }
  86. secrets, err := p.apiClient.GetSecretsV3(api.GetSecretsV3Request{
  87. EnvironmentSlug: p.apiScope.EnvironmentSlug,
  88. ProjectSlug: p.apiScope.ProjectSlug,
  89. SecretPath: p.apiScope.SecretPath,
  90. })
  91. if err != nil {
  92. return nil, err
  93. }
  94. secretMap := make(map[string][]byte)
  95. for key, value := range secrets {
  96. secretMap[key] = []byte(value)
  97. }
  98. if ref.Name == nil && ref.Path == nil {
  99. return secretMap, nil
  100. }
  101. var matcher *find.Matcher
  102. if ref.Name != nil {
  103. m, err := find.New(*ref.Name)
  104. if err != nil {
  105. return nil, err
  106. }
  107. matcher = m
  108. }
  109. selected := map[string][]byte{}
  110. for key, value := range secrets {
  111. if (matcher != nil && !matcher.MatchName(key)) || (ref.Path != nil && !strings.HasPrefix(key, *ref.Path)) {
  112. continue
  113. }
  114. selected[key] = []byte(value)
  115. }
  116. return selected, nil
  117. }
  118. // Validate checks if the client is configured correctly.
  119. // and is able to retrieve secrets from the provider.
  120. // If the validation result is unknown it will be ignored.
  121. func (p *Provider) Validate() (esv1beta1.ValidationResult, error) {
  122. // try to fetch the secrets to ensure provided credentials has access to read secrets
  123. _, err := p.apiClient.GetSecretsV3(api.GetSecretsV3Request{
  124. EnvironmentSlug: p.apiScope.EnvironmentSlug,
  125. ProjectSlug: p.apiScope.ProjectSlug,
  126. SecretPath: p.apiScope.SecretPath,
  127. })
  128. if err != nil {
  129. return esv1beta1.ValidationResultError, fmt.Errorf("cannot read secrets with provided project scope project:%s environment:%s secret-path:%s, %w", p.apiScope.ProjectSlug, p.apiScope.EnvironmentSlug, p.apiScope.SecretPath, err)
  130. }
  131. return esv1beta1.ValidationResultReady, nil
  132. }
  133. // PushSecret will write a single secret into the provider.
  134. func (p *Provider) PushSecret(ctx context.Context, secret *corev1.Secret, data esv1beta1.PushSecretData) error {
  135. return errNotImplemented
  136. }
  137. // DeleteSecret will delete the secret from a provider.
  138. func (p *Provider) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushSecretRemoteRef) error {
  139. return errNotImplemented
  140. }
  141. // SecretExists checks if a secret is already present in the provider at the given location.
  142. func (p *Provider) SecretExists(ctx context.Context, remoteRef esv1beta1.PushSecretRemoteRef) (bool, error) {
  143. return false, errNotImplemented
  144. }