keyvault.go 41 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257
  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 keyvault
  13. import (
  14. "context"
  15. "crypto/x509"
  16. b64 "encoding/base64"
  17. "encoding/json"
  18. "encoding/pem"
  19. "errors"
  20. "fmt"
  21. "os"
  22. "path"
  23. "path/filepath"
  24. "regexp"
  25. "strings"
  26. "time"
  27. "github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault"
  28. "github.com/Azure/go-autorest/autorest"
  29. "github.com/Azure/go-autorest/autorest/adal"
  30. "github.com/Azure/go-autorest/autorest/azure"
  31. kvauth "github.com/Azure/go-autorest/autorest/azure/auth"
  32. "github.com/Azure/go-autorest/autorest/date"
  33. "github.com/AzureAD/microsoft-authentication-library-for-go/apps/confidential"
  34. "github.com/lestrrat-go/jwx/v2/jwk"
  35. "github.com/tidwall/gjson"
  36. "golang.org/x/crypto/sha3"
  37. authv1 "k8s.io/api/authentication/v1"
  38. corev1 "k8s.io/api/core/v1"
  39. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  40. "k8s.io/apimachinery/pkg/types"
  41. "k8s.io/client-go/kubernetes"
  42. kcorev1 "k8s.io/client-go/kubernetes/typed/core/v1"
  43. pointer "k8s.io/utils/ptr"
  44. "sigs.k8s.io/controller-runtime/pkg/client"
  45. ctrlcfg "sigs.k8s.io/controller-runtime/pkg/client/config"
  46. "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
  47. gopkcs12 "software.sslmate.com/src/go-pkcs12"
  48. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  49. "github.com/external-secrets/external-secrets/pkg/constants"
  50. "github.com/external-secrets/external-secrets/pkg/metrics"
  51. "github.com/external-secrets/external-secrets/pkg/utils"
  52. "github.com/external-secrets/external-secrets/pkg/utils/metadata"
  53. "github.com/external-secrets/external-secrets/pkg/utils/resolvers"
  54. )
  55. const (
  56. defaultObjType = "secret"
  57. objectTypeCert = "cert"
  58. objectTypeKey = "key"
  59. AzureDefaultAudience = "api://AzureADTokenExchange"
  60. AnnotationClientID = "azure.workload.identity/client-id"
  61. AnnotationTenantID = "azure.workload.identity/tenant-id"
  62. managerLabel = "external-secrets"
  63. managedBy = "managed-by"
  64. errUnexpectedStoreSpec = "unexpected store spec"
  65. errMissingAuthType = "cannot initialize Azure Client: no valid authType was specified"
  66. errPropNotExist = "property %s does not exist in key %s"
  67. errTagNotExist = "tag %s does not exist"
  68. errUnknownObjectType = "unknown Azure Keyvault object Type for %s"
  69. errUnmarshalJSONData = "error unmarshalling json data: %w"
  70. errDataFromCert = "cannot get use dataFrom to get certificate secret"
  71. errDataFromKey = "cannot get use dataFrom to get key secret"
  72. errMissingTenant = "missing tenantID in store config"
  73. errMissingClient = "missing clientID: either serviceAccountRef or service account annotation '%s' is missing"
  74. errMissingSecretRef = "missing secretRef in provider config"
  75. errMissingClientIDSecret = "missing accessKeyID/secretAccessKey in store config"
  76. errInvalidClientCredentials = "both clientSecret and clientCredentials set"
  77. errMultipleClientID = "multiple clientID found. Check secretRef and serviceAccountRef"
  78. errMultipleTenantID = "multiple tenantID found. Check secretRef, 'spec.provider.azurekv.tenantId', and serviceAccountRef"
  79. errInvalidStore = "invalid store"
  80. errInvalidStoreSpec = "invalid store spec"
  81. errInvalidStoreProv = "invalid store provider"
  82. errInvalidAzureProv = "invalid azure keyvault provider"
  83. errInvalidSecRefClientID = "invalid AuthSecretRef.ClientID: %w"
  84. errInvalidSecRefClientSecret = "invalid AuthSecretRef.ClientSecret: %w"
  85. errInvalidSARef = "invalid ServiceAccountRef: %w"
  86. errMissingWorkloadEnvVars = "missing environment variables. AZURE_CLIENT_ID, AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE must be set"
  87. errReadTokenFile = "unable to read token file %s: %w"
  88. )
  89. // https://github.com/external-secrets/external-secrets/issues/644
  90. var _ esv1.SecretsClient = &Azure{}
  91. var _ esv1.Provider = &Azure{}
  92. // interface to keyvault.BaseClient.
  93. type SecretClient interface {
  94. GetKey(ctx context.Context, vaultBaseURL string, keyName string, keyVersion string) (result keyvault.KeyBundle, err error)
  95. GetSecret(ctx context.Context, vaultBaseURL string, secretName string, secretVersion string) (result keyvault.SecretBundle, err error)
  96. GetSecretsComplete(ctx context.Context, vaultBaseURL string, maxresults *int32) (result keyvault.SecretListResultIterator, err error)
  97. GetCertificate(ctx context.Context, vaultBaseURL string, certificateName string, certificateVersion string) (result keyvault.CertificateBundle, err error)
  98. SetSecret(ctx context.Context, vaultBaseURL string, secretName string, parameters keyvault.SecretSetParameters) (result keyvault.SecretBundle, err error)
  99. ImportKey(ctx context.Context, vaultBaseURL string, keyName string, parameters keyvault.KeyImportParameters) (result keyvault.KeyBundle, err error)
  100. ImportCertificate(ctx context.Context, vaultBaseURL string, certificateName string, parameters keyvault.CertificateImportParameters) (result keyvault.CertificateBundle, err error)
  101. DeleteCertificate(ctx context.Context, vaultBaseURL string, certificateName string) (result keyvault.DeletedCertificateBundle, err error)
  102. DeleteKey(ctx context.Context, vaultBaseURL string, keyName string) (result keyvault.DeletedKeyBundle, err error)
  103. DeleteSecret(ctx context.Context, vaultBaseURL string, secretName string) (result keyvault.DeletedSecretBundle, err error)
  104. }
  105. type Azure struct {
  106. crClient client.Client
  107. kubeClient kcorev1.CoreV1Interface
  108. store esv1.GenericStore
  109. provider *esv1.AzureKVProvider
  110. baseClient SecretClient
  111. namespace string
  112. }
  113. type PushSecretMetadataSpec struct {
  114. ExpirationDate string `json:"expirationDate,omitempty"`
  115. Tags map[string]string `json:"tags,omitempty"`
  116. }
  117. func init() {
  118. esv1.Register(&Azure{}, &esv1.SecretStoreProvider{
  119. AzureKV: &esv1.AzureKVProvider{},
  120. }, esv1.MaintenanceStatusMaintained)
  121. }
  122. // Capabilities return the provider supported capabilities (ReadOnly, WriteOnly, ReadWrite).
  123. func (a *Azure) Capabilities() esv1.SecretStoreCapabilities {
  124. return esv1.SecretStoreReadWrite
  125. }
  126. // NewClient constructs a new secrets client based on the provided store.
  127. func (a *Azure) NewClient(ctx context.Context, store esv1.GenericStore, kube client.Client, namespace string) (esv1.SecretsClient, error) {
  128. return newClient(ctx, store, kube, namespace)
  129. }
  130. func newClient(ctx context.Context, store esv1.GenericStore, kube client.Client, namespace string) (esv1.SecretsClient, error) {
  131. provider, err := getProvider(store)
  132. if err != nil {
  133. return nil, err
  134. }
  135. cfg, err := ctrlcfg.GetConfig()
  136. if err != nil {
  137. return nil, err
  138. }
  139. kubeClient, err := kubernetes.NewForConfig(cfg)
  140. if err != nil {
  141. return nil, err
  142. }
  143. az := &Azure{
  144. crClient: kube,
  145. kubeClient: kubeClient.CoreV1(),
  146. store: store,
  147. namespace: namespace,
  148. provider: provider,
  149. }
  150. // allow SecretStore controller validation to pass
  151. // when using referent namespace.
  152. if store.GetKind() == esv1.ClusterSecretStoreKind &&
  153. namespace == "" &&
  154. isReferentSpec(provider) {
  155. return az, nil
  156. }
  157. var authorizer autorest.Authorizer
  158. switch *provider.AuthType {
  159. case esv1.AzureManagedIdentity:
  160. authorizer, err = az.authorizerForManagedIdentity()
  161. case esv1.AzureServicePrincipal:
  162. authorizer, err = az.authorizerForServicePrincipal(ctx)
  163. case esv1.AzureWorkloadIdentity:
  164. authorizer, err = az.authorizerForWorkloadIdentity(ctx, NewTokenProvider)
  165. default:
  166. err = errors.New(errMissingAuthType)
  167. }
  168. cl := keyvault.New()
  169. cl.Authorizer = authorizer
  170. az.baseClient = &cl
  171. return az, err
  172. }
  173. func getProvider(store esv1.GenericStore) (*esv1.AzureKVProvider, error) {
  174. spc := store.GetSpec()
  175. if spc == nil || spc.Provider.AzureKV == nil {
  176. return nil, errors.New(errUnexpectedStoreSpec)
  177. }
  178. return spc.Provider.AzureKV, nil
  179. }
  180. func (a *Azure) ValidateStore(store esv1.GenericStore) (admission.Warnings, error) {
  181. if store == nil {
  182. return nil, errors.New(errInvalidStore)
  183. }
  184. spc := store.GetSpec()
  185. if spc == nil {
  186. return nil, errors.New(errInvalidStoreSpec)
  187. }
  188. if spc.Provider == nil {
  189. return nil, errors.New(errInvalidStoreProv)
  190. }
  191. p := spc.Provider.AzureKV
  192. if p == nil {
  193. return nil, errors.New(errInvalidAzureProv)
  194. }
  195. if p.AuthSecretRef != nil {
  196. if p.AuthSecretRef.ClientID != nil {
  197. if err := utils.ValidateReferentSecretSelector(store, *p.AuthSecretRef.ClientID); err != nil {
  198. return nil, fmt.Errorf(errInvalidSecRefClientID, err)
  199. }
  200. }
  201. if p.AuthSecretRef.ClientSecret != nil {
  202. if err := utils.ValidateReferentSecretSelector(store, *p.AuthSecretRef.ClientSecret); err != nil {
  203. return nil, fmt.Errorf(errInvalidSecRefClientSecret, err)
  204. }
  205. }
  206. }
  207. if p.ServiceAccountRef != nil {
  208. if err := utils.ValidateReferentServiceAccountSelector(store, *p.ServiceAccountRef); err != nil {
  209. return nil, fmt.Errorf(errInvalidSARef, err)
  210. }
  211. }
  212. return nil, nil
  213. }
  214. func canDelete(tags map[string]*string, err error) (bool, error) {
  215. aerr := &autorest.DetailedError{}
  216. conv := errors.As(err, aerr)
  217. if err != nil && !conv {
  218. return false, fmt.Errorf("could not parse error: %w", err)
  219. }
  220. if conv && aerr.StatusCode != 404 { // Secret is already deleted, nothing to do.
  221. return false, fmt.Errorf("unexpected api error: %w", err)
  222. }
  223. if aerr.StatusCode == 404 {
  224. return false, nil
  225. }
  226. manager, ok := tags[managedBy]
  227. if !ok || manager == nil || *manager != managerLabel {
  228. return false, errors.New("not managed by external-secrets")
  229. }
  230. return true, nil
  231. }
  232. func (a *Azure) deleteKeyVaultKey(ctx context.Context, keyName string) error {
  233. value, err := a.baseClient.GetKey(ctx, *a.provider.VaultURL, keyName, "")
  234. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetKey, err)
  235. ok, err := canDelete(value.Tags, err)
  236. if err != nil {
  237. return fmt.Errorf("error getting key %v: %w", keyName, err)
  238. }
  239. if ok {
  240. _, err = a.baseClient.DeleteKey(ctx, *a.provider.VaultURL, keyName)
  241. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVDeleteKey, err)
  242. if err != nil {
  243. return fmt.Errorf("error deleting key %v: %w", keyName, err)
  244. }
  245. }
  246. return nil
  247. }
  248. func (a *Azure) deleteKeyVaultSecret(ctx context.Context, secretName string) error {
  249. value, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "")
  250. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  251. ok, err := canDelete(value.Tags, err)
  252. if err != nil {
  253. return fmt.Errorf("error getting secret %v: %w", secretName, err)
  254. }
  255. if ok {
  256. _, err = a.baseClient.DeleteSecret(ctx, *a.provider.VaultURL, secretName)
  257. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVDeleteSecret, err)
  258. if err != nil {
  259. return fmt.Errorf("error deleting secret %v: %w", secretName, err)
  260. }
  261. }
  262. return nil
  263. }
  264. func (a *Azure) deleteKeyVaultCertificate(ctx context.Context, certName string) error {
  265. value, err := a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, certName, "")
  266. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetCertificate, err)
  267. ok, err := canDelete(value.Tags, err)
  268. if err != nil {
  269. return fmt.Errorf("error getting certificate %v: %w", certName, err)
  270. }
  271. if ok {
  272. _, err = a.baseClient.DeleteCertificate(ctx, *a.provider.VaultURL, certName)
  273. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVDeleteCertificate, err)
  274. if err != nil {
  275. return fmt.Errorf("error deleting certificate %v: %w", certName, err)
  276. }
  277. }
  278. return nil
  279. }
  280. func (a *Azure) DeleteSecret(ctx context.Context, remoteRef esv1.PushSecretRemoteRef) error {
  281. objectType, secretName := getObjType(esv1.ExternalSecretDataRemoteRef{Key: remoteRef.GetRemoteKey()})
  282. switch objectType {
  283. case defaultObjType:
  284. return a.deleteKeyVaultSecret(ctx, secretName)
  285. case objectTypeCert:
  286. return a.deleteKeyVaultCertificate(ctx, secretName)
  287. case objectTypeKey:
  288. return a.deleteKeyVaultKey(ctx, secretName)
  289. default:
  290. return fmt.Errorf("secret type '%v' is not supported", objectType)
  291. }
  292. }
  293. func (a *Azure) SecretExists(ctx context.Context, remoteRef esv1.PushSecretRemoteRef) (bool, error) {
  294. objectType, secretName := getObjType(esv1.ExternalSecretDataRemoteRef{Key: remoteRef.GetRemoteKey()})
  295. var err error
  296. switch objectType {
  297. case defaultObjType:
  298. _, err = a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "")
  299. case objectTypeCert:
  300. _, err = a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, secretName, "")
  301. case objectTypeKey:
  302. _, err = a.baseClient.GetKey(ctx, *a.provider.VaultURL, secretName, "")
  303. default:
  304. errMsg := fmt.Sprintf("secret type '%v' is not supported", objectType)
  305. return false, errors.New(errMsg)
  306. }
  307. err = parseError(err)
  308. if err != nil {
  309. var noSecretErr esv1.NoSecretError
  310. if errors.As(err, &noSecretErr) {
  311. return false, nil
  312. }
  313. return false, err
  314. }
  315. return true, nil
  316. }
  317. func getCertificateFromValue(value []byte) (*x509.Certificate, error) {
  318. // 1st: try decode pkcs12
  319. _, localCert, err := gopkcs12.Decode(value, "")
  320. if err == nil {
  321. return localCert, nil
  322. }
  323. // 2nd: try decode pkcs12 with chain
  324. _, localCert, _, err = gopkcs12.DecodeChain(value, "")
  325. if err == nil {
  326. return localCert, nil
  327. }
  328. // 3rd: try DER
  329. localCert, err = x509.ParseCertificate(value)
  330. if err == nil {
  331. return localCert, nil
  332. }
  333. // 4th: parse PEM blocks
  334. for {
  335. block, rest := pem.Decode(value)
  336. value = rest
  337. if block == nil {
  338. break
  339. }
  340. cert, err := x509.ParseCertificate(block.Bytes)
  341. if err == nil {
  342. return cert, nil
  343. }
  344. }
  345. return nil, errors.New("could not parse certificate value as PKCS#12, DER or PEM")
  346. }
  347. func getKeyFromValue(value []byte) (any, error) {
  348. val := value
  349. pemBlock, _ := pem.Decode(value)
  350. // if a private key regular expression doesn't match, we should consider this key to be symmetric
  351. if pemBlock == nil {
  352. return val, nil
  353. }
  354. val = pemBlock.Bytes
  355. switch pemBlock.Type {
  356. case "PRIVATE KEY":
  357. return x509.ParsePKCS8PrivateKey(val)
  358. case "RSA PRIVATE KEY":
  359. return x509.ParsePKCS1PrivateKey(val)
  360. case "EC PRIVATE KEY":
  361. return x509.ParseECPrivateKey(val)
  362. default:
  363. return nil, fmt.Errorf("key type %v is not supported", pemBlock.Type)
  364. }
  365. }
  366. func canCreate(tags map[string]*string, err error) (bool, error) {
  367. aerr := &autorest.DetailedError{}
  368. conv := errors.As(err, aerr)
  369. if err != nil && !conv {
  370. return false, fmt.Errorf("could not parse error: %w", err)
  371. }
  372. if conv && aerr.StatusCode != 404 {
  373. return false, fmt.Errorf("unexpected api error: %w", err)
  374. }
  375. if err == nil {
  376. manager, ok := tags[managedBy]
  377. if !ok || manager == nil || *manager != managerLabel {
  378. return false, errors.New("not managed by external-secrets")
  379. }
  380. }
  381. return true, nil
  382. }
  383. func (a *Azure) setKeyVaultSecret(ctx context.Context, secretName string, value []byte, expires *date.UnixTime, tags map[string]string) error {
  384. secret, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "")
  385. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  386. ok, err := canCreate(secret.Tags, err)
  387. if err != nil {
  388. return fmt.Errorf("cannot get secret %v: %w", secretName, err)
  389. }
  390. if !ok {
  391. return nil
  392. }
  393. val := string(value)
  394. if secret.Value != nil && val == *secret.Value {
  395. if secret.Attributes != nil {
  396. if (secret.Attributes.Expires == nil && expires == nil) ||
  397. (secret.Attributes.Expires != nil && expires != nil && *secret.Attributes.Expires == *expires) {
  398. return nil
  399. }
  400. }
  401. }
  402. secretParams := keyvault.SecretSetParameters{
  403. Value: &val,
  404. Tags: map[string]*string{
  405. managedBy: pointer.To(managerLabel),
  406. },
  407. SecretAttributes: &keyvault.SecretAttributes{
  408. Enabled: pointer.To(true),
  409. },
  410. }
  411. for k, v := range tags {
  412. secretParams.Tags[k] = &v
  413. }
  414. if expires != nil {
  415. secretParams.SecretAttributes.Expires = expires
  416. }
  417. _, err = a.baseClient.SetSecret(ctx, *a.provider.VaultURL, secretName, secretParams)
  418. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  419. if err != nil {
  420. return fmt.Errorf("could not set secret %v: %w", secretName, err)
  421. }
  422. return nil
  423. }
  424. func (a *Azure) setKeyVaultCertificate(ctx context.Context, secretName string, value []byte, tags map[string]string) error {
  425. val := b64.StdEncoding.EncodeToString(value)
  426. localCert, err := getCertificateFromValue(value)
  427. if err != nil {
  428. return fmt.Errorf("value from secret is not a valid certificate: %w", err)
  429. }
  430. cert, err := a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, secretName, "")
  431. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetCertificate, err)
  432. ok, err := canCreate(cert.Tags, err)
  433. if err != nil {
  434. return fmt.Errorf("cannot get certificate %v: %w", secretName, err)
  435. }
  436. if !ok {
  437. return nil
  438. }
  439. b512 := sha3.Sum512(localCert.Raw)
  440. if cert.Cer != nil && b512 == sha3.Sum512(*cert.Cer) {
  441. return nil
  442. }
  443. params := keyvault.CertificateImportParameters{
  444. Base64EncodedCertificate: &val,
  445. Tags: map[string]*string{
  446. managedBy: pointer.To(managerLabel),
  447. },
  448. }
  449. for k, v := range tags {
  450. params.Tags[k] = &v
  451. }
  452. _, err = a.baseClient.ImportCertificate(ctx, *a.provider.VaultURL, secretName, params)
  453. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVImportCertificate, err)
  454. if err != nil {
  455. return fmt.Errorf("could not import certificate %v: %w", secretName, err)
  456. }
  457. return nil
  458. }
  459. func equalKeys(newKey, oldKey keyvault.JSONWebKey) bool {
  460. // checks for everything except KeyID and KeyOps
  461. rsaCheck := newKey.E != nil && oldKey.E != nil && *newKey.E == *oldKey.E &&
  462. newKey.N != nil && oldKey.N != nil && *newKey.N == *oldKey.N
  463. symmetricCheck := newKey.Crv == oldKey.Crv &&
  464. newKey.T != nil && oldKey.T != nil && *newKey.T == *oldKey.T &&
  465. newKey.X != nil && oldKey.X != nil && *newKey.X == *oldKey.X &&
  466. newKey.Y != nil && oldKey.Y != nil && *newKey.Y == *oldKey.Y
  467. return newKey.Kty == oldKey.Kty && (rsaCheck || symmetricCheck)
  468. }
  469. func (a *Azure) setKeyVaultKey(ctx context.Context, secretName string, value []byte, tags map[string]string) error {
  470. key, err := getKeyFromValue(value)
  471. if err != nil {
  472. return fmt.Errorf("could not load private key %v: %w", secretName, err)
  473. }
  474. jwKey, err := jwk.FromRaw(key)
  475. if err != nil {
  476. return fmt.Errorf("failed to generate a JWK from secret %v content: %w", secretName, err)
  477. }
  478. buf, err := json.Marshal(jwKey)
  479. if err != nil {
  480. return fmt.Errorf("error parsing key: %w", err)
  481. }
  482. azkey := keyvault.JSONWebKey{}
  483. err = json.Unmarshal(buf, &azkey)
  484. if err != nil {
  485. return fmt.Errorf("error unmarshalling key: %w", err)
  486. }
  487. keyFromVault, err := a.baseClient.GetKey(ctx, *a.provider.VaultURL, secretName, "")
  488. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetKey, err)
  489. ok, err := canCreate(keyFromVault.Tags, err)
  490. if err != nil {
  491. return fmt.Errorf("cannot get key %v: %w", secretName, err)
  492. }
  493. if !ok {
  494. return nil
  495. }
  496. if keyFromVault.Key != nil && equalKeys(azkey, *keyFromVault.Key) {
  497. return nil
  498. }
  499. params := keyvault.KeyImportParameters{
  500. Key: &azkey,
  501. KeyAttributes: &keyvault.KeyAttributes{},
  502. Tags: map[string]*string{
  503. managedBy: pointer.To(managerLabel),
  504. },
  505. }
  506. for k, v := range tags {
  507. params.Tags[k] = &v
  508. }
  509. _, err = a.baseClient.ImportKey(ctx, *a.provider.VaultURL, secretName, params)
  510. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVImportKey, err)
  511. if err != nil {
  512. return fmt.Errorf("could not import key %v: %w", secretName, err)
  513. }
  514. return nil
  515. }
  516. func getSecretKey(secret *corev1.Secret, data esv1.PushSecretData) ([]byte, error) {
  517. if data.GetSecretKey() != "" {
  518. return secret.Data[data.GetSecretKey()], nil
  519. }
  520. // Must convert secret values to string, otherwise data will be sent as base64 to Vault
  521. secretStringVal := make(map[string]string)
  522. for k, v := range secret.Data {
  523. secretStringVal[k] = string(v)
  524. }
  525. value, err := utils.JSONMarshal(secretStringVal)
  526. if err != nil {
  527. return nil, fmt.Errorf("failed to serialize secret content as JSON: %w", err)
  528. }
  529. return value, nil
  530. }
  531. // PushSecret stores secrets into a Key vault instance.
  532. func (a *Azure) PushSecret(ctx context.Context, secret *corev1.Secret, data esv1.PushSecretData) error {
  533. var (
  534. value []byte
  535. err error
  536. expires *date.UnixTime
  537. tags map[string]string
  538. )
  539. if value, err = getSecretKey(secret, data); err != nil {
  540. return err
  541. }
  542. metadata, err := metadata.ParseMetadataParameters[PushSecretMetadataSpec](data.GetMetadata())
  543. if err != nil {
  544. return fmt.Errorf("failed to parse push secret metadata: %w", err)
  545. }
  546. if metadata != nil && metadata.Spec.ExpirationDate != "" {
  547. t, err := time.Parse(time.RFC3339, metadata.Spec.ExpirationDate)
  548. if err != nil {
  549. return fmt.Errorf("error parsing expiration date in metadata: %w. Expected format: YYYY-MM-DDTHH:MM:SSZ (RFC3339). Example: 2024-12-31T20:00:00Z", err)
  550. }
  551. unixTime := date.UnixTime(t)
  552. expires = &unixTime
  553. }
  554. if metadata != nil && metadata.Spec.Tags != nil {
  555. if _, exists := metadata.Spec.Tags[managedBy]; exists {
  556. return fmt.Errorf("error parsing tags in metadata: Cannot specify a '%s' tag", managedBy)
  557. }
  558. tags = metadata.Spec.Tags
  559. }
  560. objectType, secretName := getObjType(esv1.ExternalSecretDataRemoteRef{Key: data.GetRemoteKey()})
  561. switch objectType {
  562. case defaultObjType:
  563. return a.setKeyVaultSecret(ctx, secretName, value, expires, tags)
  564. case objectTypeCert:
  565. return a.setKeyVaultCertificate(ctx, secretName, value, tags)
  566. case objectTypeKey:
  567. return a.setKeyVaultKey(ctx, secretName, value, tags)
  568. default:
  569. return fmt.Errorf("secret type %v not supported", objectType)
  570. }
  571. }
  572. // Implements store.Client.GetAllSecrets Interface.
  573. // Retrieves a map[string][]byte with the secret names as key and the secret itself as the calue.
  574. func (a *Azure) GetAllSecrets(ctx context.Context, ref esv1.ExternalSecretFind) (map[string][]byte, error) {
  575. basicClient := a.baseClient
  576. secretsMap := make(map[string][]byte)
  577. checkTags := len(ref.Tags) > 0
  578. checkName := ref.Name != nil && ref.Name.RegExp != ""
  579. secretListIter, err := basicClient.GetSecretsComplete(ctx, *a.provider.VaultURL, nil)
  580. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecrets, err)
  581. err = parseError(err)
  582. if err != nil {
  583. return nil, err
  584. }
  585. for secretListIter.NotDone() {
  586. secret := secretListIter.Value()
  587. ok, secretName := isValidSecret(checkTags, checkName, ref, secret)
  588. if !ok {
  589. err = secretListIter.Next()
  590. if err != nil {
  591. return nil, err
  592. }
  593. continue
  594. }
  595. secretResp, err := basicClient.GetSecret(ctx, *a.provider.VaultURL, secretName, "")
  596. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  597. err = parseError(err)
  598. if err != nil {
  599. return nil, err
  600. }
  601. secretValue := *secretResp.Value
  602. secretsMap[secretName] = []byte(secretValue)
  603. err = secretListIter.Next()
  604. if err != nil {
  605. return nil, err
  606. }
  607. }
  608. return secretsMap, nil
  609. }
  610. // Retrieves a tag value if specified and all tags in JSON format if not.
  611. func getSecretTag(tags map[string]*string, property string) ([]byte, error) {
  612. if property == "" {
  613. secretTagsData := make(map[string]string)
  614. for k, v := range tags {
  615. secretTagsData[k] = *v
  616. }
  617. return json.Marshal(secretTagsData)
  618. }
  619. if val, exist := tags[property]; exist {
  620. return []byte(*val), nil
  621. }
  622. idx := strings.Index(property, ".")
  623. if idx < 0 {
  624. return nil, fmt.Errorf(errTagNotExist, property)
  625. }
  626. if idx > 0 {
  627. tagName := property[0:idx]
  628. if val, exist := tags[tagName]; exist {
  629. key := strings.Replace(property, tagName+".", "", 1)
  630. return getProperty(*val, key, property)
  631. }
  632. }
  633. return nil, fmt.Errorf(errTagNotExist, property)
  634. }
  635. // Retrieves a property value if specified and the secret value if not.
  636. func getProperty(secret, property, key string) ([]byte, error) {
  637. if property == "" {
  638. return []byte(secret), nil
  639. }
  640. res := gjson.Get(secret, property)
  641. if !res.Exists() {
  642. idx := strings.Index(property, ".")
  643. if idx < 0 {
  644. return nil, fmt.Errorf(errPropNotExist, property, key)
  645. }
  646. escaped := strings.ReplaceAll(property, ".", "\\.")
  647. jValue := gjson.Get(secret, escaped)
  648. if jValue.Exists() {
  649. return []byte(jValue.String()), nil
  650. }
  651. return nil, fmt.Errorf(errPropNotExist, property, key)
  652. }
  653. return []byte(res.String()), nil
  654. }
  655. func parseError(err error) error {
  656. aerr := autorest.DetailedError{}
  657. if errors.As(err, &aerr) && aerr.StatusCode == 404 {
  658. return esv1.NoSecretError{}
  659. }
  660. return err
  661. }
  662. // GetSecret implements store.Client.GetSecret Interface.
  663. // Retrieves a secret/Key/Certificate/Tag with the secret name defined in ref.Name
  664. // The Object Type is defined as a prefix in the ref.Name , if no prefix is defined , we assume a secret is required.
  665. func (a *Azure) GetSecret(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) ([]byte, error) {
  666. objectType, secretName := getObjType(ref)
  667. switch objectType {
  668. case defaultObjType:
  669. // returns a SecretBundle with the secret value
  670. // https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#SecretBundle
  671. secretResp, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, ref.Version)
  672. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  673. err = parseError(err)
  674. if err != nil {
  675. return nil, err
  676. }
  677. if ref.MetadataPolicy == esv1.ExternalSecretMetadataPolicyFetch {
  678. return getSecretTag(secretResp.Tags, ref.Property)
  679. }
  680. return getProperty(*secretResp.Value, ref.Property, ref.Key)
  681. case objectTypeCert:
  682. // returns a CertBundle. We return CER contents of x509 certificate
  683. // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#CertificateBundle
  684. certResp, err := a.baseClient.GetCertificate(ctx, *a.provider.VaultURL, secretName, ref.Version)
  685. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetCertificate, err)
  686. err = parseError(err)
  687. if err != nil {
  688. return nil, err
  689. }
  690. if ref.MetadataPolicy == esv1.ExternalSecretMetadataPolicyFetch {
  691. return getSecretTag(certResp.Tags, ref.Property)
  692. }
  693. return *certResp.Cer, nil
  694. case objectTypeKey:
  695. // returns a KeyBundle that contains a jwk
  696. // azure kv returns only public keys
  697. // see: https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/services/keyvault/v7.0/keyvault#KeyBundle
  698. keyResp, err := a.baseClient.GetKey(ctx, *a.provider.VaultURL, secretName, ref.Version)
  699. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetKey, err)
  700. err = parseError(err)
  701. if err != nil {
  702. return nil, err
  703. }
  704. if ref.MetadataPolicy == esv1.ExternalSecretMetadataPolicyFetch {
  705. return getSecretTag(keyResp.Tags, ref.Property)
  706. }
  707. return json.Marshal(keyResp.Key)
  708. }
  709. return nil, fmt.Errorf(errUnknownObjectType, secretName)
  710. }
  711. // returns a SecretBundle with the tags values.
  712. func (a *Azure) getSecretTags(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) (map[string]*string, error) {
  713. _, secretName := getObjType(ref)
  714. secretResp, err := a.baseClient.GetSecret(ctx, *a.provider.VaultURL, secretName, ref.Version)
  715. metrics.ObserveAPICall(constants.ProviderAzureKV, constants.CallAzureKVGetSecret, err)
  716. err = parseError(err)
  717. if err != nil {
  718. return nil, err
  719. }
  720. secretTagsData := make(map[string]*string)
  721. for tagname, tagval := range secretResp.Tags {
  722. name := secretName + "_" + tagname
  723. kv := make(map[string]string)
  724. err = json.Unmarshal([]byte(*tagval), &kv)
  725. // if the tagvalue is not in JSON format then we added to secretTagsData we added as it is
  726. if err != nil {
  727. secretTagsData[name] = tagval
  728. } else {
  729. for k, v := range kv {
  730. value := v
  731. secretTagsData[name+"_"+k] = &value
  732. }
  733. }
  734. }
  735. return secretTagsData, nil
  736. }
  737. // Implements store.Client.GetSecretMap Interface.
  738. // New version of GetSecretMap.
  739. func (a *Azure) GetSecretMap(ctx context.Context, ref esv1.ExternalSecretDataRemoteRef) (map[string][]byte, error) {
  740. objectType, secretName := getObjType(ref)
  741. switch objectType {
  742. case defaultObjType:
  743. data, err := a.GetSecret(ctx, ref)
  744. if err != nil {
  745. return nil, err
  746. }
  747. if ref.MetadataPolicy == esv1.ExternalSecretMetadataPolicyFetch {
  748. tags, _ := a.getSecretTags(ctx, ref)
  749. return getSecretMapProperties(tags, ref.Key, ref.Property), nil
  750. }
  751. return getSecretMapMap(data)
  752. case objectTypeCert:
  753. return nil, errors.New(errDataFromCert)
  754. case objectTypeKey:
  755. return nil, errors.New(errDataFromKey)
  756. }
  757. return nil, fmt.Errorf(errUnknownObjectType, secretName)
  758. }
  759. func getSecretMapMap(data []byte) (map[string][]byte, error) {
  760. kv := make(map[string]json.RawMessage)
  761. err := json.Unmarshal(data, &kv)
  762. if err != nil {
  763. return nil, fmt.Errorf(errUnmarshalJSONData, err)
  764. }
  765. secretData := make(map[string][]byte)
  766. for k, v := range kv {
  767. var strVal string
  768. err = json.Unmarshal(v, &strVal)
  769. if err == nil {
  770. secretData[k] = []byte(strVal)
  771. } else {
  772. secretData[k] = v
  773. }
  774. }
  775. return secretData, nil
  776. }
  777. func getSecretMapProperties(tags map[string]*string, key, property string) map[string][]byte {
  778. tagByteArray := make(map[string][]byte)
  779. if property != "" {
  780. keyPropertyName := key + "_" + property
  781. singleTag, _ := getSecretTag(tags, keyPropertyName)
  782. tagByteArray[keyPropertyName] = singleTag
  783. return tagByteArray
  784. }
  785. for k, v := range tags {
  786. tagByteArray[k] = []byte(*v)
  787. }
  788. return tagByteArray
  789. }
  790. func (a *Azure) authorizerForWorkloadIdentity(ctx context.Context, tokenProvider tokenProviderFunc) (autorest.Authorizer, error) {
  791. aadEndpoint := AadEndpointForType(a.provider.EnvironmentType)
  792. kvResource := kvResourceForProviderConfig(a.provider.EnvironmentType)
  793. // If no serviceAccountRef was provided
  794. // we expect certain env vars to be present.
  795. // They are set by the azure workload identity webhook
  796. // by adding the label `azure.workload.identity/use: "true"` to the external-secrets pod
  797. if a.provider.ServiceAccountRef == nil {
  798. clientID := os.Getenv("AZURE_CLIENT_ID")
  799. tenantID := os.Getenv("AZURE_TENANT_ID")
  800. tokenFilePath := os.Getenv("AZURE_FEDERATED_TOKEN_FILE")
  801. if clientID == "" || tenantID == "" || tokenFilePath == "" {
  802. return nil, errors.New(errMissingWorkloadEnvVars)
  803. }
  804. token, err := os.ReadFile(filepath.Clean(tokenFilePath))
  805. if err != nil {
  806. return nil, fmt.Errorf(errReadTokenFile, tokenFilePath, err)
  807. }
  808. tp, err := tokenProvider(ctx, string(token), clientID, tenantID, aadEndpoint, kvResource)
  809. if err != nil {
  810. return nil, err
  811. }
  812. return autorest.NewBearerAuthorizer(tp), nil
  813. }
  814. ns := a.namespace
  815. if a.store.GetKind() == esv1.ClusterSecretStoreKind && a.provider.ServiceAccountRef.Namespace != nil {
  816. ns = *a.provider.ServiceAccountRef.Namespace
  817. }
  818. var sa corev1.ServiceAccount
  819. err := a.crClient.Get(ctx, types.NamespacedName{
  820. Name: a.provider.ServiceAccountRef.Name,
  821. Namespace: ns,
  822. }, &sa)
  823. if err != nil {
  824. return nil, err
  825. }
  826. // Extract clientID
  827. var clientID string
  828. // First check if AuthSecretRef is set and clientID can be fetched from there
  829. if a.provider.AuthSecretRef != nil {
  830. if a.provider.AuthSecretRef.ClientID == nil {
  831. return nil, errors.New(errMissingClientIDSecret)
  832. }
  833. clientID, err = resolvers.SecretKeyRef(
  834. ctx,
  835. a.crClient,
  836. a.store.GetKind(),
  837. a.namespace, a.provider.AuthSecretRef.ClientID)
  838. if err != nil {
  839. return nil, err
  840. }
  841. }
  842. // If AuthSecretRef is not set, use default (Service Account) implementation
  843. // Try to get clientID from Annotations
  844. if len(sa.ObjectMeta.Annotations) > 0 {
  845. if val, found := sa.ObjectMeta.Annotations[AnnotationClientID]; found {
  846. // If clientID is defined in both Annotations and AuthSecretRef, return an error
  847. if clientID != "" {
  848. return nil, errors.New(errMultipleClientID)
  849. }
  850. clientID = val
  851. }
  852. }
  853. // Return an error if clientID is still empty
  854. if clientID == "" {
  855. return nil, fmt.Errorf(errMissingClient, AnnotationClientID)
  856. }
  857. // Extract tenantID
  858. var tenantID string
  859. // First check if AuthSecretRef is set and tenantID can be fetched from there
  860. if a.provider.AuthSecretRef != nil {
  861. // We may want to set tenantID explicitly in the `spec.provider.azurekv` section of the SecretStore object
  862. // So that is okay if it is not there
  863. if a.provider.AuthSecretRef.TenantID != nil {
  864. tenantID, err = resolvers.SecretKeyRef(
  865. ctx,
  866. a.crClient,
  867. a.store.GetKind(),
  868. a.namespace, a.provider.AuthSecretRef.TenantID)
  869. if err != nil {
  870. return nil, err
  871. }
  872. }
  873. }
  874. // Check if spec.provider.azurekv.tenantID is set
  875. if tenantID == "" && a.provider.TenantID != nil {
  876. tenantID = *a.provider.TenantID
  877. }
  878. // Try to get tenantID from Annotations first. Default implementation.
  879. if len(sa.ObjectMeta.Annotations) > 0 {
  880. if val, found := sa.ObjectMeta.Annotations[AnnotationTenantID]; found {
  881. // If tenantID is defined in both Annotations and AuthSecretRef, return an error
  882. if tenantID != "" {
  883. return nil, errors.New(errMultipleTenantID)
  884. }
  885. tenantID = val
  886. }
  887. }
  888. // Fallback: use the AZURE_TENANT_ID env var which is set by the azure workload identity webhook
  889. // https://azure.github.io/azure-workload-identity/docs/topics/service-account-labels-and-annotations.html#service-account
  890. if tenantID == "" {
  891. tenantID = os.Getenv("AZURE_TENANT_ID")
  892. }
  893. // Return an error if tenantID is still empty
  894. if tenantID == "" {
  895. return nil, errors.New(errMissingTenant)
  896. }
  897. audiences := []string{AzureDefaultAudience}
  898. if len(a.provider.ServiceAccountRef.Audiences) > 0 {
  899. audiences = append(audiences, a.provider.ServiceAccountRef.Audiences...)
  900. }
  901. token, err := FetchSAToken(ctx, ns, a.provider.ServiceAccountRef.Name, audiences, a.kubeClient)
  902. if err != nil {
  903. return nil, err
  904. }
  905. tp, err := tokenProvider(ctx, token, clientID, tenantID, aadEndpoint, kvResource)
  906. if err != nil {
  907. return nil, err
  908. }
  909. return autorest.NewBearerAuthorizer(tp), nil
  910. }
  911. func FetchSAToken(ctx context.Context, ns, name string, audiences []string, kubeClient kcorev1.CoreV1Interface) (string, error) {
  912. token, err := kubeClient.ServiceAccounts(ns).CreateToken(ctx, name, &authv1.TokenRequest{
  913. Spec: authv1.TokenRequestSpec{
  914. Audiences: audiences,
  915. },
  916. }, metav1.CreateOptions{})
  917. if err != nil {
  918. return "", err
  919. }
  920. return token.Status.Token, nil
  921. }
  922. // tokenProvider satisfies the adal.OAuthTokenProvider interface.
  923. type tokenProvider struct {
  924. accessToken string
  925. }
  926. type tokenProviderFunc func(ctx context.Context, token, clientID, tenantID, aadEndpoint, kvResource string) (adal.OAuthTokenProvider, error)
  927. func NewTokenProvider(ctx context.Context, token, clientID, tenantID, aadEndpoint, kvResource string) (adal.OAuthTokenProvider, error) {
  928. // exchange token with Azure AccessToken
  929. cred := confidential.NewCredFromAssertionCallback(func(ctx context.Context, aro confidential.AssertionRequestOptions) (string, error) {
  930. return token, nil
  931. })
  932. cClient, err := confidential.New(fmt.Sprintf("%s%s", aadEndpoint, tenantID), clientID, cred)
  933. if err != nil {
  934. return nil, err
  935. }
  936. scope := kvResource
  937. // .default needs to be added to the scope
  938. if !strings.Contains(kvResource, ".default") {
  939. scope = fmt.Sprintf("%s/.default", kvResource)
  940. }
  941. authRes, err := cClient.AcquireTokenByCredential(ctx, []string{
  942. scope,
  943. })
  944. if err != nil {
  945. return nil, err
  946. }
  947. return &tokenProvider{
  948. accessToken: authRes.AccessToken,
  949. }, nil
  950. }
  951. func (t *tokenProvider) OAuthToken() string {
  952. return t.accessToken
  953. }
  954. func (a *Azure) authorizerForManagedIdentity() (autorest.Authorizer, error) {
  955. msiConfig := kvauth.NewMSIConfig()
  956. msiConfig.Resource = kvResourceForProviderConfig(a.provider.EnvironmentType)
  957. if a.provider.IdentityID != nil {
  958. msiConfig.ClientID = *a.provider.IdentityID
  959. }
  960. return msiConfig.Authorizer()
  961. }
  962. func (a *Azure) authorizerForServicePrincipal(ctx context.Context) (autorest.Authorizer, error) {
  963. if a.provider.TenantID == nil {
  964. return nil, errors.New(errMissingTenant)
  965. }
  966. if a.provider.AuthSecretRef == nil {
  967. return nil, errors.New(errMissingSecretRef)
  968. }
  969. if a.provider.AuthSecretRef.ClientID == nil || (a.provider.AuthSecretRef.ClientSecret == nil && a.provider.AuthSecretRef.ClientCertificate == nil) {
  970. return nil, errors.New(errMissingClientIDSecret)
  971. }
  972. if a.provider.AuthSecretRef.ClientSecret != nil && a.provider.AuthSecretRef.ClientCertificate != nil {
  973. return nil, errors.New(errInvalidClientCredentials)
  974. }
  975. return a.getAuthorizerFromCredentials(ctx)
  976. }
  977. func (a *Azure) getAuthorizerFromCredentials(ctx context.Context) (autorest.Authorizer, error) {
  978. clientID, err := resolvers.SecretKeyRef(
  979. ctx,
  980. a.crClient,
  981. a.store.GetKind(),
  982. a.namespace, a.provider.AuthSecretRef.ClientID,
  983. )
  984. if err != nil {
  985. return nil, err
  986. }
  987. if a.provider.AuthSecretRef.ClientSecret != nil {
  988. clientSecret, err := resolvers.SecretKeyRef(
  989. ctx,
  990. a.crClient,
  991. a.store.GetKind(),
  992. a.namespace, a.provider.AuthSecretRef.ClientSecret,
  993. )
  994. if err != nil {
  995. return nil, err
  996. }
  997. return getAuthorizerForClientSecret(
  998. clientID,
  999. clientSecret,
  1000. *a.provider.TenantID,
  1001. a.provider.EnvironmentType,
  1002. )
  1003. } else {
  1004. clientCertificate, err := resolvers.SecretKeyRef(
  1005. ctx,
  1006. a.crClient,
  1007. a.store.GetKind(),
  1008. a.namespace, a.provider.AuthSecretRef.ClientCertificate,
  1009. )
  1010. if err != nil {
  1011. return nil, err
  1012. }
  1013. return getAuthorizerForClientCertificate(
  1014. clientID,
  1015. []byte(clientCertificate),
  1016. *a.provider.TenantID,
  1017. a.provider.EnvironmentType,
  1018. )
  1019. }
  1020. }
  1021. func getAuthorizerForClientSecret(clientID, clientSecret, tenantID string, environmentType esv1.AzureEnvironmentType) (autorest.Authorizer, error) {
  1022. clientCredentialsConfig := kvauth.NewClientCredentialsConfig(clientID, clientSecret, tenantID)
  1023. clientCredentialsConfig.Resource = kvResourceForProviderConfig(environmentType)
  1024. clientCredentialsConfig.AADEndpoint = AadEndpointForType(environmentType)
  1025. return clientCredentialsConfig.Authorizer()
  1026. }
  1027. func getAuthorizerForClientCertificate(clientID string, certificateBytes []byte, tenantID string, environmentType esv1.AzureEnvironmentType) (autorest.Authorizer, error) {
  1028. clientCertificateConfig := NewClientInMemoryCertificateConfig(clientID, certificateBytes, tenantID)
  1029. clientCertificateConfig.Resource = kvResourceForProviderConfig(environmentType)
  1030. clientCertificateConfig.AADEndpoint = AadEndpointForType(environmentType)
  1031. return clientCertificateConfig.Authorizer()
  1032. }
  1033. func (a *Azure) Close(_ context.Context) error {
  1034. return nil
  1035. }
  1036. func (a *Azure) Validate() (esv1.ValidationResult, error) {
  1037. if a.store.GetKind() == esv1.ClusterSecretStoreKind && isReferentSpec(a.provider) {
  1038. return esv1.ValidationResultUnknown, nil
  1039. }
  1040. return esv1.ValidationResultReady, nil
  1041. }
  1042. func isReferentSpec(prov *esv1.AzureKVProvider) bool {
  1043. if prov.AuthSecretRef != nil &&
  1044. ((prov.AuthSecretRef.ClientID != nil &&
  1045. prov.AuthSecretRef.ClientID.Namespace == nil) ||
  1046. (prov.AuthSecretRef.ClientSecret != nil &&
  1047. prov.AuthSecretRef.ClientSecret.Namespace == nil)) {
  1048. return true
  1049. }
  1050. if prov.ServiceAccountRef != nil &&
  1051. prov.ServiceAccountRef.Namespace == nil {
  1052. return true
  1053. }
  1054. return false
  1055. }
  1056. func AadEndpointForType(t esv1.AzureEnvironmentType) string {
  1057. switch t {
  1058. case esv1.AzureEnvironmentPublicCloud:
  1059. return azure.PublicCloud.ActiveDirectoryEndpoint
  1060. case esv1.AzureEnvironmentChinaCloud:
  1061. return azure.ChinaCloud.ActiveDirectoryEndpoint
  1062. case esv1.AzureEnvironmentUSGovernmentCloud:
  1063. return azure.USGovernmentCloud.ActiveDirectoryEndpoint
  1064. case esv1.AzureEnvironmentGermanCloud:
  1065. return azure.GermanCloud.ActiveDirectoryEndpoint
  1066. default:
  1067. return azure.PublicCloud.ActiveDirectoryEndpoint
  1068. }
  1069. }
  1070. func ServiceManagementEndpointForType(t esv1.AzureEnvironmentType) string {
  1071. switch t {
  1072. case esv1.AzureEnvironmentPublicCloud:
  1073. return azure.PublicCloud.ServiceManagementEndpoint
  1074. case esv1.AzureEnvironmentChinaCloud:
  1075. return azure.ChinaCloud.ServiceManagementEndpoint
  1076. case esv1.AzureEnvironmentUSGovernmentCloud:
  1077. return azure.USGovernmentCloud.ServiceManagementEndpoint
  1078. case esv1.AzureEnvironmentGermanCloud:
  1079. return azure.GermanCloud.ServiceManagementEndpoint
  1080. default:
  1081. return azure.PublicCloud.ServiceManagementEndpoint
  1082. }
  1083. }
  1084. func kvResourceForProviderConfig(t esv1.AzureEnvironmentType) string {
  1085. var res string
  1086. switch t {
  1087. case esv1.AzureEnvironmentPublicCloud:
  1088. res = azure.PublicCloud.KeyVaultEndpoint
  1089. case esv1.AzureEnvironmentChinaCloud:
  1090. res = azure.ChinaCloud.KeyVaultEndpoint
  1091. case esv1.AzureEnvironmentUSGovernmentCloud:
  1092. res = azure.USGovernmentCloud.KeyVaultEndpoint
  1093. case esv1.AzureEnvironmentGermanCloud:
  1094. res = azure.GermanCloud.KeyVaultEndpoint
  1095. default:
  1096. res = azure.PublicCloud.KeyVaultEndpoint
  1097. }
  1098. return strings.TrimSuffix(res, "/")
  1099. }
  1100. func getObjType(ref esv1.ExternalSecretDataRemoteRef) (string, string) {
  1101. objectType := defaultObjType
  1102. secretName := ref.Key
  1103. nameSplitted := strings.Split(secretName, "/")
  1104. if len(nameSplitted) > 1 {
  1105. objectType = nameSplitted[0]
  1106. secretName = nameSplitted[1]
  1107. // TODO: later tokens can be used to read the secret tags
  1108. }
  1109. return objectType, secretName
  1110. }
  1111. func isValidSecret(checkTags, checkName bool, ref esv1.ExternalSecretFind, secret keyvault.SecretItem) (bool, string) {
  1112. if secret.ID == nil || !*secret.Attributes.Enabled {
  1113. return false, ""
  1114. }
  1115. if checkTags && !okByTags(ref, secret) {
  1116. return false, ""
  1117. }
  1118. secretName := path.Base(*secret.ID)
  1119. if checkName && !okByName(ref, secretName) {
  1120. return false, ""
  1121. }
  1122. return true, secretName
  1123. }
  1124. func okByName(ref esv1.ExternalSecretFind, secretName string) bool {
  1125. matches, _ := regexp.MatchString(ref.Name.RegExp, secretName)
  1126. return matches
  1127. }
  1128. func okByTags(ref esv1.ExternalSecretFind, secret keyvault.SecretItem) bool {
  1129. tagsFound := true
  1130. for k, v := range ref.Tags {
  1131. if val, ok := secret.Tags[k]; !ok || *val != v {
  1132. tagsFound = false
  1133. break
  1134. }
  1135. }
  1136. return tagsFound
  1137. }