vault.go 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123
  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. "net/http"
  21. "os"
  22. "strconv"
  23. "strings"
  24. "github.com/go-logr/logr"
  25. vault "github.com/hashicorp/vault/api"
  26. approle "github.com/hashicorp/vault/api/auth/approle"
  27. authkubernetes "github.com/hashicorp/vault/api/auth/kubernetes"
  28. authldap "github.com/hashicorp/vault/api/auth/ldap"
  29. "github.com/tidwall/gjson"
  30. authenticationv1 "k8s.io/api/authentication/v1"
  31. corev1 "k8s.io/api/core/v1"
  32. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  33. "k8s.io/apimachinery/pkg/types"
  34. "k8s.io/client-go/kubernetes"
  35. typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  36. ctrl "sigs.k8s.io/controller-runtime"
  37. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  38. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  39. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  40. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  41. "github.com/external-secrets/external-secrets/pkg/find"
  42. "github.com/external-secrets/external-secrets/pkg/utils"
  43. )
  44. var (
  45. _ esv1beta1.Provider = &connector{}
  46. _ esv1beta1.SecretsClient = &client{}
  47. )
  48. const (
  49. serviceAccTokenPath = "/var/run/secrets/kubernetes.io/serviceaccount/token"
  50. errVaultStore = "received invalid Vault SecretStore resource: %w"
  51. errVaultClient = "cannot setup new vault client: %w"
  52. errVaultCert = "cannot set Vault CA certificate: %w"
  53. errReadSecret = "cannot read secret data from Vault: %w"
  54. errAuthFormat = "cannot initialize Vault client: no valid auth method specified"
  55. errInvalidCredentials = "invalid vault credentials: %w"
  56. errDataField = "failed to find data field"
  57. errJSONUnmarshall = "failed to unmarshall JSON"
  58. errPathInvalid = "provided Path isn't a valid kv v2 path"
  59. errSecretFormat = "secret data not in expected format"
  60. errUnexpectedKey = "unexpected key in data: %s"
  61. errVaultToken = "cannot parse Vault authentication token: %w"
  62. errVaultRequest = "error from Vault request: %w"
  63. errServiceAccount = "cannot read Kubernetes service account token from file system: %w"
  64. errJwtNoTokenSource = "neither `secretRef` nor `kubernetesServiceAccountToken` was supplied as token source for jwt authentication"
  65. errUnsupportedKvVersion = "cannot perform find operations with kv version v1"
  66. errGetKubeSA = "cannot get Kubernetes service account %q: %w"
  67. errGetKubeSASecrets = "cannot find secrets bound to service account: %q"
  68. errGetKubeSANoToken = "cannot find token in secrets bound to service account: %q"
  69. errGetKubeSATokenRequest = "cannot request Kubernetes service account token for service account %q: %w"
  70. errGetKubeSecret = "cannot get Kubernetes secret %q: %w"
  71. errSecretKeyFmt = "cannot find secret data for key: %q"
  72. errConfigMapFmt = "cannot find config map data for key: %q"
  73. errClientTLSAuth = "error from Client TLS Auth: %q"
  74. errVaultRevokeToken = "error while revoking token: %w"
  75. errUnknownCAProvider = "unknown caProvider type given"
  76. errCANamespace = "cannot read secret for CAProvider due to missing namespace on kind ClusterSecretStore"
  77. errInvalidStore = "invalid store"
  78. errInvalidStoreSpec = "invalid store spec"
  79. errInvalidStoreProv = "invalid store provider"
  80. errInvalidVaultProv = "invalid vault provider"
  81. errInvalidAppRoleSec = "invalid Auth.AppRole.SecretRef: %w"
  82. errInvalidClientCert = "invalid Auth.Cert.ClientCert: %w"
  83. errInvalidCertSec = "invalid Auth.Cert.SecretRef: %w"
  84. errInvalidJwtSec = "invalid Auth.Jwt.SecretRef: %w"
  85. errInvalidJwtK8sSA = "invalid Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef: %w"
  86. errInvalidKubeSA = "invalid Auth.Kubernetes.ServiceAccountRef: %w"
  87. errInvalidKubeSec = "invalid Auth.Kubernetes.SecretRef: %w"
  88. errInvalidLdapSec = "invalid Auth.Ldap.SecretRef: %w"
  89. errInvalidTokenRef = "invalid Auth.TokenSecretRef: %w"
  90. )
  91. // https://github.com/external-secrets/external-secrets/issues/644
  92. var _ esv1beta1.SecretsClient = &client{}
  93. var _ esv1beta1.Provider = &connector{}
  94. type Auth interface {
  95. Login(ctx context.Context, authMethod vault.AuthMethod) (*vault.Secret, error)
  96. }
  97. type Token interface {
  98. RevokeSelfWithContext(ctx context.Context, token string) error
  99. LookupSelfWithContext(ctx context.Context) (*vault.Secret, error)
  100. }
  101. type Logical interface {
  102. ReadWithDataWithContext(ctx context.Context, path string, data map[string][]string) (*vault.Secret, error)
  103. ListWithContext(ctx context.Context, path string) (*vault.Secret, error)
  104. WriteWithContext(ctx context.Context, path string, data map[string]interface{}) (*vault.Secret, error)
  105. }
  106. type Client interface {
  107. SetToken(v string)
  108. Token() string
  109. ClearToken()
  110. Auth() Auth
  111. Logical() Logical
  112. AuthToken() Token
  113. SetNamespace(namespace string)
  114. AddHeader(key, value string)
  115. }
  116. type VClient struct {
  117. setToken func(v string)
  118. token func() string
  119. clearToken func()
  120. auth Auth
  121. logical Logical
  122. authToken Token
  123. setNamespace func(namespace string)
  124. addHeader func(key, value string)
  125. }
  126. func (v VClient) AddHeader(key, value string) {
  127. v.addHeader(key, value)
  128. }
  129. func (v VClient) SetNamespace(namespace string) {
  130. v.setNamespace(namespace)
  131. }
  132. func (v VClient) ClearToken() {
  133. v.clearToken()
  134. }
  135. func (v VClient) Token() string {
  136. return v.token()
  137. }
  138. func (v VClient) SetToken(token string) {
  139. v.setToken(token)
  140. }
  141. func (v VClient) Auth() Auth {
  142. return v.auth
  143. }
  144. func (v VClient) AuthToken() Token {
  145. return v.authToken
  146. }
  147. func (v VClient) Logical() Logical {
  148. return v.logical
  149. }
  150. type client struct {
  151. kube kclient.Client
  152. store *esv1beta1.VaultProvider
  153. log logr.Logger
  154. corev1 typedcorev1.CoreV1Interface
  155. client Client
  156. auth Auth
  157. logical Logical
  158. token Token
  159. namespace string
  160. storeKind string
  161. }
  162. func init() {
  163. esv1beta1.Register(&connector{
  164. newVaultClient: newVaultClient,
  165. }, &esv1beta1.SecretStoreProvider{
  166. Vault: &esv1beta1.VaultProvider{},
  167. })
  168. }
  169. func newVaultClient(c *vault.Config) (Client, error) {
  170. cl, err := vault.NewClient(c)
  171. if err != nil {
  172. return nil, err
  173. }
  174. auth := cl.Auth()
  175. logical := cl.Logical()
  176. token := cl.Auth().Token()
  177. out := VClient{
  178. setToken: cl.SetToken,
  179. token: cl.Token,
  180. clearToken: cl.ClearToken,
  181. auth: auth,
  182. authToken: token,
  183. logical: logical,
  184. setNamespace: cl.SetNamespace,
  185. addHeader: cl.AddHeader,
  186. }
  187. return out, nil
  188. }
  189. type connector struct {
  190. newVaultClient func(c *vault.Config) (Client, error)
  191. }
  192. func (c *connector) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
  193. // controller-runtime/client does not support TokenRequest or other subresource APIs
  194. // so we need to construct our own client and use it to fetch tokens
  195. // (for Kubernetes service account token auth)
  196. restCfg, err := ctrlcfg.GetConfig()
  197. if err != nil {
  198. return nil, err
  199. }
  200. clientset, err := kubernetes.NewForConfig(restCfg)
  201. if err != nil {
  202. return nil, err
  203. }
  204. return c.newClient(ctx, store, kube, clientset.CoreV1(), namespace)
  205. }
  206. func (c *connector) newClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, corev1 typedcorev1.CoreV1Interface, namespace string) (esv1beta1.SecretsClient, error) {
  207. storeSpec := store.GetSpec()
  208. if storeSpec == nil || storeSpec.Provider == nil || storeSpec.Provider.Vault == nil {
  209. return nil, errors.New(errVaultStore)
  210. }
  211. vaultSpec := storeSpec.Provider.Vault
  212. vStore := &client{
  213. kube: kube,
  214. corev1: corev1,
  215. store: vaultSpec,
  216. log: ctrl.Log.WithName("provider").WithName("vault"),
  217. namespace: namespace,
  218. storeKind: store.GetObjectKind().GroupVersionKind().Kind,
  219. }
  220. cfg, err := vStore.newConfig()
  221. if err != nil {
  222. return nil, err
  223. }
  224. client, err := c.newVaultClient(cfg)
  225. if err != nil {
  226. return nil, fmt.Errorf(errVaultClient, err)
  227. }
  228. if vaultSpec.Namespace != nil {
  229. client.SetNamespace(*vaultSpec.Namespace)
  230. }
  231. if vaultSpec.ReadYourWrites && vaultSpec.ForwardInconsistent {
  232. client.AddHeader("X-Vault-Inconsistent", "forward-active-node")
  233. }
  234. vStore.client = client
  235. vStore.auth = client.Auth()
  236. vStore.logical = client.Logical()
  237. vStore.token = client.AuthToken()
  238. if err := vStore.setAuth(ctx, cfg); err != nil {
  239. return nil, err
  240. }
  241. return vStore, nil
  242. }
  243. func (c *connector) ValidateStore(store esv1beta1.GenericStore) error {
  244. if store == nil {
  245. return fmt.Errorf(errInvalidStore)
  246. }
  247. spc := store.GetSpec()
  248. if spc == nil {
  249. return fmt.Errorf(errInvalidStoreSpec)
  250. }
  251. if spc.Provider == nil {
  252. return fmt.Errorf(errInvalidStoreProv)
  253. }
  254. p := spc.Provider.Vault
  255. if p == nil {
  256. return fmt.Errorf(errInvalidVaultProv)
  257. }
  258. if p.Auth.AppRole != nil {
  259. if err := utils.ValidateSecretSelector(store, p.Auth.AppRole.SecretRef); err != nil {
  260. return fmt.Errorf(errInvalidAppRoleSec, err)
  261. }
  262. }
  263. if p.Auth.Cert != nil {
  264. if err := utils.ValidateSecretSelector(store, p.Auth.Cert.ClientCert); err != nil {
  265. return fmt.Errorf(errInvalidClientCert, err)
  266. }
  267. if err := utils.ValidateSecretSelector(store, p.Auth.Cert.SecretRef); err != nil {
  268. return fmt.Errorf(errInvalidCertSec, err)
  269. }
  270. }
  271. if p.Auth.Jwt != nil {
  272. if p.Auth.Jwt.SecretRef != nil {
  273. if err := utils.ValidateSecretSelector(store, *p.Auth.Jwt.SecretRef); err != nil {
  274. return fmt.Errorf(errInvalidJwtSec, err)
  275. }
  276. } else if p.Auth.Jwt.KubernetesServiceAccountToken != nil {
  277. if err := utils.ValidateServiceAccountSelector(store, p.Auth.Jwt.KubernetesServiceAccountToken.ServiceAccountRef); err != nil {
  278. return fmt.Errorf(errInvalidJwtK8sSA, err)
  279. }
  280. } else {
  281. return fmt.Errorf(errJwtNoTokenSource)
  282. }
  283. }
  284. if p.Auth.Kubernetes != nil {
  285. if p.Auth.Kubernetes.ServiceAccountRef != nil {
  286. if err := utils.ValidateServiceAccountSelector(store, *p.Auth.Kubernetes.ServiceAccountRef); err != nil {
  287. return fmt.Errorf(errInvalidKubeSA, err)
  288. }
  289. }
  290. if p.Auth.Kubernetes.SecretRef != nil {
  291. if err := utils.ValidateSecretSelector(store, *p.Auth.Kubernetes.SecretRef); err != nil {
  292. return fmt.Errorf(errInvalidKubeSec, err)
  293. }
  294. }
  295. }
  296. if p.Auth.Ldap != nil {
  297. if err := utils.ValidateSecretSelector(store, p.Auth.Ldap.SecretRef); err != nil {
  298. return fmt.Errorf(errInvalidLdapSec, err)
  299. }
  300. }
  301. if p.Auth.TokenSecretRef != nil {
  302. if err := utils.ValidateSecretSelector(store, *p.Auth.TokenSecretRef); err != nil {
  303. return fmt.Errorf(errInvalidTokenRef, err)
  304. }
  305. }
  306. return nil
  307. }
  308. // Empty GetAllSecrets.
  309. // GetAllSecrets
  310. // First load all secrets from secretStore path configuration.
  311. // Then, gets secrets from a matching name or matching custom_metadata.
  312. func (v *client) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  313. if v.store.Version == esv1beta1.VaultKVStoreV1 {
  314. return nil, errors.New(errUnsupportedKvVersion)
  315. }
  316. searchPath := ""
  317. if ref.Path != nil {
  318. searchPath = *ref.Path + "/"
  319. }
  320. potentialSecrets, err := v.listSecrets(ctx, searchPath)
  321. if err != nil {
  322. return nil, err
  323. }
  324. if ref.Name != nil {
  325. return v.findSecretsFromName(ctx, potentialSecrets, *ref.Name)
  326. }
  327. return v.findSecretsFromTags(ctx, potentialSecrets, ref.Tags)
  328. }
  329. func (v *client) findSecretsFromTags(ctx context.Context, candidates []string, tags map[string]string) (map[string][]byte, error) {
  330. secrets := make(map[string][]byte)
  331. for _, name := range candidates {
  332. match := true
  333. metadata, err := v.readSecretMetadata(ctx, name)
  334. if err != nil {
  335. return nil, err
  336. }
  337. for tk, tv := range tags {
  338. p, ok := metadata[tk]
  339. if !ok || p != tv {
  340. match = false
  341. break
  342. }
  343. }
  344. if match {
  345. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  346. if err != nil {
  347. return nil, err
  348. }
  349. secrets[name] = secret
  350. }
  351. }
  352. return secrets, nil
  353. }
  354. func (v *client) findSecretsFromName(ctx context.Context, candidates []string, ref esv1beta1.FindName) (map[string][]byte, error) {
  355. secrets := make(map[string][]byte)
  356. matcher, err := find.New(ref)
  357. if err != nil {
  358. return nil, err
  359. }
  360. for _, name := range candidates {
  361. ok := matcher.MatchName(name)
  362. if ok {
  363. secret, err := v.GetSecret(ctx, esv1beta1.ExternalSecretDataRemoteRef{Key: name})
  364. if err != nil {
  365. return nil, err
  366. }
  367. secrets[name] = secret
  368. }
  369. }
  370. return secrets, nil
  371. }
  372. func (v *client) listSecrets(ctx context.Context, path string) ([]string, error) {
  373. secrets := make([]string, 0)
  374. url, err := v.buildMetadataPath(path)
  375. if err != nil {
  376. return nil, err
  377. }
  378. secret, err := v.logical.ListWithContext(ctx, url)
  379. if err != nil {
  380. return nil, fmt.Errorf(errReadSecret, err)
  381. }
  382. t, ok := secret.Data["keys"]
  383. if !ok {
  384. return nil, nil
  385. }
  386. paths := t.([]interface{})
  387. for _, p := range paths {
  388. strPath := p.(string)
  389. fullPath := path + strPath // because path always ends with a /
  390. if path == "" {
  391. fullPath = strPath
  392. }
  393. // Recurrently find secrets
  394. if !strings.HasSuffix(p.(string), "/") {
  395. secrets = append(secrets, fullPath)
  396. } else {
  397. partial, err := v.listSecrets(ctx, fullPath)
  398. if err != nil {
  399. return nil, err
  400. }
  401. secrets = append(secrets, partial...)
  402. }
  403. }
  404. return secrets, nil
  405. }
  406. func (v *client) readSecretMetadata(ctx context.Context, path string) (map[string]string, error) {
  407. metadata := make(map[string]string)
  408. url, err := v.buildMetadataPath(path)
  409. if err != nil {
  410. return nil, err
  411. }
  412. secret, err := v.logical.ReadWithDataWithContext(ctx, url, nil)
  413. if err != nil {
  414. return nil, fmt.Errorf(errReadSecret, err)
  415. }
  416. t, ok := secret.Data["custom_metadata"]
  417. if !ok {
  418. return nil, nil
  419. }
  420. d, ok := t.(map[string]interface{})
  421. if !ok {
  422. return metadata, nil
  423. }
  424. for k, v := range d {
  425. metadata[k] = v.(string)
  426. }
  427. return metadata, nil
  428. }
  429. // GetSecret supports two types:
  430. // 1. get the full secret as json-encoded value
  431. // by leaving the ref.Property empty.
  432. // 2. get a key from the secret.
  433. // Nested values are supported by specifying a gjson expression
  434. func (v *client) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  435. data, err := v.readSecret(ctx, ref.Key, ref.Version)
  436. if err != nil {
  437. return nil, err
  438. }
  439. jsonStr, err := json.Marshal(data)
  440. if err != nil {
  441. return nil, err
  442. }
  443. // (1): return raw json if no property is defined
  444. if ref.Property == "" {
  445. return jsonStr, nil
  446. }
  447. // For backwards compatibility we want the
  448. // actual keys to take precedence over gjson syntax
  449. // (2): extract key from secret with property
  450. if _, ok := data[ref.Property]; ok {
  451. return getTypedKey(data, ref.Property)
  452. }
  453. // (3): extract key from secret using gjson
  454. val := gjson.Get(string(jsonStr), ref.Property)
  455. if !val.Exists() {
  456. return nil, fmt.Errorf(errSecretKeyFmt, ref.Property)
  457. }
  458. return []byte(val.String()), nil
  459. }
  460. // GetSecretMap supports two modes of operation:
  461. // 1. get the full secret from the vault data payload (by leaving .property empty).
  462. // 2. extract key/value pairs from a (nested) object.
  463. func (v *client) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  464. data, err := v.GetSecret(ctx, ref)
  465. if err != nil {
  466. return nil, err
  467. }
  468. var secretData map[string]interface{}
  469. err = json.Unmarshal(data, &secretData)
  470. if err != nil {
  471. return nil, err
  472. }
  473. byteMap := make(map[string][]byte, len(secretData))
  474. for k := range secretData {
  475. byteMap[k], err = getTypedKey(secretData, k)
  476. if err != nil {
  477. return nil, err
  478. }
  479. }
  480. return byteMap, nil
  481. }
  482. func getTypedKey(data map[string]interface{}, key string) ([]byte, error) {
  483. v, ok := data[key]
  484. if !ok {
  485. return nil, fmt.Errorf(errUnexpectedKey, key)
  486. }
  487. switch t := v.(type) {
  488. case string:
  489. return []byte(t), nil
  490. case map[string]interface{}:
  491. return json.Marshal(t)
  492. case []byte:
  493. return t, nil
  494. // also covers int and float32 due to json.Marshal
  495. case float64:
  496. return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil
  497. case bool:
  498. return []byte(strconv.FormatBool(t)), nil
  499. case nil:
  500. return []byte(nil), nil
  501. default:
  502. return nil, errors.New(errSecretFormat)
  503. }
  504. }
  505. func (v *client) Close(ctx context.Context) error {
  506. // Revoke the token if we have one set and it wasn't sourced from a TokenSecretRef
  507. if v.client.Token() != "" && v.store.Auth.TokenSecretRef == nil {
  508. revoke, err := checkToken(ctx, v)
  509. if err != nil {
  510. return fmt.Errorf(errVaultRevokeToken, err)
  511. }
  512. if revoke {
  513. err = v.token.RevokeSelfWithContext(ctx, v.client.Token())
  514. if err != nil {
  515. return fmt.Errorf(errVaultRevokeToken, err)
  516. }
  517. v.client.ClearToken()
  518. }
  519. }
  520. return nil
  521. }
  522. func (v *client) Validate() (esv1beta1.ValidationResult, error) {
  523. _, err := checkToken(context.Background(), v)
  524. if err != nil {
  525. return esv1beta1.ValidationResultError, fmt.Errorf(errInvalidCredentials, err)
  526. }
  527. return esv1beta1.ValidationResultReady, nil
  528. }
  529. func (v *client) buildMetadataPath(path string) (string, error) {
  530. var url string
  531. if v.store.Path == nil && !strings.Contains(path, "data") {
  532. return "", fmt.Errorf(errPathInvalid)
  533. }
  534. if v.store.Path == nil {
  535. path = strings.Replace(path, "data", "metadata", 1)
  536. url = path
  537. } else {
  538. url = fmt.Sprintf("%s/metadata/%s", *v.store.Path, path)
  539. }
  540. return url, nil
  541. }
  542. func (v *client) buildPath(path string) string {
  543. optionalMount := v.store.Path
  544. origPath := strings.Split(path, "/")
  545. newPath := make([]string, 0)
  546. cursor := 0
  547. if optionalMount != nil && origPath[0] != *optionalMount {
  548. // Default case before path was optional
  549. // Ensure that the requested path includes the SecretStores paths as prefix
  550. newPath = append(newPath, *optionalMount)
  551. } else {
  552. newPath = append(newPath, origPath[cursor])
  553. cursor++
  554. }
  555. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  556. // Add the required `data` part of the URL for the v2 API
  557. if len(origPath) < 2 || origPath[1] != "data" {
  558. newPath = append(newPath, "data")
  559. }
  560. }
  561. newPath = append(newPath, origPath[cursor:]...)
  562. returnPath := strings.Join(newPath, "/")
  563. return returnPath
  564. }
  565. func (v *client) readSecret(ctx context.Context, path, version string) (map[string]interface{}, error) {
  566. dataPath := v.buildPath(path)
  567. // path formated according to vault docs for v1 and v2 API
  568. // v1: https://www.vaultproject.io/api-docs/secret/kv/kv-v1#read-secret
  569. // v2: https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  570. var params map[string][]string
  571. if version != "" {
  572. params = make(map[string][]string)
  573. params["version"] = []string{version}
  574. }
  575. vaultSecret, err := v.logical.ReadWithDataWithContext(ctx, dataPath, params)
  576. if err != nil {
  577. return nil, fmt.Errorf(errReadSecret, err)
  578. }
  579. secretData := vaultSecret.Data
  580. if v.store.Version == esv1beta1.VaultKVStoreV2 {
  581. // Vault KV2 has data embedded within sub-field
  582. // reference - https://www.vaultproject.io/api/secret/kv/kv-v2#read-secret-version
  583. dataInt, ok := vaultSecret.Data["data"]
  584. if !ok {
  585. return nil, errors.New(errDataField)
  586. }
  587. secretData, ok = dataInt.(map[string]interface{})
  588. if !ok {
  589. return nil, errors.New(errJSONUnmarshall)
  590. }
  591. }
  592. return secretData, nil
  593. }
  594. func (v *client) newConfig() (*vault.Config, error) {
  595. cfg := vault.DefaultConfig()
  596. cfg.Address = v.store.Server
  597. // In a controller-runtime context, we rely on the reconciliation process for retrying
  598. cfg.MaxRetries = 0
  599. if len(v.store.CABundle) == 0 && v.store.CAProvider == nil {
  600. return cfg, nil
  601. }
  602. caCertPool := x509.NewCertPool()
  603. if len(v.store.CABundle) > 0 {
  604. ok := caCertPool.AppendCertsFromPEM(v.store.CABundle)
  605. if !ok {
  606. return nil, errors.New(errVaultCert)
  607. }
  608. }
  609. if v.store.CAProvider != nil && v.storeKind == esv1beta1.ClusterSecretStoreKind && v.store.CAProvider.Namespace == nil {
  610. return nil, errors.New(errCANamespace)
  611. }
  612. if v.store.CAProvider != nil {
  613. var cert []byte
  614. var err error
  615. switch v.store.CAProvider.Type {
  616. case esv1beta1.CAProviderTypeSecret:
  617. cert, err = getCertFromSecret(v)
  618. case esv1beta1.CAProviderTypeConfigMap:
  619. cert, err = getCertFromConfigMap(v)
  620. default:
  621. return nil, errors.New(errUnknownCAProvider)
  622. }
  623. if err != nil {
  624. return nil, err
  625. }
  626. ok := caCertPool.AppendCertsFromPEM(cert)
  627. if !ok {
  628. return nil, errors.New(errVaultCert)
  629. }
  630. }
  631. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  632. transport.TLSClientConfig.RootCAs = caCertPool
  633. }
  634. // If either read-after-write consistency feature is enabled, enable ReadYourWrites
  635. cfg.ReadYourWrites = v.store.ReadYourWrites || v.store.ForwardInconsistent
  636. return cfg, nil
  637. }
  638. func getCertFromSecret(v *client) ([]byte, error) {
  639. secretRef := esmeta.SecretKeySelector{
  640. Name: v.store.CAProvider.Name,
  641. Key: v.store.CAProvider.Key,
  642. }
  643. if v.store.CAProvider.Namespace != nil {
  644. secretRef.Namespace = v.store.CAProvider.Namespace
  645. }
  646. ctx := context.Background()
  647. res, err := v.secretKeyRef(ctx, &secretRef)
  648. if err != nil {
  649. return nil, fmt.Errorf(errVaultCert, err)
  650. }
  651. return []byte(res), nil
  652. }
  653. func getCertFromConfigMap(v *client) ([]byte, error) {
  654. objKey := types.NamespacedName{
  655. Name: v.store.CAProvider.Name,
  656. }
  657. if v.store.CAProvider.Namespace != nil {
  658. objKey.Namespace = *v.store.CAProvider.Namespace
  659. }
  660. configMapRef := &corev1.ConfigMap{}
  661. ctx := context.Background()
  662. err := v.kube.Get(ctx, objKey, configMapRef)
  663. if err != nil {
  664. return nil, fmt.Errorf(errVaultCert, err)
  665. }
  666. val, ok := configMapRef.Data[v.store.CAProvider.Key]
  667. if !ok {
  668. return nil, fmt.Errorf(errConfigMapFmt, v.store.CAProvider.Key)
  669. }
  670. return []byte(val), nil
  671. }
  672. func (v *client) setAuth(ctx context.Context, cfg *vault.Config) error {
  673. tokenExists, err := setSecretKeyToken(ctx, v)
  674. if tokenExists {
  675. return err
  676. }
  677. tokenExists, err = setAppRoleToken(ctx, v)
  678. if tokenExists {
  679. return err
  680. }
  681. tokenExists, err = setKubernetesAuthToken(ctx, v)
  682. if tokenExists {
  683. return err
  684. }
  685. tokenExists, err = setLdapAuthToken(ctx, v)
  686. if tokenExists {
  687. return err
  688. }
  689. tokenExists, err = setJwtAuthToken(ctx, v)
  690. if tokenExists {
  691. return err
  692. }
  693. tokenExists, err = setCertAuthToken(ctx, v, cfg)
  694. if tokenExists {
  695. return err
  696. }
  697. return errors.New(errAuthFormat)
  698. }
  699. func setAppRoleToken(ctx context.Context, v *client) (bool, error) {
  700. tokenRef := v.store.Auth.TokenSecretRef
  701. if tokenRef != nil {
  702. token, err := v.secretKeyRef(ctx, tokenRef)
  703. if err != nil {
  704. return true, err
  705. }
  706. v.client.SetToken(token)
  707. return true, nil
  708. }
  709. return false, nil
  710. }
  711. func setSecretKeyToken(ctx context.Context, v *client) (bool, error) {
  712. appRole := v.store.Auth.AppRole
  713. if appRole != nil {
  714. err := v.requestTokenWithAppRoleRef(ctx, appRole)
  715. if err != nil {
  716. return true, err
  717. }
  718. return true, nil
  719. }
  720. return false, nil
  721. }
  722. func setKubernetesAuthToken(ctx context.Context, v *client) (bool, error) {
  723. kubernetesAuth := v.store.Auth.Kubernetes
  724. if kubernetesAuth != nil {
  725. err := v.requestTokenWithKubernetesAuth(ctx, kubernetesAuth)
  726. if err != nil {
  727. return true, err
  728. }
  729. return true, nil
  730. }
  731. return false, nil
  732. }
  733. func setLdapAuthToken(ctx context.Context, v *client) (bool, error) {
  734. ldapAuth := v.store.Auth.Ldap
  735. if ldapAuth != nil {
  736. err := v.requestTokenWithLdapAuth(ctx, ldapAuth)
  737. if err != nil {
  738. return true, err
  739. }
  740. return true, nil
  741. }
  742. return false, nil
  743. }
  744. func setJwtAuthToken(ctx context.Context, v *client) (bool, error) {
  745. jwtAuth := v.store.Auth.Jwt
  746. if jwtAuth != nil {
  747. err := v.requestTokenWithJwtAuth(ctx, jwtAuth)
  748. if err != nil {
  749. return true, err
  750. }
  751. return true, nil
  752. }
  753. return false, nil
  754. }
  755. func setCertAuthToken(ctx context.Context, v *client, cfg *vault.Config) (bool, error) {
  756. certAuth := v.store.Auth.Cert
  757. if certAuth != nil {
  758. err := v.requestTokenWithCertAuth(ctx, certAuth, cfg)
  759. if err != nil {
  760. return true, err
  761. }
  762. return true, nil
  763. }
  764. return false, nil
  765. }
  766. func (v *client) secretKeyRefForServiceAccount(ctx context.Context, serviceAccountRef *esmeta.ServiceAccountSelector) (string, error) {
  767. serviceAccount := &corev1.ServiceAccount{}
  768. ref := types.NamespacedName{
  769. Namespace: v.namespace,
  770. Name: serviceAccountRef.Name,
  771. }
  772. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  773. (serviceAccountRef.Namespace != nil) {
  774. ref.Namespace = *serviceAccountRef.Namespace
  775. }
  776. err := v.kube.Get(ctx, ref, serviceAccount)
  777. if err != nil {
  778. return "", fmt.Errorf(errGetKubeSA, ref.Name, err)
  779. }
  780. if len(serviceAccount.Secrets) == 0 {
  781. return "", fmt.Errorf(errGetKubeSASecrets, ref.Name)
  782. }
  783. for _, tokenRef := range serviceAccount.Secrets {
  784. retval, err := v.secretKeyRef(ctx, &esmeta.SecretKeySelector{
  785. Name: tokenRef.Name,
  786. Namespace: &ref.Namespace,
  787. Key: "token",
  788. })
  789. if err != nil {
  790. continue
  791. }
  792. return retval, nil
  793. }
  794. return "", fmt.Errorf(errGetKubeSANoToken, ref.Name)
  795. }
  796. func (v *client) secretKeyRef(ctx context.Context, secretRef *esmeta.SecretKeySelector) (string, error) {
  797. secret := &corev1.Secret{}
  798. ref := types.NamespacedName{
  799. Namespace: v.namespace,
  800. Name: secretRef.Name,
  801. }
  802. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  803. (secretRef.Namespace != nil) {
  804. ref.Namespace = *secretRef.Namespace
  805. }
  806. err := v.kube.Get(ctx, ref, secret)
  807. if err != nil {
  808. return "", fmt.Errorf(errGetKubeSecret, ref.Name, err)
  809. }
  810. keyBytes, ok := secret.Data[secretRef.Key]
  811. if !ok {
  812. return "", fmt.Errorf(errSecretKeyFmt, secretRef.Key)
  813. }
  814. value := string(keyBytes)
  815. valueStr := strings.TrimSpace(value)
  816. return valueStr, nil
  817. }
  818. func (v *client) serviceAccountToken(ctx context.Context, serviceAccountRef esmeta.ServiceAccountSelector, audiences []string, expirationSeconds int64) (string, error) {
  819. tokenRequest := &authenticationv1.TokenRequest{
  820. ObjectMeta: metav1.ObjectMeta{
  821. Namespace: v.namespace,
  822. },
  823. Spec: authenticationv1.TokenRequestSpec{
  824. Audiences: audiences,
  825. ExpirationSeconds: &expirationSeconds,
  826. },
  827. }
  828. if (v.storeKind == esv1beta1.ClusterSecretStoreKind) &&
  829. (serviceAccountRef.Namespace != nil) {
  830. tokenRequest.Namespace = *serviceAccountRef.Namespace
  831. }
  832. tokenResponse, err := v.corev1.ServiceAccounts(tokenRequest.Namespace).CreateToken(ctx, serviceAccountRef.Name, tokenRequest, metav1.CreateOptions{})
  833. if err != nil {
  834. return "", fmt.Errorf(errGetKubeSATokenRequest, serviceAccountRef.Name, err)
  835. }
  836. return tokenResponse.Status.Token, nil
  837. }
  838. // checkToken does a lookup and checks if the provided token exists.
  839. func checkToken(ctx context.Context, vStore *client) (bool, error) {
  840. // https://www.vaultproject.io/api-docs/auth/token#lookup-a-token-self
  841. resp, err := vStore.token.LookupSelfWithContext(ctx)
  842. if err != nil {
  843. return false, err
  844. }
  845. t, ok := resp.Data["type"]
  846. if !ok {
  847. return false, fmt.Errorf("could not assert token type")
  848. }
  849. tokenType := t.(string)
  850. if tokenType == "batch" {
  851. return false, nil
  852. }
  853. return true, nil
  854. }
  855. func (v *client) requestTokenWithAppRoleRef(ctx context.Context, appRole *esv1beta1.VaultAppRole) error {
  856. roleID := strings.TrimSpace(appRole.RoleID)
  857. secretID, err := v.secretKeyRef(ctx, &appRole.SecretRef)
  858. if err != nil {
  859. return err
  860. }
  861. secret := approle.SecretID{FromString: secretID}
  862. appRoleClient, err := approle.NewAppRoleAuth(roleID, &secret, approle.WithMountPath(appRole.Path))
  863. if err != nil {
  864. return err
  865. }
  866. _, err = v.auth.Login(ctx, appRoleClient)
  867. if err != nil {
  868. return err
  869. }
  870. return nil
  871. }
  872. func (v *client) requestTokenWithKubernetesAuth(ctx context.Context, kubernetesAuth *esv1beta1.VaultKubernetesAuth) error {
  873. jwtString, err := getJwtString(ctx, v, kubernetesAuth)
  874. if err != nil {
  875. return err
  876. }
  877. k, err := authkubernetes.NewKubernetesAuth(kubernetesAuth.Role, authkubernetes.WithServiceAccountToken(jwtString), authkubernetes.WithMountPath(kubernetesAuth.Path))
  878. if err != nil {
  879. return err
  880. }
  881. _, err = v.auth.Login(ctx, k)
  882. if err != nil {
  883. return err
  884. }
  885. return nil
  886. }
  887. func getJwtString(ctx context.Context, v *client, kubernetesAuth *esv1beta1.VaultKubernetesAuth) (string, error) {
  888. if kubernetesAuth.ServiceAccountRef != nil {
  889. jwt, err := v.secretKeyRefForServiceAccount(ctx, kubernetesAuth.ServiceAccountRef)
  890. if err != nil {
  891. return "", err
  892. }
  893. return jwt, nil
  894. } else if kubernetesAuth.SecretRef != nil {
  895. tokenRef := kubernetesAuth.SecretRef
  896. if tokenRef.Key == "" {
  897. tokenRef = kubernetesAuth.SecretRef.DeepCopy()
  898. tokenRef.Key = "token"
  899. }
  900. jwt, err := v.secretKeyRef(ctx, tokenRef)
  901. if err != nil {
  902. return "", err
  903. }
  904. return jwt, nil
  905. } else {
  906. // Kubernetes authentication is specified, but without a referenced
  907. // Kubernetes secret. We check if the file path for in-cluster service account
  908. // exists and attempt to use the token for Vault Kubernetes auth.
  909. if _, err := os.Stat(serviceAccTokenPath); err != nil {
  910. return "", fmt.Errorf(errServiceAccount, err)
  911. }
  912. jwtByte, err := os.ReadFile(serviceAccTokenPath)
  913. if err != nil {
  914. return "", fmt.Errorf(errServiceAccount, err)
  915. }
  916. return string(jwtByte), nil
  917. }
  918. }
  919. func (v *client) requestTokenWithLdapAuth(ctx context.Context, ldapAuth *esv1beta1.VaultLdapAuth) error {
  920. username := strings.TrimSpace(ldapAuth.Username)
  921. password, err := v.secretKeyRef(ctx, &ldapAuth.SecretRef)
  922. if err != nil {
  923. return err
  924. }
  925. pass := authldap.Password{FromString: password}
  926. l, err := authldap.NewLDAPAuth(username, &pass, authldap.WithMountPath(ldapAuth.Path))
  927. if err != nil {
  928. return err
  929. }
  930. _, err = v.auth.Login(ctx, l)
  931. if err != nil {
  932. return err
  933. }
  934. return nil
  935. }
  936. func (v *client) requestTokenWithJwtAuth(ctx context.Context, jwtAuth *esv1beta1.VaultJwtAuth) error {
  937. role := strings.TrimSpace(jwtAuth.Role)
  938. var jwt string
  939. var err error
  940. if jwtAuth.SecretRef != nil {
  941. jwt, err = v.secretKeyRef(ctx, jwtAuth.SecretRef)
  942. } else if k8sServiceAccountToken := jwtAuth.KubernetesServiceAccountToken; k8sServiceAccountToken != nil {
  943. audiences := k8sServiceAccountToken.Audiences
  944. if audiences == nil {
  945. audiences = &[]string{"vault"}
  946. }
  947. expirationSeconds := k8sServiceAccountToken.ExpirationSeconds
  948. if expirationSeconds == nil {
  949. tmp := int64(600)
  950. expirationSeconds = &tmp
  951. }
  952. jwt, err = v.serviceAccountToken(ctx, k8sServiceAccountToken.ServiceAccountRef, *audiences, *expirationSeconds)
  953. } else {
  954. err = fmt.Errorf(errJwtNoTokenSource)
  955. }
  956. if err != nil {
  957. return err
  958. }
  959. parameters := map[string]interface{}{
  960. "role": role,
  961. "jwt": jwt,
  962. }
  963. url := strings.Join([]string{"auth", jwtAuth.Path, "login"}, "/")
  964. vaultResult, err := v.logical.WriteWithContext(ctx, url, parameters)
  965. if err != nil {
  966. return err
  967. }
  968. token, err := vaultResult.TokenID()
  969. if err != nil {
  970. return fmt.Errorf(errVaultToken, err)
  971. }
  972. v.client.SetToken(token)
  973. return nil
  974. }
  975. func (v *client) requestTokenWithCertAuth(ctx context.Context, certAuth *esv1beta1.VaultCertAuth, cfg *vault.Config) error {
  976. clientKey, err := v.secretKeyRef(ctx, &certAuth.SecretRef)
  977. if err != nil {
  978. return err
  979. }
  980. clientCert, err := v.secretKeyRef(ctx, &certAuth.ClientCert)
  981. if err != nil {
  982. return err
  983. }
  984. cert, err := tls.X509KeyPair([]byte(clientCert), []byte(clientKey))
  985. if err != nil {
  986. return fmt.Errorf(errClientTLSAuth, err)
  987. }
  988. if transport, ok := cfg.HttpClient.Transport.(*http.Transport); ok {
  989. transport.TLSClientConfig.Certificates = []tls.Certificate{cert}
  990. }
  991. url := strings.Join([]string{"auth", "cert", "login"}, "/")
  992. vaultResult, err := v.logical.WriteWithContext(ctx, url, nil)
  993. if err != nil {
  994. return fmt.Errorf(errVaultRequest, err)
  995. }
  996. token, err := vaultResult.TokenID()
  997. if err != nil {
  998. return fmt.Errorf(errVaultToken, err)
  999. }
  1000. v.client.SetToken(token)
  1001. return nil
  1002. }