provider.go 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  1. /*
  2. Copyright © The ESO Authors
  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 dvls
  14. import (
  15. "context"
  16. "fmt"
  17. "net/url"
  18. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  19. "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
  20. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  21. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  22. "github.com/external-secrets/external-secrets/runtime/esutils"
  23. )
  24. var _ esv1.Provider = &Provider{}
  25. // Provider implements the external-secrets Provider interface for DVLS.
  26. type Provider struct{}
  27. // NewClient creates a new DVLS SecretsClient.
  28. func (p *Provider) NewClient(ctx context.Context, store esv1.GenericStore, kube kclient.Client, namespace string) (esv1.SecretsClient, error) {
  29. dvlsProvider, err := getDVLSProvider(store)
  30. if err != nil {
  31. return nil, err
  32. }
  33. storeKind := store.GetObjectKind().GroupVersionKind().Kind
  34. dvlsClient, err := NewDVLSClient(ctx, kube, storeKind, namespace, dvlsProvider)
  35. if err != nil {
  36. return nil, fmt.Errorf("failed to create DVLS client: %w", err)
  37. }
  38. return NewClient(dvlsClient), nil
  39. }
  40. // ValidateStore validates the SecretStore configuration.
  41. func (p *Provider) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
  42. dvlsProvider, err := getDVLSProvider(store)
  43. if err != nil {
  44. return nil, err
  45. }
  46. if dvlsProvider.ServerURL == "" {
  47. return nil, fmt.Errorf("serverUrl is required")
  48. }
  49. parsedURL, err := url.Parse(dvlsProvider.ServerURL)
  50. if err != nil {
  51. return nil, fmt.Errorf("serverUrl must be a valid URL: %w", err)
  52. }
  53. if parsedURL.Scheme == "" || parsedURL.Host == "" {
  54. return nil, fmt.Errorf("serverUrl must be a valid URL with scheme and host")
  55. }
  56. if parsedURL.Scheme != "https" && parsedURL.Scheme != "http" {
  57. return nil, fmt.Errorf("serverUrl scheme must be http or https, got %q", parsedURL.Scheme)
  58. }
  59. if parsedURL.Scheme == "http" && !dvlsProvider.Insecure {
  60. return nil, fmt.Errorf("http URLs require 'insecure: true' to be set explicitly")
  61. }
  62. // Validate auth configuration
  63. if err := validateAuthSecretRef(store, &dvlsProvider.Auth.SecretRef); err != nil {
  64. return nil, err
  65. }
  66. return nil, nil
  67. }
  68. // Capabilities returns the provider's capabilities.
  69. func (p *Provider) Capabilities() esv1.SecretStoreCapabilities {
  70. return esv1.SecretStoreReadWrite
  71. }
  72. // validateAuthSecretRef validates the authentication secret references.
  73. func validateAuthSecretRef(store esv1.GenericStore, ref *esv1.DVLSAuthSecretRef) error {
  74. if err := requireSecretSelector(ref.AppID, "appId"); err != nil {
  75. return err
  76. }
  77. if err := esutils.ValidateSecretSelector(store, ref.AppID); err != nil {
  78. return fmt.Errorf("invalid appId: %w", err)
  79. }
  80. if err := requireSecretSelector(ref.AppSecret, "appSecret"); err != nil {
  81. return err
  82. }
  83. if err := esutils.ValidateSecretSelector(store, ref.AppSecret); err != nil {
  84. return fmt.Errorf("invalid appSecret: %w", err)
  85. }
  86. return nil
  87. }
  88. func requireSecretSelector(sel esmeta.SecretKeySelector, field string) error {
  89. if sel.Name == "" {
  90. return fmt.Errorf("%s secret name is required", field)
  91. }
  92. if sel.Key == "" {
  93. return fmt.Errorf("%s secret key is required", field)
  94. }
  95. return nil
  96. }
  97. // getDVLSProvider extracts the DVLS provider configuration from the store.
  98. func getDVLSProvider(store esv1.GenericStore) (*esv1.DVLSProvider, error) {
  99. spec := store.GetSpec()
  100. if spec == nil || spec.Provider == nil || spec.Provider.DVLS == nil {
  101. return nil, fmt.Errorf("DVLS provider configuration is missing")
  102. }
  103. return spec.Provider.DVLS, nil
  104. }
  105. // NewProvider creates a new DVLS Provider instance.
  106. func NewProvider() esv1.Provider {
  107. return &Provider{}
  108. }
  109. // ProviderSpec returns the provider specification for registration.
  110. func ProviderSpec() *esv1.SecretStoreProvider {
  111. return &esv1.SecretStoreProvider{
  112. DVLS: &esv1.DVLSProvider{},
  113. }
  114. }
  115. // MaintenanceStatus returns the maintenance status of the provider.
  116. func MaintenanceStatus() esv1.MaintenanceStatus {
  117. return esv1.MaintenanceStatusMaintained
  118. }