provider.go 19 KB

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