vault.go 54 KB

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