vault.go 21 KB

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