provider.go 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  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 implied.
  9. See the License for the specific language governing permissions and
  10. limitations under the License.
  11. */
  12. package vault
  13. import (
  14. "context"
  15. "fmt"
  16. "net/http"
  17. vault "github.com/hashicorp/vault/api"
  18. //nolint
  19. . "github.com/onsi/ginkgo/v2"
  20. //nolint
  21. . "github.com/onsi/gomega"
  22. v1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. esv1alpha1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1alpha1"
  25. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  26. "github.com/external-secrets/external-secrets/e2e/framework"
  27. "github.com/external-secrets/external-secrets/e2e/framework/addon"
  28. )
  29. type vaultProvider struct {
  30. url string
  31. client *vault.Client
  32. framework *framework.Framework
  33. }
  34. const (
  35. certAuthProviderName = "cert-auth-provider"
  36. appRoleAuthProviderName = "app-role-provider"
  37. kvv1ProviderName = "kv-v1-provider"
  38. jwtProviderName = "jwt-provider"
  39. kubernetesProviderName = "kubernetes-provider"
  40. )
  41. var (
  42. secretStorePath = "secret"
  43. )
  44. func newVaultProvider(f *framework.Framework) *vaultProvider {
  45. prov := &vaultProvider{
  46. framework: f,
  47. }
  48. BeforeEach(prov.BeforeEach)
  49. return prov
  50. }
  51. // CreateSecret creates a secret in both kv v1 and v2 provider.
  52. func (s *vaultProvider) CreateSecret(key, val string) {
  53. req := s.client.NewRequest(http.MethodPost, fmt.Sprintf("/v1/secret/data/%s", key))
  54. req.BodyBytes = []byte(fmt.Sprintf(`{"data": %s}`, val))
  55. _, err := s.client.RawRequestWithContext(context.Background(), req)
  56. Expect(err).ToNot(HaveOccurred())
  57. req = s.client.NewRequest(http.MethodPost, fmt.Sprintf("/v1/secret_v1/%s", key))
  58. req.BodyBytes = []byte(val)
  59. _, err = s.client.RawRequestWithContext(context.Background(), req)
  60. Expect(err).ToNot(HaveOccurred())
  61. }
  62. func (s *vaultProvider) DeleteSecret(key string) {
  63. req := s.client.NewRequest(http.MethodDelete, fmt.Sprintf("/v1/secret/data/%s", key))
  64. _, err := s.client.RawRequestWithContext(context.Background(), req)
  65. Expect(err).ToNot(HaveOccurred())
  66. req = s.client.NewRequest(http.MethodDelete, fmt.Sprintf("/v1/secret_v1/%s", key))
  67. _, err = s.client.RawRequestWithContext(context.Background(), req)
  68. Expect(err).ToNot(HaveOccurred())
  69. }
  70. func (s *vaultProvider) BeforeEach() {
  71. ns := s.framework.Namespace.Name
  72. v := addon.NewVault(ns)
  73. s.framework.Install(v)
  74. s.client = v.VaultClient
  75. s.url = v.VaultURL
  76. s.CreateCertStore(v, ns)
  77. s.CreateTokenStore(v, ns)
  78. s.CreateAppRoleStore(v, ns)
  79. s.CreateV1Store(v, ns)
  80. s.CreateJWTStore(v, ns)
  81. s.CreateKubernetesAuthStore(v, ns)
  82. }
  83. func makeStore(name, ns string, v *addon.Vault) *esv1alpha1.SecretStore {
  84. return &esv1alpha1.SecretStore{
  85. ObjectMeta: metav1.ObjectMeta{
  86. Name: name,
  87. Namespace: ns,
  88. },
  89. Spec: esv1alpha1.SecretStoreSpec{
  90. Provider: &esv1alpha1.SecretStoreProvider{
  91. Vault: &esv1alpha1.VaultProvider{
  92. Version: esv1alpha1.VaultKVStoreV2,
  93. Path: &secretStorePath,
  94. Server: v.VaultURL,
  95. CABundle: v.VaultServerCA,
  96. },
  97. },
  98. },
  99. }
  100. }
  101. func (s *vaultProvider) CreateCertStore(v *addon.Vault, ns string) {
  102. By("creating a vault secret")
  103. clientCert := v.ClientCert
  104. clientKey := v.ClientKey
  105. vaultCreds := &v1.Secret{
  106. ObjectMeta: metav1.ObjectMeta{
  107. Name: certAuthProviderName,
  108. Namespace: ns,
  109. },
  110. Data: map[string][]byte{
  111. "token": []byte(v.RootToken),
  112. "client_cert": clientCert,
  113. "client_key": clientKey,
  114. },
  115. }
  116. err := s.framework.CRClient.Create(context.Background(), vaultCreds)
  117. Expect(err).ToNot(HaveOccurred())
  118. By("creating an secret store for vault")
  119. secretStore := makeStore(certAuthProviderName, ns, v)
  120. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  121. Cert: &esv1alpha1.VaultCertAuth{
  122. ClientCert: esmeta.SecretKeySelector{
  123. Name: certAuthProviderName,
  124. Key: "client_cert",
  125. },
  126. SecretRef: esmeta.SecretKeySelector{
  127. Name: certAuthProviderName,
  128. Key: "client_key",
  129. },
  130. },
  131. }
  132. err = s.framework.CRClient.Create(context.Background(), secretStore)
  133. Expect(err).ToNot(HaveOccurred())
  134. }
  135. func (s vaultProvider) CreateTokenStore(v *addon.Vault, ns string) {
  136. vaultCreds := &v1.Secret{
  137. ObjectMeta: metav1.ObjectMeta{
  138. Name: "token-provider",
  139. Namespace: ns,
  140. },
  141. Data: map[string][]byte{
  142. "token": []byte(v.RootToken),
  143. },
  144. }
  145. err := s.framework.CRClient.Create(context.Background(), vaultCreds)
  146. Expect(err).ToNot(HaveOccurred())
  147. secretStore := makeStore(s.framework.Namespace.Name, ns, v)
  148. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  149. TokenSecretRef: &esmeta.SecretKeySelector{
  150. Name: "token-provider",
  151. Key: "token",
  152. },
  153. }
  154. err = s.framework.CRClient.Create(context.Background(), secretStore)
  155. Expect(err).ToNot(HaveOccurred())
  156. }
  157. func (s vaultProvider) CreateAppRoleStore(v *addon.Vault, ns string) {
  158. By("creating a vault secret")
  159. vaultCreds := &v1.Secret{
  160. ObjectMeta: metav1.ObjectMeta{
  161. Name: appRoleAuthProviderName,
  162. Namespace: ns,
  163. },
  164. Data: map[string][]byte{
  165. "approle_secret": []byte(v.AppRoleSecret),
  166. },
  167. }
  168. err := s.framework.CRClient.Create(context.Background(), vaultCreds)
  169. Expect(err).ToNot(HaveOccurred())
  170. By("creating an secret store for vault")
  171. secretStore := makeStore(appRoleAuthProviderName, ns, v)
  172. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  173. AppRole: &esv1alpha1.VaultAppRole{
  174. Path: v.AppRolePath,
  175. RoleID: v.AppRoleID,
  176. SecretRef: esmeta.SecretKeySelector{
  177. Name: appRoleAuthProviderName,
  178. Key: "approle_secret",
  179. },
  180. },
  181. }
  182. err = s.framework.CRClient.Create(context.Background(), secretStore)
  183. Expect(err).ToNot(HaveOccurred())
  184. }
  185. func (s vaultProvider) CreateV1Store(v *addon.Vault, ns string) {
  186. vaultCreds := &v1.Secret{
  187. ObjectMeta: metav1.ObjectMeta{
  188. Name: "v1-provider",
  189. Namespace: ns,
  190. },
  191. Data: map[string][]byte{
  192. "token": []byte(v.RootToken),
  193. },
  194. }
  195. err := s.framework.CRClient.Create(context.Background(), vaultCreds)
  196. Expect(err).ToNot(HaveOccurred())
  197. secretStore := makeStore(kvv1ProviderName, ns, v)
  198. secretV1StorePath := "secret_v1"
  199. secretStore.Spec.Provider.Vault.Version = esv1alpha1.VaultKVStoreV1
  200. secretStore.Spec.Provider.Vault.Path = &secretV1StorePath
  201. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  202. TokenSecretRef: &esmeta.SecretKeySelector{
  203. Name: "v1-provider",
  204. Key: "token",
  205. },
  206. }
  207. err = s.framework.CRClient.Create(context.Background(), secretStore)
  208. Expect(err).ToNot(HaveOccurred())
  209. }
  210. func (s vaultProvider) CreateJWTStore(v *addon.Vault, ns string) {
  211. vaultCreds := &v1.Secret{
  212. ObjectMeta: metav1.ObjectMeta{
  213. Name: "jwt-provider",
  214. Namespace: ns,
  215. },
  216. Data: map[string][]byte{
  217. "jwt": []byte(v.JWTToken),
  218. },
  219. }
  220. err := s.framework.CRClient.Create(context.Background(), vaultCreds)
  221. Expect(err).ToNot(HaveOccurred())
  222. secretStore := makeStore(jwtProviderName, ns, v)
  223. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  224. Jwt: &esv1alpha1.VaultJwtAuth{
  225. Path: v.JWTPath,
  226. Role: v.JWTRole,
  227. SecretRef: esmeta.SecretKeySelector{
  228. Name: "jwt-provider",
  229. Key: "jwt",
  230. },
  231. },
  232. }
  233. err = s.framework.CRClient.Create(context.Background(), secretStore)
  234. Expect(err).ToNot(HaveOccurred())
  235. }
  236. func (s vaultProvider) CreateKubernetesAuthStore(v *addon.Vault, ns string) {
  237. secretStore := makeStore(kubernetesProviderName, ns, v)
  238. secretStore.Spec.Provider.Vault.Auth = esv1alpha1.VaultAuth{
  239. Kubernetes: &esv1alpha1.VaultKubernetesAuth{
  240. Path: v.KubernetesAuthPath,
  241. Role: v.KubernetesAuthRole,
  242. ServiceAccountRef: &esmeta.ServiceAccountSelector{
  243. Name: "default",
  244. },
  245. },
  246. }
  247. err := s.framework.CRClient.Create(context.Background(), secretStore)
  248. Expect(err).ToNot(HaveOccurred())
  249. }