provider.go 7.8 KB

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