vault.go 22 KB

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