keyvault.go 47 KB

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