validate.go 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  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 vault
  14. import (
  15. "context"
  16. "errors"
  17. "fmt"
  18. "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
  19. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  20. "github.com/external-secrets/external-secrets/pkg/esutils"
  21. )
  22. const (
  23. errInvalidCredentials = "invalid vault credentials: %w"
  24. errInvalidStore = "invalid store"
  25. errInvalidStoreSpec = "invalid store spec"
  26. errInvalidStoreProv = "invalid store provider"
  27. errInvalidVaultProv = "invalid vault provider"
  28. errInvalidAppRoleRef = "invalid Auth.AppRole.RoleRef: %w"
  29. errInvalidAppRoleSec = "invalid Auth.AppRole.SecretRef: %w"
  30. errInvalidClientCert = "invalid Auth.Cert.ClientCert: %w"
  31. errInvalidCertSec = "invalid Auth.Cert.SecretRef: %w"
  32. errInvalidJwtSec = "invalid Auth.Jwt.SecretRef: %w"
  33. errInvalidJwtK8sSA = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
  34. errInvalidKubeSA = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
  35. errInvalidKubeSec = "invalid Auth.Kubernetes.SecretRef: %w"
  36. errInvalidLdapSec = "invalid Auth.Ldap.SecretRef: %w"
  37. errInvalidTokenRef = "invalid Auth.TokenSecretRef: %w"
  38. errInvalidUserPassSec = "invalid Auth.UserPass.SecretRef: %w"
  39. errInvalidClientTLSCert = "invalid ClientTLS.ClientCert: %w"
  40. errInvalidClientTLSSecret = "invalid ClientTLS.SecretRef: %w"
  41. errInvalidClientTLS = "when provided, both ClientTLS.ClientCert and ClientTLS.SecretRef should be provided"
  42. errCASNotSupportedInKVv1 = "checkAndSet is not supported with Vault KV version v1"
  43. )
  44. // ValidateStore validates the Vault provider configuration in the SecretStore.
  45. func (p *Provider) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
  46. if store == nil {
  47. return nil, errors.New(errInvalidStore)
  48. }
  49. spc := store.GetSpec()
  50. if spc == nil {
  51. return nil, errors.New(errInvalidStoreSpec)
  52. }
  53. if spc.Provider == nil {
  54. return nil, errors.New(errInvalidStoreProv)
  55. }
  56. vaultProvider := spc.Provider.Vault
  57. if vaultProvider == nil {
  58. return nil, errors.New(errInvalidVaultProv)
  59. }
  60. if vaultProvider.Auth != nil {
  61. if vaultProvider.Auth.AppRole != nil {
  62. // check SecretRef for valid configuration
  63. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.AppRole.SecretRef); err != nil {
  64. return nil, fmt.Errorf(errInvalidAppRoleSec, err)
  65. }
  66. // prefer .auth.appRole.roleId, fallback to .auth.appRole.roleRef, give up after that.
  67. if vaultProvider.Auth.AppRole.RoleID == "" { // prevents further RoleID tests if .auth.appRole.roleId is given
  68. if vaultProvider.Auth.AppRole.RoleRef != nil { // check RoleRef for valid configuration
  69. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.Auth.AppRole.RoleRef); err != nil {
  70. return nil, fmt.Errorf(errInvalidAppRoleRef, err)
  71. }
  72. } else { // we ran out of ways to get RoleID. return an appropriate error
  73. return nil, errors.New(errInvalidAppRoleID)
  74. }
  75. }
  76. }
  77. if vaultProvider.Auth.Cert != nil {
  78. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.Cert.ClientCert); err != nil {
  79. return nil, fmt.Errorf(errInvalidClientCert, err)
  80. }
  81. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.Cert.SecretRef); err != nil {
  82. return nil, fmt.Errorf(errInvalidCertSec, err)
  83. }
  84. }
  85. if vaultProvider.Auth.Jwt != nil {
  86. if vaultProvider.Auth.Jwt.SecretRef != nil {
  87. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.Auth.Jwt.SecretRef); err != nil {
  88. return nil, fmt.Errorf(errInvalidJwtSec, err)
  89. }
  90. } else if vaultProvider.Auth.Jwt.KubernetesServiceAccountToken != nil {
  91. if err := esutils.ValidateReferentServiceAccountSelector(store, vaultProvider.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
  92. return nil, fmt.Errorf(errInvalidJwtK8sSA, err)
  93. }
  94. } else {
  95. return nil, errors.New(errJwtNoTokenSource)
  96. }
  97. }
  98. if vaultProvider.Auth.Kubernetes != nil {
  99. if vaultProvider.Auth.Kubernetes.ServiceAccountRef != nil {
  100. if err := esutils.ValidateReferentServiceAccountSelector(store, *vaultProvider.Auth.Kubernetes.ServiceAccountRef); err != nil {
  101. return nil, fmt.Errorf(errInvalidKubeSA, err)
  102. }
  103. }
  104. if vaultProvider.Auth.Kubernetes.SecretRef != nil {
  105. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.Auth.Kubernetes.SecretRef); err != nil {
  106. return nil, fmt.Errorf(errInvalidKubeSec, err)
  107. }
  108. }
  109. }
  110. if vaultProvider.Auth.Ldap != nil {
  111. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.Ldap.SecretRef); err != nil {
  112. return nil, fmt.Errorf(errInvalidLdapSec, err)
  113. }
  114. }
  115. if vaultProvider.Auth.UserPass != nil {
  116. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.UserPass.SecretRef); err != nil {
  117. return nil, fmt.Errorf(errInvalidUserPassSec, err)
  118. }
  119. }
  120. if vaultProvider.Auth.TokenSecretRef != nil {
  121. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.Auth.TokenSecretRef); err != nil {
  122. return nil, fmt.Errorf(errInvalidTokenRef, err)
  123. }
  124. }
  125. if vaultProvider.Auth.Iam != nil {
  126. if vaultProvider.Auth.Iam.JWTAuth != nil {
  127. if vaultProvider.Auth.Iam.JWTAuth.ServiceAccountRef != nil {
  128. if err := esutils.ValidateReferentServiceAccountSelector(store, *vaultProvider.Auth.Iam.JWTAuth.ServiceAccountRef); err != nil {
  129. return nil, fmt.Errorf(errInvalidTokenRef, err)
  130. }
  131. }
  132. }
  133. if vaultProvider.Auth.Iam.SecretRef != nil {
  134. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.Iam.SecretRef.AccessKeyID); err != nil {
  135. return nil, fmt.Errorf(errInvalidTokenRef, err)
  136. }
  137. if err := esutils.ValidateReferentSecretSelector(store, vaultProvider.Auth.Iam.SecretRef.SecretAccessKey); err != nil {
  138. return nil, fmt.Errorf(errInvalidTokenRef, err)
  139. }
  140. if vaultProvider.Auth.Iam.SecretRef.SessionToken != nil {
  141. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.Auth.Iam.SecretRef.SessionToken); err != nil {
  142. return nil, fmt.Errorf(errInvalidTokenRef, err)
  143. }
  144. }
  145. }
  146. }
  147. }
  148. if vaultProvider.ClientTLS.CertSecretRef != nil && vaultProvider.ClientTLS.KeySecretRef != nil {
  149. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.ClientTLS.CertSecretRef); err != nil {
  150. return nil, fmt.Errorf(errInvalidClientTLSCert, err)
  151. }
  152. if err := esutils.ValidateReferentSecretSelector(store, *vaultProvider.ClientTLS.KeySecretRef); err != nil {
  153. return nil, fmt.Errorf(errInvalidClientTLSSecret, err)
  154. }
  155. } else if vaultProvider.ClientTLS.CertSecretRef != nil || vaultProvider.ClientTLS.KeySecretRef != nil {
  156. return nil, errors.New(errInvalidClientTLS)
  157. }
  158. // Validate CAS configuration
  159. if vaultProvider.CheckAndSet != nil && vaultProvider.CheckAndSet.Required {
  160. if vaultProvider.Version == esv1.VaultKVStoreV1 {
  161. return nil, errors.New(errCASNotSupportedInKVv1)
  162. }
  163. }
  164. return nil, nil
  165. }
  166. func (c *client) Validate() (esv1.ValidationResult, error) {
  167. // when using referent namespace we can not validate the token
  168. // because the namespace is not known yet when Validate() is called
  169. // from the SecretStore controller.
  170. if c.storeKind == esv1.ClusterSecretStoreKind && isReferentSpec(c.store) {
  171. return esv1.ValidationResultUnknown, nil
  172. }
  173. _, err := checkToken(context.Background(), c.token)
  174. if err != nil {
  175. return esv1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
  176. }
  177. return esv1.ValidationResultReady, nil
  178. }