vault.go 56 KB

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