vault.go 21 KB

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