vault.go 58 KB

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