vault.go 42 KB

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