vault.go 22 KB

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