vault.go 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199
  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. "context"
  15. "crypto/tls"
  16. "crypto/x509"
  17. "encoding/json"
  18. "errors"
  19. "fmt"
  20. "net/http"
  21. "os"
  22. "strconv"
  23. "strings"
  24. "github.com/go-logr/logr"
  25. vault "github.com/hashicorp/vault/api"
  26. approle "github.com/hashicorp/vault/api/auth/approle"
  27. authkubernetes "github.com/hashicorp/vault/api/auth/kubernetes"
  28. authldap "github.com/hashicorp/vault/api/auth/ldap"
  29. "github.com/tidwall/gjson"
  30. authenticationv1 "k8s.io/api/authentication/v1"
  31. corev1 "k8s.io/api/core/v1"
  32. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  33. "k8s.io/apimachinery/pkg/types"
  34. "k8s.io/client-go/kubernetes"
  35. typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  36. ctrl "sigs.k8s.io/controller-runtime"
  37. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  38. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  39. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  40. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  41. "github.com/external-secrets/external-secrets/pkg/find"
  42. "github.com/external-secrets/external-secrets/pkg/utils"
  43. )
  44. var (
  45. _ esv1beta1.Provider = &connector{}
  46. _ esv1beta1.SecretsClient = &client{}
  47. )
  48. const (
  49. serviceAccTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  50. errVaultStore = "received invalid Vault SecretStore resource: %w"
  51. errVaultClient = "cannot setup new vault client: %w"
  52. errVaultCert = "cannot set Vault CA certificate: %w"
  53. errReadSecret = "cannot read secret data from Vault: %w"
  54. errAuthFormat = "cannot initialize Vault client: no valid auth method specified"
  55. errInvalidCredentials = "invalid vault credentials: %w"
  56. errDataField = "failed to find data field"
  57. errJSONUnmarshall = "failed to unmarshall JSON"
  58. errPathInvalid = "provided Path isn't a valid kv v2 path"
  59. errSecretFormat = "secret data not in expected format"
  60. errUnexpectedKey = "unexpected key in data: %s"
  61. errVaultToken = "cannot parse Vault authentication token: %w"
  62. errVaultRequest = "error from Vault request: %w"
  63. errServiceAccount = "cannot read Kubernetes service account token from file system: %w"
  64. errJwtNoTokenSource = "neither `secretRef` nor `kubernetesServiceAccountToken` was supplied as token source for jwt authentication"
  65. errUnsupportedKvVersion = "cannot perform find operations with kv version v1"
  66. errNotFound = "secret not found"
  67. errGetKubeSA = "cannot get Kubernetes service account %q: %w"
  68. errGetKubeSASecrets = "cannot find secrets bound to service account: %q"
  69. errGetKubeSANoToken = "cannot find token in secrets bound to service account: %q"
  70. errGetKubeSATokenRequest = "cannot request Kubernetes service account token for service account %q: %w"
  71. errGetKubeSecret = "cannot get Kubernetes secret %q: %w"
  72. errSecretKeyFmt = "cannot find secret data for key: %q"
  73. errConfigMapFmt = "cannot find config map data for key: %q"
  74. errClientTLSAuth = "error from Client TLS Auth: %q"
  75. errVaultRevokeToken = "error while revoking token: %w"
  76. errUnknownCAProvider = "unknown caProvider type given"
  77. errCANamespace = "cannot read secret for CAProvider due to missing namespace on kind ClusterSecretStore"
  78. errInvalidStore = "invalid store"
  79. errInvalidStoreSpec = "invalid store spec"
  80. errInvalidStoreProv = "invalid store provider"
  81. errInvalidVaultProv = "invalid vault provider"
  82. errInvalidAppRoleSec = "invalid Auth.AppRole.SecretRef: %w"
  83. errInvalidClientCert = "invalid Auth.Cert.ClientCert: %w"
  84. errInvalidCertSec = "invalid Auth.Cert.SecretRef: %w"
  85. errInvalidJwtSec = "invalid Auth.Jwt.SecretRef: %w"
  86. errInvalidJwtK8sSA = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
  87. errInvalidKubeSA = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
  88. errInvalidKubeSec = "invalid Auth.Kubernetes.SecretRef: %w"
  89. errInvalidLdapSec = "invalid Auth.Ldap.SecretRef: %w"
  90. errInvalidTokenRef = "invalid Auth.TokenSecretRef: %w"
  91. )
  92. // https://github.com/external-secrets/external-secrets/issues/644
  93. var _ esv1beta1.SecretsClient = &client{}
  94. var _ esv1beta1.Provider = &connector{}
  95. type Auth interface {
  96. Login(ctx context.Context, authMethod vault.AuthMethod) (*vault.Secret, error)
  97. }
  98. type Token interface {
  99. RevokeSelfWithContext(ctx context.Context, token string) error
  100. LookupSelfWithContext(ctx context.Context) (*vault.Secret, error)
  101. }
  102. type Logical interface {
  103. ReadWithDataWithContext(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error)
  104. ListWithContext(ctx context.Context, path string) (*vault.Secret, error)
  105. WriteWithContext(ctx context.Context, path string, data map[string]interface{}) (*vault.Secret, error)
  106. }
  107. type Client interface {
  108. SetToken(v string)
  109. Token() string
  110. ClearToken()
  111. Auth() Auth
  112. Logical() Logical
  113. AuthToken() Token
  114. SetNamespace(namespace string)
  115. AddHeader(key, value string)
  116. }
  117. type VClient struct {
  118. setToken func(v string)
  119. token func() string
  120. clearToken func()
  121. auth Auth
  122. logical Logical
  123. authToken Token
  124. setNamespace func(namespace string)
  125. addHeader func(key, value string)
  126. }
  127. func (v VClient) AddHeader(key, value string) {
  128. v.addHeader(key, value)
  129. }
  130. func (v VClient) SetNamespace(namespace string) {
  131. v.setNamespace(namespace)
  132. }
  133. func (v VClient) ClearToken() {
  134. v.clearToken()
  135. }
  136. func (v VClient) Token() string {
  137. return v.token()
  138. }
  139. func (v VClient) SetToken(token string) {
  140. v.setToken(token)
  141. }
  142. func (v VClient) Auth() Auth {
  143. return v.auth
  144. }
  145. func (v VClient) AuthToken() Token {
  146. return v.authToken
  147. }
  148. func (v VClient) Logical() Logical {
  149. return v.logical
  150. }
  151. type client struct {
  152. kube kclient.Client
  153. store *esv1beta1.VaultProvider
  154. log logr.Logger
  155. corev1 typedcorev1.CoreV1Interface
  156. client Client
  157. auth Auth
  158. logical Logical
  159. token Token
  160. namespace string
  161. storeKind string
  162. }
  163. func init() {
  164. esv1beta1.Register(&connector{
  165. newVaultClient: newVaultClient,
  166. }, &esv1beta1.SecretStoreProvider{
  167. Vault: &esv1beta1.VaultProvider{},
  168. })
  169. }
  170. func newVaultClient(c *vault.Config) (Client, error) {
  171. cl, err := vault.NewClient(c)
  172. if err != nil {
  173. return nil, err
  174. }
  175. auth := cl.Auth()
  176. logical := cl.Logical()
  177. token := cl.Auth().Token()
  178. out := VClient{
  179. setToken: cl.SetToken,
  180. token: cl.Token,
  181. clearToken: cl.ClearToken,
  182. auth: auth,
  183. authToken: token,
  184. logical: logical,
  185. setNamespace: cl.SetNamespace,
  186. addHeader: cl.AddHeader,
  187. }
  188. return out, nil
  189. }
  190. type connector struct {
  191. newVaultClient func(c *vault.Config) (Client, error)
  192. }
  193. func (c *connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
  194. // controller-runtime/client does not support TokenRequest or other subresource APIs
  195. // so we need to construct our own client and use it to fetch tokens
  196. // (for Kubernetes service account token auth)
  197. restCfg, err := ctrlcfg.GetConfig()
  198. if err != nil {
  199. return nil, err
  200. }
  201. clientset, err := kubernetes.NewForConfig(restCfg)
  202. if err != nil {
  203. return nil, err
  204. }
  205. return c.newClient(ctx, store, kube, clientset.CoreV1(), namespace)
  206. }
  207. func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) {
  208. storeSpec := store.GetSpec()
  209. if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Vault == nil {
  210. return nil, errors.New(errVaultStore)
  211. }
  212. vaultSpec := storeSpec.Provider.Vault
  213. vStore := &client{
  214. kube: kube,
  215. corev1: corev1,
  216. store: vaultSpec,
  217. log: ctrl.Log.WithName("provider").WithName("vault"),
  218. namespace: namespace,
  219. storeKind: store.GetObjectKind().GroupVersionKind().Kind,
  220. }
  221. cfg, err := vStore.newConfig()
  222. if err != nil {
  223. return nil, err
  224. }
  225. client, err := c.newVaultClient(cfg)
  226. if err != nil {
  227. return nil, fmt.Errorf(errVaultClient, err)
  228. }
  229. if vaultSpec.Namespace != nil {
  230. client.SetNamespace(*vaultSpec.Namespace)
  231. }
  232. if vaultSpec.ReadYourWrites && vaultSpec.ForwardInconsistent {
  233. client.AddHeader("X-Vault-Inconsistent", "forward-active-node")
  234. }
  235. vStore.client = client
  236. vStore.auth = client.Auth()
  237. vStore.logical = client.Logical()
  238. vStore.token = client.AuthToken()
  239. // allow SecretStore controller validation to pass
  240. // when using referent namespace.
  241. if vStore.storeKind == esv1beta1.ClusterSecretStoreKind && vStore.namespace == "" && isReferentSpec(vaultSpec) {
  242. return vStore, nil
  243. }
  244. if err := vStore.setAuth(ctx, cfg); err != nil {
  245. return nil, err
  246. }
  247. return vStore, nil
  248. }
  249. func (c *connector) ValidateStore(store esv1beta1.GenericStore) error {
  250. if store == nil {
  251. return fmt.Errorf(errInvalidStore)
  252. }
  253. spc := store.GetSpec()
  254. if spc == nil {
  255. return fmt.Errorf(errInvalidStoreSpec)
  256. }
  257. if spc.Provider == nil {
  258. return fmt.Errorf(errInvalidStoreProv)
  259. }
  260. p := spc.Provider.Vault
  261. if p == nil {
  262. return fmt.Errorf(errInvalidVaultProv)
  263. }
  264. if p.Auth.AppRole != nil {
  265. if err := utils.ValidateReferentSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
  266. return fmt.Errorf(errInvalidAppRoleSec, err)
  267. }
  268. }
  269. if p.Auth.Cert != nil {
  270. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
  271. return fmt.Errorf(errInvalidClientCert, err)
  272. }
  273. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
  274. return fmt.Errorf(errInvalidCertSec, err)
  275. }
  276. }
  277. if p.Auth.Jwt != nil {
  278. if p.Auth.Jwt.SecretRef != nil {
  279. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
  280. return fmt.Errorf(errInvalidJwtSec, err)
  281. }
  282. } else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
  283. if err := utils.ValidateReferentServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
  284. return fmt.Errorf(errInvalidJwtK8sSA, err)
  285. }
  286. } else {
  287. return fmt.Errorf(errJwtNoTokenSource)
  288. }
  289. }
  290. if p.Auth.Kubernetes != nil {
  291. if p.Auth.Kubernetes.ServiceAccountRef != nil {
  292. if err := utils.ValidateReferentServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
  293. return fmt.Errorf(errInvalidKubeSA, err)
  294. }
  295. }
  296. if p.Auth.Kubernetes.SecretRef != nil {
  297. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
  298. return fmt.Errorf(errInvalidKubeSec, err)
  299. }
  300. }
  301. }
  302. if p.Auth.Ldap != nil {
  303. if err := utils.ValidateReferentSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
  304. return fmt.Errorf(errInvalidLdapSec, err)
  305. }
  306. }
  307. if p.Auth.TokenSecretRef != nil {
  308. if err := utils.ValidateReferentSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
  309. return fmt.Errorf(errInvalidTokenRef, err)
  310. }
  311. }
  312. return nil
  313. }
  314. // Empty GetAllSecrets.
  315. // GetAllSecrets
  316. // First load all secrets from secretStore path configuration.
  317. // Then, gets secrets from a matching name or matching custom_metadata.
  318. func (v *client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  319. if v.store.Version == esv1beta1.VaultKVStoreV1 {
  320. return nil, errors.New(errUnsupportedKvVersion)
  321. }
  322. searchPath := ""
  323. if ref.Path != nil {
  324. searchPath = *ref.Path + "/"
  325. }
  326. potentialSecrets, err := v.listSecrets(ctx, searchPath)
  327. if err != nil {
  328. return nil, err
  329. }
  330. if ref.Name != nil {
  331. return v.findSecretsFromName(ctx, potentialSecrets, *ref.Name)
  332. }
  333. return v.findSecretsFromTags(ctx, potentialSecrets, ref.Tags)
  334. }
  335. func (v *client) findSecretsFromTags(ctx context.Context, candidates []string, tags map[string]string) (map[string][]byte, error) {
  336. secrets := make(map[string][]byte)
  337. for _, name := range candidates {
  338. match := true
  339. metadata, err := v.readSecretMetadata(ctx, name)
  340. if err != nil {
  341. return nil, err
  342. }
  343. for tk, tv := range tags {
  344. p, ok := metadata[tk]
  345. if !ok || p != tv {
  346. match = false
  347. break
  348. }
  349. }
  350. if match {
  351. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  352. if err != nil {
  353. return nil, err
  354. }
  355. if secret != nil {
  356. secrets[name] = secret
  357. }
  358. }
  359. }
  360. return secrets, nil
  361. }
  362. func (v *client) findSecretsFromName(ctx context.Context, candidates []string, ref esv1beta1.FindName) (map[string][]byte, error) {
  363. secrets := make(map[string][]byte)
  364. matcher, err := find.New(ref)
  365. if err != nil {
  366. return nil, err
  367. }
  368. for _, name := range candidates {
  369. ok := matcher.MatchName(name)
  370. if ok {
  371. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  372. if err != nil {
  373. return nil, err
  374. }
  375. if secret != nil {
  376. secrets[name] = secret
  377. }
  378. }
  379. }
  380. return secrets, nil
  381. }
  382. func (v *client) listSecrets(ctx context.Context, path string) ([]string, error) {
  383. secrets := make([]string, 0)
  384. url, err := v.buildMetadataPath(path)
  385. if err != nil {
  386. return nil, err
  387. }
  388. secret, err := v.logical.ListWithContext(ctx, url)
  389. if err != nil {
  390. return nil, fmt.Errorf(errReadSecret, err)
  391. }
  392. if secret == nil {
  393. return nil, fmt.Errorf("provided path %v does not contain any secrets", url)
  394. }
  395. t, ok := secret.Data["keys"]
  396. if !ok {
  397. return nil, nil
  398. }
  399. paths := t.([]interface{})
  400. for _, p := range paths {
  401. strPath := p.(string)
  402. fullPath := path + strPath // because path always ends with a /
  403. if path == "" {
  404. fullPath = strPath
  405. }
  406. // Recurrently find secrets
  407. if !strings.HasSuffix(p.(string), "/") {
  408. secrets = append(secrets, fullPath)
  409. } else {
  410. partial, err := v.listSecrets(ctx, fullPath)
  411. if err != nil {
  412. return nil, err
  413. }
  414. secrets = append(secrets, partial...)
  415. }
  416. }
  417. return secrets, nil
  418. }
  419. func (v *client) readSecretMetadata(ctx context.Context, path string) (map[string]string, error) {
  420. metadata := make(map[string]string)
  421. url, err := v.buildMetadataPath(path)
  422. if err != nil {
  423. return nil, err
  424. }
  425. secret, err := v.logical.ReadWithDataWithContext(ctx, url, nil)
  426. if err != nil {
  427. return nil, fmt.Errorf(errReadSecret, err)
  428. }
  429. if secret == nil {
  430. return nil, errors.New(errNotFound)
  431. }
  432. t, ok := secret.Data["custom_metadata"]
  433. if !ok {
  434. return nil, nil
  435. }
  436. d, ok := t.(map[string]interface{})
  437. if !ok {
  438. return metadata, nil
  439. }
  440. for k, v := range d {
  441. metadata[k] = v.(string)
  442. }
  443. return metadata, nil
  444. }
  445. // GetSecret supports two types:
  446. // 1. get the full secret as json-encoded value
  447. // by leaving the ref.Property empty.
  448. // 2. get a key from the secret.
  449. // Nested values are supported by specifying a gjson expression
  450. func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  451. data, err := v.readSecret(ctx, ref.Key, ref.Version)
  452. if err != nil {
  453. return nil, err
  454. }
  455. // Return nil if secret value is null
  456. if data == nil {
  457. return nil, nil
  458. }
  459. jsonStr, err := json.Marshal(data)
  460. if err != nil {
  461. return nil, err
  462. }
  463. // (1): return raw json if no property is defined
  464. if ref.Property == "" {
  465. return jsonStr, nil
  466. }
  467. // For backwards compatibility we want the
  468. // actual keys to take precedence over gjson syntax
  469. // (2): extract key from secret with property
  470. if _, ok := data[ref.Property]; ok {
  471. return getTypedKey(data, ref.Property)
  472. }
  473. // (3): extract key from secret using gjson
  474. val := gjson.Get(string(jsonStr), ref.Property)
  475. if !val.Exists() {
  476. return nil, fmt.Errorf(errSecretKeyFmt, ref.Property)
  477. }
  478. return []byte(val.String()), nil
  479. }
  480. // GetSecretMap supports two modes of operation:
  481. // 1. get the full secret from the vault data payload (by leaving .property empty).
  482. // 2. extract key/value pairs from a (nested) object.
  483. func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  484. data, err := v.GetSecret(ctx, ref)
  485. if err != nil {
  486. return nil, err
  487. }
  488. var secretData map[string]interface{}
  489. err = json.Unmarshal(data, &secretData)
  490. if err != nil {
  491. return nil, err
  492. }
  493. byteMap := make(map[string][]byte, len(secretData))
  494. for k := range secretData {
  495. byteMap[k], err = getTypedKey(secretData, k)
  496. if err != nil {
  497. return nil, err
  498. }
  499. }
  500. return byteMap, nil
  501. }
  502. func getTypedKey(data map[string]interface{}, key string) ([]byte, error) {
  503. v, ok := data[key]
  504. if !ok {
  505. return nil, fmt.Errorf(errUnexpectedKey, key)
  506. }
  507. switch t := v.(type) {
  508. case string:
  509. return []byte(t), nil
  510. case map[string]interface{}:
  511. return json.Marshal(t)
  512. case []byte:
  513. return t, nil
  514. // also covers int and float32 due to json.Marshal
  515. case float64:
  516. return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil
  517. case bool:
  518. return []byte(strconv.FormatBool(t)), nil
  519. case nil:
  520. return []byte(nil), nil
  521. default:
  522. return nil, errors.New(errSecretFormat)
  523. }
  524. }
  525. func (v *client) Close(ctx context.Context) error {
  526. // Revoke the token if we have one set and it wasn't sourced from a TokenSecretRef
  527. if v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil {
  528. revoke, err := checkToken(ctx, v)
  529. if err != nil {
  530. return fmt.Errorf(errVaultRevokeToken, err)
  531. }
  532. if revoke {
  533. err = v.token.RevokeSelfWithContext(ctx, v.client.Token())
  534. if err != nil {
  535. return fmt.Errorf(errVaultRevokeToken, err)
  536. }
  537. v.client.ClearToken()
  538. }
  539. }
  540. return nil
  541. }
  542. func isReferentSpec(prov *esv1beta1.VaultProvider) bool {
  543. if prov.Auth.TokenSecretRef != nil && prov.Auth.TokenSecretRef.Namespace == nil {
  544. return true
  545. }
  546. if prov.Auth.AppRole != nil && prov.Auth.AppRole.SecretRef.Namespace == nil {
  547. return true
  548. }
  549. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.SecretRef != nil && prov.Auth.Kubernetes.SecretRef.Namespace == nil {
  550. return true
  551. }
  552. if prov.Auth.Kubernetes != nil && prov.Auth.Kubernetes.ServiceAccountRef != nil && prov.Auth.Kubernetes.ServiceAccountRef.Namespace == nil {
  553. return true
  554. }
  555. if prov.Auth.Ldap != nil && prov.Auth.Ldap.SecretRef.Namespace == nil {
  556. return true
  557. }
  558. if prov.Auth.Jwt != nil && prov.Auth.Jwt.SecretRef != nil && prov.Auth.Jwt.SecretRef.Namespace == nil {
  559. return true
  560. }
  561. if prov.Auth.Jwt != nil && prov.Auth.Jwt.KubernetesServiceAccountToken != nil && prov.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef.Namespace == nil {
  562. return true
  563. }
  564. if prov.Auth.Cert != nil && prov.Auth.Cert.SecretRef.Namespace == nil {
  565. return true
  566. }
  567. return false
  568. }
  569. func (v *client) Validate() (esv1beta1.ValidationResult, error) {
  570. // when using referent namespace we can not validate the token
  571. // because the namespace is not known yet when Validate() is called
  572. // from the SecretStore controller.
  573. if v.storeKind == esv1beta1.ClusterSecretStoreKind && isReferentSpec(v.store) {
  574. return esv1beta1.ValidationResultUnknown, nil
  575. }
  576. _, err := checkToken(context.Background(), v)
  577. if err != nil {
  578. return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
  579. }
  580. return esv1beta1.ValidationResultReady, nil
  581. }
  582. func (v *client) buildMetadataPath(path string) (string, error) {
  583. var url string
  584. if v.store.Path == nil && !strings.Contains(path, "data") {
  585. return "", fmt.Errorf(errPathInvalid)
  586. }
  587. if v.store.Path == nil {
  588. path = strings.Replace(path, "data", "metadata", 1)
  589. url = path
  590. } else {
  591. url = fmt.Sprintf("%s/metadata/%s", *v.store.Path, path)
  592. }
  593. return url, nil
  594. }
  595. func (v *client) buildPath(path string) string {
  596. optionalMount := v.store.Path
  597. origPath := strings.Split(path, "/")
  598. newPath := make([]string, 0)
  599. cursor := 0
  600. if optionalMount != nil && origPath[0] != *optionalMount {
  601. // Default case before path was optional
  602. // Ensure that the requested path includes the SecretStores paths as prefix
  603. newPath = append(newPath, *optionalMount)
  604. } else {
  605. newPath = append(newPath, origPath[cursor])
  606. cursor++
  607. }
  608. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  609. // Add the required `data` part of the URL for the v2 API
  610. if len(origPath) < 2 || origPath[1] != "data" {
  611. newPath = append(newPath, "data")
  612. }
  613. }
  614. newPath = append(newPath, origPath[cursor:]...)
  615. returnPath := strings.Join(newPath, "/")
  616. return returnPath
  617. }
  618. func (v *client) readSecret(ctx context.Context, path, version string) (map[string]interface{}, error) {
  619. dataPath := v.buildPath(path)
  620. // path formated according to vault docs for v1 and v2 API
  621. // v1: https://www.vaultproject.io/api-docs/secret/kv/kv-v1#read-secret
  622. // v2: https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  623. var params map[string][]string
  624. if version != "" {
  625. params = make(map[string][]string)
  626. params["version"] = []string{version}
  627. }
  628. vaultSecret, err := v.logical.ReadWithDataWithContext(ctx, dataPath, params)
  629. if err != nil {
  630. return nil, fmt.Errorf(errReadSecret, err)
  631. }
  632. if vaultSecret == nil {
  633. return nil, errors.New(errNotFound)
  634. }
  635. secretData := vaultSecret.Data
  636. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  637. // Vault KV2 has data embedded within sub-field
  638. // reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  639. dataInt, ok := vaultSecret.Data["data"]
  640. if !ok {
  641. return nil, errors.New(errDataField)
  642. }
  643. if dataInt == nil {
  644. return nil, nil
  645. }
  646. secretData, ok = dataInt.(map[string]interface{})
  647. if !ok {
  648. return nil, errors.New(errJSONUnmarshall)
  649. }
  650. }
  651. return secretData, nil
  652. }
  653. func (v *client) newConfig() (*vault.Config, error) {
  654. cfg := vault.DefaultConfig()
  655. cfg.Address = v.store.Server
  656. // In a controller-runtime context, we rely on the reconciliation process for retrying
  657. cfg.MaxRetries = 0
  658. if len(v.store.CABundle) == 0 && v.store.CAProvider == nil {
  659. return cfg, nil
  660. }
  661. caCertPool := x509.NewCertPool()
  662. if len(v.store.CABundle) > 0 {
  663. ok := caCertPool.AppendCertsFromPEM(v.store.CABundle)
  664. if !ok {
  665. return nil, errors.New(errVaultCert)
  666. }
  667. }
  668. if v.store.CAProvider != nil && v.storeKind == esv1beta1.ClusterSecretStoreKind && v.store.CAProvider.Namespace == nil {
  669. return nil, errors.New(errCANamespace)
  670. }
  671. if v.store.CAProvider != nil {
  672. var cert []byte
  673. var err error
  674. switch v.store.CAProvider.Type {
  675. case esv1beta1.CAProviderTypeSecret:
  676. cert, err = getCertFromSecret(v)
  677. case esv1beta1.CAProviderTypeConfigMap:
  678. cert, err = getCertFromConfigMap(v)
  679. default:
  680. return nil, errors.New(errUnknownCAProvider)
  681. }
  682. if err != nil {
  683. return nil, err
  684. }
  685. ok := caCertPool.AppendCertsFromPEM(cert)
  686. if !ok {
  687. return nil, errors.New(errVaultCert)
  688. }
  689. }
  690. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  691. transport.TLSClientConfig.RootCAs = caCertPool
  692. }
  693. // If either read-after-write consistency feature is enabled, enable ReadYourWrites
  694. cfg.ReadYourWrites = v.store.ReadYourWrites || v.store.ForwardInconsistent
  695. return cfg, nil
  696. }
  697. func getCertFromSecret(v *client) ([]byte, error) {
  698. secretRef := esmeta.SecretKeySelector{
  699. Name: v.store.CAProvider.Name,
  700. Key: v.store.CAProvider.Key,
  701. }
  702. if v.store.CAProvider.Namespace != nil {
  703. secretRef.Namespace = v.store.CAProvider.Namespace
  704. }
  705. ctx := context.Background()
  706. res, err := v.secretKeyRef(ctx, &secretRef)
  707. if err != nil {
  708. return nil, fmt.Errorf(errVaultCert, err)
  709. }
  710. return []byte(res), nil
  711. }
  712. func getCertFromConfigMap(v *client) ([]byte, error) {
  713. objKey := types.NamespacedName{
  714. Name: v.store.CAProvider.Name,
  715. }
  716. if v.store.CAProvider.Namespace != nil {
  717. objKey.Namespace = *v.store.CAProvider.Namespace
  718. }
  719. configMapRef := &corev1.ConfigMap{}
  720. ctx := context.Background()
  721. err := v.kube.Get(ctx, objKey, configMapRef)
  722. if err != nil {
  723. return nil, fmt.Errorf(errVaultCert, err)
  724. }
  725. val, ok := configMapRef.Data[v.store.CAProvider.Key]
  726. if !ok {
  727. return nil, fmt.Errorf(errConfigMapFmt, v.store.CAProvider.Key)
  728. }
  729. return []byte(val), nil
  730. }
  731. func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
  732. tokenExists, err := setSecretKeyToken(ctx, v)
  733. if tokenExists {
  734. return err
  735. }
  736. tokenExists, err = setAppRoleToken(ctx, v)
  737. if tokenExists {
  738. return err
  739. }
  740. tokenExists, err = setKubernetesAuthToken(ctx, v)
  741. if tokenExists {
  742. return err
  743. }
  744. tokenExists, err = setLdapAuthToken(ctx, v)
  745. if tokenExists {
  746. return err
  747. }
  748. tokenExists, err = setJwtAuthToken(ctx, v)
  749. if tokenExists {
  750. return err
  751. }
  752. tokenExists, err = setCertAuthToken(ctx, v, cfg)
  753. if tokenExists {
  754. return err
  755. }
  756. return errors.New(errAuthFormat)
  757. }
  758. func setAppRoleToken(ctx context.Context, v *client) (bool, error) {
  759. tokenRef := v.store.Auth.TokenSecretRef
  760. if tokenRef != nil {
  761. token, err := v.secretKeyRef(ctx, tokenRef)
  762. if err != nil {
  763. return true, err
  764. }
  765. v.client.SetToken(token)
  766. return true, nil
  767. }
  768. return false, nil
  769. }
  770. func setSecretKeyToken(ctx context.Context, v *client) (bool, error) {
  771. appRole := v.store.Auth.AppRole
  772. if appRole != nil {
  773. err := v.requestTokenWithAppRoleRef(ctx, appRole)
  774. if err != nil {
  775. return true, err
  776. }
  777. return true, nil
  778. }
  779. return false, nil
  780. }
  781. func setKubernetesAuthToken(ctx context.Context, v *client) (bool, error) {
  782. kubernetesAuth := v.store.Auth.Kubernetes
  783. if kubernetesAuth != nil {
  784. err := v.requestTokenWithKubernetesAuth(ctx, kubernetesAuth)
  785. if err != nil {
  786. return true, err
  787. }
  788. return true, nil
  789. }
  790. return false, nil
  791. }
  792. func setLdapAuthToken(ctx context.Context, v *client) (bool, error) {
  793. ldapAuth := v.store.Auth.Ldap
  794. if ldapAuth != nil {
  795. err := v.requestTokenWithLdapAuth(ctx, ldapAuth)
  796. if err != nil {
  797. return true, err
  798. }
  799. return true, nil
  800. }
  801. return false, nil
  802. }
  803. func setJwtAuthToken(ctx context.Context, v *client) (bool, error) {
  804. jwtAuth := v.store.Auth.Jwt
  805. if jwtAuth != nil {
  806. err := v.requestTokenWithJwtAuth(ctx, jwtAuth)
  807. if err != nil {
  808. return true, err
  809. }
  810. return true, nil
  811. }
  812. return false, nil
  813. }
  814. func setCertAuthToken(ctx context.Context, v *client, cfg *vault.Config) (bool, error) {
  815. certAuth := v.store.Auth.Cert
  816. if certAuth != nil {
  817. err := v.requestTokenWithCertAuth(ctx, certAuth, cfg)
  818. if err != nil {
  819. return true, err
  820. }
  821. return true, nil
  822. }
  823. return false, nil
  824. }
  825. func (v *client) secretKeyRefForServiceAccount(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) (string, error) {
  826. serviceAccount := &corev1.ServiceAccount{}
  827. ref := types.NamespacedName{
  828. Namespace: v.namespace,
  829. Name: serviceAccountRef.Name,
  830. }
  831. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  832. (serviceAccountRef.Namespace != nil) {
  833. ref.Namespace = *serviceAccountRef.Namespace
  834. }
  835. err := v.kube.Get(ctx, ref, serviceAccount)
  836. if err != nil {
  837. return "", fmt.Errorf(errGetKubeSA, ref.Name, err)
  838. }
  839. if len(serviceAccount.Secrets) == 0 {
  840. return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
  841. }
  842. for _, tokenRef := range serviceAccount.Secrets {
  843. retval, err := v.secretKeyRef(ctx, &esmeta.SecretKeySelector{
  844. Name: tokenRef.Name,
  845. Namespace: &ref.Namespace,
  846. Key: "token",
  847. })
  848. if err != nil {
  849. continue
  850. }
  851. return retval, nil
  852. }
  853. return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
  854. }
  855. func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
  856. secret := &corev1.Secret{}
  857. ref := types.NamespacedName{
  858. Namespace: v.namespace,
  859. Name: secretRef.Name,
  860. }
  861. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  862. (secretRef.Namespace != nil) {
  863. ref.Namespace = *secretRef.Namespace
  864. }
  865. err := v.kube.Get(ctx, ref, secret)
  866. if err != nil {
  867. return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
  868. }
  869. keyBytes, ok := secret.Data[secretRef.Key]
  870. if !ok {
  871. return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
  872. }
  873. value := string(keyBytes)
  874. valueStr := strings.TrimSpace(value)
  875. return valueStr, nil
  876. }
  877. func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, additionalAud []string, expirationSeconds int64) (string, error) {
  878. audiences := serviceAccountRef.Audiences
  879. if len(additionalAud) > 0 {
  880. audiences = append(audiences, additionalAud...)
  881. }
  882. tokenRequest := &authenticationv1.TokenRequest{
  883. ObjectMeta: metav1.ObjectMeta{
  884. Namespace: v.namespace,
  885. },
  886. Spec: authenticationv1.TokenRequestSpec{
  887. Audiences: audiences,
  888. ExpirationSeconds: &expirationSeconds,
  889. },
  890. }
  891. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  892. (serviceAccountRef.Namespace != nil) {
  893. tokenRequest.Namespace = *serviceAccountRef.Namespace
  894. }
  895. tokenResponse, err := v.corev1.ServiceAccounts(tokenRequest.Namespace).CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
  896. if err != nil {
  897. return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
  898. }
  899. return tokenResponse.Status.Token, nil
  900. }
  901. // checkToken does a lookup and checks if the provided token exists.
  902. func checkToken(ctx context.Context, vStore *client) (bool, error) {
  903. // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self
  904. resp, err := vStore.token.LookupSelfWithContext(ctx)
  905. if err != nil {
  906. return false, err
  907. }
  908. t, ok := resp.Data["type"]
  909. if !ok {
  910. return false, fmt.Errorf("could not assert token type")
  911. }
  912. tokenType := t.(string)
  913. if tokenType == "batch" {
  914. return false, nil
  915. }
  916. return true, nil
  917. }
  918. func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1beta1.VaultAppRole) error {
  919. roleID := strings.TrimSpace(appRole.RoleID)
  920. secretID, err := v.secretKeyRef(ctx, &appRole.SecretRef)
  921. if err != nil {
  922. return err
  923. }
  924. secret := approle.SecretID{FromString: secretID}
  925. appRoleClient, err := approle.NewAppRoleAuth(roleID, &secret, approle.WithMountPath(appRole.Path))
  926. if err != nil {
  927. return err
  928. }
  929. _, err = v.auth.Login(ctx, appRoleClient)
  930. if err != nil {
  931. return err
  932. }
  933. return nil
  934. }
  935. func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesAuth *esv1beta1.VaultKubernetesAuth) error {
  936. jwtString, err := getJwtString(ctx, v, kubernetesAuth)
  937. if err != nil {
  938. return err
  939. }
  940. k, err := authkubernetes.NewKubernetesAuth(kubernetesAuth.Role, authkubernetes.WithServiceAccountToken(jwtString), authkubernetes.WithMountPath(kubernetesAuth.Path))
  941. if err != nil {
  942. return err
  943. }
  944. _, err = v.auth.Login(ctx, k)
  945. if err != nil {
  946. return err
  947. }
  948. return nil
  949. }
  950. func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.VaultKubernetesAuth) (string, error) {
  951. if kubernetesAuth.ServiceAccountRef != nil {
  952. // Kubernetes <v1.24 fetch token via ServiceAccount.Secrets[]
  953. // this behavior was removed in v1.24 and we must use TokenRequest API (see below)
  954. jwt, err := v.secretKeyRefForServiceAccount(ctx, kubernetesAuth.ServiceAccountRef)
  955. if jwt != "" {
  956. return jwt, err
  957. }
  958. if err != nil {
  959. v.log.V(1).Info("unable to fetch jwt from service account secret")
  960. }
  961. // Kubernetes >=v1.24: fetch token via TokenRequest API
  962. // note: this is a massive change from vault perspective: the `iss` claim will very likely change.
  963. // Vault 1.9 deprecated issuer validation by default, and authentication with Vault clusters <1.9 will likely fail.
  964. jwt, err = v.serviceAccountToken(ctx, *kubernetesAuth.ServiceAccountRef, nil, 600)
  965. if err != nil {
  966. return "", err
  967. }
  968. return jwt, nil
  969. } else if kubernetesAuth.SecretRef != nil {
  970. tokenRef := kubernetesAuth.SecretRef
  971. if tokenRef.Key == "" {
  972. tokenRef = kubernetesAuth.SecretRef.DeepCopy()
  973. tokenRef.Key = "token"
  974. }
  975. jwt, err := v.secretKeyRef(ctx, tokenRef)
  976. if err != nil {
  977. return "", err
  978. }
  979. return jwt, nil
  980. } else {
  981. // Kubernetes authentication is specified, but without a referenced
  982. // Kubernetes secret. We check if the file path for in-cluster service account
  983. // exists and attempt to use the token for Vault Kubernetes auth.
  984. if _, err := os.Stat(serviceAccTokenPath); err != nil {
  985. return "", fmt.Errorf(errServiceAccount, err)
  986. }
  987. jwtByte, err := os.ReadFile(serviceAccTokenPath)
  988. if err != nil {
  989. return "", fmt.Errorf(errServiceAccount, err)
  990. }
  991. return string(jwtByte), nil
  992. }
  993. }
  994. func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1beta1.VaultLdapAuth) error {
  995. username := strings.TrimSpace(ldapAuth.Username)
  996. password, err := v.secretKeyRef(ctx, &ldapAuth.SecretRef)
  997. if err != nil {
  998. return err
  999. }
  1000. pass := authldap.Password{FromString: password}
  1001. l, err := authldap.NewLDAPAuth(username, &pass, authldap.WithMountPath(ldapAuth.Path))
  1002. if err != nil {
  1003. return err
  1004. }
  1005. _, err = v.auth.Login(ctx, l)
  1006. if err != nil {
  1007. return err
  1008. }
  1009. return nil
  1010. }
  1011. func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1.VaultJwtAuth) error {
  1012. role := strings.TrimSpace(jwtAuth.Role)
  1013. var jwt string
  1014. var err error
  1015. if jwtAuth.SecretRef != nil {
  1016. jwt, err = v.secretKeyRef(ctx, jwtAuth.SecretRef)
  1017. } else if k8sServiceAccountToken := jwtAuth.KubernetesServiceAccountToken; k8sServiceAccountToken != nil {
  1018. audiences := k8sServiceAccountToken.Audiences
  1019. if audiences == nil {
  1020. audiences = &[]string{"vault"}
  1021. }
  1022. expirationSeconds := k8sServiceAccountToken.ExpirationSeconds
  1023. if expirationSeconds == nil {
  1024. tmp := int64(600)
  1025. expirationSeconds = &tmp
  1026. }
  1027. jwt, err = v.serviceAccountToken(ctx, k8sServiceAccountToken.ServiceAccountRef, *audiences, *expirationSeconds)
  1028. } else {
  1029. err = fmt.Errorf(errJwtNoTokenSource)
  1030. }
  1031. if err != nil {
  1032. return err
  1033. }
  1034. parameters := map[string]interface{}{
  1035. "role": role,
  1036. "jwt": jwt,
  1037. }
  1038. url := strings.Join([]string{"auth", jwtAuth.Path, "login"}, "/")
  1039. vaultResult, err := v.logical.WriteWithContext(ctx, url, parameters)
  1040. if err != nil {
  1041. return err
  1042. }
  1043. token, err := vaultResult.TokenID()
  1044. if err != nil {
  1045. return fmt.Errorf(errVaultToken, err)
  1046. }
  1047. v.client.SetToken(token)
  1048. return nil
  1049. }
  1050. func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1beta1.VaultCertAuth, cfg *vault.Config) error {
  1051. clientKey, err := v.secretKeyRef(ctx, &certAuth.SecretRef)
  1052. if err != nil {
  1053. return err
  1054. }
  1055. clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
  1056. if err != nil {
  1057. return err
  1058. }
  1059. cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
  1060. if err != nil {
  1061. return fmt.Errorf(errClientTLSAuth, err)
  1062. }
  1063. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  1064. transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
  1065. }
  1066. url := strings.Join([]string{"auth", "cert", "login"}, "/")
  1067. vaultResult, err := v.logical.WriteWithContext(ctx, url, nil)
  1068. if err != nil {
  1069. return fmt.Errorf(errVaultRequest, err)
  1070. }
  1071. token, err := vaultResult.TokenID()
  1072. if err != nil {
  1073. return fmt.Errorf(errVaultToken, err)
  1074. }
  1075. v.client.SetToken(token)
  1076. return nil
  1077. }