vault.go 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429
  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 err != nil {
  443. return nil, err
  444. }
  445. if secret != nil {
  446. secrets[name] = secret
  447. }
  448. }
  449. }
  450. return secrets, nil
  451. }
  452. func (v *client) findSecretsFromName(ctx context.Context, candidates []string, ref esv1beta1.FindName) (map[string][]byte, error) {
  453. secrets := make(map[string][]byte)
  454. matcher, err := find.New(ref)
  455. if err != nil {
  456. return nil, err
  457. }
  458. for _, name := range candidates {
  459. ok := matcher.MatchName(name)
  460. if ok {
  461. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  462. if err != nil {
  463. return nil, err
  464. }
  465. if secret != nil {
  466. secrets[name] = secret
  467. }
  468. }
  469. }
  470. return secrets, nil
  471. }
  472. func (v *client) listSecrets(ctx context.Context, path string) ([]string, error) {
  473. secrets := make([]string, 0)
  474. url, err := v.buildMetadataPath(path)
  475. if err != nil {
  476. return nil, err
  477. }
  478. secret, err := v.logical.ListWithContext(ctx, url)
  479. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultListSecrets, err)
  480. if err != nil {
  481. return nil, fmt.Errorf(errReadSecret, err)
  482. }
  483. if secret == nil {
  484. return nil, fmt.Errorf("provided path %v does not contain any secrets", url)
  485. }
  486. t, ok := secret.Data["keys"]
  487. if !ok {
  488. return nil, nil
  489. }
  490. paths := t.([]interface{})
  491. for _, p := range paths {
  492. strPath := p.(string)
  493. fullPath := path + strPath // because path always ends with a /
  494. if path == "" {
  495. fullPath = strPath
  496. }
  497. // Recurrently find secrets
  498. if !strings.HasSuffix(p.(string), "/") {
  499. secrets = append(secrets, fullPath)
  500. } else {
  501. partial, err := v.listSecrets(ctx, fullPath)
  502. if err != nil {
  503. return nil, err
  504. }
  505. secrets = append(secrets, partial...)
  506. }
  507. }
  508. return secrets, nil
  509. }
  510. func (v *client) readSecretMetadata(ctx context.Context, path string) (map[string]string, error) {
  511. metadata := make(map[string]string)
  512. url, err := v.buildMetadataPath(path)
  513. if err != nil {
  514. return nil, err
  515. }
  516. secret, err := v.logical.ReadWithDataWithContext(ctx, url, nil)
  517. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err)
  518. if err != nil {
  519. return nil, fmt.Errorf(errReadSecret, err)
  520. }
  521. if secret == nil {
  522. return nil, errors.New(errNotFound)
  523. }
  524. t, ok := secret.Data["custom_metadata"]
  525. if !ok {
  526. return nil, nil
  527. }
  528. d, ok := t.(map[string]interface{})
  529. if !ok {
  530. return metadata, nil
  531. }
  532. for k, v := range d {
  533. metadata[k] = v.(string)
  534. }
  535. return metadata, nil
  536. }
  537. // GetSecret supports two types:
  538. // 1. get the full secret as json-encoded value
  539. // by leaving the ref.Property empty.
  540. // 2. get a key from the secret.
  541. // Nested values are supported by specifying a gjson expression
  542. func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  543. var data map[string]interface{}
  544. var err error
  545. if ref.MetadataPolicy == esv1beta1.ExternalSecretMetadataPolicyFetch {
  546. if v.store.Version == esv1beta1.VaultKVStoreV1 {
  547. return nil, errors.New(errUnsupportedMetadataKvVersion)
  548. }
  549. metadata, err := v.readSecretMetadata(ctx, ref.Key)
  550. if err != nil {
  551. return nil, err
  552. }
  553. if len(metadata) == 0 {
  554. return nil, nil
  555. }
  556. data = make(map[string]interface{}, len(metadata))
  557. for k, v := range metadata {
  558. data[k] = v
  559. }
  560. } else {
  561. data, err = v.readSecret(ctx, ref.Key, ref.Version)
  562. if err != nil {
  563. return nil, err
  564. }
  565. }
  566. // Return nil if secret value is null
  567. if data == nil {
  568. return nil, nil
  569. }
  570. jsonStr, err := json.Marshal(data)
  571. if err != nil {
  572. return nil, err
  573. }
  574. // (1): return raw json if no property is defined
  575. if ref.Property == "" {
  576. return jsonStr, nil
  577. }
  578. // For backwards compatibility we want the
  579. // actual keys to take precedence over gjson syntax
  580. // (2): extract key from secret with property
  581. if _, ok := data[ref.Property]; ok {
  582. return GetTypedKey(data, ref.Property)
  583. }
  584. // (3): extract key from secret using gjson
  585. val := gjson.Get(string(jsonStr), ref.Property)
  586. if !val.Exists() {
  587. return nil, fmt.Errorf(errSecretKeyFmt, ref.Property)
  588. }
  589. return []byte(val.String()), nil
  590. }
  591. // GetSecretMap supports two modes of operation:
  592. // 1. get the full secret from the vault data payload (by leaving .property empty).
  593. // 2. extract key/value pairs from a (nested) object.
  594. func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  595. data, err := v.GetSecret(ctx, ref)
  596. if err != nil {
  597. return nil, err
  598. }
  599. var secretData map[string]interface{}
  600. err = json.Unmarshal(data, &secretData)
  601. if err != nil {
  602. return nil, err
  603. }
  604. byteMap := make(map[string][]byte, len(secretData))
  605. for k := range secretData {
  606. byteMap[k], err = GetTypedKey(secretData, k)
  607. if err != nil {
  608. return nil, err
  609. }
  610. }
  611. return byteMap, nil
  612. }
  613. func GetTypedKey(data map[string]interface{}, key string) ([]byte, error) {
  614. v, ok := data[key]
  615. if !ok {
  616. return nil, fmt.Errorf(errUnexpectedKey, key)
  617. }
  618. switch t := v.(type) {
  619. case string:
  620. return []byte(t), nil
  621. case map[string]interface{}:
  622. return json.Marshal(t)
  623. case []string:
  624. return []byte(strings.Join(t, "\n")), nil
  625. case []byte:
  626. return t, nil
  627. // also covers int and float32 due to json.Marshal
  628. case float64:
  629. return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil
  630. case json.Number:
  631. return []byte(t.String()), nil
  632. case []interface{}:
  633. return json.Marshal(t)
  634. case bool:
  635. return []byte(strconv.FormatBool(t)), nil
  636. case nil:
  637. return []byte(nil), nil
  638. default:
  639. return nil, fmt.Errorf(errSecretFormat, key, reflect.TypeOf(t))
  640. }
  641. }
  642. func (v *client) Close(ctx context.Context) error {
  643. // Revoke the token if we have one set, it wasn't sourced from a TokenSecretRef,
  644. // and token caching isn't enabled
  645. if !enableCache && v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil {
  646. err := revokeTokenIfValid(ctx, v.client)
  647. if err != nil {
  648. return err
  649. }
  650. }
  651. return nil
  652. }
  653. func isReferentSpec(prov *esv1beta1.VaultProvider) bool {
  654. if prov.Auth.TokenSecretRef != nil && prov.Auth.TokenSecretRef.Namespace == nil {
  655. return true
  656. }
  657. if prov.Auth.AppRole != nil && prov.Auth.AppRole.SecretRef.Namespace == nil {
  658. return true
  659. }
  660. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.SecretRef != nil && prov.Auth.Kubernetes.SecretRef.Namespace == nil {
  661. return true
  662. }
  663. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.ServiceAccountRef != nil && prov.Auth.Kubernetes.ServiceAccountRef.Namespace == nil {
  664. return true
  665. }
  666. if prov.Auth.Ldap != nil && prov.Auth.Ldap.SecretRef.Namespace == nil {
  667. return true
  668. }
  669. if prov.Auth.Jwt != nil && prov.Auth.Jwt.SecretRef != nil && prov.Auth.Jwt.SecretRef.Namespace == nil {
  670. return true
  671. }
  672. if prov.Auth.Jwt != nil && prov.Auth.Jwt.KubernetesServiceAccountToken != nil && prov.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef.Namespace == nil {
  673. return true
  674. }
  675. if prov.Auth.Cert != nil && prov.Auth.Cert.SecretRef.Namespace == nil {
  676. return true
  677. }
  678. return false
  679. }
  680. func (v *client) Validate() (esv1beta1.ValidationResult, error) {
  681. // when using referent namespace we can not validate the token
  682. // because the namespace is not known yet when Validate() is called
  683. // from the SecretStore controller.
  684. if v.storeKind == esv1beta1.ClusterSecretStoreKind && isReferentSpec(v.store) {
  685. return esv1beta1.ValidationResultUnknown, nil
  686. }
  687. _, err := checkToken(context.Background(), v.token)
  688. if err != nil {
  689. return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
  690. }
  691. return esv1beta1.ValidationResultReady, nil
  692. }
  693. func (v *client) buildMetadataPath(path string) (string, error) {
  694. var url string
  695. if v.store.Path == nil && !strings.Contains(path, "data") {
  696. return "", fmt.Errorf(errPathInvalid)
  697. }
  698. if v.store.Path == nil {
  699. path = strings.Replace(path, "data", "metadata", 1)
  700. url = path
  701. } else {
  702. url = fmt.Sprintf("%s/metadata/%s", *v.store.Path, path)
  703. }
  704. return url, nil
  705. }
  706. /*
  707. buildPath is a helper method to build the vault equivalent path
  708. from ExternalSecrets and SecretStore manifests. the path build logic
  709. varies depending on the SecretStore KV version:
  710. Example inputs/outputs:
  711. # simple build:
  712. kv version == "v2":
  713. provider_path: "secret/path"
  714. input: "foo"
  715. output: "secret/path/data/foo" # provider_path and data are prepended
  716. kv version == "v1":
  717. provider_path: "secret/path"
  718. input: "foo"
  719. output: "secret/path/foo" # provider_path is prepended
  720. # inheriting paths:
  721. kv version == "v2":
  722. provider_path: "secret/path"
  723. input: "secret/path/foo"
  724. output: "secret/path/data/foo" #data is prepended
  725. kv version == "v2":
  726. provider_path: "secret/path"
  727. input: "secret/path/data/foo"
  728. output: "secret/path/data/foo" #noop
  729. kv version == "v1":
  730. provider_path: "secret/path"
  731. input: "secret/path/foo"
  732. output: "secret/path/foo" #noop
  733. # provider path not defined:
  734. kv version == "v2":
  735. provider_path: nil
  736. input: "secret/path/foo"
  737. output: "secret/data/path/foo" # data is prepended to secret/
  738. kv version == "v2":
  739. provider_path: nil
  740. input: "secret/path/data/foo"
  741. output: "secret/path/data/foo" #noop
  742. kv version == "v1":
  743. provider_path: nil
  744. input: "secret/path/foo"
  745. output: "secret/path/foo" #noop
  746. */
  747. func (v *client) buildPath(path string) string {
  748. optionalMount := v.store.Path
  749. out := path
  750. // if optionalMount is Set, remove it from path if its there
  751. if optionalMount != nil {
  752. cut := *optionalMount + "/"
  753. if strings.HasPrefix(out, cut) {
  754. // This current logic induces a bug when the actual secret resides on same path names as the mount path.
  755. _, out, _ = strings.Cut(out, cut)
  756. // if data succeeds optionalMount on v2 store, we should remove it as well
  757. if strings.HasPrefix(out, "data/") && v.store.Version == esv1beta1.VaultKVStoreV2 {
  758. _, out, _ = strings.Cut(out, "data/")
  759. }
  760. }
  761. buildPath := strings.Split(out, "/")
  762. buildMount := strings.Split(*optionalMount, "/")
  763. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  764. buildMount = append(buildMount, "data")
  765. }
  766. buildMount = append(buildMount, buildPath...)
  767. out = strings.Join(buildMount, "/")
  768. return out
  769. }
  770. if !strings.Contains(out, "/data/") && v.store.Version == esv1beta1.VaultKVStoreV2 {
  771. buildPath := strings.Split(out, "/")
  772. buildMount := []string{buildPath[0], "data"}
  773. buildMount = append(buildMount, buildPath[1:]...)
  774. out = strings.Join(buildMount, "/")
  775. return out
  776. }
  777. return out
  778. }
  779. func (v *client) readSecret(ctx context.Context, path, version string) (map[string]interface{}, error) {
  780. dataPath := v.buildPath(path)
  781. // path formated according to vault docs for v1 and v2 API
  782. // v1: https://www.vaultproject.io/api-docs/secret/kv/kv-v1#read-secret
  783. // v2: https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  784. var params map[string][]string
  785. if version != "" {
  786. params = make(map[string][]string)
  787. params["version"] = []string{version}
  788. }
  789. vaultSecret, err := v.logical.ReadWithDataWithContext(ctx, dataPath, params)
  790. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultReadSecretData, err)
  791. if err != nil {
  792. return nil, fmt.Errorf(errReadSecret, err)
  793. }
  794. if vaultSecret == nil {
  795. return nil, esv1beta1.NoSecretError{}
  796. }
  797. secretData := vaultSecret.Data
  798. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  799. // Vault KV2 has data embedded within sub-field
  800. // reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  801. dataInt, ok := vaultSecret.Data["data"]
  802. if !ok {
  803. return nil, errors.New(errDataField)
  804. }
  805. if dataInt == nil {
  806. return nil, nil
  807. }
  808. secretData, ok = dataInt.(map[string]interface{})
  809. if !ok {
  810. return nil, errors.New(errJSONUnmarshall)
  811. }
  812. }
  813. return secretData, nil
  814. }
  815. func (v *client) newConfig() (*vault.Config, error) {
  816. cfg := vault.DefaultConfig()
  817. cfg.Address = v.store.Server
  818. // In a controller-runtime context, we rely on the reconciliation process for retrying
  819. cfg.MaxRetries = 0
  820. if len(v.store.CABundle) == 0 && v.store.CAProvider == nil {
  821. return cfg, nil
  822. }
  823. caCertPool := x509.NewCertPool()
  824. if len(v.store.CABundle) > 0 {
  825. ok := caCertPool.AppendCertsFromPEM(v.store.CABundle)
  826. if !ok {
  827. return nil, errors.New(errVaultCert)
  828. }
  829. }
  830. if v.store.CAProvider != nil && v.storeKind == esv1beta1.ClusterSecretStoreKind && v.store.CAProvider.Namespace == nil {
  831. return nil, errors.New(errCANamespace)
  832. }
  833. if v.store.CAProvider != nil {
  834. var cert []byte
  835. var err error
  836. switch v.store.CAProvider.Type {
  837. case esv1beta1.CAProviderTypeSecret:
  838. cert, err = getCertFromSecret(v)
  839. case esv1beta1.CAProviderTypeConfigMap:
  840. cert, err = getCertFromConfigMap(v)
  841. default:
  842. return nil, errors.New(errUnknownCAProvider)
  843. }
  844. if err != nil {
  845. return nil, err
  846. }
  847. ok := caCertPool.AppendCertsFromPEM(cert)
  848. if !ok {
  849. return nil, errors.New(errVaultCert)
  850. }
  851. }
  852. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  853. transport.TLSClientConfig.RootCAs = caCertPool
  854. }
  855. // If either read-after-write consistency feature is enabled, enable ReadYourWrites
  856. cfg.ReadYourWrites = v.store.ReadYourWrites || v.store.ForwardInconsistent
  857. return cfg, nil
  858. }
  859. func getCertFromSecret(v *client) ([]byte, error) {
  860. secretRef := esmeta.SecretKeySelector{
  861. Name: v.store.CAProvider.Name,
  862. Key: v.store.CAProvider.Key,
  863. }
  864. if v.store.CAProvider.Namespace != nil {
  865. secretRef.Namespace = v.store.CAProvider.Namespace
  866. }
  867. ctx := context.Background()
  868. res, err := v.secretKeyRef(ctx, &secretRef)
  869. if err != nil {
  870. return nil, fmt.Errorf(errVaultCert, err)
  871. }
  872. return []byte(res), nil
  873. }
  874. func getCertFromConfigMap(v *client) ([]byte, error) {
  875. objKey := types.NamespacedName{
  876. Name: v.store.CAProvider.Name,
  877. }
  878. if v.store.CAProvider.Namespace != nil {
  879. objKey.Namespace = *v.store.CAProvider.Namespace
  880. }
  881. configMapRef := &corev1.ConfigMap{}
  882. ctx := context.Background()
  883. err := v.kube.Get(ctx, objKey, configMapRef)
  884. if err != nil {
  885. return nil, fmt.Errorf(errVaultCert, err)
  886. }
  887. val, ok := configMapRef.Data[v.store.CAProvider.Key]
  888. if !ok {
  889. return nil, fmt.Errorf(errConfigMapFmt, v.store.CAProvider.Key)
  890. }
  891. return []byte(val), nil
  892. }
  893. /*
  894. setAuth gets a new token using the configured mechanism.
  895. If there's already a valid token, does nothing.
  896. */
  897. func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
  898. tokenExists := false
  899. var err error
  900. if v.client.Token() != "" {
  901. tokenExists, err = checkToken(ctx, v.token)
  902. }
  903. if tokenExists {
  904. v.log.V(1).Info("Re-using existing token")
  905. return err
  906. }
  907. tokenExists, err = setSecretKeyToken(ctx, v)
  908. if tokenExists {
  909. v.log.V(1).Info("Set token from secret")
  910. return err
  911. }
  912. tokenExists, err = setAppRoleToken(ctx, v)
  913. if tokenExists {
  914. v.log.V(1).Info("Retrieved new token using AppRole auth")
  915. return err
  916. }
  917. tokenExists, err = setKubernetesAuthToken(ctx, v)
  918. if tokenExists {
  919. v.log.V(1).Info("Retrieved new token using Kubernetes auth")
  920. return err
  921. }
  922. tokenExists, err = setLdapAuthToken(ctx, v)
  923. if tokenExists {
  924. v.log.V(1).Info("Retrieved new token using LDAP auth")
  925. return err
  926. }
  927. tokenExists, err = setJwtAuthToken(ctx, v)
  928. if tokenExists {
  929. v.log.V(1).Info("Retrieved new token using JWT auth")
  930. return err
  931. }
  932. tokenExists, err = setCertAuthToken(ctx, v, cfg)
  933. if tokenExists {
  934. v.log.V(1).Info("Retrieved new token using certificate auth")
  935. return err
  936. }
  937. return errors.New(errAuthFormat)
  938. }
  939. func setSecretKeyToken(ctx context.Context, v *client) (bool, error) {
  940. tokenRef := v.store.Auth.TokenSecretRef
  941. if tokenRef != nil {
  942. token, err := v.secretKeyRef(ctx, tokenRef)
  943. if err != nil {
  944. return true, err
  945. }
  946. v.client.SetToken(token)
  947. return true, nil
  948. }
  949. return false, nil
  950. }
  951. func setAppRoleToken(ctx context.Context, v *client) (bool, error) {
  952. appRole := v.store.Auth.AppRole
  953. if appRole != nil {
  954. err := v.requestTokenWithAppRoleRef(ctx, appRole)
  955. if err != nil {
  956. return true, err
  957. }
  958. return true, nil
  959. }
  960. return false, nil
  961. }
  962. func setKubernetesAuthToken(ctx context.Context, v *client) (bool, error) {
  963. kubernetesAuth := v.store.Auth.Kubernetes
  964. if kubernetesAuth != nil {
  965. err := v.requestTokenWithKubernetesAuth(ctx, kubernetesAuth)
  966. if err != nil {
  967. return true, err
  968. }
  969. return true, nil
  970. }
  971. return false, nil
  972. }
  973. func setLdapAuthToken(ctx context.Context, v *client) (bool, error) {
  974. ldapAuth := v.store.Auth.Ldap
  975. if ldapAuth != nil {
  976. err := v.requestTokenWithLdapAuth(ctx, ldapAuth)
  977. if err != nil {
  978. return true, err
  979. }
  980. return true, nil
  981. }
  982. return false, nil
  983. }
  984. func setJwtAuthToken(ctx context.Context, v *client) (bool, error) {
  985. jwtAuth := v.store.Auth.Jwt
  986. if jwtAuth != nil {
  987. err := v.requestTokenWithJwtAuth(ctx, jwtAuth)
  988. if err != nil {
  989. return true, err
  990. }
  991. return true, nil
  992. }
  993. return false, nil
  994. }
  995. func setCertAuthToken(ctx context.Context, v *client, cfg *vault.Config) (bool, error) {
  996. certAuth := v.store.Auth.Cert
  997. if certAuth != nil {
  998. err := v.requestTokenWithCertAuth(ctx, certAuth, cfg)
  999. if err != nil {
  1000. return true, err
  1001. }
  1002. return true, nil
  1003. }
  1004. return false, nil
  1005. }
  1006. func (v *client) secretKeyRefForServiceAccount(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) (string, error) {
  1007. serviceAccount := &corev1.ServiceAccount{}
  1008. ref := types.NamespacedName{
  1009. Namespace: v.namespace,
  1010. Name: serviceAccountRef.Name,
  1011. }
  1012. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1013. (serviceAccountRef.Namespace != nil) {
  1014. ref.Namespace = *serviceAccountRef.Namespace
  1015. }
  1016. err := v.kube.Get(ctx, ref, serviceAccount)
  1017. if err != nil {
  1018. return "", fmt.Errorf(errGetKubeSA, ref.Name, err)
  1019. }
  1020. if len(serviceAccount.Secrets) == 0 {
  1021. return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
  1022. }
  1023. for _, tokenRef := range serviceAccount.Secrets {
  1024. retval, err := v.secretKeyRef(ctx, &esmeta.SecretKeySelector{
  1025. Name: tokenRef.Name,
  1026. Namespace: &ref.Namespace,
  1027. Key: "token",
  1028. })
  1029. if err != nil {
  1030. continue
  1031. }
  1032. return retval, nil
  1033. }
  1034. return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
  1035. }
  1036. func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
  1037. secret := &corev1.Secret{}
  1038. ref := types.NamespacedName{
  1039. Namespace: v.namespace,
  1040. Name: secretRef.Name,
  1041. }
  1042. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1043. (secretRef.Namespace != nil) {
  1044. ref.Namespace = *secretRef.Namespace
  1045. }
  1046. err := v.kube.Get(ctx, ref, secret)
  1047. if err != nil {
  1048. return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
  1049. }
  1050. keyBytes, ok := secret.Data[secretRef.Key]
  1051. if !ok {
  1052. return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
  1053. }
  1054. value := string(keyBytes)
  1055. valueStr := strings.TrimSpace(value)
  1056. return valueStr, nil
  1057. }
  1058. func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, additionalAud []string, expirationSeconds int64) (string, error) {
  1059. audiences := serviceAccountRef.Audiences
  1060. if len(additionalAud) > 0 {
  1061. audiences = append(audiences, additionalAud...)
  1062. }
  1063. tokenRequest := &authenticationv1.TokenRequest{
  1064. ObjectMeta: metav1.ObjectMeta{
  1065. Namespace: v.namespace,
  1066. },
  1067. Spec: authenticationv1.TokenRequestSpec{
  1068. Audiences: audiences,
  1069. ExpirationSeconds: &expirationSeconds,
  1070. },
  1071. }
  1072. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  1073. (serviceAccountRef.Namespace != nil) {
  1074. tokenRequest.Namespace = *serviceAccountRef.Namespace
  1075. }
  1076. tokenResponse, err := v.corev1.ServiceAccounts(tokenRequest.Namespace).CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
  1077. if err != nil {
  1078. return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
  1079. }
  1080. return tokenResponse.Status.Token, nil
  1081. }
  1082. // checkToken does a lookup and checks if the provided token exists.
  1083. func checkToken(ctx context.Context, token util.Token) (bool, error) {
  1084. // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self
  1085. resp, err := token.LookupSelfWithContext(ctx)
  1086. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLookupSelf, err)
  1087. if err != nil {
  1088. return false, err
  1089. }
  1090. t, ok := resp.Data["type"]
  1091. if !ok {
  1092. return false, fmt.Errorf("could not assert token type")
  1093. }
  1094. tokenType := t.(string)
  1095. if tokenType == "batch" {
  1096. return false, nil
  1097. }
  1098. return true, nil
  1099. }
  1100. func revokeTokenIfValid(ctx context.Context, client util.Client) error {
  1101. valid, err := checkToken(ctx, client.AuthToken())
  1102. if err != nil {
  1103. return fmt.Errorf(errVaultRevokeToken, err)
  1104. }
  1105. if valid {
  1106. err = client.AuthToken().RevokeSelfWithContext(ctx, client.Token())
  1107. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultRevokeSelf, err)
  1108. if err != nil {
  1109. return fmt.Errorf(errVaultRevokeToken, err)
  1110. }
  1111. client.ClearToken()
  1112. }
  1113. return nil
  1114. }
  1115. func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1beta1.VaultAppRole) error {
  1116. roleID := strings.TrimSpace(appRole.RoleID)
  1117. secretID, err := v.secretKeyRef(ctx, &appRole.SecretRef)
  1118. if err != nil {
  1119. return err
  1120. }
  1121. secret := approle.SecretID{FromString: secretID}
  1122. appRoleClient, err := approle.NewAppRoleAuth(roleID, &secret, approle.WithMountPath(appRole.Path))
  1123. if err != nil {
  1124. return err
  1125. }
  1126. _, err = v.auth.Login(ctx, appRoleClient)
  1127. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1128. if err != nil {
  1129. return err
  1130. }
  1131. return nil
  1132. }
  1133. func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesAuth *esv1beta1.VaultKubernetesAuth) error {
  1134. jwtString, err := getJwtString(ctx, v, kubernetesAuth)
  1135. if err != nil {
  1136. return err
  1137. }
  1138. k, err := authkubernetes.NewKubernetesAuth(kubernetesAuth.Role, authkubernetes.WithServiceAccountToken(jwtString), authkubernetes.WithMountPath(kubernetesAuth.Path))
  1139. if err != nil {
  1140. return err
  1141. }
  1142. _, err = v.auth.Login(ctx, k)
  1143. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1144. if err != nil {
  1145. return err
  1146. }
  1147. return nil
  1148. }
  1149. func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.VaultKubernetesAuth) (string, error) {
  1150. if kubernetesAuth.ServiceAccountRef != nil {
  1151. // Kubernetes <v1.24 fetch token via ServiceAccount.Secrets[]
  1152. // this behavior was removed in v1.24 and we must use TokenRequest API (see below)
  1153. jwt, err := v.secretKeyRefForServiceAccount(ctx, kubernetesAuth.ServiceAccountRef)
  1154. if jwt != "" {
  1155. return jwt, err
  1156. }
  1157. if err != nil {
  1158. v.log.V(1).Info("unable to fetch jwt from service account secret, trying service account token next")
  1159. }
  1160. // Kubernetes >=v1.24: fetch token via TokenRequest API
  1161. // note: this is a massive change from vault perspective: the `iss` claim will very likely change.
  1162. // Vault 1.9 deprecated issuer validation by default, and authentication with Vault clusters <1.9 will likely fail.
  1163. jwt, err = v.serviceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600)
  1164. if err != nil {
  1165. return "", err
  1166. }
  1167. return jwt, nil
  1168. } else if kubernetesAuth.SecretRef != nil {
  1169. tokenRef := kubernetesAuth.SecretRef
  1170. if tokenRef.Key == "" {
  1171. tokenRef = kubernetesAuth.SecretRef.DeepCopy()
  1172. tokenRef.Key = "token"
  1173. }
  1174. jwt, err := v.secretKeyRef(ctx, tokenRef)
  1175. if err != nil {
  1176. return "", err
  1177. }
  1178. return jwt, nil
  1179. } else {
  1180. // Kubernetes authentication is specified, but without a referenced
  1181. // Kubernetes secret. We check if the file path for in-cluster service account
  1182. // exists and attempt to use the token for Vault Kubernetes auth.
  1183. if _, err := os.Stat(serviceAccTokenPath); err != nil {
  1184. return "", fmt.Errorf(errServiceAccount, err)
  1185. }
  1186. jwtByte, err := os.ReadFile(serviceAccTokenPath)
  1187. if err != nil {
  1188. return "", fmt.Errorf(errServiceAccount, err)
  1189. }
  1190. return string(jwtByte), nil
  1191. }
  1192. }
  1193. func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1beta1.VaultLdapAuth) error {
  1194. username := strings.TrimSpace(ldapAuth.Username)
  1195. password, err := v.secretKeyRef(ctx, &ldapAuth.SecretRef)
  1196. if err != nil {
  1197. return err
  1198. }
  1199. pass := authldap.Password{FromString: password}
  1200. l, err := authldap.NewLDAPAuth(username, &pass, authldap.WithMountPath(ldapAuth.Path))
  1201. if err != nil {
  1202. return err
  1203. }
  1204. _, err = v.auth.Login(ctx, l)
  1205. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultLogin, err)
  1206. if err != nil {
  1207. return err
  1208. }
  1209. return nil
  1210. }
  1211. func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1.VaultJwtAuth) error {
  1212. role := strings.TrimSpace(jwtAuth.Role)
  1213. var jwt string
  1214. var err error
  1215. if jwtAuth.SecretRef != nil {
  1216. jwt, err = v.secretKeyRef(ctx, jwtAuth.SecretRef)
  1217. } else if k8sServiceAccountToken := jwtAuth.KubernetesServiceAccountToken; k8sServiceAccountToken != nil {
  1218. audiences := k8sServiceAccountToken.Audiences
  1219. if audiences == nil {
  1220. audiences = &[]string{"vault"}
  1221. }
  1222. expirationSeconds := k8sServiceAccountToken.ExpirationSeconds
  1223. if expirationSeconds == nil {
  1224. tmp := int64(600)
  1225. expirationSeconds = &tmp
  1226. }
  1227. jwt, err = v.serviceAccountToken(ctx, k8sServiceAccountToken.ServiceAccountRef, *audiences, *expirationSeconds)
  1228. } else {
  1229. err = fmt.Errorf(errJwtNoTokenSource)
  1230. }
  1231. if err != nil {
  1232. return err
  1233. }
  1234. parameters := map[string]interface{}{
  1235. "role": role,
  1236. "jwt": jwt,
  1237. }
  1238. url := strings.Join([]string{"auth", jwtAuth.Path, "login"}, "/")
  1239. vaultResult, err := v.logical.WriteWithContext(ctx, url, parameters)
  1240. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  1241. if err != nil {
  1242. return err
  1243. }
  1244. token, err := vaultResult.TokenID()
  1245. if err != nil {
  1246. return fmt.Errorf(errVaultToken, err)
  1247. }
  1248. v.client.SetToken(token)
  1249. return nil
  1250. }
  1251. func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1beta1.VaultCertAuth, cfg *vault.Config) error {
  1252. clientKey, err := v.secretKeyRef(ctx, &certAuth.SecretRef)
  1253. if err != nil {
  1254. return err
  1255. }
  1256. clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
  1257. if err != nil {
  1258. return err
  1259. }
  1260. cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
  1261. if err != nil {
  1262. return fmt.Errorf(errClientTLSAuth, err)
  1263. }
  1264. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  1265. transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
  1266. }
  1267. url := strings.Join([]string{"auth", "cert", "login"}, "/")
  1268. vaultResult, err := v.logical.WriteWithContext(ctx, url, nil)
  1269. metrics.ObserveAPICall(metrics.ProviderHCVault, metrics.CallHCVaultWriteSecretData, err)
  1270. if err != nil {
  1271. return fmt.Errorf(errVaultRequest, err)
  1272. }
  1273. token, err := vaultResult.TokenID()
  1274. if err != nil {
  1275. return fmt.Errorf(errVaultToken, err)
  1276. }
  1277. v.client.SetToken(token)
  1278. return nil
  1279. }
  1280. func init() {
  1281. var vaultTokenCacheSize int
  1282. fs := pflag.NewFlagSet("vault", pflag.ExitOnError)
  1283. 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.")
  1284. // max. 265k vault leases with 30bytes each ~= 7MB
  1285. 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.")
  1286. lateInit := func() {
  1287. logger.Info("initializing vault cache with size=%d", vaultTokenCacheSize)
  1288. clientCache = cache.Must(vaultTokenCacheSize, func(client util.Client) {
  1289. err := revokeTokenIfValid(context.Background(), client)
  1290. if err != nil {
  1291. logger.Error(err, "unable to revoke cached token on eviction")
  1292. }
  1293. })
  1294. }
  1295. feature.Register(feature.Feature{
  1296. Flags: fs,
  1297. Initialize: lateInit,
  1298. })
  1299. esv1beta1.Register(&Connector{
  1300. NewVaultClient: NewVaultClient,
  1301. }, &esv1beta1.SecretStoreProvider{
  1302. Vault: &esv1beta1.VaultProvider{},
  1303. })
  1304. }