oracle.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660
  1. /*
  2. Copyright © 2025 ESO Maintainer Team
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. https://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package oracle
  14. import (
  15. "bytes"
  16. "context"
  17. "encoding/base64"
  18. "encoding/json"
  19. "errors"
  20. "fmt"
  21. "os"
  22. "regexp"
  23. "sync"
  24. "time"
  25. "github.com/oracle/oci-go-sdk/v65/common"
  26. "github.com/oracle/oci-go-sdk/v65/common/auth"
  27. "github.com/oracle/oci-go-sdk/v65/keymanagement"
  28. "github.com/oracle/oci-go-sdk/v65/secrets"
  29. "github.com/oracle/oci-go-sdk/v65/vault"
  30. "github.com/tidwall/gjson"
  31. corev1 "k8s.io/api/core/v1"
  32. "k8s.io/client-go/kubernetes"
  33. kclient "sigs.k8s.io/controller-runtime/pkg/client"
  34. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  35. "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
  36. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  37. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  38. "github.com/external-secrets/external-secrets/pkg/utils"
  39. "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
  40. )
  41. const (
  42. errOracleClient = "cannot setup new oracle client: %w"
  43. errORACLECredSecretName = "invalid oracle SecretStore resource: missing oracle APIKey"
  44. errUninitalizedOracleProvider = "provider oracle is not initialized"
  45. errFetchSAKSecret = "could not fetch SecretAccessKey secret: %w"
  46. errMissingPK = "missing PrivateKey"
  47. errMissingUser = "missing User ID"
  48. errMissingTenancy = "missing Tenancy ID"
  49. errMissingRegion = "missing Region"
  50. errMissingFingerprint = "missing Fingerprint"
  51. errMissingVault = "missing Vault"
  52. errJSONSecretUnmarshal = "unable to unmarshal secret from JSON: %w"
  53. errMissingKey = "missing Key in secret: %s"
  54. errUnexpectedContent = "unexpected secret bundle content"
  55. errSettingOCIEnvVariables = "unable to set OCI SDK environment variable %s: %w"
  56. )
  57. // https://github.com/external-secrets/external-secrets/issues/644
  58. var _ esv1.SecretsClient = &VaultManagementService{}
  59. var _ esv1.Provider = &VaultManagementService{}
  60. type VaultManagementService struct {
  61. Client VMInterface
  62. KmsVaultClient KmsVCInterface
  63. VaultClient VaultInterface
  64. vault string
  65. compartment string
  66. encryptionKey string
  67. workloadIdentityMutex sync.Mutex
  68. }
  69. type VMInterface interface {
  70. GetSecretBundleByName(ctx context.Context, request secrets.GetSecretBundleByNameRequest) (secrets.GetSecretBundleByNameResponse, error)
  71. }
  72. type KmsVCInterface interface {
  73. GetVault(ctx context.Context, request keymanagement.GetVaultRequest) (response keymanagement.GetVaultResponse, err error)
  74. }
  75. type VaultInterface interface {
  76. ListSecrets(ctx context.Context, request vault.ListSecretsRequest) (response vault.ListSecretsResponse, err error)
  77. CreateSecret(ctx context.Context, request vault.CreateSecretRequest) (response vault.CreateSecretResponse, err error)
  78. UpdateSecret(ctx context.Context, request vault.UpdateSecretRequest) (response vault.UpdateSecretResponse, err error)
  79. ScheduleSecretDeletion(ctx context.Context, request vault.ScheduleSecretDeletionRequest) (response vault.ScheduleSecretDeletionResponse, err error)
  80. }
  81. const (
  82. SecretNotFound = iota
  83. SecretExists
  84. SecretAPIError
  85. )
  86. func (vms *VaultManagementService) PushSecret(ctx context.Context, secret *corev1.Secret, data esv1.PushSecretData) error {
  87. if vms.encryptionKey == "" {
  88. return errors.New("SecretStore must reference encryption key")
  89. }
  90. value := secret.Data[data.GetSecretKey()]
  91. if data.GetSecretKey() == "" {
  92. secretData := map[string]string{}
  93. for k, v := range secret.Data {
  94. secretData[k] = string(v)
  95. }
  96. jsonSecret, err := json.Marshal(secretData)
  97. if err != nil {
  98. return fmt.Errorf("unable to create json %v from value: %v", value, secretData)
  99. }
  100. value = jsonSecret
  101. }
  102. secretName := data.GetRemoteKey()
  103. encodedValue := base64.StdEncoding.EncodeToString(value)
  104. sec, action, err := vms.getSecretBundleWithCode(ctx, secretName)
  105. switch action {
  106. case SecretNotFound:
  107. _, err = vms.VaultClient.CreateSecret(ctx, vault.CreateSecretRequest{
  108. CreateSecretDetails: vault.CreateSecretDetails{
  109. CompartmentId: &vms.compartment,
  110. KeyId: &vms.encryptionKey,
  111. SecretContent: vault.Base64SecretContentDetails{
  112. Content: &encodedValue,
  113. },
  114. SecretName: &secretName,
  115. VaultId: &vms.vault,
  116. },
  117. })
  118. return sanitizeOCISDKErr(err)
  119. case SecretExists:
  120. payload, err := decodeBundle(sec)
  121. if err != nil {
  122. return err
  123. }
  124. if bytes.Equal(payload, value) {
  125. return nil
  126. }
  127. _, err = vms.VaultClient.UpdateSecret(ctx, vault.UpdateSecretRequest{
  128. SecretId: sec.SecretId,
  129. UpdateSecretDetails: vault.UpdateSecretDetails{
  130. SecretContent: vault.Base64SecretContentDetails{
  131. Content: &encodedValue,
  132. },
  133. },
  134. })
  135. return sanitizeOCISDKErr(err)
  136. default:
  137. return sanitizeOCISDKErr(err)
  138. }
  139. }
  140. func (vms *VaultManagementService) DeleteSecret(ctx context.Context, remoteRef esv1.PushSecretRemoteRef) error {
  141. secretName := remoteRef.GetRemoteKey()
  142. resp, action, err := vms.getSecretBundleWithCode(ctx, secretName)
  143. switch action {
  144. case SecretNotFound:
  145. return nil
  146. case SecretExists:
  147. if resp.TimeOfDeletion != nil {
  148. return nil
  149. }
  150. _, err = vms.VaultClient.ScheduleSecretDeletion(ctx, vault.ScheduleSecretDeletionRequest{
  151. SecretId: resp.SecretId,
  152. })
  153. return sanitizeOCISDKErr(err)
  154. default:
  155. return sanitizeOCISDKErr(err)
  156. }
  157. }
  158. func (vms *VaultManagementService) SecretExists(_ context.Context, _ esv1.PushSecretRemoteRef) (bool, error) {
  159. return false, errors.New("not implemented")
  160. }
  161. func (vms *VaultManagementService) GetAllSecrets(ctx context.Context, ref esv1.ExternalSecretFind) (map[string][]byte, error) {
  162. var page *string
  163. var summaries []vault.SecretSummary
  164. for {
  165. resp, err := vms.VaultClient.ListSecrets(ctx, vault.ListSecretsRequest{
  166. CompartmentId: &vms.compartment,
  167. Page: page,
  168. VaultId: &vms.vault,
  169. })
  170. if err != nil {
  171. return nil, sanitizeOCISDKErr(err)
  172. }
  173. summaries = append(summaries, resp.Items...)
  174. if page = resp.OpcNextPage; resp.OpcNextPage == nil {
  175. break
  176. }
  177. }
  178. return vms.filteredSummaryResult(ctx, summaries, ref)
  179. }
  180. func (vms *VaultManagementService) GetSecret(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) ([]byte, error) {
  181. if utils.IsNil(vms.Client) {
  182. return nil, errors.New(errUninitalizedOracleProvider)
  183. }
  184. sec, err := vms.Client.GetSecretBundleByName(ctx, secrets.GetSecretBundleByNameRequest{
  185. VaultId: &vms.vault,
  186. SecretName: &ref.Key,
  187. Stage: secrets.GetSecretBundleByNameStageEnum(ref.Version),
  188. })
  189. if err != nil {
  190. return nil, sanitizeOCISDKErr(err)
  191. }
  192. payload, err := decodeBundle(sec)
  193. if err != nil {
  194. return nil, err
  195. }
  196. if ref.Property == "" {
  197. return payload, nil
  198. }
  199. val := gjson.Get(string(payload), ref.Property)
  200. if !val.Exists() {
  201. return nil, fmt.Errorf(errMissingKey, ref.Key)
  202. }
  203. return []byte(val.String()), nil
  204. }
  205. func decodeBundle(sec secrets.GetSecretBundleByNameResponse) ([]byte, error) {
  206. bt, ok := sec.SecretBundleContent.(secrets.Base64SecretBundleContentDetails)
  207. if !ok {
  208. return nil, errors.New(errUnexpectedContent)
  209. }
  210. payload, err := base64.StdEncoding.DecodeString(*bt.Content)
  211. if err != nil {
  212. return nil, err
  213. }
  214. return payload, nil
  215. }
  216. func (vms *VaultManagementService) GetSecretMap(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  217. data, err := vms.GetSecret(ctx, ref)
  218. if err != nil {
  219. return nil, sanitizeOCISDKErr(err)
  220. }
  221. kv := make(map[string]string)
  222. err = json.Unmarshal(data, &kv)
  223. if err != nil {
  224. return nil, fmt.Errorf(errJSONSecretUnmarshal, err)
  225. }
  226. secretData := make(map[string][]byte)
  227. for k, v := range kv {
  228. secretData[k] = []byte(v)
  229. }
  230. return secretData, nil
  231. }
  232. // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite).
  233. func (vms *VaultManagementService) Capabilities() esv1.SecretStoreCapabilities {
  234. return esv1.SecretStoreReadOnly
  235. }
  236. // NewClient constructs a new secrets client based on the provided store.
  237. func (vms *VaultManagementService) NewClient(ctx context.Context, store esv1.GenericStore, kube kclient.Client, namespace string) (esv1.SecretsClient, error) {
  238. storeSpec := store.GetSpec()
  239. oracleSpec := storeSpec.Provider.Oracle
  240. if oracleSpec.Vault == "" {
  241. return nil, errors.New(errMissingVault)
  242. }
  243. if oracleSpec.Region == "" {
  244. return nil, errors.New(errMissingRegion)
  245. }
  246. configurationProvider, err := vms.constructProvider(ctx, store, oracleSpec, kube, namespace)
  247. if err != nil {
  248. return nil, err
  249. }
  250. secretManagementService, err := secrets.NewSecretsClientWithConfigurationProvider(configurationProvider)
  251. if err != nil {
  252. return nil, fmt.Errorf(errOracleClient, err)
  253. }
  254. secretManagementService.SetRegion(oracleSpec.Region)
  255. kmsVaultClient, err := keymanagement.NewKmsVaultClientWithConfigurationProvider(configurationProvider)
  256. if err != nil {
  257. return nil, fmt.Errorf(errOracleClient, err)
  258. }
  259. kmsVaultClient.SetRegion(oracleSpec.Region)
  260. vaultClient, err := vault.NewVaultsClientWithConfigurationProvider(configurationProvider)
  261. if err != nil {
  262. return nil, fmt.Errorf(errOracleClient, err)
  263. }
  264. vaultClient.SetRegion(oracleSpec.Region)
  265. if storeSpec.RetrySettings != nil {
  266. if err := vms.configureRetryPolicy(storeSpec, secretManagementService, kmsVaultClient, vaultClient); err != nil {
  267. return nil, fmt.Errorf(errOracleClient, err)
  268. }
  269. }
  270. return &VaultManagementService{
  271. Client: secretManagementService,
  272. KmsVaultClient: kmsVaultClient,
  273. VaultClient: vaultClient,
  274. vault: oracleSpec.Vault,
  275. compartment: oracleSpec.Compartment,
  276. encryptionKey: oracleSpec.EncryptionKey,
  277. }, nil
  278. }
  279. func (vms *VaultManagementService) constructOptions(storeSpec *esv1.SecretStoreSpec) ([]common.RetryPolicyOption, error) {
  280. opts := []common.RetryPolicyOption{common.WithShouldRetryOperation(common.DefaultShouldRetryOperation)}
  281. if mr := storeSpec.RetrySettings.MaxRetries; mr != nil {
  282. attempts := safeConvert(*mr)
  283. opts = append(opts, common.WithMaximumNumberAttempts(attempts))
  284. }
  285. if ri := storeSpec.RetrySettings.RetryInterval; ri != nil {
  286. i, err := time.ParseDuration(*storeSpec.RetrySettings.RetryInterval)
  287. if err != nil {
  288. return nil, fmt.Errorf(errOracleClient, err)
  289. }
  290. opts = append(opts, common.WithFixedBackoff(i))
  291. }
  292. return opts, nil
  293. }
  294. func safeConvert(i int32) uint {
  295. if i < 0 {
  296. return 0
  297. }
  298. return uint(i)
  299. }
  300. func (vms *VaultManagementService) getSecretBundleWithCode(ctx context.Context, secretName string) (secrets.GetSecretBundleByNameResponse, int, error) {
  301. // Try to look up the secret, which will determine if we should create or update the secret.
  302. resp, err := vms.Client.GetSecretBundleByName(ctx, secrets.GetSecretBundleByNameRequest{
  303. SecretName: &secretName,
  304. VaultId: &vms.vault,
  305. })
  306. // Get a PushSecret action depending on the ListSecrets response.
  307. action := getSecretBundleCode(err)
  308. return resp, action, err
  309. }
  310. func getSecretBundleCode(err error) int {
  311. if err != nil {
  312. // If we got a 404 service error, try to create the secret.
  313. if serviceErr, ok := err.(common.ServiceError); ok && serviceErr.GetHTTPStatusCode() == 404 {
  314. return SecretNotFound
  315. }
  316. return SecretAPIError
  317. }
  318. // Otherwise, update the existing secret.
  319. return SecretExists
  320. }
  321. func (vms *VaultManagementService) filteredSummaryResult(ctx context.Context, secretSummaries []vault.SecretSummary, ref esv1.ExternalSecretFind) (map[string][]byte, error) {
  322. secretMap := map[string][]byte{}
  323. for _, summary := range secretSummaries {
  324. matches, err := matchesRef(summary, ref)
  325. if err != nil {
  326. return nil, err
  327. }
  328. if !matches || summary.TimeOfDeletion != nil {
  329. continue
  330. }
  331. secret, err := vms.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{
  332. Key: *summary.SecretName,
  333. })
  334. if err != nil {
  335. return nil, err
  336. }
  337. secretMap[*summary.SecretName] = secret
  338. }
  339. return secretMap, nil
  340. }
  341. func matchesRef(secretSummary vault.SecretSummary, ref esv1.ExternalSecretFind) (bool, error) {
  342. if ref.Name != nil {
  343. matchString, err := regexp.MatchString(ref.Name.RegExp, *secretSummary.SecretName)
  344. if err != nil {
  345. return false, err
  346. }
  347. return matchString, nil
  348. }
  349. for k, v := range ref.Tags {
  350. if val, ok := secretSummary.FreeformTags[k]; ok {
  351. if val == v {
  352. return true, nil
  353. }
  354. }
  355. }
  356. return false, nil
  357. }
  358. func getSecretData(ctx context.Context, kube kclient.Client, namespace, storeKind string, secretRef esmeta.SecretKeySelector) (string, error) {
  359. if secretRef.Name == "" {
  360. return "", errors.New(errORACLECredSecretName)
  361. }
  362. secret, err := resolvers.SecretKeyRef(
  363. ctx,
  364. kube,
  365. storeKind,
  366. namespace,
  367. &secretRef,
  368. )
  369. if err != nil {
  370. return "", fmt.Errorf(errFetchSAKSecret, err)
  371. }
  372. return secret, nil
  373. }
  374. func getUserAuthConfigurationProvider(ctx context.Context, kube kclient.Client, store *esv1.OracleProvider, namespace, storeKind, region string) (common.ConfigurationProvider, error) {
  375. privateKey, err := getSecretData(ctx, kube, namespace, storeKind, store.Auth.SecretRef.PrivateKey)
  376. if err != nil {
  377. return nil, err
  378. }
  379. if privateKey == "" {
  380. return nil, errors.New(errMissingPK)
  381. }
  382. fingerprint, err := getSecretData(ctx, kube, namespace, storeKind, store.Auth.SecretRef.Fingerprint)
  383. if err != nil {
  384. return nil, err
  385. }
  386. if fingerprint == "" {
  387. return nil, errors.New(errMissingFingerprint)
  388. }
  389. if store.Auth.User == "" {
  390. return nil, errors.New(errMissingUser)
  391. }
  392. if store.Auth.Tenancy == "" {
  393. return nil, errors.New(errMissingTenancy)
  394. }
  395. return common.NewRawConfigurationProvider(store.Auth.Tenancy, store.Auth.User, region, fingerprint, privateKey, nil), nil
  396. }
  397. func (vms *VaultManagementService) Close(_ context.Context) error {
  398. return nil
  399. }
  400. func (vms *VaultManagementService) Validate() (esv1.ValidationResult, error) {
  401. _, err := vms.KmsVaultClient.GetVault(
  402. context.Background(), keymanagement.GetVaultRequest{
  403. VaultId: &vms.vault,
  404. },
  405. )
  406. if err != nil {
  407. failure, ok := common.IsServiceError(err)
  408. if ok {
  409. code := failure.GetCode()
  410. switch code {
  411. case "NotAuthenticated":
  412. return esv1.ValidationResultError, sanitizeOCISDKErr(err)
  413. case "NotAuthorizedOrNotFound":
  414. // User authentication was successful, but user might not have a permission like:
  415. //
  416. // Allow group external_secrets to read vaults in tenancy
  417. //
  418. // Which is fine, because to read secrets we only need:
  419. //
  420. // Allow group external_secrets to read secret-family in tenancy
  421. //
  422. // But we can't test for this permission without knowing the name of a secret
  423. return esv1.ValidationResultUnknown, sanitizeOCISDKErr(err)
  424. default:
  425. return esv1.ValidationResultError, sanitizeOCISDKErr(err)
  426. }
  427. } else {
  428. return esv1.ValidationResultError, err
  429. }
  430. }
  431. return esv1.ValidationResultReady, nil
  432. }
  433. func (vms *VaultManagementService) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
  434. storeSpec := store.GetSpec()
  435. oracleSpec := storeSpec.Provider.Oracle
  436. vault := oracleSpec.Vault
  437. if vault == "" {
  438. return nil, errors.New("vault cannot be empty")
  439. }
  440. region := oracleSpec.Region
  441. if region == "" {
  442. return nil, errors.New("region cannot be empty")
  443. }
  444. auth := oracleSpec.Auth
  445. if auth == nil {
  446. return nil, nil
  447. }
  448. user := oracleSpec.Auth.User
  449. if user == "" {
  450. return nil, errors.New("user cannot be empty")
  451. }
  452. tenant := oracleSpec.Auth.Tenancy
  453. if tenant == "" {
  454. return nil, errors.New("tenant cannot be empty")
  455. }
  456. privateKey := oracleSpec.Auth.SecretRef.PrivateKey
  457. if privateKey.Name == "" {
  458. return nil, errors.New("privateKey.name cannot be empty")
  459. }
  460. if privateKey.Key == "" {
  461. return nil, errors.New("privateKey.key cannot be empty")
  462. }
  463. err := utils.ValidateSecretSelector(store, privateKey)
  464. if err != nil {
  465. return nil, err
  466. }
  467. fingerprint := oracleSpec.Auth.SecretRef.Fingerprint
  468. if fingerprint.Name == "" {
  469. return nil, errors.New("fingerprint.name cannot be empty")
  470. }
  471. if fingerprint.Key == "" {
  472. return nil, errors.New("fingerprint.key cannot be empty")
  473. }
  474. err = utils.ValidateSecretSelector(store, fingerprint)
  475. if err != nil {
  476. return nil, err
  477. }
  478. if oracleSpec.ServiceAccountRef != nil {
  479. if err := utils.ValidateReferentServiceAccountSelector(store, *oracleSpec.ServiceAccountRef); err != nil {
  480. return nil, fmt.Errorf("invalid ServiceAccountRef: %w", err)
  481. }
  482. }
  483. return nil, nil
  484. }
  485. func (vms *VaultManagementService) getWorkloadIdentityProvider(store esv1.GenericStore, serviceAcccountRef *esmeta.ServiceAccountSelector, region, namespace string) (configurationProvider common.ConfigurationProvider, err error) {
  486. defer func() {
  487. if uerr := os.Unsetenv(auth.ResourcePrincipalVersionEnvVar); uerr != nil {
  488. err = errors.Join(err, fmt.Errorf(errSettingOCIEnvVariables, auth.ResourcePrincipalRegionEnvVar, uerr))
  489. }
  490. if uerr := os.Unsetenv(auth.ResourcePrincipalRegionEnvVar); uerr != nil {
  491. err = errors.Join(err, fmt.Errorf("unabled to unset OCI SDK environment variable %s: %w", auth.ResourcePrincipalVersionEnvVar, uerr))
  492. }
  493. vms.workloadIdentityMutex.Unlock()
  494. }()
  495. vms.workloadIdentityMutex.Lock()
  496. // OCI SDK requires specific environment variables for workload identity.
  497. if err := os.Setenv(auth.ResourcePrincipalVersionEnvVar, auth.ResourcePrincipalVersion2_2); err != nil {
  498. return nil, fmt.Errorf(errSettingOCIEnvVariables, auth.ResourcePrincipalVersionEnvVar, err)
  499. }
  500. if err := os.Setenv(auth.ResourcePrincipalRegionEnvVar, region); err != nil {
  501. return nil, fmt.Errorf(errSettingOCIEnvVariables, auth.ResourcePrincipalRegionEnvVar, err)
  502. }
  503. // If no service account is specified, use the pod service account to create the Workload Identity provider.
  504. if serviceAcccountRef == nil {
  505. return auth.OkeWorkloadIdentityConfigurationProvider()
  506. }
  507. // Ensure the service account ref is being used appropriately, so arbitrary tokens are not minted by the provider.
  508. if err = utils.ValidateServiceAccountSelector(store, *serviceAcccountRef); err != nil {
  509. return nil, fmt.Errorf("invalid ServiceAccountRef: %w", err)
  510. }
  511. cfg, err := ctrlcfg.GetConfig()
  512. if err != nil {
  513. return nil, err
  514. }
  515. clientset, err := kubernetes.NewForConfig(cfg)
  516. if err != nil {
  517. return nil, err
  518. }
  519. tokenProvider := NewTokenProvider(clientset, serviceAcccountRef, namespace)
  520. return auth.OkeWorkloadIdentityConfigurationProviderWithServiceAccountTokenProvider(tokenProvider)
  521. }
  522. func (vms *VaultManagementService) constructProvider(ctx context.Context, store esv1.GenericStore, oracleSpec *esv1.OracleProvider, kube kclient.Client, namespace string) (common.ConfigurationProvider, error) {
  523. var (
  524. configurationProvider common.ConfigurationProvider
  525. err error
  526. )
  527. if oracleSpec.PrincipalType == esv1.WorkloadPrincipal {
  528. configurationProvider, err = vms.getWorkloadIdentityProvider(store, oracleSpec.ServiceAccountRef, oracleSpec.Region, namespace)
  529. } else if oracleSpec.PrincipalType == esv1.InstancePrincipal || oracleSpec.Auth == nil {
  530. configurationProvider, err = auth.InstancePrincipalConfigurationProvider()
  531. } else {
  532. configurationProvider, err = getUserAuthConfigurationProvider(ctx, kube, oracleSpec, namespace, store.GetObjectKind().GroupVersionKind().Kind, oracleSpec.Region)
  533. }
  534. if err != nil {
  535. return nil, fmt.Errorf(errOracleClient, err)
  536. }
  537. return configurationProvider, nil
  538. }
  539. func (vms *VaultManagementService) configureRetryPolicy(
  540. storeSpec *esv1.SecretStoreSpec,
  541. secretManagementService secrets.SecretsClient,
  542. kmsVaultClient keymanagement.KmsVaultClient,
  543. vaultClient vault.VaultsClient,
  544. ) error {
  545. opts, err := vms.constructOptions(storeSpec)
  546. if err != nil {
  547. return err
  548. }
  549. customRetryPolicy := common.NewRetryPolicyWithOptions(opts...)
  550. secretManagementService.SetCustomClientConfiguration(common.CustomClientConfiguration{
  551. RetryPolicy: &customRetryPolicy,
  552. })
  553. kmsVaultClient.SetCustomClientConfiguration(common.CustomClientConfiguration{
  554. RetryPolicy: &customRetryPolicy,
  555. })
  556. vaultClient.SetCustomClientConfiguration(common.CustomClientConfiguration{
  557. RetryPolicy: &customRetryPolicy,
  558. })
  559. return err
  560. }
  561. func sanitizeOCISDKErr(err error) error {
  562. if err == nil {
  563. return nil
  564. }
  565. // If we have a ServiceError from the OCI SDK, strip only the message from the verbose error
  566. if serviceError, ok := err.(common.ServiceErrorRichInfo); ok {
  567. return fmt.Errorf("%s service failed to %s, HTTP status code %d: %s", serviceError.GetTargetService(), serviceError.GetOperationName(), serviceError.GetHTTPStatusCode(), serviceError.GetMessage())
  568. }
  569. return err
  570. }
  571. func init() {
  572. esv1.Register(&VaultManagementService{}, &esv1.SecretStoreProvider{
  573. Oracle: &esv1.OracleProvider{},
  574. }, esv1.MaintenanceStatusMaintained)
  575. }