provider.go 8.7 KB

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