vault.go 43 KB

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