provider.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  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 ibm
  13. import (
  14. "context"
  15. "encoding/json"
  16. "fmt"
  17. "os"
  18. "strconv"
  19. "strings"
  20. "time"
  21. core "github.com/IBM/go-sdk-core/v5/core"
  22. sm "github.com/IBM/secrets-manager-go-sdk/secretsmanagerv1"
  23. gjson "github.com/tidwall/gjson"
  24. corev1 "k8s.io/api/core/v1"
  25. types "k8s.io/apimachinery/pkg/types"
  26. ctrl "sigs.k8s.io/controller-runtime"
  27. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  28. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  29. utils "github.com/external-secrets/external-secrets/pkg/utils"
  30. )
  31. const (
  32. SecretsManagerEndpointEnv = "IBM_SECRETSMANAGER_ENDPOINT"
  33. STSEndpointEnv = "IBM_STS_ENDPOINT"
  34. SSMEndpointEnv = "IBM_SSM_ENDPOINT"
  35. errIBMClient = "cannot setup new ibm client: %w"
  36. errIBMCredSecretName = "invalid IBM SecretStore resource: missing IBM APIKey"
  37. errUninitalizedIBMProvider = "provider IBM is not initialized"
  38. errInvalidClusterStoreMissingSKNamespace = "invalid ClusterStore, missing namespace"
  39. errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
  40. errMissingSAK = "missing SecretAccessKey"
  41. errJSONSecretUnmarshal = "unable to unmarshal secret: %w"
  42. )
  43. // https://github.com/external-secrets/external-secrets/issues/644
  44. var _ esv1beta1.SecretsClient = &providerIBM{}
  45. var _ esv1beta1.Provider = &providerIBM{}
  46. type SecretManagerClient interface {
  47. GetSecret(getSecretOptions *sm.GetSecretOptions) (result *sm.GetSecret, response *core.DetailedResponse, err error)
  48. }
  49. type providerIBM struct {
  50. IBMClient SecretManagerClient
  51. }
  52. type client struct {
  53. kube kclient.Client
  54. store *esv1beta1.IBMProvider
  55. namespace string
  56. storeKind string
  57. credentials []byte
  58. }
  59. var log = ctrl.Log.WithName("provider").WithName("ibm").WithName("secretsmanager")
  60. func (c *client) setAuth(ctx context.Context) error {
  61. credentialsSecret := &corev1.Secret{}
  62. credentialsSecretName := c.store.Auth.SecretRef.SecretAPIKey.Name
  63. if credentialsSecretName == "" {
  64. return fmt.Errorf(errIBMCredSecretName)
  65. }
  66. objectKey := types.NamespacedName{
  67. Name: credentialsSecretName,
  68. Namespace: c.namespace,
  69. }
  70. // only ClusterStore is allowed to set namespace (and then it's required)
  71. if c.storeKind == esv1beta1.ClusterSecretStoreKind {
  72. if c.store.Auth.SecretRef.SecretAPIKey.Namespace == nil {
  73. return fmt.Errorf(errInvalidClusterStoreMissingSKNamespace)
  74. }
  75. objectKey.Namespace = *c.store.Auth.SecretRef.SecretAPIKey.Namespace
  76. }
  77. err := c.kube.Get(ctx, objectKey, credentialsSecret)
  78. if err != nil {
  79. return fmt.Errorf(errFetchSAKSecret, err)
  80. }
  81. c.credentials = credentialsSecret.Data[c.store.Auth.SecretRef.SecretAPIKey.Key]
  82. if (c.credentials == nil) || (len(c.credentials) == 0) {
  83. return fmt.Errorf(errMissingSAK)
  84. }
  85. return nil
  86. }
  87. func (ibm *providerIBM) DeleteSecret(ctx context.Context, remoteRef esv1beta1.PushRemoteRef) error {
  88. return fmt.Errorf("not implemented")
  89. }
  90. // Not Implemented PushSecret.
  91. func (ibm *providerIBM) PushSecret(ctx context.Context, value []byte, remoteRef esv1beta1.PushRemoteRef) error {
  92. return fmt.Errorf("not implemented")
  93. }
  94. // Empty GetAllSecrets.
  95. func (ibm *providerIBM) GetAllSecrets(ctx context.Context, ref esv1beta1.ExternalSecretFind) (map[string][]byte, error) {
  96. // TO be implemented
  97. return nil, fmt.Errorf("GetAllSecrets not implemented")
  98. }
  99. func (ibm *providerIBM) GetSecret(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  100. if utils.IsNil(ibm.IBMClient) {
  101. return nil, fmt.Errorf(errUninitalizedIBMProvider)
  102. }
  103. secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
  104. secretName := ref.Key
  105. nameSplitted := strings.Split(secretName, "/")
  106. if len(nameSplitted) > 1 {
  107. secretType = nameSplitted[0]
  108. secretName = nameSplitted[1]
  109. }
  110. switch secretType {
  111. case sm.GetSecretOptionsSecretTypeArbitraryConst:
  112. return getArbitrarySecret(ibm, &secretName)
  113. case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
  114. if ref.Property == "" {
  115. return nil, fmt.Errorf("remoteRef.property required for secret type username_password")
  116. }
  117. return getUsernamePasswordSecret(ibm, &secretName, ref)
  118. case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
  119. return getIamCredentialsSecret(ibm, &secretName)
  120. case sm.CreateSecretOptionsSecretTypeImportedCertConst:
  121. if ref.Property == "" {
  122. return nil, fmt.Errorf("remoteRef.property required for secret type imported_cert")
  123. }
  124. return getImportCertSecret(ibm, &secretName, ref)
  125. case sm.CreateSecretOptionsSecretTypePublicCertConst:
  126. if ref.Property == "" {
  127. return nil, fmt.Errorf("remoteRef.property required for secret type public_cert")
  128. }
  129. return getPublicCertSecret(ibm, &secretName, ref)
  130. case sm.CreateSecretOptionsSecretTypePrivateCertConst:
  131. if ref.Property == "" {
  132. return nil, fmt.Errorf("remoteRef.property required for secret type private_cert")
  133. }
  134. return getPrivateCertSecret(ibm, &secretName, ref)
  135. case sm.CreateSecretOptionsSecretTypeKvConst:
  136. return getKVSecret(ibm, &secretName, ref)
  137. default:
  138. return nil, fmt.Errorf("unknown secret type %s", secretType)
  139. }
  140. }
  141. func getArbitrarySecret(ibm *providerIBM, secretName *string) ([]byte, error) {
  142. response, _, err := ibm.IBMClient.GetSecret(
  143. &sm.GetSecretOptions{
  144. SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
  145. ID: secretName,
  146. })
  147. if err != nil {
  148. return nil, err
  149. }
  150. secret := response.Resources[0].(*sm.SecretResource)
  151. secretData := secret.SecretData
  152. arbitrarySecretPayload := secretData["payload"].(string)
  153. return []byte(arbitrarySecretPayload), nil
  154. }
  155. func getImportCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  156. response, _, err := ibm.IBMClient.GetSecret(
  157. &sm.GetSecretOptions{
  158. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
  159. ID: secretName,
  160. })
  161. if err != nil {
  162. return nil, err
  163. }
  164. secret := response.Resources[0].(*sm.SecretResource)
  165. secretData := secret.SecretData
  166. if val, ok := secretData[ref.Property]; ok {
  167. return []byte(val.(string)), nil
  168. }
  169. return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
  170. }
  171. func getPublicCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  172. response, _, err := ibm.IBMClient.GetSecret(
  173. &sm.GetSecretOptions{
  174. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst),
  175. ID: secretName,
  176. })
  177. if err != nil {
  178. return nil, err
  179. }
  180. secret := response.Resources[0].(*sm.SecretResource)
  181. secretData := secret.SecretData
  182. if val, ok := secretData[ref.Property]; ok {
  183. return []byte(val.(string)), nil
  184. }
  185. return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
  186. }
  187. func getPrivateCertSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  188. response, _, err := ibm.IBMClient.GetSecret(
  189. &sm.GetSecretOptions{
  190. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst),
  191. ID: secretName,
  192. })
  193. if err != nil {
  194. return nil, err
  195. }
  196. secret := response.Resources[0].(*sm.SecretResource)
  197. secretData := secret.SecretData
  198. if val, ok := secretData[ref.Property]; ok {
  199. return []byte(val.(string)), nil
  200. }
  201. return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
  202. }
  203. func getIamCredentialsSecret(ibm *providerIBM, secretName *string) ([]byte, error) {
  204. response, _, err := ibm.IBMClient.GetSecret(
  205. &sm.GetSecretOptions{
  206. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
  207. ID: secretName,
  208. })
  209. if err != nil {
  210. return nil, err
  211. }
  212. secret := response.Resources[0].(*sm.SecretResource)
  213. secretData := *secret.APIKey
  214. return []byte(secretData), nil
  215. }
  216. func getUsernamePasswordSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  217. response, _, err := ibm.IBMClient.GetSecret(
  218. &sm.GetSecretOptions{
  219. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
  220. ID: secretName,
  221. })
  222. if err != nil {
  223. return nil, err
  224. }
  225. secret := response.Resources[0].(*sm.SecretResource)
  226. secretData := secret.SecretData
  227. if val, ok := secretData[ref.Property]; ok {
  228. return []byte(val.(string)), nil
  229. }
  230. return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
  231. }
  232. // Returns a secret of type kv and supports json path.
  233. func getKVSecret(ibm *providerIBM, secretName *string, ref esv1beta1.ExternalSecretDataRemoteRef) ([]byte, error) {
  234. secret, err := getSecretByType(ibm, secretName, sm.CreateSecretOptionsSecretTypeKvConst)
  235. if err != nil {
  236. return nil, err
  237. }
  238. log.Info("fetching secret", "secretName", secretName, "key", ref.Key)
  239. secretData := secret.SecretData
  240. payload, ok := secretData["payload"]
  241. if !ok {
  242. return nil, fmt.Errorf("no payload returned for secret %s", ref.Key)
  243. }
  244. payloadJSON := payload
  245. payloadJSONMap, ok := payloadJSON.(map[string]interface{})
  246. if ok {
  247. var payloadJSONByte []byte
  248. payloadJSONByte, err = json.Marshal(payloadJSONMap)
  249. if err != nil {
  250. return nil, fmt.Errorf("marshaling payload from secret failed. %w", err)
  251. }
  252. payloadJSON = string(payloadJSONByte)
  253. }
  254. // no property requested, return the entire payload
  255. if ref.Property == "" {
  256. return []byte(payloadJSON.(string)), nil
  257. }
  258. // returns the requested key
  259. // consider that the key contains a ".". this could be one of 2 options
  260. // a) "." is part of the key name
  261. // b) "." is symbole for JSON path
  262. if ref.Property != "" {
  263. refProperty := ref.Property
  264. // a) "." is part the key name
  265. // escape "."
  266. idx := strings.Index(refProperty, ".")
  267. if idx > 0 {
  268. refProperty = strings.ReplaceAll(refProperty, ".", "\\.")
  269. val := gjson.Get(payloadJSON.(string), refProperty)
  270. if val.Exists() {
  271. return []byte(val.String()), nil
  272. }
  273. }
  274. // b) "." is symbole for JSON path
  275. // try to get value for this path
  276. val := gjson.Get(payloadJSON.(string), ref.Property)
  277. if !val.Exists() {
  278. return nil, fmt.Errorf("key %s does not exist in secret %s", ref.Property, ref.Key)
  279. }
  280. return []byte(val.String()), nil
  281. }
  282. return nil, fmt.Errorf("no property provided for secret %s", ref.Key)
  283. }
  284. func getSecretByType(ibm *providerIBM, secretName *string, secretType string) (*sm.SecretResource, error) {
  285. response, _, err := ibm.IBMClient.GetSecret(
  286. &sm.GetSecretOptions{
  287. SecretType: core.StringPtr(secretType),
  288. ID: secretName,
  289. })
  290. if err != nil {
  291. return nil, err
  292. }
  293. secret := response.Resources[0].(*sm.SecretResource)
  294. return secret, nil
  295. }
  296. func (ibm *providerIBM) GetSecretMap(ctx context.Context, ref esv1beta1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  297. if utils.IsNil(ibm.IBMClient) {
  298. return nil, fmt.Errorf(errUninitalizedIBMProvider)
  299. }
  300. secretType := sm.GetSecretOptionsSecretTypeArbitraryConst
  301. secretName := ref.Key
  302. nameSplitted := strings.Split(secretName, "/")
  303. if len(nameSplitted) > 1 {
  304. secretType = nameSplitted[0]
  305. secretName = nameSplitted[1]
  306. }
  307. switch secretType {
  308. case sm.GetSecretOptionsSecretTypeArbitraryConst:
  309. response, _, err := ibm.IBMClient.GetSecret(
  310. &sm.GetSecretOptions{
  311. SecretType: core.StringPtr(sm.GetSecretOptionsSecretTypeArbitraryConst),
  312. ID: &ref.Key,
  313. })
  314. if err != nil {
  315. return nil, err
  316. }
  317. secret := response.Resources[0].(*sm.SecretResource)
  318. secretData := secret.SecretData
  319. arbitrarySecretPayload := secretData["payload"].(string)
  320. kv := make(map[string]interface{})
  321. err = json.Unmarshal([]byte(arbitrarySecretPayload), &kv)
  322. if err != nil {
  323. return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
  324. }
  325. secretMap := byteArrayMap(kv)
  326. return secretMap, nil
  327. case sm.CreateSecretOptionsSecretTypeUsernamePasswordConst:
  328. response, _, err := ibm.IBMClient.GetSecret(
  329. &sm.GetSecretOptions{
  330. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeUsernamePasswordConst),
  331. ID: &secretName,
  332. })
  333. if err != nil {
  334. return nil, err
  335. }
  336. secret := response.Resources[0].(*sm.SecretResource)
  337. secretData := secret.SecretData
  338. secretMap := byteArrayMap(secretData)
  339. return secretMap, nil
  340. case sm.CreateSecretOptionsSecretTypeIamCredentialsConst:
  341. response, _, err := ibm.IBMClient.GetSecret(
  342. &sm.GetSecretOptions{
  343. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeIamCredentialsConst),
  344. ID: &secretName,
  345. })
  346. if err != nil {
  347. return nil, err
  348. }
  349. secret := response.Resources[0].(*sm.SecretResource)
  350. secretData := *secret.APIKey
  351. secretMap := make(map[string][]byte)
  352. secretMap["apikey"] = []byte(secretData)
  353. return secretMap, nil
  354. case sm.CreateSecretOptionsSecretTypeImportedCertConst:
  355. response, _, err := ibm.IBMClient.GetSecret(
  356. &sm.GetSecretOptions{
  357. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypeImportedCertConst),
  358. ID: &secretName,
  359. })
  360. if err != nil {
  361. return nil, err
  362. }
  363. secret := response.Resources[0].(*sm.SecretResource)
  364. secretData := secret.SecretData
  365. secretMap := byteArrayMap(secretData)
  366. return secretMap, nil
  367. case sm.CreateSecretOptionsSecretTypePublicCertConst:
  368. response, _, err := ibm.IBMClient.GetSecret(
  369. &sm.GetSecretOptions{
  370. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePublicCertConst),
  371. ID: &secretName,
  372. })
  373. if err != nil {
  374. return nil, err
  375. }
  376. secret := response.Resources[0].(*sm.SecretResource)
  377. secretData := secret.SecretData
  378. secretMap := byteArrayMap(secretData)
  379. return secretMap, nil
  380. case sm.CreateSecretOptionsSecretTypePrivateCertConst:
  381. response, _, err := ibm.IBMClient.GetSecret(
  382. &sm.GetSecretOptions{
  383. SecretType: core.StringPtr(sm.CreateSecretOptionsSecretTypePrivateCertConst),
  384. ID: &secretName,
  385. })
  386. if err != nil {
  387. return nil, err
  388. }
  389. secret := response.Resources[0].(*sm.SecretResource)
  390. secretData := secret.SecretData
  391. secretMap := byteArrayMap(secretData)
  392. return secretMap, nil
  393. case sm.CreateSecretOptionsSecretTypeKvConst:
  394. secret, err := getKVSecret(ibm, &secretName, ref)
  395. if err != nil {
  396. return nil, err
  397. }
  398. m := make(map[string]interface{})
  399. err = json.Unmarshal(secret, &m)
  400. if err != nil {
  401. return nil, err
  402. }
  403. secretMap := byteArrayMap(m)
  404. return secretMap, nil
  405. default:
  406. return nil, fmt.Errorf("unknown secret type %s", secretType)
  407. }
  408. }
  409. func byteArrayMap(secretData map[string]interface{}) map[string][]byte {
  410. var err error
  411. secretMap := make(map[string][]byte)
  412. for k, v := range secretData {
  413. secretMap[k], err = getTypedKey(v)
  414. if err != nil {
  415. return nil
  416. }
  417. }
  418. return secretMap
  419. }
  420. // kudos Vault Provider - convert from various types.
  421. func getTypedKey(v interface{}) ([]byte, error) {
  422. switch t := v.(type) {
  423. case string:
  424. return []byte(t), nil
  425. case map[string]interface{}:
  426. return json.Marshal(t)
  427. case map[string]string:
  428. return json.Marshal(t)
  429. case []byte:
  430. return t, nil
  431. // also covers int and float32 due to json.Marshal
  432. case float64:
  433. return []byte(strconv.FormatFloat(t, 'f', -1, 64)), nil
  434. case bool:
  435. return []byte(strconv.FormatBool(t)), nil
  436. case nil:
  437. return []byte(nil), nil
  438. default:
  439. return nil, fmt.Errorf("secret not in expected format")
  440. }
  441. }
  442. func (ibm *providerIBM) Close(ctx context.Context) error {
  443. return nil
  444. }
  445. func (ibm *providerIBM) Validate() (esv1beta1.ValidationResult, error) {
  446. return esv1beta1.ValidationResultReady, nil
  447. }
  448. func (ibm *providerIBM) ValidateStore(store esv1beta1.GenericStore) error {
  449. storeSpec := store.GetSpec()
  450. ibmSpec := storeSpec.Provider.IBM
  451. if ibmSpec.ServiceURL == nil {
  452. return fmt.Errorf("serviceURL is required")
  453. }
  454. containerRef := ibmSpec.Auth.ContainerAuth
  455. secretKeyRef := ibmSpec.Auth.SecretRef.SecretAPIKey
  456. if utils.IsNil(containerRef.Profile) || (containerRef.Profile == "") {
  457. // proceed with API Key Auth validation
  458. err := utils.ValidateSecretSelector(store, secretKeyRef)
  459. if err != nil {
  460. return err
  461. }
  462. if secretKeyRef.Name == "" {
  463. return fmt.Errorf("secretAPIKey.name cannot be empty")
  464. }
  465. if secretKeyRef.Key == "" {
  466. return fmt.Errorf("secretAPIKey.key cannot be empty")
  467. }
  468. } else {
  469. // proceed with container auth
  470. if containerRef.TokenLocation == "" {
  471. containerRef.TokenLocation = "/var/run/secrets/tokens/vault-token"
  472. }
  473. if _, err := os.Open(containerRef.TokenLocation); err != nil {
  474. return fmt.Errorf("cannot read container auth token %s. %w", containerRef.TokenLocation, err)
  475. }
  476. }
  477. return nil
  478. }
  479. // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite).
  480. func (ibm *providerIBM) Capabilities() esv1beta1.SecretStoreCapabilities {
  481. return esv1beta1.SecretStoreReadOnly
  482. }
  483. func (ibm *providerIBM) NewClient(ctx context.Context, store esv1beta1.GenericStore, kube kclient.Client, namespace string) (esv1beta1.SecretsClient, error) {
  484. storeSpec := store.GetSpec()
  485. ibmSpec := storeSpec.Provider.IBM
  486. iStore := &client{
  487. kube: kube,
  488. store: ibmSpec,
  489. namespace: namespace,
  490. storeKind: store.GetObjectKind().GroupVersionKind().Kind,
  491. }
  492. var err error
  493. var secretsManager *sm.SecretsManagerV1
  494. containerAuthProfile := iStore.store.Auth.ContainerAuth.Profile
  495. if containerAuthProfile != "" {
  496. // container-based auth
  497. containerAuthToken := iStore.store.Auth.ContainerAuth.TokenLocation
  498. containerAuthEndpoint := iStore.store.Auth.ContainerAuth.IAMEndpoint
  499. if containerAuthToken == "" {
  500. // API default path
  501. containerAuthToken = "/var/run/secrets/tokens/vault-token"
  502. }
  503. if containerAuthEndpoint == "" {
  504. // API default path
  505. containerAuthEndpoint = "https://iam.cloud.ibm.com"
  506. }
  507. authenticator, err := core.NewContainerAuthenticatorBuilder().
  508. SetIAMProfileName(containerAuthProfile).
  509. SetCRTokenFilename(containerAuthToken).
  510. SetURL(containerAuthEndpoint).
  511. Build()
  512. if err != nil {
  513. return nil, fmt.Errorf(errIBMClient, err)
  514. }
  515. secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
  516. URL: *storeSpec.Provider.IBM.ServiceURL,
  517. Authenticator: authenticator,
  518. })
  519. if err != nil {
  520. return nil, fmt.Errorf(errIBMClient, err)
  521. }
  522. } else {
  523. // API Key-based auth
  524. if err := iStore.setAuth(ctx); err != nil {
  525. return nil, err
  526. }
  527. secretsManager, err = sm.NewSecretsManagerV1(&sm.SecretsManagerV1Options{
  528. URL: *storeSpec.Provider.IBM.ServiceURL,
  529. Authenticator: &core.IamAuthenticator{
  530. ApiKey: string(iStore.credentials),
  531. },
  532. })
  533. }
  534. // Setup retry options, but only if present
  535. if storeSpec.RetrySettings != nil {
  536. var retryAmount int
  537. var retryDuration time.Duration
  538. if storeSpec.RetrySettings.MaxRetries != nil {
  539. retryAmount = int(*storeSpec.RetrySettings.MaxRetries)
  540. } else {
  541. retryAmount = 3
  542. }
  543. if storeSpec.RetrySettings.RetryInterval != nil {
  544. retryDuration, err = time.ParseDuration(*storeSpec.RetrySettings.RetryInterval)
  545. } else {
  546. retryDuration = 5 * time.Second
  547. }
  548. if err == nil {
  549. secretsManager.Service.EnableRetries(retryAmount, retryDuration)
  550. }
  551. }
  552. if err != nil {
  553. return nil, fmt.Errorf(errIBMClient, err)
  554. }
  555. ibm.IBMClient = secretsManager
  556. return ibm, nil
  557. }
  558. func init() {
  559. esv1beta1.Register(&providerIBM{}, &esv1beta1.SecretStoreProvider{
  560. IBM: &esv1beta1.IBMProvider{},
  561. })
  562. }