vault.go 55 KB

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