keyvault_auth_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  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. "net/http"
  16. "os"
  17. "strings"
  18. "testing"
  19. "github.com/Azure/go-autorest/autorest"
  20. "github.com/Azure/go-autorest/autorest/adal"
  21. tassert "github.com/stretchr/testify/assert"
  22. corev1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. pointer "k8s.io/utils/ptr"
  25. "sigs.k8s.io/controller-runtime/pkg/client"
  26. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  27. esv1beta1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1beta1"
  28. v1 "github.com/external-secrets/external-secrets/apis/meta/v1"
  29. utilfake "github.com/external-secrets/external-secrets/pkg/provider/util/fake"
  30. )
  31. var vaultURL = "https://local.vault.url"
  32. var mockCertificate = `
  33. -----BEGIN CERTIFICATE-----
  34. MIICBzCCAbGgAwIBAgIUSoCD1fgywDbmeRaGrkYzGWUd1wMwDQYJKoZIhvcNAQEL
  35. BQAwcTELMAkGA1UEBhMCQVoxGTAXBgNVBAgMEE1vY2sgQ2VydGlmaWNhdGUxMzAx
  36. BgNVBAoMKkV4dGVybmFsIFNlY3JldHMgT3BlcmF0b3IgTW9jayBDZXJ0aWZpY2F0
  37. ZTESMBAGA1UEAwwJTW9jayBDZXJ0MB4XDTI0MDUwODA4NDkzMFoXDTI1MDUwODA4
  38. NDkzMFowcTELMAkGA1UEBhMCQVoxGTAXBgNVBAgMEE1vY2sgQ2VydGlmaWNhdGUx
  39. MzAxBgNVBAoMKkV4dGVybmFsIFNlY3JldHMgT3BlcmF0b3IgTW9jayBDZXJ0aWZp
  40. Y2F0ZTESMBAGA1UEAwwJTW9jayBDZXJ0MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJB
  41. ALkU1YgMk1Dk149F/HsHA0TjzLwfDa9tT0cfqA1u0hoJkb2r9jdWUyiugGaEz/PU
  42. TGWrvp8aiXPrGuu5Y6PY27ECAwEAAaMhMB8wHQYDVR0OBBYEFAMB0YwnYjUm00og
  43. kGce8Yhr4I03MA0GCSqGSIb3DQEBCwUAA0EAr0BMs/3hIOdZc0WHZUCTZ0GGor3G
  44. ViYUPHOw8z6UZGPGN6qiAejmkT6uP3LkkSW+7TIIQ1pkQxcn5xfFJXBexw==
  45. -----END CERTIFICATE-----
  46. -----BEGIN PRIVATE KEY-----
  47. MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAuRTViAyTUOTXj0X8
  48. ewcDROPMvB8Nr21PRx+oDW7SGgmRvav2N1ZTKK6AZoTP89RMZau+nxqJc+sa67lj
  49. o9jbsQIDAQABAkA35CnDpwCJykGqW5kuUeTT1fMK0FnioyDwuoeWXuQFxmB6Md89
  50. +ABxyjAt3nmwRRVBrVFdNibb9asR5KFHwn1NAiEA4NlrSnJrY1xODIjEXf0fLTwu
  51. wpyUO1lX585OjYDiOYsCIQDSuP4ttH/1Hg3f9veEE4RgDEk+QcisrzF8q4Oa5sDP
  52. MwIgfejiTtcR0ZsPza8Mn0EuIyuPV8VMsItQUWtSy6R/ig8CIQC86cBmNUXp+HGz
  53. 8fLg46ZvfVREjjFcLwwMmq83tdvxZQIgPAbezuRCrduH19xgMO8BXndS5DAovgvE
  54. /MpQnEyQtVA=
  55. -----END PRIVATE KEY-----
  56. `
  57. func TestNewClientManagedIdentityNoNeedForCredentials(t *testing.T) {
  58. namespace := "internal"
  59. identityID := "1234"
  60. authType := esv1beta1.AzureManagedIdentity
  61. store := esv1beta1.SecretStore{
  62. ObjectMeta: metav1.ObjectMeta{
  63. Namespace: namespace,
  64. },
  65. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{AzureKV: &esv1beta1.AzureKVProvider{
  66. AuthType: &authType,
  67. IdentityID: &identityID,
  68. VaultURL: &vaultURL,
  69. }}},
  70. }
  71. k8sClient := clientfake.NewClientBuilder().Build()
  72. az := &Azure{
  73. crClient: k8sClient,
  74. namespace: namespace,
  75. provider: store.Spec.Provider.AzureKV,
  76. store: &store,
  77. }
  78. authorizer, err := az.authorizerForManagedIdentity()
  79. if err != nil {
  80. // On non Azure environment, MSI auth not available, so this error should be returned
  81. tassert.EqualError(t, err, "failed to get oauth token from MSI: MSI not available")
  82. } else {
  83. // On Azure (where GitHub Actions are running) a secretClient is returned, as only an Authorizer is configured, but no token is requested for MI
  84. tassert.NotNil(t, authorizer)
  85. }
  86. }
  87. func TestGetAuthorizorForWorkloadIdentity(t *testing.T) {
  88. const (
  89. tenantID = "my-tenant-id"
  90. clientID = "my-client-id"
  91. azAccessToken = "my-access-token"
  92. saToken = "FAKETOKEN"
  93. saName = "az-wi"
  94. namespace = "default"
  95. secretName = "mi-spec"
  96. )
  97. // create a temporary file to imitate
  98. // azure workload identity webhook
  99. // see AZURE_FEDERATED_TOKEN_FILE
  100. tf, err := os.CreateTemp("", "")
  101. tassert.Nil(t, err)
  102. defer os.RemoveAll(tf.Name())
  103. _, err = tf.WriteString(saToken)
  104. tassert.Nil(t, err)
  105. tokenFile := tf.Name()
  106. authType := esv1beta1.AzureWorkloadIdentity
  107. defaultProvider := &esv1beta1.AzureKVProvider{
  108. VaultURL: &vaultURL,
  109. AuthType: &authType,
  110. ServiceAccountRef: &v1.ServiceAccountSelector{
  111. Name: saName,
  112. },
  113. }
  114. type testCase struct {
  115. name string
  116. provider *esv1beta1.AzureKVProvider
  117. k8sObjects []client.Object
  118. prep func(*testing.T)
  119. expErr string
  120. }
  121. for _, row := range []testCase{
  122. {
  123. name: "missing service account",
  124. provider: defaultProvider,
  125. expErr: "serviceaccounts \"" + saName + "\" not found",
  126. },
  127. {
  128. name: "missing webhook env vars",
  129. provider: &esv1beta1.AzureKVProvider{},
  130. expErr: "missing environment variables. AZURE_CLIENT_ID, AZURE_TENANT_ID and AZURE_FEDERATED_TOKEN_FILE must be set",
  131. },
  132. {
  133. name: "missing workload identity token file",
  134. provider: &esv1beta1.AzureKVProvider{},
  135. prep: func(t *testing.T) {
  136. t.Setenv("AZURE_CLIENT_ID", clientID)
  137. t.Setenv("AZURE_TENANT_ID", tenantID)
  138. t.Setenv("AZURE_FEDERATED_TOKEN_FILE", "invalid file")
  139. },
  140. expErr: "unable to read token file invalid file: open invalid file: no such file or directory",
  141. },
  142. {
  143. name: "correct workload identity",
  144. provider: &esv1beta1.AzureKVProvider{},
  145. prep: func(t *testing.T) {
  146. t.Setenv("AZURE_CLIENT_ID", clientID)
  147. t.Setenv("AZURE_TENANT_ID", tenantID)
  148. t.Setenv("AZURE_FEDERATED_TOKEN_FILE", tokenFile)
  149. },
  150. },
  151. {
  152. name: "missing sa annotations, tenantID, and clientId/tenantId AuthSecretRef",
  153. provider: defaultProvider,
  154. k8sObjects: []client.Object{
  155. &corev1.ServiceAccount{
  156. ObjectMeta: metav1.ObjectMeta{
  157. Name: saName,
  158. Namespace: namespace,
  159. Annotations: map[string]string{},
  160. },
  161. },
  162. },
  163. expErr: "missing clientID: either serviceAccountRef or service account annotation 'azure.workload.identity/client-id' is missing",
  164. },
  165. {
  166. name: "duplicated clientId",
  167. provider: &esv1beta1.AzureKVProvider{
  168. VaultURL: &vaultURL,
  169. AuthType: &authType,
  170. TenantID: pointer.To(tenantID),
  171. ServiceAccountRef: &v1.ServiceAccountSelector{
  172. Name: saName,
  173. },
  174. AuthSecretRef: &esv1beta1.AzureKVAuth{
  175. ClientID: &v1.SecretKeySelector{Name: secretName, Namespace: pointer.To(namespace), Key: clientID},
  176. TenantID: &v1.SecretKeySelector{Name: secretName, Namespace: pointer.To(namespace), Key: tenantID},
  177. },
  178. },
  179. k8sObjects: []client.Object{
  180. &corev1.ServiceAccount{
  181. ObjectMeta: metav1.ObjectMeta{
  182. Name: saName,
  183. Namespace: namespace,
  184. Annotations: map[string]string{
  185. AnnotationClientID: clientID,
  186. AnnotationTenantID: tenantID,
  187. },
  188. },
  189. },
  190. &corev1.Secret{
  191. ObjectMeta: metav1.ObjectMeta{
  192. Name: secretName,
  193. Namespace: namespace,
  194. },
  195. Data: map[string][]byte{
  196. clientID: []byte("clientid"),
  197. tenantID: []byte("tenantid"),
  198. },
  199. },
  200. },
  201. expErr: "multiple clientID found. Check secretRef and serviceAccountRef",
  202. },
  203. {
  204. name: "duplicated tenantId",
  205. provider: &esv1beta1.AzureKVProvider{
  206. VaultURL: &vaultURL,
  207. AuthType: &authType,
  208. TenantID: pointer.To(tenantID),
  209. ServiceAccountRef: &v1.ServiceAccountSelector{
  210. Name: saName,
  211. },
  212. },
  213. k8sObjects: []client.Object{
  214. &corev1.ServiceAccount{
  215. ObjectMeta: metav1.ObjectMeta{
  216. Name: saName,
  217. Namespace: namespace,
  218. Annotations: map[string]string{
  219. AnnotationClientID: clientID,
  220. AnnotationTenantID: tenantID,
  221. },
  222. },
  223. },
  224. },
  225. expErr: "multiple tenantID found. Check secretRef, 'spec.provider.azurekv.tenantId', and serviceAccountRef",
  226. },
  227. {
  228. name: "successful case #1: ClientID, TenantID from ServiceAccountRef",
  229. provider: defaultProvider,
  230. k8sObjects: []client.Object{
  231. &corev1.ServiceAccount{
  232. ObjectMeta: metav1.ObjectMeta{
  233. Name: saName,
  234. Namespace: namespace,
  235. Annotations: map[string]string{
  236. AnnotationClientID: clientID,
  237. AnnotationTenantID: tenantID,
  238. },
  239. },
  240. },
  241. },
  242. },
  243. {
  244. name: "successful case #2: ClientID, TenantID from AuthSecretRef",
  245. provider: &esv1beta1.AzureKVProvider{
  246. VaultURL: &vaultURL,
  247. AuthType: &authType,
  248. ServiceAccountRef: &v1.ServiceAccountSelector{
  249. Name: saName,
  250. },
  251. AuthSecretRef: &esv1beta1.AzureKVAuth{
  252. ClientID: &v1.SecretKeySelector{Name: secretName, Namespace: pointer.To(namespace), Key: clientID},
  253. TenantID: &v1.SecretKeySelector{Name: secretName, Namespace: pointer.To(namespace), Key: tenantID},
  254. },
  255. },
  256. k8sObjects: []client.Object{
  257. &corev1.ServiceAccount{
  258. ObjectMeta: metav1.ObjectMeta{
  259. Name: saName,
  260. Namespace: namespace,
  261. Annotations: map[string]string{},
  262. },
  263. },
  264. &corev1.Secret{
  265. ObjectMeta: metav1.ObjectMeta{
  266. Name: secretName,
  267. Namespace: namespace,
  268. },
  269. Data: map[string][]byte{
  270. clientID: []byte("clientid"),
  271. tenantID: []byte("tenantid"),
  272. },
  273. },
  274. },
  275. },
  276. {
  277. name: "successful case #3: ClientID from AuthSecretRef, TenantID from provider",
  278. provider: &esv1beta1.AzureKVProvider{
  279. VaultURL: &vaultURL,
  280. AuthType: &authType,
  281. TenantID: pointer.To(tenantID),
  282. ServiceAccountRef: &v1.ServiceAccountSelector{
  283. Name: saName,
  284. },
  285. AuthSecretRef: &esv1beta1.AzureKVAuth{
  286. ClientID: &v1.SecretKeySelector{Name: secretName, Namespace: pointer.To(namespace), Key: clientID},
  287. },
  288. },
  289. k8sObjects: []client.Object{
  290. &corev1.ServiceAccount{
  291. ObjectMeta: metav1.ObjectMeta{
  292. Name: saName,
  293. Namespace: namespace,
  294. Annotations: map[string]string{},
  295. },
  296. },
  297. &corev1.Secret{
  298. ObjectMeta: metav1.ObjectMeta{
  299. Name: secretName,
  300. Namespace: namespace,
  301. },
  302. Data: map[string][]byte{
  303. clientID: []byte("clientid"),
  304. },
  305. },
  306. },
  307. },
  308. } {
  309. t.Run(row.name, func(t *testing.T) {
  310. store := esv1beta1.SecretStore{
  311. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{
  312. AzureKV: row.provider,
  313. }},
  314. }
  315. k8sClient := clientfake.NewClientBuilder().
  316. WithObjects(row.k8sObjects...).
  317. Build()
  318. az := &Azure{
  319. store: &store,
  320. namespace: namespace,
  321. crClient: k8sClient,
  322. kubeClient: utilfake.NewCreateTokenMock().WithToken(saToken),
  323. provider: store.Spec.Provider.AzureKV,
  324. }
  325. tokenProvider := func(ctx context.Context, token, clientID, tenantID, aadEndpoint, kvResource string) (adal.OAuthTokenProvider, error) {
  326. tassert.Equal(t, token, saToken)
  327. tassert.Equal(t, clientID, clientID)
  328. tassert.Equal(t, tenantID, tenantID)
  329. return &tokenProvider{accessToken: azAccessToken}, nil
  330. }
  331. if row.prep != nil {
  332. row.prep(t)
  333. }
  334. authorizer, err := az.authorizerForWorkloadIdentity(context.Background(), tokenProvider)
  335. if row.expErr == "" {
  336. tassert.NotNil(t, authorizer)
  337. tassert.Equal(t, getTokenFromAuthorizer(t, authorizer), azAccessToken)
  338. } else {
  339. tassert.EqualError(t, err, row.expErr)
  340. }
  341. })
  342. }
  343. }
  344. func TestAuth(t *testing.T) {
  345. defaultStore := esv1beta1.SecretStore{
  346. ObjectMeta: metav1.ObjectMeta{
  347. Namespace: "default",
  348. },
  349. Spec: esv1beta1.SecretStoreSpec{
  350. Provider: &esv1beta1.SecretStoreProvider{},
  351. },
  352. }
  353. authType := esv1beta1.AzureServicePrincipal
  354. type testCase struct {
  355. name string
  356. provider *esv1beta1.AzureKVProvider
  357. store esv1beta1.GenericStore
  358. objects []client.Object
  359. expErr string
  360. }
  361. for _, row := range []testCase{
  362. {
  363. name: "bad config",
  364. expErr: "missing secretRef in provider config",
  365. store: &defaultStore,
  366. provider: &esv1beta1.AzureKVProvider{
  367. AuthType: &authType,
  368. VaultURL: &vaultURL,
  369. TenantID: pointer.To("mytenant"),
  370. },
  371. },
  372. {
  373. name: "bad config",
  374. expErr: "missing accessKeyID/secretAccessKey in store config",
  375. store: &defaultStore,
  376. provider: &esv1beta1.AzureKVProvider{
  377. AuthType: &authType,
  378. VaultURL: &vaultURL,
  379. TenantID: pointer.To("mytenant"),
  380. AuthSecretRef: &esv1beta1.AzureKVAuth{},
  381. },
  382. },
  383. {
  384. name: "bad config: missing secret",
  385. expErr: "cannot get Kubernetes secret \"password\": secrets \"password\" not found",
  386. store: &defaultStore,
  387. provider: &esv1beta1.AzureKVProvider{
  388. AuthType: &authType,
  389. VaultURL: &vaultURL,
  390. TenantID: pointer.To("mytenant"),
  391. AuthSecretRef: &esv1beta1.AzureKVAuth{
  392. ClientSecret: &v1.SecretKeySelector{Name: "password"},
  393. ClientID: &v1.SecretKeySelector{Name: "password"},
  394. },
  395. },
  396. },
  397. {
  398. name: "cluster secret store",
  399. expErr: "cannot get Kubernetes secret \"password\": secrets \"password\" not found",
  400. store: &esv1beta1.ClusterSecretStore{
  401. TypeMeta: metav1.TypeMeta{
  402. Kind: esv1beta1.ClusterSecretStoreKind,
  403. },
  404. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{}},
  405. },
  406. provider: &esv1beta1.AzureKVProvider{
  407. AuthType: &authType,
  408. VaultURL: &vaultURL,
  409. TenantID: pointer.To("mytenant"),
  410. AuthSecretRef: &esv1beta1.AzureKVAuth{
  411. ClientSecret: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo")},
  412. ClientID: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo")},
  413. },
  414. },
  415. },
  416. {
  417. name: "correct cluster secret store with ClientSecret",
  418. objects: []client.Object{&corev1.Secret{
  419. ObjectMeta: metav1.ObjectMeta{
  420. Name: "password",
  421. Namespace: "foo",
  422. },
  423. Data: map[string][]byte{
  424. "id": []byte("foo"),
  425. "secret": []byte("bar"),
  426. },
  427. }},
  428. store: &esv1beta1.ClusterSecretStore{
  429. TypeMeta: metav1.TypeMeta{
  430. Kind: esv1beta1.ClusterSecretStoreKind,
  431. },
  432. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{}},
  433. },
  434. provider: &esv1beta1.AzureKVProvider{
  435. AuthType: &authType,
  436. VaultURL: &vaultURL,
  437. TenantID: pointer.To("mytenant"),
  438. AuthSecretRef: &esv1beta1.AzureKVAuth{
  439. ClientSecret: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "secret"},
  440. ClientID: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "id"},
  441. },
  442. },
  443. },
  444. {
  445. name: "bad config: both clientSecret and clientCredentials are configured",
  446. expErr: "both clientSecret and clientCredentials set",
  447. objects: []client.Object{&corev1.Secret{
  448. ObjectMeta: metav1.ObjectMeta{
  449. Name: "password",
  450. Namespace: "foo",
  451. },
  452. Data: map[string][]byte{
  453. "id": []byte("foo"),
  454. "certificate": []byte("bar"),
  455. "secret": []byte("bar"),
  456. },
  457. }},
  458. store: &esv1beta1.ClusterSecretStore{
  459. TypeMeta: metav1.TypeMeta{
  460. Kind: esv1beta1.ClusterSecretStoreKind,
  461. },
  462. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{}},
  463. },
  464. provider: &esv1beta1.AzureKVProvider{
  465. AuthType: &authType,
  466. VaultURL: &vaultURL,
  467. TenantID: pointer.To("mytenant"),
  468. AuthSecretRef: &esv1beta1.AzureKVAuth{
  469. ClientID: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "id"},
  470. ClientCertificate: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "certificate"},
  471. ClientSecret: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "secret"},
  472. },
  473. },
  474. },
  475. {
  476. name: "bad config: no valid client certificate in pem file",
  477. expErr: "failed to get oauth token from certificate auth: failed to decode certificate: no certificate found in PEM file",
  478. objects: []client.Object{&corev1.Secret{
  479. ObjectMeta: metav1.ObjectMeta{
  480. Name: "password",
  481. Namespace: "foo",
  482. },
  483. Data: map[string][]byte{
  484. "id": []byte("foo"),
  485. "certificate": []byte("bar"),
  486. },
  487. }},
  488. store: &esv1beta1.ClusterSecretStore{
  489. TypeMeta: metav1.TypeMeta{
  490. Kind: esv1beta1.ClusterSecretStoreKind,
  491. },
  492. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{}},
  493. },
  494. provider: &esv1beta1.AzureKVProvider{
  495. AuthType: &authType,
  496. VaultURL: &vaultURL,
  497. TenantID: pointer.To("mytenant"),
  498. AuthSecretRef: &esv1beta1.AzureKVAuth{
  499. ClientID: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "id"},
  500. ClientCertificate: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "certificate"},
  501. },
  502. },
  503. },
  504. {
  505. name: "correct configuration with certificate authentication",
  506. objects: []client.Object{&corev1.Secret{
  507. ObjectMeta: metav1.ObjectMeta{
  508. Name: "password",
  509. Namespace: "foo",
  510. },
  511. Data: map[string][]byte{
  512. "id": []byte("foo"),
  513. "certificate": []byte(mockCertificate),
  514. },
  515. }},
  516. store: &esv1beta1.ClusterSecretStore{
  517. TypeMeta: metav1.TypeMeta{
  518. Kind: esv1beta1.ClusterSecretStoreKind,
  519. },
  520. Spec: esv1beta1.SecretStoreSpec{Provider: &esv1beta1.SecretStoreProvider{}},
  521. },
  522. provider: &esv1beta1.AzureKVProvider{
  523. AuthType: &authType,
  524. VaultURL: &vaultURL,
  525. TenantID: pointer.To("mytenant"),
  526. AuthSecretRef: &esv1beta1.AzureKVAuth{
  527. ClientID: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "id"},
  528. ClientCertificate: &v1.SecretKeySelector{Name: "password", Namespace: pointer.To("foo"), Key: "certificate"},
  529. },
  530. },
  531. },
  532. } {
  533. t.Run(row.name, func(t *testing.T) {
  534. k8sClient := clientfake.NewClientBuilder().WithObjects(row.objects...).Build()
  535. spec := row.store.GetSpec()
  536. spec.Provider.AzureKV = row.provider
  537. az := &Azure{
  538. crClient: k8sClient,
  539. namespace: "default",
  540. provider: spec.Provider.AzureKV,
  541. store: row.store,
  542. }
  543. authorizer, err := az.authorizerForServicePrincipal(context.Background())
  544. if row.expErr == "" {
  545. tassert.Nil(t, err)
  546. tassert.NotNil(t, authorizer)
  547. } else {
  548. tassert.EqualError(t, err, row.expErr)
  549. }
  550. })
  551. }
  552. }
  553. func getTokenFromAuthorizer(t *testing.T, authorizer autorest.Authorizer) string {
  554. rq, _ := http.NewRequest("POST", "http://example.com", http.NoBody)
  555. _, err := authorizer.WithAuthorization()(
  556. autorest.PreparerFunc(func(r *http.Request) (*http.Request, error) {
  557. return rq, nil
  558. })).Prepare(rq)
  559. tassert.Nil(t, err)
  560. return strings.TrimPrefix(rq.Header.Get("Authorization"), "Bearer ")
  561. }