vault.go 58 KB

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