vault.go 30 KB

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