vault.go 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435
  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. "bytes"
  15. "context"
  16. "crypto/tls"
  17. "crypto/x509"
  18. "encoding/json"
  19. "errors"
  20. "fmt"
  21. "net/http"
  22. "os"
  23. "reflect"
  24. "strconv"
  25. "strings"
  26. "github.com/go-logr/logr"
  27. vault "github.com/hashicorp/vault/api"
  28. approle "github.com/hashicorp/vault/api/auth/approle"
  29. authkubernetes "github.com/hashicorp/vault/api/auth/kubernetes"
  30. authldap "github.com/hashicorp/vault/api/auth/ldap"
  31. "github.com/spf13/pflag"
  32. "github.com/tidwall/gjson"
  33. authenticationv1 "k8s.io/api/authentication/v1"
  34. corev1 "k8s.io/api/core/v1"
  35. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  36. "k8s.io/apimachinery/pkg/types"
  37. "k8s.io/client-go/kubernetes"
  38. typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  39. ctrl "sigs.k8s.io/controller-runtime"
  40. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  41. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  42. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  43. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  44. "github.com/external-secrets/external-secrets/pkg/cache"
  45. "github.com/external-secrets/external-secrets/pkg/feature"
  46. "github.com/external-secrets/external-secrets/pkg/find"
  47. "github.com/external-secrets/external-secrets/pkg/provider/metrics"
  48. "github.com/external-secrets/external-secrets/pkg/provider/vault/util"
  49. "github.com/external-secrets/external-secrets/pkg/utils"
  50. )
  51. var (
  52. _ esv1beta1.Provider = &Connector{}
  53. _ esv1beta1.SecretsClient = &client{}
  54. enableCache bool
  55. logger = ctrl.Log.WithName("provider").WithName("vault")
  56. clientCache *cache.Cache[util.Client]
  57. )
  58. const (
  59. serviceAccTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  60. errVaultStore = "received invalid Vault SecretStore resource: %w"
  61. errVaultCacheCreate = "cannot create Vault client cache: %s"
  62. errVaultCacheRemove = "error removing item from Vault client cache: %w"
  63. errVaultCacheEviction = "unexpected eviction from Vault client cache"
  64. errVaultClient = "cannot setup new vault client: %w"
  65. errVaultCert = "cannot set Vault CA certificate: %w"
  66. errReadSecret = "cannot read secret data from Vault: %w"
  67. errAuthFormat = "cannot initialize Vault client: no valid auth method specified"
  68. errInvalidCredentials = "invalid vault credentials: %w"
  69. errDataField = "failed to find data field"
  70. errJSONUnmarshall = "failed to unmarshall JSON"
  71. errPathInvalid = "provided Path isn't a valid kv v2 path"
  72. errSecretFormat = "secret data for property %s not in expected format: %s"
  73. errUnexpectedKey = "unexpected key in data: %s"
  74. errVaultToken = "cannot parse Vault authentication token: %w"
  75. errVaultRequest = "error from Vault request: %w"
  76. errServiceAccount = "cannot read Kubernetes service account token from file system: %w"
  77. errJwtNoTokenSource = "neither `secretRef` nor `kubernetesServiceAccountToken` was supplied as token source for jwt authentication"
  78. errUnsupportedKvVersion = "cannot perform find operations with kv version v1"
  79. errUnsupportedMetadataKvVersion = "cannot perform metadata fetch operations with kv version v1"
  80. errNotFound = "secret not found"
  81. errGetKubeSA = "cannot get Kubernetes service account %q: %w"
  82. errGetKubeSASecrets = "cannot find secrets bound to service account: %q"
  83. errGetKubeSANoToken = "cannot find token in secrets bound to service account: %q"
  84. errGetKubeSATokenRequest = "cannot request Kubernetes service account token for service account %q: %w"
  85. errGetKubeSecret = "cannot get Kubernetes secret %q: %w"
  86. errSecretKeyFmt = "cannot find secret data for key: %q"
  87. errConfigMapFmt = "cannot find config map data for key: %q"
  88. errClientTLSAuth = "error from Client TLS Auth: %q"
  89. errVaultRevokeToken = "error while revoking token: %w"
  90. errUnknownCAProvider = "unknown caProvider type given"
  91. errCANamespace = "cannot read secret for CAProvider due to missing namespace on kind ClusterSecretStore"
  92. errInvalidStore = "invalid store"
  93. errInvalidStoreSpec = "invalid store spec"
  94. errInvalidStoreProv = "invalid store provider"
  95. errInvalidVaultProv = "invalid vault provider"
  96. errInvalidAppRoleSec = "invalid Auth.AppRole.SecretRef: %w"
  97. errInvalidClientCert = "invalid Auth.Cert.ClientCert: %w"
  98. errInvalidCertSec = "invalid Auth.Cert.SecretRef: %w"
  99. errInvalidJwtSec = "invalid Auth.Jwt.SecretRef: %w"
  100. errInvalidJwtK8sSA = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
  101. errInvalidKubeSA = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
  102. errInvalidKubeSec = "invalid Auth.Kubernetes.SecretRef: %w"
  103. errInvalidLdapSec = "invalid Auth.Ldap.SecretRef: %w"
  104. errInvalidTokenRef = "invalid Auth.TokenSecretRef: %w"
  105. )
  106. // https://github.com/external-secrets/external-secrets/issues/644
  107. var _ esv1beta1.SecretsClient = &client{}
  108. var _ esv1beta1.Provider = &Connector{}
  109. type client struct {
  110. kube kclient.Client
  111. store *esv1beta1.VaultProvider
  112. log logr.Logger
  113. corev1 typedcorev1.CoreV1Interface
  114. client util.Client
  115. auth util.Auth
  116. logical util.Logical
  117. token util.Token
  118. namespace string
  119. storeKind string
  120. }
  121. func NewVaultClient(c *vault.Config) (util.Client, error) {
  122. cl, err := vault.NewClient(c)
  123. if err != nil {
  124. return nil, err
  125. }
  126. auth := cl.Auth()
  127. logical := cl.Logical()
  128. token := cl.Auth().Token()
  129. out := util.VClient{
  130. SetTokenFunc: cl.SetToken,
  131. TokenFunc: cl.Token,
  132. ClearTokenFunc: cl.ClearToken,
  133. AuthField: auth,
  134. AuthTokenField: token,
  135. LogicalField: logical,
  136. SetNamespaceFunc: cl.SetNamespace,
  137. AddHeaderFunc: cl.AddHeader,
  138. }
  139. return &out, nil
  140. }
  141. func getVaultClient(c *Connector, store esv1beta1.GenericStore, cfg *vault.Config) (util.Client, error) {
  142. isStaticToken := store.GetSpec().Provider.Vault.Auth.TokenSecretRef != nil
  143. useCache := enableCache && !isStaticToken
  144. key := cache.Key{
  145. Name: store.GetObjectMeta().Name,
  146. Namespace: store.GetObjectMeta().Namespace,
  147. Kind: store.GetTypeMeta().Kind,
  148. }
  149. if useCache {
  150. client, ok := clientCache.Get(store.GetObjectMeta().ResourceVersion, key)
  151. if ok {
  152. return client, nil
  153. }
  154. }
  155. client, err := c.NewVaultClient(cfg)
  156. if err != nil {
  157. return nil, fmt.Errorf(errVaultClient, err)
  158. }
  159. if useCache && !clientCache.Contains(key) {
  160. clientCache.Add(store.GetObjectMeta().ResourceVersion, key, client)
  161. }
  162. return client, nil
  163. }
  164. type Connector struct {
  165. NewVaultClient func(c *vault.Config) (util.Client, error)
  166. }
  167. // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite).
  168. func (c *Connector) Capabilities() esv1beta1.SecretStoreCapabilities {
  169. return esv1beta1.SecretStoreReadWrite
  170. }
  171. func (c *Connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
  172. // controller-runtime/client does not support TokenRequest or other subresource APIs
  173. // so we need to construct our own client and use it to fetch tokens
  174. // (for Kubernetes service account token auth)
  175. restCfg, err := ctrlcfg.GetConfig()
  176. if err != nil {
  177. return nil, err
  178. }
  179. clientset, err := kubernetes.NewForConfig(restCfg)
  180. if err != nil {
  181. return nil, err
  182. }
  183. return c.newClient(ctx, store, kube, clientset.CoreV1(), namespace)
  184. }
  185. func (c *Connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) {
  186. storeSpec := store.GetSpec()
  187. if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Vault == nil {
  188. return nil, errors.New(errVaultStore)
  189. }
  190. vaultSpec := storeSpec.Provider.Vault
  191. vStore, cfg, err := c.prepareConfig(kube, corev1, vaultSpec, namespace, store.GetObjectKind().GroupVersionKind().Kind)
  192. if err != nil {
  193. return nil, err
  194. }
  195. client, err := getVaultClient(c, store, cfg)
  196. if err != nil {
  197. return nil, fmt.Errorf(errVaultClient, err)
  198. }
  199. return c.initClient(ctx, vStore, client, cfg, vaultSpec)
  200. }
  201. func (c *Connector) NewGeneratorClient(ctx context.Context, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, vaultSpec *esv1beta1.VaultProvider, namespace string) (util.Client, error) {
  202. vStore, cfg, err := c.prepareConfig(kube, corev1, vaultSpec, namespace, "Generator")
  203. if err != nil {
  204. return nil, err
  205. }
  206. client, err := c.NewVaultClient(cfg)
  207. if err != nil {
  208. return nil, err
  209. }
  210. _, err = c.initClient(ctx, vStore, client, cfg, vaultSpec)
  211. if err != nil {
  212. return nil, err
  213. }
  214. return client, nil
  215. }
  216. func (c *Connector) prepareConfig(kube kclient.Client, corev1 typedcorev1.CoreV1Interface, vaultSpec *esv1beta1.VaultProvider, namespace, storeKind string) (*client, *vault.Config, error) {
  217. vStore := &client{
  218. kube: kube,
  219. corev1: corev1,
  220. store: vaultSpec,
  221. log: logger,
  222. namespace: namespace,
  223. storeKind: storeKind,
  224. }
  225. cfg, err := vStore.newConfig()
  226. if err != nil {
  227. return nil, nil, err
  228. }
  229. return vStore, cfg, nil
  230. }
  231. func (c *Connector) initClient(ctx context.Context, vStore *client, client util.Client, cfg *vault.Config, vaultSpec *esv1beta1.VaultProvider) (esv1beta1.SecretsClient, error) {
  232. if vaultSpec.Namespace != nil {
  233. client.SetNamespace(*vaultSpec.Namespace)
  234. }
  235. if vaultSpec.ReadYourWrites && vaultSpec.ForwardInconsistent {
  236. client.AddHeader("X-Vault-Inconsistent", "forward-active-node")
  237. }
  238. vStore.client = client
  239. vStore.auth = client.Auth()
  240. vStore.logical = client.Logical()
  241. vStore.token = client.AuthToken()
  242. // allow SecretStore controller validation to pass
  243. // when using referent namespace.
  244. if vStore.storeKind == esv1beta1.ClusterSecretStoreKind && vStore.namespace == "" && isReferentSpec(vaultSpec) {
  245. return vStore, nil
  246. }
  247. if err := vStore.setAuth(ctx, cfg); err != nil {
  248. return nil, err
  249. }
  250. return vStore, nil
  251. }
  252. func (c *Connector) ValidateStore(store esv1beta1.GenericStore) error {
  253. if store == nil {
  254. return fmt.Errorf(errInvalidStore)
  255. }
  256. spc := store.GetSpec()
  257. if spc == nil {
  258. return fmt.Errorf(errInvalidStoreSpec)
  259. }
  260. if spc.Provider == nil {
  261. return fmt.Errorf(errInvalidStoreProv)
  262. }
  263. p := spc.Provider.Vault
  264. if p == nil {
  265. return fmt.Errorf(errInvalidVaultProv)
  266. }
  267. if p.Auth.AppRole != nil {
  268. if err := utils.ValidateReferentSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
  269. return fmt.Errorf(errInvalidAppRoleSec, err)
  270. }
  271. }
  272. if p.Auth.Cert != nil {
  273. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
  274. return fmt.Errorf(errInvalidClientCert, err)
  275. }
  276. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
  277. return fmt.Errorf(errInvalidCertSec, err)
  278. }
  279. }
  280. if p.Auth.Jwt != nil {
  281. if p.Auth.Jwt.SecretRef != nil {
  282. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
  283. return fmt.Errorf(errInvalidJwtSec, err)
  284. }
  285. } else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
  286. if err := utils.ValidateReferentServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
  287. return fmt.Errorf(errInvalidJwtK8sSA, err)
  288. }
  289. } else {
  290. return fmt.Errorf(errJwtNoTokenSource)
  291. }
  292. }
  293. if p.Auth.Kubernetes != nil {
  294. if p.Auth.Kubernetes.ServiceAccountRef != nil {
  295. if err := utils.ValidateReferentServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
  296. return fmt.Errorf(errInvalidKubeSA, err)
  297. }
  298. }
  299. if p.Auth.Kubernetes.SecretRef != nil {
  300. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
  301. return fmt.Errorf(errInvalidKubeSec, err)
  302. }
  303. }
  304. }
  305. if p.Auth.Ldap != nil {
  306. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
  307. return fmt.Errorf(errInvalidLdapSec, err)
  308. }
  309. }
  310. if p.Auth.TokenSecretRef != nil {
  311. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
  312. return fmt.Errorf(errInvalidTokenRef, err)
  313. }
  314. }
  315. return nil
  316. }
  317. func (v *client) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error {
  318. path := v.buildPath(remoteRef.GetRemoteKey())
  319. metaPath, err := v.buildMetadataPath(remoteRef.GetRemoteKey())
  320. if err != nil {
  321. return err
  322. }
  323. // Retrieve the secret map from vault and convert the secret value in string form.
  324. _, err = v.readSecret(ctx, path, "")
  325. // If error is not of type secret not found, we should error
  326. if err != nil && errors.Is(err, esv1beta1.NoSecretError{}) {
  327. return nil
  328. }
  329. if err != nil {
  330. return err
  331. }
  332. metadata, err := v.readSecretMetadata(ctx, remoteRef.GetRemoteKey())
  333. if err != nil {
  334. return err
  335. }
  336. manager, ok := metadata["managed-by"]
  337. if !ok || manager != "external-secrets" {
  338. return nil
  339. }
  340. _, err = v.logical.DeleteWithContext(ctx, path)
  341. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultDeleteSecret, err)
  342. if err != nil {
  343. return fmt.Errorf("could not delete secret %v: %w", remoteRef.GetRemoteKey(), err)
  344. }
  345. _, err = v.logical.DeleteWithContext(ctx, metaPath)
  346. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultDeleteSecret, err)
  347. if err != nil {
  348. return fmt.Errorf("could not delete secret metadata %v: %w", remoteRef.GetRemoteKey(), err)
  349. }
  350. return nil
  351. }
  352. func (v *client) PushSecret(ctx context.Context, value []byte, remoteRef esv1beta1.PushRemoteRef) error {
  353. label := map[string]interface{}{
  354. "custom_metadata": map[string]string{
  355. "managed-by": "external-secrets",
  356. },
  357. }
  358. secretVal := make(map[string]interface{})
  359. err := json.Unmarshal(value, &secretVal)
  360. if err != nil {
  361. return fmt.Errorf("failed to convert value to a valid JSON: %w", err)
  362. }
  363. secretToPush := map[string]interface{}{
  364. "data": secretVal,
  365. }
  366. path := v.buildPath(remoteRef.GetRemoteKey())
  367. metaPath, err := v.buildMetadataPath(remoteRef.GetRemoteKey())
  368. if err != nil {
  369. return err
  370. }
  371. // Retrieve the secret map from vault and convert the secret value in string form.
  372. vaultSecret, err := v.readSecret(ctx, path, "")
  373. // If error is not of type secret not found, we should error
  374. if err != nil && !errors.Is(err, esv1beta1.NoSecretError{}) {
  375. return err
  376. }
  377. // If the secret exists (err == nil), we should check if it is managed by external-secrets
  378. if err == nil {
  379. metadata, err := v.readSecretMetadata(ctx, remoteRef.GetRemoteKey())
  380. if err != nil {
  381. return err
  382. }
  383. manager, ok := metadata["managed-by"]
  384. if !ok || manager != "external-secrets" {
  385. return fmt.Errorf("secret not managed by external-secrets")
  386. }
  387. }
  388. vaultSecretValue, err := json.Marshal(vaultSecret)
  389. if err != nil {
  390. return fmt.Errorf("error marshaling vault secret: %w", err)
  391. }
  392. if bytes.Equal(vaultSecretValue, value) {
  393. return nil
  394. }
  395. _, err = v.logical.WriteWithContext(ctx, metaPath, label)
  396. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  397. if err != nil {
  398. return err
  399. }
  400. // Otherwise, create or update the version.
  401. _, err = v.logical.WriteWithContext(ctx, path, secretToPush)
  402. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  403. return err
  404. }
  405. // GetAllSecrets gets multiple secrets from the provider and loads into a kubernetes secret.
  406. // First load all secrets from secretStore path configuration
  407. // Then, gets secrets from a matching name or matching custom_metadata.
  408. func (v *client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  409. if v.store.Version == esv1beta1.VaultKVStoreV1 {
  410. return nil, errors.New(errUnsupportedKvVersion)
  411. }
  412. searchPath := ""
  413. if ref.Path != nil {
  414. searchPath = *ref.Path + "/"
  415. }
  416. potentialSecrets, err := v.listSecrets(ctx, searchPath)
  417. if err != nil {
  418. return nil, err
  419. }
  420. if ref.Name != nil {
  421. return v.findSecretsFromName(ctx, potentialSecrets, *ref.Name)
  422. }
  423. return v.findSecretsFromTags(ctx, potentialSecrets, ref.Tags)
  424. }
  425. func (v *client) findSecretsFromTags(ctx context.Context, candidates []string, tags map[string]string) (map[string][]byte, error) {
  426. secrets := make(map[string][]byte)
  427. for _, name := range candidates {
  428. match := true
  429. metadata, err := v.readSecretMetadata(ctx, name)
  430. if err != nil {
  431. return nil, err
  432. }
  433. for tk, tv := range tags {
  434. p, ok := metadata[tk]
  435. if !ok || p != tv {
  436. match = false
  437. break
  438. }
  439. }
  440. if match {
  441. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  442. if errors.Is(err, esv1beta1.NoSecretError{}) {
  443. continue
  444. }
  445. if err != nil {
  446. return nil, err
  447. }
  448. if secret != nil {
  449. secrets[name] = secret
  450. }
  451. }
  452. }
  453. return secrets, nil
  454. }
  455. func (v *client) findSecretsFromName(ctx context.Context, candidates []string, ref esv1beta1.FindName) (map[string][]byte, error) {
  456. secrets := make(map[string][]byte)
  457. matcher, err := find.New(ref)
  458. if err != nil {
  459. return nil, err
  460. }
  461. for _, name := range candidates {
  462. ok := matcher.MatchName(name)
  463. if ok {
  464. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  465. if errors.Is(err, esv1beta1.NoSecretError{}) {
  466. continue
  467. }
  468. if err != nil {
  469. return nil, err
  470. }
  471. if secret != nil {
  472. secrets[name] = secret
  473. }
  474. }
  475. }
  476. return secrets, nil
  477. }
  478. func (v *client) listSecrets(ctx context.Context, path string) ([]string, error) {
  479. secrets := make([]string, 0)
  480. url, err := v.buildMetadataPath(path)
  481. if err != nil {
  482. return nil, err
  483. }
  484. secret, err := v.logical.ListWithContext(ctx, url)
  485. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultListSecrets, err)
  486. if err != nil {
  487. return nil, fmt.Errorf(errReadSecret, err)
  488. }
  489. if secret == nil {
  490. return nil, fmt.Errorf("provided path %v does not contain any secrets", url)
  491. }
  492. t, ok := secret.Data["keys"]
  493. if !ok {
  494. return nil, nil
  495. }
  496. paths := t.([]interface{})
  497. for _, p := range paths {
  498. strPath := p.(string)
  499. fullPath := path + strPath // because path always ends with a /
  500. if path == "" {
  501. fullPath = strPath
  502. }
  503. // Recurrently find secrets
  504. if !strings.HasSuffix(p.(string), "/") {
  505. secrets = append(secrets, fullPath)
  506. } else {
  507. partial, err := v.listSecrets(ctx, fullPath)
  508. if err != nil {
  509. return nil, err
  510. }
  511. secrets = append(secrets, partial...)
  512. }
  513. }
  514. return secrets, nil
  515. }
  516. func (v *client) readSecretMetadata(ctx context.Context, path string) (map[string]string, error) {
  517. metadata := make(map[string]string)
  518. url, err := v.buildMetadataPath(path)
  519. if err != nil {
  520. return nil, err
  521. }
  522. secret, err := v.logical.ReadWithDataWithContext(ctx, url, nil)
  523. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err)
  524. if err != nil {
  525. return nil, fmt.Errorf(errReadSecret, err)
  526. }
  527. if secret == nil {
  528. return nil, errors.New(errNotFound)
  529. }
  530. t, ok := secret.Data["custom_metadata"]
  531. if !ok {
  532. return nil, nil
  533. }
  534. d, ok := t.(map[string]interface{})
  535. if !ok {
  536. return metadata, nil
  537. }
  538. for k, v := range d {
  539. metadata[k] = v.(string)
  540. }
  541. return metadata, nil
  542. }
  543. // GetSecret supports two types:
  544. // 1. get the full secret as json-encoded value
  545. // by leaving the ref.Property empty.
  546. // 2. get a key from the secret.
  547. // Nested values are supported by specifying a gjson expression
  548. func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  549. var data map[string]interface{}
  550. var err error
  551. if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch {
  552. if v.store.Version == esv1beta1.VaultKVStoreV1 {
  553. return nil, errors.New(errUnsupportedMetadataKvVersion)
  554. }
  555. metadata, err := v.readSecretMetadata(ctx, ref.Key)
  556. if err != nil {
  557. return nil, err
  558. }
  559. if len(metadata) == 0 {
  560. return nil, nil
  561. }
  562. data = make(map[string]interface{}, len(metadata))
  563. for k, v := range metadata {
  564. data[k] = v
  565. }
  566. } else {
  567. data, err = v.readSecret(ctx, ref.Key, ref.Version)
  568. if err != nil {
  569. return nil, err
  570. }
  571. }
  572. // Return nil if secret value is null
  573. if data == nil {
  574. return nil, nil
  575. }
  576. jsonStr, err := json.Marshal(data)
  577. if err != nil {
  578. return nil, err
  579. }
  580. // (1): return raw json if no property is defined
  581. if ref.Property == "" {
  582. return jsonStr, nil
  583. }
  584. // For backwards compatibility we want the
  585. // actual keys to take precedence over gjson syntax
  586. // (2): extract key from secret with property
  587. if _, ok := data[ref.Property]; ok {
  588. return GetTypedKey(data, ref.Property)
  589. }
  590. // (3): extract key from secret using gjson
  591. val := gjson.Get(string(jsonStr), ref.Property)
  592. if !val.Exists() {
  593. return nil, fmt.Errorf(errSecretKeyFmt, ref.Property)
  594. }
  595. return []byte(val.String()), nil
  596. }
  597. // GetSecretMap supports two modes of operation:
  598. // 1. get the full secret from the vault data payload (by leaving .property empty).
  599. // 2. extract key/value pairs from a (nested) object.
  600. func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  601. data, err := v.GetSecret(ctx, ref)
  602. if err != nil {
  603. return nil, err
  604. }
  605. var secretData map[string]interface{}
  606. err = json.Unmarshal(data, &secretData)
  607. if err != nil {
  608. return nil, err
  609. }
  610. byteMap := make(map[string][]byte, len(secretData))
  611. for k := range secretData {
  612. byteMap[k], err = GetTypedKey(secretData, k)
  613. if err != nil {
  614. return nil, err
  615. }
  616. }
  617. return byteMap, nil
  618. }
  619. func GetTypedKey(data map[string]interface{}, key string) ([]byte, error) {
  620. v, ok := data[key]
  621. if !ok {
  622. return nil, fmt.Errorf(errUnexpectedKey, key)
  623. }
  624. switch t := v.(type) {
  625. case string:
  626. return []byte(t), nil
  627. case map[string]interface{}:
  628. return json.Marshal(t)
  629. case []string:
  630. return []byte(strings.Join(t, "\n")), nil
  631. case []byte:
  632. return t, nil
  633. // also covers int and float32 due to json.Marshal
  634. case float64:
  635. return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil
  636. case json.Number:
  637. return []byte(t.String()), nil
  638. case []interface{}:
  639. return json.Marshal(t)
  640. case bool:
  641. return []byte(strconv.FormatBool(t)), nil
  642. case nil:
  643. return []byte(nil), nil
  644. default:
  645. return nil, fmt.Errorf(errSecretFormat, key, reflect.TypeOf(t))
  646. }
  647. }
  648. func (v *client) Close(ctx context.Context) error {
  649. // Revoke the token if we have one set, it wasn't sourced from a TokenSecretRef,
  650. // and token caching isn't enabled
  651. if !enableCache && v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil {
  652. err := revokeTokenIfValid(ctx, v.client)
  653. if err != nil {
  654. return err
  655. }
  656. }
  657. return nil
  658. }
  659. func isReferentSpec(prov *esv1beta1.VaultProvider) bool {
  660. if prov.Auth.TokenSecretRef != nil && prov.Auth.TokenSecretRef.Namespace == nil {
  661. return true
  662. }
  663. if prov.Auth.AppRole != nil && prov.Auth.AppRole.SecretRef.Namespace == nil {
  664. return true
  665. }
  666. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.SecretRef != nil && prov.Auth.Kubernetes.SecretRef.Namespace == nil {
  667. return true
  668. }
  669. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.ServiceAccountRef != nil && prov.Auth.Kubernetes.ServiceAccountRef.Namespace == nil {
  670. return true
  671. }
  672. if prov.Auth.Ldap != nil && prov.Auth.Ldap.SecretRef.Namespace == nil {
  673. return true
  674. }
  675. if prov.Auth.Jwt != nil && prov.Auth.Jwt.SecretRef != nil && prov.Auth.Jwt.SecretRef.Namespace == nil {
  676. return true
  677. }
  678. if prov.Auth.Jwt != nil && prov.Auth.Jwt.KubernetesServiceAccountToken != nil && prov.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef.Namespace == nil {
  679. return true
  680. }
  681. if prov.Auth.Cert != nil && prov.Auth.Cert.SecretRef.Namespace == nil {
  682. return true
  683. }
  684. return false
  685. }
  686. func (v *client) Validate() (esv1beta1.ValidationResult, error) {
  687. // when using referent namespace we can not validate the token
  688. // because the namespace is not known yet when Validate() is called
  689. // from the SecretStore controller.
  690. if v.storeKind == esv1beta1.ClusterSecretStoreKind && isReferentSpec(v.store) {
  691. return esv1beta1.ValidationResultUnknown, nil
  692. }
  693. _, err := checkToken(context.Background(), v.token)
  694. if err != nil {
  695. return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
  696. }
  697. return esv1beta1.ValidationResultReady, nil
  698. }
  699. func (v *client) buildMetadataPath(path string) (string, error) {
  700. var url string
  701. if v.store.Path == nil && !strings.Contains(path, "data") {
  702. return "", fmt.Errorf(errPathInvalid)
  703. }
  704. if v.store.Path == nil {
  705. path = strings.Replace(path, "data", "metadata", 1)
  706. url = path
  707. } else {
  708. url = fmt.Sprintf("%s/metadata/%s", *v.store.Path, path)
  709. }
  710. return url, nil
  711. }
  712. /*
  713. buildPath is a helper method to build the vault equivalent path
  714. from ExternalSecrets and SecretStore manifests. the path build logic
  715. varies depending on the SecretStore KV version:
  716. Example inputs/outputs:
  717. # simple build:
  718. kv version == "v2":
  719. provider_path: "secret/path"
  720. input: "foo"
  721. output: "secret/path/data/foo" # provider_path and data are prepended
  722. kv version == "v1":
  723. provider_path: "secret/path"
  724. input: "foo"
  725. output: "secret/path/foo" # provider_path is prepended
  726. # inheriting paths:
  727. kv version == "v2":
  728. provider_path: "secret/path"
  729. input: "secret/path/foo"
  730. output: "secret/path/data/foo" #data is prepended
  731. kv version == "v2":
  732. provider_path: "secret/path"
  733. input: "secret/path/data/foo"
  734. output: "secret/path/data/foo" #noop
  735. kv version == "v1":
  736. provider_path: "secret/path"
  737. input: "secret/path/foo"
  738. output: "secret/path/foo" #noop
  739. # provider path not defined:
  740. kv version == "v2":
  741. provider_path: nil
  742. input: "secret/path/foo"
  743. output: "secret/data/path/foo" # data is prepended to secret/
  744. kv version == "v2":
  745. provider_path: nil
  746. input: "secret/path/data/foo"
  747. output: "secret/path/data/foo" #noop
  748. kv version == "v1":
  749. provider_path: nil
  750. input: "secret/path/foo"
  751. output: "secret/path/foo" #noop
  752. */
  753. func (v *client) buildPath(path string) string {
  754. optionalMount := v.store.Path
  755. out := path
  756. // if optionalMount is Set, remove it from path if its there
  757. if optionalMount != nil {
  758. cut := *optionalMount + "/"
  759. if strings.HasPrefix(out, cut) {
  760. // This current logic induces a bug when the actual secret resides on same path names as the mount path.
  761. _, out, _ = strings.Cut(out, cut)
  762. // if data succeeds optionalMount on v2 store, we should remove it as well
  763. if strings.HasPrefix(out, "data/") && v.store.Version == esv1beta1.VaultKVStoreV2 {
  764. _, out, _ = strings.Cut(out, "data/")
  765. }
  766. }
  767. buildPath := strings.Split(out, "/")
  768. buildMount := strings.Split(*optionalMount, "/")
  769. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  770. buildMount = append(buildMount, "data")
  771. }
  772. buildMount = append(buildMount, buildPath...)
  773. out = strings.Join(buildMount, "/")
  774. return out
  775. }
  776. if !strings.Contains(out, "/data/") && v.store.Version == esv1beta1.VaultKVStoreV2 {
  777. buildPath := strings.Split(out, "/")
  778. buildMount := []string{buildPath[0], "data"}
  779. buildMount = append(buildMount, buildPath[1:]...)
  780. out = strings.Join(buildMount, "/")
  781. return out
  782. }
  783. return out
  784. }
  785. func (v *client) readSecret(ctx context.Context, path, version string) (map[string]interface{}, error) {
  786. dataPath := v.buildPath(path)
  787. // path formated according to vault docs for v1 and v2 API
  788. // v1: https://www.vaultproject.io/api-docs/secret/kv/kv-v1#read-secret
  789. // v2: https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  790. var params map[string][]string
  791. if version != "" {
  792. params = make(map[string][]string)
  793. params["version"] = []string{version}
  794. }
  795. vaultSecret, err := v.logical.ReadWithDataWithContext(ctx, dataPath, params)
  796. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err)
  797. if err != nil {
  798. return nil, fmt.Errorf(errReadSecret, err)
  799. }
  800. if vaultSecret == nil {
  801. return nil, esv1beta1.NoSecretError{}
  802. }
  803. secretData := vaultSecret.Data
  804. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  805. // Vault KV2 has data embedded within sub-field
  806. // reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  807. dataInt, ok := vaultSecret.Data["data"]
  808. if !ok {
  809. return nil, errors.New(errDataField)
  810. }
  811. if dataInt == nil {
  812. return nil, esv1beta1.NoSecretError{}
  813. }
  814. secretData, ok = dataInt.(map[string]interface{})
  815. if !ok {
  816. return nil, errors.New(errJSONUnmarshall)
  817. }
  818. }
  819. return secretData, nil
  820. }
  821. func (v *client) newConfig() (*vault.Config, error) {
  822. cfg := vault.DefaultConfig()
  823. cfg.Address = v.store.Server
  824. // In a controller-runtime context, we rely on the reconciliation process for retrying
  825. cfg.MaxRetries = 0
  826. if len(v.store.CABundle) == 0 && v.store.CAProvider == nil {
  827. return cfg, nil
  828. }
  829. caCertPool := x509.NewCertPool()
  830. if len(v.store.CABundle) > 0 {
  831. ok := caCertPool.AppendCertsFromPEM(v.store.CABundle)
  832. if !ok {
  833. return nil, errors.New(errVaultCert)
  834. }
  835. }
  836. if v.store.CAProvider != nil && v.storeKind == esv1beta1.ClusterSecretStoreKind && v.store.CAProvider.Namespace == nil {
  837. return nil, errors.New(errCANamespace)
  838. }
  839. if v.store.CAProvider != nil {
  840. var cert []byte
  841. var err error
  842. switch v.store.CAProvider.Type {
  843. case esv1beta1.CAProviderTypeSecret:
  844. cert, err = getCertFromSecret(v)
  845. case esv1beta1.CAProviderTypeConfigMap:
  846. cert, err = getCertFromConfigMap(v)
  847. default:
  848. return nil, errors.New(errUnknownCAProvider)
  849. }
  850. if err != nil {
  851. return nil, err
  852. }
  853. ok := caCertPool.AppendCertsFromPEM(cert)
  854. if !ok {
  855. return nil, errors.New(errVaultCert)
  856. }
  857. }
  858. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  859. transport.TLSClientConfig.RootCAs = caCertPool
  860. }
  861. // If either read-after-write consistency feature is enabled, enable ReadYourWrites
  862. cfg.ReadYourWrites = v.store.ReadYourWrites || v.store.ForwardInconsistent
  863. return cfg, nil
  864. }
  865. func getCertFromSecret(v *client) ([]byte, error) {
  866. secretRef := esmeta.SecretKeySelector{
  867. Name: v.store.CAProvider.Name,
  868. Key: v.store.CAProvider.Key,
  869. }
  870. if v.store.CAProvider.Namespace != nil {
  871. secretRef.Namespace = v.store.CAProvider.Namespace
  872. }
  873. ctx := context.Background()
  874. res, err := v.secretKeyRef(ctx, &secretRef)
  875. if err != nil {
  876. return nil, fmt.Errorf(errVaultCert, err)
  877. }
  878. return []byte(res), nil
  879. }
  880. func getCertFromConfigMap(v *client) ([]byte, error) {
  881. objKey := types.NamespacedName{
  882. Name: v.store.CAProvider.Name,
  883. }
  884. if v.store.CAProvider.Namespace != nil {
  885. objKey.Namespace = *v.store.CAProvider.Namespace
  886. }
  887. configMapRef := &corev1.ConfigMap{}
  888. ctx := context.Background()
  889. err := v.kube.Get(ctx, objKey, configMapRef)
  890. if err != nil {
  891. return nil, fmt.Errorf(errVaultCert, err)
  892. }
  893. val, ok := configMapRef.Data[v.store.CAProvider.Key]
  894. if !ok {
  895. return nil, fmt.Errorf(errConfigMapFmt, v.store.CAProvider.Key)
  896. }
  897. return []byte(val), nil
  898. }
  899. /*
  900. setAuth gets a new token using the configured mechanism.
  901. If there's already a valid token, does nothing.
  902. */
  903. func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
  904. tokenExists := false
  905. var err error
  906. if v.client.Token() != "" {
  907. tokenExists, err = checkToken(ctx, v.token)
  908. }
  909. if tokenExists {
  910. v.log.V(1).Info("Re-using existing token")
  911. return err
  912. }
  913. tokenExists, err = setSecretKeyToken(ctx, v)
  914. if tokenExists {
  915. v.log.V(1).Info("Set token from secret")
  916. return err
  917. }
  918. tokenExists, err = setAppRoleToken(ctx, v)
  919. if tokenExists {
  920. v.log.V(1).Info("Retrieved new token using AppRole auth")
  921. return err
  922. }
  923. tokenExists, err = setKubernetesAuthToken(ctx, v)
  924. if tokenExists {
  925. v.log.V(1).Info("Retrieved new token using Kubernetes auth")
  926. return err
  927. }
  928. tokenExists, err = setLdapAuthToken(ctx, v)
  929. if tokenExists {
  930. v.log.V(1).Info("Retrieved new token using LDAP auth")
  931. return err
  932. }
  933. tokenExists, err = setJwtAuthToken(ctx, v)
  934. if tokenExists {
  935. v.log.V(1).Info("Retrieved new token using JWT auth")
  936. return err
  937. }
  938. tokenExists, err = setCertAuthToken(ctx, v, cfg)
  939. if tokenExists {
  940. v.log.V(1).Info("Retrieved new token using certificate auth")
  941. return err
  942. }
  943. return errors.New(errAuthFormat)
  944. }
  945. func setSecretKeyToken(ctx context.Context, v *client) (bool, error) {
  946. tokenRef := v.store.Auth.TokenSecretRef
  947. if tokenRef != nil {
  948. token, err := v.secretKeyRef(ctx, tokenRef)
  949. if err != nil {
  950. return true, err
  951. }
  952. v.client.SetToken(token)
  953. return true, nil
  954. }
  955. return false, nil
  956. }
  957. func setAppRoleToken(ctx context.Context, v *client) (bool, error) {
  958. appRole := v.store.Auth.AppRole
  959. if appRole != nil {
  960. err := v.requestTokenWithAppRoleRef(ctx, appRole)
  961. if err != nil {
  962. return true, err
  963. }
  964. return true, nil
  965. }
  966. return false, nil
  967. }
  968. func setKubernetesAuthToken(ctx context.Context, v *client) (bool, error) {
  969. kubernetesAuth := v.store.Auth.Kubernetes
  970. if kubernetesAuth != nil {
  971. err := v.requestTokenWithKubernetesAuth(ctx, kubernetesAuth)
  972. if err != nil {
  973. return true, err
  974. }
  975. return true, nil
  976. }
  977. return false, nil
  978. }
  979. func setLdapAuthToken(ctx context.Context, v *client) (bool, error) {
  980. ldapAuth := v.store.Auth.Ldap
  981. if ldapAuth != nil {
  982. err := v.requestTokenWithLdapAuth(ctx, ldapAuth)
  983. if err != nil {
  984. return true, err
  985. }
  986. return true, nil
  987. }
  988. return false, nil
  989. }
  990. func setJwtAuthToken(ctx context.Context, v *client) (bool, error) {
  991. jwtAuth := v.store.Auth.Jwt
  992. if jwtAuth != nil {
  993. err := v.requestTokenWithJwtAuth(ctx, jwtAuth)
  994. if err != nil {
  995. return true, err
  996. }
  997. return true, nil
  998. }
  999. return false, nil
  1000. }
  1001. func setCertAuthToken(ctx context.Context, v *client, cfg *vault.Config) (bool, error) {
  1002. certAuth := v.store.Auth.Cert
  1003. if certAuth != nil {
  1004. err := v.requestTokenWithCertAuth(ctx, certAuth, cfg)
  1005. if err != nil {
  1006. return true, err
  1007. }
  1008. return true, nil
  1009. }
  1010. return false, nil
  1011. }
  1012. func (v *client) secretKeyRefForServiceAccount(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) (string, error) {
  1013. serviceAccount := &corev1.ServiceAccount{}
  1014. ref := types.NamespacedName{
  1015. Namespace: v.namespace,
  1016. Name: serviceAccountRef.Name,
  1017. }
  1018. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1019. (serviceAccountRef.Namespace != nil) {
  1020. ref.Namespace = *serviceAccountRef.Namespace
  1021. }
  1022. err := v.kube.Get(ctx, ref, serviceAccount)
  1023. if err != nil {
  1024. return "", fmt.Errorf(errGetKubeSA, ref.Name, err)
  1025. }
  1026. if len(serviceAccount.Secrets) == 0 {
  1027. return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
  1028. }
  1029. for _, tokenRef := range serviceAccount.Secrets {
  1030. retval, err := v.secretKeyRef(ctx, &esmeta.SecretKeySelector{
  1031. Name: tokenRef.Name,
  1032. Namespace: &ref.Namespace,
  1033. Key: "token",
  1034. })
  1035. if err != nil {
  1036. continue
  1037. }
  1038. return retval, nil
  1039. }
  1040. return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
  1041. }
  1042. func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
  1043. secret := &corev1.Secret{}
  1044. ref := types.NamespacedName{
  1045. Namespace: v.namespace,
  1046. Name: secretRef.Name,
  1047. }
  1048. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1049. (secretRef.Namespace != nil) {
  1050. ref.Namespace = *secretRef.Namespace
  1051. }
  1052. err := v.kube.Get(ctx, ref, secret)
  1053. if err != nil {
  1054. return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
  1055. }
  1056. keyBytes, ok := secret.Data[secretRef.Key]
  1057. if !ok {
  1058. return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
  1059. }
  1060. value := string(keyBytes)
  1061. valueStr := strings.TrimSpace(value)
  1062. return valueStr, nil
  1063. }
  1064. func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, additionalAud []string, expirationSeconds int64) (string, error) {
  1065. audiences := serviceAccountRef.Audiences
  1066. if len(additionalAud) > 0 {
  1067. audiences = append(audiences, additionalAud...)
  1068. }
  1069. tokenRequest := &authenticationv1.TokenRequest{
  1070. ObjectMeta: metav1.ObjectMeta{
  1071. Namespace: v.namespace,
  1072. },
  1073. Spec: authenticationv1.TokenRequestSpec{
  1074. Audiences: audiences,
  1075. ExpirationSeconds: &expirationSeconds,
  1076. },
  1077. }
  1078. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1079. (serviceAccountRef.Namespace != nil) {
  1080. tokenRequest.Namespace = *serviceAccountRef.Namespace
  1081. }
  1082. tokenResponse, err := v.corev1.ServiceAccounts(tokenRequest.Namespace).CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
  1083. if err != nil {
  1084. return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
  1085. }
  1086. return tokenResponse.Status.Token, nil
  1087. }
  1088. // checkToken does a lookup and checks if the provided token exists.
  1089. func checkToken(ctx context.Context, token util.Token) (bool, error) {
  1090. // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self
  1091. resp, err := token.LookupSelfWithContext(ctx)
  1092. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLookupSelf, err)
  1093. if err != nil {
  1094. return false, err
  1095. }
  1096. t, ok := resp.Data["type"]
  1097. if !ok {
  1098. return false, fmt.Errorf("could not assert token type")
  1099. }
  1100. tokenType := t.(string)
  1101. if tokenType == "batch" {
  1102. return false, nil
  1103. }
  1104. return true, nil
  1105. }
  1106. func revokeTokenIfValid(ctx context.Context, client util.Client) error {
  1107. valid, err := checkToken(ctx, client.AuthToken())
  1108. if err != nil {
  1109. return fmt.Errorf(errVaultRevokeToken, err)
  1110. }
  1111. if valid {
  1112. err = client.AuthToken().RevokeSelfWithContext(ctx, client.Token())
  1113. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultRevokeSelf, err)
  1114. if err != nil {
  1115. return fmt.Errorf(errVaultRevokeToken, err)
  1116. }
  1117. client.ClearToken()
  1118. }
  1119. return nil
  1120. }
  1121. func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1beta1.VaultAppRole) error {
  1122. roleID := strings.TrimSpace(appRole.RoleID)
  1123. secretID, err := v.secretKeyRef(ctx, &appRole.SecretRef)
  1124. if err != nil {
  1125. return err
  1126. }
  1127. secret := approle.SecretID{FromString: secretID}
  1128. appRoleClient, err := approle.NewAppRoleAuth(roleID, &secret, approle.WithMountPath(appRole.Path))
  1129. if err != nil {
  1130. return err
  1131. }
  1132. _, err = v.auth.Login(ctx, appRoleClient)
  1133. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1134. if err != nil {
  1135. return err
  1136. }
  1137. return nil
  1138. }
  1139. func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesAuth *esv1beta1.VaultKubernetesAuth) error {
  1140. jwtString, err := getJwtString(ctx, v, kubernetesAuth)
  1141. if err != nil {
  1142. return err
  1143. }
  1144. k, err := authkubernetes.NewKubernetesAuth(kubernetesAuth.Role, authkubernetes.WithServiceAccountToken(jwtString), authkubernetes.WithMountPath(kubernetesAuth.Path))
  1145. if err != nil {
  1146. return err
  1147. }
  1148. _, err = v.auth.Login(ctx, k)
  1149. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1150. if err != nil {
  1151. return err
  1152. }
  1153. return nil
  1154. }
  1155. func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.VaultKubernetesAuth) (string, error) {
  1156. if kubernetesAuth.ServiceAccountRef != nil {
  1157. // Kubernetes <v1.24 fetch token via ServiceAccount.Secrets[]
  1158. // this behavior was removed in v1.24 and we must use TokenRequest API (see below)
  1159. jwt, err := v.secretKeyRefForServiceAccount(ctx, kubernetesAuth.ServiceAccountRef)
  1160. if jwt != "" {
  1161. return jwt, err
  1162. }
  1163. if err != nil {
  1164. v.log.V(1).Info("unable to fetch jwt from service account secret, trying service account token next")
  1165. }
  1166. // Kubernetes >=v1.24: fetch token via TokenRequest API
  1167. // note: this is a massive change from vault perspective: the `iss` claim will very likely change.
  1168. // Vault 1.9 deprecated issuer validation by default, and authentication with Vault clusters <1.9 will likely fail.
  1169. jwt, err = v.serviceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600)
  1170. if err != nil {
  1171. return "", err
  1172. }
  1173. return jwt, nil
  1174. } else if kubernetesAuth.SecretRef != nil {
  1175. tokenRef := kubernetesAuth.SecretRef
  1176. if tokenRef.Key == "" {
  1177. tokenRef = kubernetesAuth.SecretRef.DeepCopy()
  1178. tokenRef.Key = "token"
  1179. }
  1180. jwt, err := v.secretKeyRef(ctx, tokenRef)
  1181. if err != nil {
  1182. return "", err
  1183. }
  1184. return jwt, nil
  1185. } else {
  1186. // Kubernetes authentication is specified, but without a referenced
  1187. // Kubernetes secret. We check if the file path for in-cluster service account
  1188. // exists and attempt to use the token for Vault Kubernetes auth.
  1189. if _, err := os.Stat(serviceAccTokenPath); err != nil {
  1190. return "", fmt.Errorf(errServiceAccount, err)
  1191. }
  1192. jwtByte, err := os.ReadFile(serviceAccTokenPath)
  1193. if err != nil {
  1194. return "", fmt.Errorf(errServiceAccount, err)
  1195. }
  1196. return string(jwtByte), nil
  1197. }
  1198. }
  1199. func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1beta1.VaultLdapAuth) error {
  1200. username := strings.TrimSpace(ldapAuth.Username)
  1201. password, err := v.secretKeyRef(ctx, &ldapAuth.SecretRef)
  1202. if err != nil {
  1203. return err
  1204. }
  1205. pass := authldap.Password{FromString: password}
  1206. l, err := authldap.NewLDAPAuth(username, &pass, authldap.WithMountPath(ldapAuth.Path))
  1207. if err != nil {
  1208. return err
  1209. }
  1210. _, err = v.auth.Login(ctx, l)
  1211. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1212. if err != nil {
  1213. return err
  1214. }
  1215. return nil
  1216. }
  1217. func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1.VaultJwtAuth) error {
  1218. role := strings.TrimSpace(jwtAuth.Role)
  1219. var jwt string
  1220. var err error
  1221. if jwtAuth.SecretRef != nil {
  1222. jwt, err = v.secretKeyRef(ctx, jwtAuth.SecretRef)
  1223. } else if k8sServiceAccountToken := jwtAuth.KubernetesServiceAccountToken; k8sServiceAccountToken != nil {
  1224. audiences := k8sServiceAccountToken.Audiences
  1225. if audiences == nil {
  1226. audiences = &[]string{"vault"}
  1227. }
  1228. expirationSeconds := k8sServiceAccountToken.ExpirationSeconds
  1229. if expirationSeconds == nil {
  1230. tmp := int64(600)
  1231. expirationSeconds = &tmp
  1232. }
  1233. jwt, err = v.serviceAccountToken(ctx, k8sServiceAccountToken.ServiceAccountRef, *audiences, *expirationSeconds)
  1234. } else {
  1235. err = fmt.Errorf(errJwtNoTokenSource)
  1236. }
  1237. if err != nil {
  1238. return err
  1239. }
  1240. parameters := map[string]interface{}{
  1241. "role": role,
  1242. "jwt": jwt,
  1243. }
  1244. url := strings.Join([]string{"auth", jwtAuth.Path, "login"}, "/")
  1245. vaultResult, err := v.logical.WriteWithContext(ctx, url, parameters)
  1246. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  1247. if err != nil {
  1248. return err
  1249. }
  1250. token, err := vaultResult.TokenID()
  1251. if err != nil {
  1252. return fmt.Errorf(errVaultToken, err)
  1253. }
  1254. v.client.SetToken(token)
  1255. return nil
  1256. }
  1257. func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1beta1.VaultCertAuth, cfg *vault.Config) error {
  1258. clientKey, err := v.secretKeyRef(ctx, &certAuth.SecretRef)
  1259. if err != nil {
  1260. return err
  1261. }
  1262. clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
  1263. if err != nil {
  1264. return err
  1265. }
  1266. cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
  1267. if err != nil {
  1268. return fmt.Errorf(errClientTLSAuth, err)
  1269. }
  1270. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  1271. transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
  1272. }
  1273. url := strings.Join([]string{"auth", "cert", "login"}, "/")
  1274. vaultResult, err := v.logical.WriteWithContext(ctx, url, nil)
  1275. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  1276. if err != nil {
  1277. return fmt.Errorf(errVaultRequest, err)
  1278. }
  1279. token, err := vaultResult.TokenID()
  1280. if err != nil {
  1281. return fmt.Errorf(errVaultToken, err)
  1282. }
  1283. v.client.SetToken(token)
  1284. return nil
  1285. }
  1286. func init() {
  1287. var vaultTokenCacheSize int
  1288. fs := pflag.NewFlagSet("vault", pflag.ExitOnError)
  1289. fs.BoolVar(&enableCache, "experimental-enable-vault-token-cache", false, "Enable experimental Vault token cache. External secrets will reuse the Vault token without creating a new one on each request.")
  1290. // max. 265k vault leases with 30bytes each ~= 7MB
  1291. fs.IntVar(&vaultTokenCacheSize, "experimental-vault-token-cache-size", 2<<17, "Maximum size of Vault token cache. When more tokens than Only used if --experimental-enable-vault-token-cache is set.")
  1292. lateInit := func() {
  1293. logger.Info("initializing vault cache", "size", vaultTokenCacheSize)
  1294. clientCache = cache.Must(vaultTokenCacheSize, func(client util.Client) {
  1295. err := revokeTokenIfValid(context.Background(), client)
  1296. if err != nil {
  1297. logger.Error(err, "unable to revoke cached token on eviction")
  1298. }
  1299. })
  1300. }
  1301. feature.Register(feature.Feature{
  1302. Flags: fs,
  1303. Initialize: lateInit,
  1304. })
  1305. esv1beta1.Register(&Connector{
  1306. NewVaultClient: NewVaultClient,
  1307. }, &esv1beta1.SecretStoreProvider{
  1308. Vault: &esv1beta1.VaultProvider{},
  1309. })
  1310. }