provider.go 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /*
  2. Copyright © 2025 ESO Maintainer Team
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. // Package previder implements a secret store provider for Previder Vault.
  14. package previder
  15. import (
  16. "context"
  17. "errors"
  18. "fmt"
  19. previderclient "github.com/previder/vault-cli/pkg"
  20. corev1 "k8s.io/api/core/v1"
  21. "sigs.k8s.io/controller-runtime/pkg/client"
  22. "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
  23. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  24. "github.com/external-secrets/external-secrets/pkg/esutils/resolvers"
  25. )
  26. const (
  27. errNotImplemented = "not implemented"
  28. )
  29. var _ esv1.Provider = &SecretManager{}
  30. // SecretManager implements the esv1.Provider interface for Previder Vault.
  31. type SecretManager struct {
  32. VaultClient previderclient.PreviderVaultClient
  33. TokenType string
  34. }
  35. func init() {
  36. esv1.Register(&SecretManager{}, &esv1.SecretStoreProvider{
  37. Previder: &esv1.PreviderProvider{},
  38. }, esv1.MaintenanceStatusMaintained)
  39. }
  40. // NewClient creates a new Previder Vault client.
  41. func (s *SecretManager) NewClient(ctx context.Context, store esv1.GenericStore, kube client.Client, namespace string) (esv1.SecretsClient, error) {
  42. if store == nil {
  43. return nil, fmt.Errorf("secret store not found: %v", "nil store")
  44. }
  45. storeSpec := store.GetSpec().Provider.Previder
  46. storeKind := store.GetObjectKind().GroupVersionKind().Kind
  47. accessToken, err := resolvers.SecretKeyRef(ctx, kube, storeKind, namespace, &storeSpec.Auth.SecretRef.AccessToken)
  48. if err != nil {
  49. return nil, fmt.Errorf(accessToken, err)
  50. }
  51. s.VaultClient, err = previderclient.NewVaultClient(storeSpec.BaseURI, accessToken)
  52. if err != nil {
  53. return nil, err
  54. }
  55. tokenInfo, err := s.VaultClient.GetTokenInfo()
  56. if err != nil {
  57. return nil, err
  58. }
  59. s.TokenType = tokenInfo.TokenType
  60. return s, nil
  61. }
  62. // ValidateStore validates the Previder Vault store configuration.
  63. func (s *SecretManager) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
  64. storeSpec := store.GetSpec()
  65. previderSpec := storeSpec.Provider.Previder
  66. if previderSpec == nil {
  67. return nil, errors.New("missing Previder spec")
  68. }
  69. if previderSpec.Auth.SecretRef == nil {
  70. return nil, errors.New("missing Previder Auth SecretRef")
  71. }
  72. accessToken := previderSpec.Auth.SecretRef.AccessToken
  73. if accessToken.Name == "" {
  74. return nil, errors.New("missing Previder accessToken name")
  75. }
  76. if accessToken.Key == "" {
  77. return nil, errors.New("missing Previder accessToken key")
  78. }
  79. return nil, nil
  80. }
  81. // Capabilities returns the capabilities of the Previder Vault provider.
  82. func (s *SecretManager) Capabilities() esv1.SecretStoreCapabilities {
  83. return esv1.SecretStoreReadOnly
  84. }
  85. // GetSecret retrieves a secret from Previder Vault.
  86. func (s *SecretManager) GetSecret(_ context.Context, ref esv1.ExternalSecretDataRemoteRef) ([]byte, error) {
  87. secret, err := s.VaultClient.DecryptSecret(ref.Key)
  88. if err != nil {
  89. return nil, err
  90. }
  91. return []byte(secret.Secret), nil
  92. }
  93. // PushSecret is not implemented for Previder Vault.
  94. func (s *SecretManager) PushSecret(context.Context, *corev1.Secret, esv1.PushSecretData) error {
  95. return errors.New(errNotImplemented)
  96. }
  97. // DeleteSecret is not implemented for Previder Vault.
  98. func (s *SecretManager) DeleteSecret(context.Context, esv1.PushSecretRemoteRef) error {
  99. return errors.New(errNotImplemented)
  100. }
  101. // SecretExists is not implemented for Previder Vault.
  102. func (s *SecretManager) SecretExists(context.Context, esv1.PushSecretRemoteRef) (bool, error) {
  103. return false, errors.New(errNotImplemented)
  104. }
  105. // Validate checks if the Vault client can connect and retrieve secrets.
  106. func (s *SecretManager) Validate() (esv1.ValidationResult, error) {
  107. _, err := s.VaultClient.GetTokenInfo()
  108. if err != nil {
  109. return esv1.ValidationResultError, err
  110. }
  111. return esv1.ValidationResultReady, nil
  112. }
  113. // GetSecretMap retrieves a secret and returns it as a map with a single key-value pair.
  114. func (s *SecretManager) GetSecretMap(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  115. secrets, err := s.GetSecret(ctx, ref)
  116. if err != nil {
  117. return nil, err
  118. }
  119. secretData := make(map[string][]byte)
  120. secretData[ref.Key] = secrets
  121. return secretData, nil
  122. }
  123. // GetAllSecrets is not implemented for Previder Vault.
  124. func (s *SecretManager) GetAllSecrets(context.Context, esv1.ExternalSecretFind) (map[string][]byte, error) {
  125. return nil, errors.New(errNotImplemented)
  126. }
  127. // Close cleans up any resources held by the client.
  128. func (s *SecretManager) Close(context.Context) error {
  129. return nil
  130. }