vault.go 25 KB

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