vault.go 54 KB

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