vault.go 31 KB

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