certificatemanager_test.go 45 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106
  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 certificatemanager
  13. import (
  14. "context"
  15. "encoding/json"
  16. "strings"
  17. "testing"
  18. "time"
  19. "github.com/google/uuid"
  20. tassert "github.com/stretchr/testify/assert"
  21. "github.com/yandex-cloud/go-genproto/yandex/cloud/certificatemanager/v1"
  22. "github.com/yandex-cloud/go-sdk/iamkey"
  23. corev1 "k8s.io/api/core/v1"
  24. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  25. ctrl "sigs.k8s.io/controller-runtime"
  26. k8sclient "sigs.k8s.io/controller-runtime/pkg/client"
  27. clientfake "sigs.k8s.io/controller-runtime/pkg/client/fake"
  28. esv1 "github.com/external-secrets/external-secrets/apis/externalsecrets/v1"
  29. esmeta "github.com/external-secrets/external-secrets/apis/meta/v1"
  30. "github.com/external-secrets/external-secrets/pkg/provider/yandex/certificatemanager/client"
  31. "github.com/external-secrets/external-secrets/pkg/provider/yandex/common"
  32. "github.com/external-secrets/external-secrets/pkg/provider/yandex/common/clock"
  33. )
  34. const (
  35. errMissingKey = "invalid Yandex Certificate Manager SecretStore resource: missing AuthorizedKey Name"
  36. errSecretPayloadPermissionDenied = "unable to request certificate content to get secret: permission denied"
  37. errSecretPayloadNotFound = "unable to request certificate content to get secret: certificate not found"
  38. errSecretPayloadVersionNotFound = "unable to request certificate content to get secret: version not found"
  39. )
  40. func TestNewClient(t *testing.T) {
  41. ctx := context.Background()
  42. const namespace = "namespace"
  43. const authorizedKeySecretName = "authorizedKeySecretName"
  44. const authorizedKeySecretKey = "authorizedKeySecretKey"
  45. store := &esv1.SecretStore{
  46. ObjectMeta: metav1.ObjectMeta{
  47. Namespace: namespace,
  48. },
  49. Spec: esv1.SecretStoreSpec{
  50. Provider: &esv1.SecretStoreProvider{
  51. YandexCertificateManager: &esv1.YandexCertificateManagerProvider{
  52. Auth: esv1.YandexAuth{
  53. AuthorizedKey: esmeta.SecretKeySelector{
  54. Key: authorizedKeySecretKey,
  55. Name: authorizedKeySecretName,
  56. },
  57. },
  58. },
  59. },
  60. },
  61. }
  62. provider, err := esv1.GetProvider(store)
  63. tassert.Nil(t, err)
  64. k8sClient := clientfake.NewClientBuilder().Build()
  65. secretClient, err := provider.NewClient(context.Background(), store, k8sClient, namespace)
  66. tassert.EqualError(t, err, "cannot get Kubernetes secret \"authorizedKeySecretName\" from namespace \"namespace\": secrets \"authorizedKeySecretName\" not found")
  67. tassert.Nil(t, secretClient)
  68. err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, newFakeAuthorizedKey()))
  69. tassert.Nil(t, err)
  70. const caCertificateSecretName = "caCertificateSecretName"
  71. const caCertificateSecretKey = "caCertificateSecretKey"
  72. store.Spec.Provider.YandexCertificateManager.CAProvider = &esv1.YandexCAProvider{
  73. Certificate: esmeta.SecretKeySelector{
  74. Key: caCertificateSecretKey,
  75. Name: caCertificateSecretName,
  76. },
  77. }
  78. secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
  79. tassert.EqualError(t, err, "cannot get Kubernetes secret \"caCertificateSecretName\" from namespace \"namespace\": secrets \"caCertificateSecretName\" not found")
  80. tassert.Nil(t, secretClient)
  81. err = createK8sSecret(ctx, t, k8sClient, namespace, caCertificateSecretName, caCertificateSecretKey, []byte("it-is-not-a-certificate"))
  82. tassert.Nil(t, err)
  83. secretClient, err = provider.NewClient(context.Background(), store, k8sClient, namespace)
  84. tassert.EqualError(t, err, "failed to create Yandex.Cloud client: unable to read trusted CA certificates")
  85. tassert.Nil(t, secretClient)
  86. }
  87. func TestGetSecretWithoutProperty(t *testing.T) {
  88. ctx := context.Background()
  89. namespace := uuid.NewString()
  90. authorizedKey := newFakeAuthorizedKey()
  91. fakeClock := clock.NewFakeClock()
  92. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  93. certificate1 := uuid.NewString()
  94. certificate2 := uuid.NewString()
  95. privateKey := uuid.NewString()
  96. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  97. "folderId", "certificateName",
  98. &certificatemanager.GetCertificateContentResponse{
  99. CertificateChain: []string{certificate1, certificate2},
  100. PrivateKey: privateKey,
  101. })
  102. k8sClient := clientfake.NewClientBuilder().Build()
  103. const authorizedKeySecretName = "authorizedKeySecretName"
  104. const authorizedKeySecretKey = "authorizedKeySecretKey"
  105. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  106. tassert.Nil(t, err)
  107. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  108. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  109. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  110. tassert.Nil(t, err)
  111. data, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID})
  112. tassert.Nil(t, err)
  113. tassert.Equal(
  114. t,
  115. strings.TrimSpace(strings.Join([]string{certificate1, certificate2, privateKey}, "\n")),
  116. strings.TrimSpace(string(data)),
  117. )
  118. }
  119. func TestGetSecretWithProperty(t *testing.T) {
  120. ctx := context.Background()
  121. namespace := uuid.NewString()
  122. authorizedKey := newFakeAuthorizedKey()
  123. fakeClock := clock.NewFakeClock()
  124. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  125. certificate1 := uuid.NewString()
  126. certificate2 := uuid.NewString()
  127. privateKey := uuid.NewString()
  128. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  129. "folderId", "certificateName",
  130. &certificatemanager.GetCertificateContentResponse{
  131. CertificateChain: []string{certificate1, certificate2},
  132. PrivateKey: privateKey,
  133. })
  134. k8sClient := clientfake.NewClientBuilder().Build()
  135. const authorizedKeySecretName = "authorizedKeySecretName"
  136. const authorizedKeySecretKey = "authorizedKeySecretKey"
  137. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  138. tassert.Nil(t, err)
  139. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  140. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  141. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  142. tassert.Nil(t, err)
  143. chainData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: chainProperty})
  144. tassert.Nil(t, err)
  145. tassert.Equal(
  146. t,
  147. strings.TrimSpace(certificate1+"\n"+certificate2),
  148. strings.TrimSpace(string(chainData)),
  149. )
  150. privateKeyData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: privateKeyProperty})
  151. tassert.Nil(t, err)
  152. tassert.Equal(
  153. t,
  154. strings.TrimSpace(privateKey),
  155. strings.TrimSpace(string(privateKeyData)),
  156. )
  157. chainAndPrivateKeyData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: chainAndPrivateKeyProperty})
  158. tassert.Nil(t, err)
  159. tassert.Equal(
  160. t,
  161. strings.TrimSpace(strings.Join([]string{certificate1, certificate2, privateKey}, "\n")),
  162. strings.TrimSpace(string(chainAndPrivateKeyData)),
  163. )
  164. }
  165. func TestGetSecretByVersionID(t *testing.T) {
  166. ctx := context.Background()
  167. namespace := uuid.NewString()
  168. authorizedKey := newFakeAuthorizedKey()
  169. fakeClock := clock.NewFakeClock()
  170. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  171. oldCertificate1 := uuid.NewString()
  172. oldCertificate2 := uuid.NewString()
  173. oldPrivateKey := uuid.NewString()
  174. certificateID, oldVersionID := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  175. "folderId", "certificateName",
  176. &certificatemanager.GetCertificateContentResponse{
  177. CertificateChain: []string{oldCertificate1, oldCertificate2},
  178. PrivateKey: oldPrivateKey,
  179. })
  180. k8sClient := clientfake.NewClientBuilder().Build()
  181. const authorizedKeySecretName = "authorizedKeySecretName"
  182. const authorizedKeySecretKey = "authorizedKeySecretKey"
  183. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  184. tassert.Nil(t, err)
  185. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  186. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  187. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  188. tassert.Nil(t, err)
  189. data, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: oldVersionID})
  190. tassert.Nil(t, err)
  191. tassert.Equal(
  192. t,
  193. strings.TrimSpace(strings.Join([]string{oldCertificate1, oldCertificate2, oldPrivateKey}, "\n")),
  194. strings.TrimSpace(string(data)),
  195. )
  196. newCertificate1 := uuid.NewString()
  197. newCertificate2 := uuid.NewString()
  198. newPrivateKey := uuid.NewString()
  199. newVersionID := fakeCertificateManagerServer.AddVersion(certificateID,
  200. &certificatemanager.GetCertificateContentResponse{
  201. CertificateChain: []string{newCertificate1, newCertificate2},
  202. PrivateKey: newPrivateKey,
  203. })
  204. data, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: oldVersionID})
  205. tassert.Nil(t, err)
  206. tassert.Equal(
  207. t,
  208. strings.TrimSpace(strings.Join([]string{oldCertificate1, oldCertificate2, oldPrivateKey}, "\n")),
  209. strings.TrimSpace(string(data)),
  210. )
  211. data, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: newVersionID})
  212. tassert.Nil(t, err)
  213. tassert.Equal(
  214. t,
  215. strings.TrimSpace(strings.Join([]string{newCertificate1, newCertificate2, newPrivateKey}, "\n")),
  216. strings.TrimSpace(string(data)),
  217. )
  218. }
  219. func TestGetSecretUnauthorized(t *testing.T) {
  220. ctx := context.Background()
  221. namespace := uuid.NewString()
  222. authorizedKeyA := newFakeAuthorizedKey()
  223. authorizedKeyB := newFakeAuthorizedKey()
  224. fakeClock := clock.NewFakeClock()
  225. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  226. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKeyA,
  227. "folderId", "certificateName",
  228. &certificatemanager.GetCertificateContentResponse{
  229. CertificateChain: []string{uuid.NewString()},
  230. PrivateKey: uuid.NewString(),
  231. })
  232. k8sClient := clientfake.NewClientBuilder().Build()
  233. const authorizedKeySecretName = "authorizedKeySecretName"
  234. const authorizedKeySecretKey = "authorizedKeySecretKey"
  235. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKeyB))
  236. tassert.Nil(t, err)
  237. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  238. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  239. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  240. tassert.Nil(t, err)
  241. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID})
  242. tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
  243. }
  244. func TestGetSecretNotFound(t *testing.T) {
  245. ctx := context.Background()
  246. namespace := uuid.NewString()
  247. authorizedKey := newFakeAuthorizedKey()
  248. fakeClock := clock.NewFakeClock()
  249. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  250. k8sClient := clientfake.NewClientBuilder().Build()
  251. const authorizedKeySecretName = "authorizedKeySecretName"
  252. const authorizedKeySecretKey = "authorizedKeySecretKey"
  253. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  254. tassert.Nil(t, err)
  255. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  256. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  257. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  258. tassert.Nil(t, err)
  259. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: "no-secret-with-this-id"})
  260. tassert.EqualError(t, err, errSecretPayloadNotFound)
  261. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  262. "folderId", "certificateName",
  263. &certificatemanager.GetCertificateContentResponse{
  264. CertificateChain: []string{uuid.NewString()},
  265. PrivateKey: uuid.NewString(),
  266. })
  267. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: "no-version-with-this-id"})
  268. tassert.EqualError(t, err, errSecretPayloadVersionNotFound)
  269. }
  270. func TestGetSecretWithTwoNamespaces(t *testing.T) {
  271. ctx := context.Background()
  272. namespace1 := uuid.NewString()
  273. namespace2 := uuid.NewString()
  274. authorizedKey1 := newFakeAuthorizedKey()
  275. authorizedKey2 := newFakeAuthorizedKey()
  276. fakeClock := clock.NewFakeClock()
  277. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  278. certificate1 := uuid.NewString()
  279. privateKey1 := uuid.NewString()
  280. certificateID1, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey1,
  281. "folderId", "certificateName1",
  282. &certificatemanager.GetCertificateContentResponse{
  283. CertificateChain: []string{certificate1},
  284. PrivateKey: privateKey1,
  285. })
  286. certificate2 := uuid.NewString()
  287. privateKey2 := uuid.NewString()
  288. certificateID2, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey2,
  289. "folderId", "certificateName2",
  290. &certificatemanager.GetCertificateContentResponse{
  291. CertificateChain: []string{certificate2},
  292. PrivateKey: privateKey2,
  293. })
  294. k8sClient := clientfake.NewClientBuilder().Build()
  295. const authorizedKeySecretName = "authorizedKeySecretName"
  296. const authorizedKeySecretKey = "authorizedKeySecretKey"
  297. err := createK8sSecret(ctx, t, k8sClient, namespace1, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey1))
  298. tassert.Nil(t, err)
  299. err = createK8sSecret(ctx, t, k8sClient, namespace2, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey2))
  300. tassert.Nil(t, err)
  301. store1 := newYandexCertificateManagerSecretStore("", namespace1, authorizedKeySecretName, authorizedKeySecretKey)
  302. store2 := newYandexCertificateManagerSecretStore("", namespace2, authorizedKeySecretName, authorizedKeySecretKey)
  303. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  304. secretsClient1, err := provider.NewClient(ctx, store1, k8sClient, namespace1)
  305. tassert.Nil(t, err)
  306. secretsClient2, err := provider.NewClient(ctx, store2, k8sClient, namespace2)
  307. tassert.Nil(t, err)
  308. data, err := secretsClient1.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID1, Property: privateKeyProperty})
  309. tassert.Equal(t, privateKey1, strings.TrimSpace(string(data)))
  310. tassert.Nil(t, err)
  311. data, err = secretsClient1.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID2, Property: privateKeyProperty})
  312. tassert.Nil(t, data)
  313. tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
  314. data, err = secretsClient2.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID1, Property: privateKeyProperty})
  315. tassert.Nil(t, data)
  316. tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
  317. data, err = secretsClient2.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID2, Property: privateKeyProperty})
  318. tassert.Equal(t, privateKey2, strings.TrimSpace(string(data)))
  319. tassert.Nil(t, err)
  320. }
  321. func TestGetSecretWithTwoApiEndpoints(t *testing.T) {
  322. ctx := context.Background()
  323. apiEndpoint1 := uuid.NewString()
  324. apiEndpoint2 := uuid.NewString()
  325. namespace := uuid.NewString()
  326. authorizedKey1 := newFakeAuthorizedKey()
  327. authorizedKey2 := newFakeAuthorizedKey()
  328. fakeClock := clock.NewFakeClock()
  329. fakeCertificateManagerServer1 := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  330. certificate1 := uuid.NewString()
  331. privateKey1 := uuid.NewString()
  332. certificateID1, _ := fakeCertificateManagerServer1.CreateCertificate(authorizedKey1,
  333. "folderId", "certificateName",
  334. &certificatemanager.GetCertificateContentResponse{
  335. CertificateChain: []string{certificate1},
  336. PrivateKey: privateKey1,
  337. })
  338. fakeCertificateManagerServer2 := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  339. certificate2 := uuid.NewString()
  340. privateKey2 := uuid.NewString()
  341. certificateID2, _ := fakeCertificateManagerServer2.CreateCertificate(authorizedKey2,
  342. "folderId", "certificateName",
  343. &certificatemanager.GetCertificateContentResponse{
  344. CertificateChain: []string{certificate2},
  345. PrivateKey: privateKey2,
  346. })
  347. k8sClient := clientfake.NewClientBuilder().Build()
  348. const authorizedKeySecretName1 = "authorizedKeySecretName1"
  349. const authorizedKeySecretKey1 = "authorizedKeySecretKey1"
  350. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName1, authorizedKeySecretKey1, toJSON(t, authorizedKey1))
  351. tassert.Nil(t, err)
  352. const authorizedKeySecretName2 = "authorizedKeySecretName2"
  353. const authorizedKeySecretKey2 = "authorizedKeySecretKey2"
  354. err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName2, authorizedKeySecretKey2, toJSON(t, authorizedKey2))
  355. tassert.Nil(t, err)
  356. store1 := newYandexCertificateManagerSecretStore(apiEndpoint1, namespace, authorizedKeySecretName1, authorizedKeySecretKey1)
  357. store2 := newYandexCertificateManagerSecretStore(apiEndpoint2, namespace, authorizedKeySecretName2, authorizedKeySecretKey2)
  358. provider1 := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer1)
  359. provider2 := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer2)
  360. secretsClient1, err := provider1.NewClient(ctx, store1, k8sClient, namespace)
  361. tassert.Nil(t, err)
  362. secretsClient2, err := provider2.NewClient(ctx, store2, k8sClient, namespace)
  363. tassert.Nil(t, err)
  364. var data []byte
  365. data, err = secretsClient1.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID1, Property: chainProperty})
  366. tassert.Equal(t, certificate1, strings.TrimSpace(string(data)))
  367. tassert.Nil(t, err)
  368. data, err = secretsClient1.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID2, Property: chainProperty})
  369. tassert.Nil(t, data)
  370. tassert.EqualError(t, err, errSecretPayloadNotFound)
  371. data, err = secretsClient2.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID1, Property: chainProperty})
  372. tassert.Nil(t, data)
  373. tassert.EqualError(t, err, errSecretPayloadNotFound)
  374. data, err = secretsClient2.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID2, Property: chainProperty})
  375. tassert.Equal(t, certificate2, strings.TrimSpace(string(data)))
  376. tassert.Nil(t, err)
  377. }
  378. func TestGetSecretWithIamTokenExpiration(t *testing.T) {
  379. ctx := context.Background()
  380. namespace := uuid.NewString()
  381. authorizedKey := newFakeAuthorizedKey()
  382. fakeClock := clock.NewFakeClock()
  383. tokenExpirationTime := time.Hour
  384. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, tokenExpirationTime)
  385. certificate := uuid.NewString()
  386. privateKey := uuid.NewString()
  387. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  388. "folderId", "certificateName",
  389. &certificatemanager.GetCertificateContentResponse{
  390. CertificateChain: []string{certificate},
  391. PrivateKey: privateKey,
  392. })
  393. k8sClient := clientfake.NewClientBuilder().Build()
  394. const authorizedKeySecretName = "authorizedKeySecretName"
  395. const authorizedKeySecretKey = "authorizedKeySecretKey"
  396. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  397. tassert.Nil(t, err)
  398. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  399. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  400. var data []byte
  401. oldSecretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  402. tassert.Nil(t, err)
  403. data, err = oldSecretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: privateKeyProperty})
  404. tassert.Equal(t, privateKey, strings.TrimSpace(string(data)))
  405. tassert.Nil(t, err)
  406. fakeClock.AddDuration(2 * tokenExpirationTime)
  407. data, err = oldSecretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: privateKeyProperty})
  408. tassert.Nil(t, data)
  409. tassert.EqualError(t, err, "unable to request certificate content to get secret: iam token expired")
  410. newSecretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  411. tassert.Nil(t, err)
  412. data, err = newSecretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Property: privateKeyProperty})
  413. tassert.Equal(t, privateKey, strings.TrimSpace(string(data)))
  414. tassert.Nil(t, err)
  415. }
  416. func TestGetSecretWithIamTokenCleanup(t *testing.T) {
  417. ctx := context.Background()
  418. namespace := uuid.NewString()
  419. authorizedKey1 := newFakeAuthorizedKey()
  420. authorizedKey2 := newFakeAuthorizedKey()
  421. fakeClock := clock.NewFakeClock()
  422. tokenExpirationDuration := time.Hour
  423. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, tokenExpirationDuration)
  424. certificateID1, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey1,
  425. "folderId", "certificateName1",
  426. &certificatemanager.GetCertificateContentResponse{
  427. CertificateChain: []string{uuid.NewString()},
  428. PrivateKey: uuid.NewString(),
  429. })
  430. certificateID2, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey2,
  431. "folderId", "certificateName2",
  432. &certificatemanager.GetCertificateContentResponse{
  433. CertificateChain: []string{uuid.NewString()},
  434. PrivateKey: uuid.NewString(),
  435. })
  436. var err error
  437. k8sClient := clientfake.NewClientBuilder().Build()
  438. const authorizedKeySecretName1 = "authorizedKeySecretName1"
  439. const authorizedKeySecretKey1 = "authorizedKeySecretKey1"
  440. err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName1, authorizedKeySecretKey1, toJSON(t, authorizedKey1))
  441. tassert.Nil(t, err)
  442. const authorizedKeySecretName2 = "authorizedKeySecretName2"
  443. const authorizedKeySecretKey2 = "authorizedKeySecretKey2"
  444. err = createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName2, authorizedKeySecretKey2, toJSON(t, authorizedKey2))
  445. tassert.Nil(t, err)
  446. store1 := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName1, authorizedKeySecretKey1)
  447. store2 := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName2, authorizedKeySecretKey2)
  448. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  449. tassert.False(t, provider.IsIamTokenCached(authorizedKey1))
  450. tassert.False(t, provider.IsIamTokenCached(authorizedKey2))
  451. // Access secretID1 with authorizedKey1, IAM token for authorizedKey1 should be cached
  452. secretsClient, err := provider.NewClient(ctx, store1, k8sClient, namespace)
  453. tassert.Nil(t, err)
  454. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID1})
  455. tassert.Nil(t, err)
  456. tassert.True(t, provider.IsIamTokenCached(authorizedKey1))
  457. tassert.False(t, provider.IsIamTokenCached(authorizedKey2))
  458. fakeClock.AddDuration(tokenExpirationDuration * 2)
  459. // Access secretID2 with authorizedKey2, IAM token for authorizedKey2 should be cached
  460. secretsClient, err = provider.NewClient(ctx, store2, k8sClient, namespace)
  461. tassert.Nil(t, err)
  462. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID2})
  463. tassert.Nil(t, err)
  464. tassert.True(t, provider.IsIamTokenCached(authorizedKey1))
  465. tassert.True(t, provider.IsIamTokenCached(authorizedKey2))
  466. fakeClock.AddDuration(tokenExpirationDuration)
  467. tassert.True(t, provider.IsIamTokenCached(authorizedKey1))
  468. tassert.True(t, provider.IsIamTokenCached(authorizedKey2))
  469. provider.CleanUpIamTokenMap()
  470. tassert.False(t, provider.IsIamTokenCached(authorizedKey1))
  471. tassert.True(t, provider.IsIamTokenCached(authorizedKey2))
  472. fakeClock.AddDuration(tokenExpirationDuration)
  473. tassert.False(t, provider.IsIamTokenCached(authorizedKey1))
  474. tassert.True(t, provider.IsIamTokenCached(authorizedKey2))
  475. provider.CleanUpIamTokenMap()
  476. tassert.False(t, provider.IsIamTokenCached(authorizedKey1))
  477. tassert.False(t, provider.IsIamTokenCached(authorizedKey2))
  478. }
  479. func TestGetSecretMap(t *testing.T) {
  480. ctx := context.Background()
  481. namespace := uuid.NewString()
  482. authorizedKey := newFakeAuthorizedKey()
  483. fakeClock := clock.NewFakeClock()
  484. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  485. certificate1 := uuid.NewString()
  486. certificate2 := uuid.NewString()
  487. privateKey := uuid.NewString()
  488. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  489. "folderId", "certificateName",
  490. &certificatemanager.GetCertificateContentResponse{
  491. CertificateChain: []string{certificate1, certificate2},
  492. PrivateKey: privateKey,
  493. })
  494. k8sClient := clientfake.NewClientBuilder().Build()
  495. const authorizedKeySecretName = "authorizedKeySecretName"
  496. const authorizedKeySecretKey = "authorizedKeySecretKey"
  497. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  498. tassert.Nil(t, err)
  499. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  500. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  501. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  502. tassert.Nil(t, err)
  503. data, err := secretsClient.GetSecretMap(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID})
  504. tassert.Nil(t, err)
  505. tassert.Equal(
  506. t,
  507. map[string][]byte{
  508. chainProperty: []byte(certificate1 + "\n" + certificate2),
  509. privateKeyProperty: []byte(privateKey),
  510. },
  511. data,
  512. )
  513. }
  514. func TestGetSecretMapByVersionID(t *testing.T) {
  515. ctx := context.Background()
  516. namespace := uuid.NewString()
  517. authorizedKey := newFakeAuthorizedKey()
  518. fakeClock := clock.NewFakeClock()
  519. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  520. oldCertificate := uuid.NewString()
  521. oldPrivateKey := uuid.NewString()
  522. certificateID, oldVersionID := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  523. "folderId", "certificateName",
  524. &certificatemanager.GetCertificateContentResponse{
  525. CertificateChain: []string{oldCertificate},
  526. PrivateKey: oldPrivateKey,
  527. })
  528. k8sClient := clientfake.NewClientBuilder().Build()
  529. const authorizedKeySecretName = "authorizedKeySecretName"
  530. const authorizedKeySecretKey = "authorizedKeySecretKey"
  531. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  532. tassert.Nil(t, err)
  533. store := newYandexCertificateManagerSecretStore("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  534. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  535. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  536. tassert.Nil(t, err)
  537. data, err := secretsClient.GetSecretMap(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: oldVersionID})
  538. tassert.Nil(t, err)
  539. tassert.Equal(
  540. t,
  541. map[string][]byte{
  542. chainProperty: []byte(oldCertificate),
  543. privateKeyProperty: []byte(oldPrivateKey),
  544. },
  545. data,
  546. )
  547. newCertificate := uuid.NewString()
  548. newPrivateKey := uuid.NewString()
  549. newVersionID := fakeCertificateManagerServer.AddVersion(certificateID,
  550. &certificatemanager.GetCertificateContentResponse{
  551. CertificateChain: []string{newCertificate},
  552. PrivateKey: newPrivateKey,
  553. })
  554. data, err = secretsClient.GetSecretMap(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: oldVersionID})
  555. tassert.Nil(t, err)
  556. tassert.Equal(
  557. t,
  558. map[string][]byte{
  559. chainProperty: []byte(oldCertificate),
  560. privateKeyProperty: []byte(oldPrivateKey),
  561. },
  562. data,
  563. )
  564. data, err = secretsClient.GetSecretMap(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID, Version: newVersionID})
  565. tassert.Nil(t, err)
  566. tassert.Equal(
  567. t,
  568. map[string][]byte{
  569. chainProperty: []byte(newCertificate),
  570. privateKeyProperty: []byte(newPrivateKey),
  571. },
  572. data,
  573. )
  574. }
  575. func TestGetSecretWithByNameFetchingPolicyWithoutProperty(t *testing.T) {
  576. ctx := context.Background()
  577. namespace := uuid.NewString()
  578. authorizedKey := newFakeAuthorizedKey()
  579. fakeClock := clock.NewFakeClock()
  580. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  581. certificate1 := uuid.NewString()
  582. certificate2 := uuid.NewString()
  583. privateKey := uuid.NewString()
  584. folderID := uuid.NewString()
  585. const certificateName = "certificateName"
  586. _, _ = fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  587. folderID, certificateName,
  588. &certificatemanager.GetCertificateContentResponse{
  589. CertificateChain: []string{certificate1, certificate2},
  590. PrivateKey: privateKey,
  591. })
  592. k8sClient := clientfake.NewClientBuilder().Build()
  593. const authorizedKeySecretName = "authorizedKeySecretName"
  594. const authorizedKeySecretKey = "authorizedKeySecretKey"
  595. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  596. tassert.Nil(t, err)
  597. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID)
  598. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  599. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  600. tassert.Nil(t, err)
  601. data, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName})
  602. tassert.Nil(t, err)
  603. tassert.Equal(
  604. t,
  605. strings.TrimSpace(strings.Join([]string{certificate1, certificate2, privateKey}, "\n")),
  606. strings.TrimSpace(string(data)),
  607. )
  608. }
  609. func TestGetSecretWithByNameFetchingPolicyWithProperty(t *testing.T) {
  610. ctx := context.Background()
  611. namespace := uuid.NewString()
  612. authorizedKey := newFakeAuthorizedKey()
  613. fakeClock := clock.NewFakeClock()
  614. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  615. certificate1 := uuid.NewString()
  616. certificate2 := uuid.NewString()
  617. privateKey := uuid.NewString()
  618. folderID := uuid.NewString()
  619. const certificateName = "certificateName"
  620. _, _ = fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  621. folderID, certificateName,
  622. &certificatemanager.GetCertificateContentResponse{
  623. CertificateChain: []string{certificate1, certificate2},
  624. PrivateKey: privateKey,
  625. })
  626. k8sClient := clientfake.NewClientBuilder().Build()
  627. const authorizedKeySecretName = "authorizedKeySecretName"
  628. const authorizedKeySecretKey = "authorizedKeySecretKey"
  629. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  630. tassert.Nil(t, err)
  631. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID)
  632. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  633. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  634. tassert.Nil(t, err)
  635. chainData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Property: chainProperty})
  636. tassert.Nil(t, err)
  637. tassert.Equal(
  638. t,
  639. strings.TrimSpace(certificate1+"\n"+certificate2),
  640. strings.TrimSpace(string(chainData)),
  641. )
  642. privateKeyData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Property: privateKeyProperty})
  643. tassert.Nil(t, err)
  644. tassert.Equal(
  645. t,
  646. strings.TrimSpace(privateKey),
  647. strings.TrimSpace(string(privateKeyData)),
  648. )
  649. chainAndPrivateKeyData, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Property: chainAndPrivateKeyProperty})
  650. tassert.Nil(t, err)
  651. tassert.Equal(
  652. t,
  653. strings.TrimSpace(strings.Join([]string{certificate1, certificate2, privateKey}, "\n")),
  654. strings.TrimSpace(string(chainAndPrivateKeyData)),
  655. )
  656. }
  657. func TestGetSecretWithByNameFetchingPolicyAndVersionID(t *testing.T) {
  658. ctx := context.Background()
  659. namespace := uuid.NewString()
  660. authorizedKey := newFakeAuthorizedKey()
  661. fakeClock := clock.NewFakeClock()
  662. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  663. oldCertificate1 := uuid.NewString()
  664. oldCertificate2 := uuid.NewString()
  665. oldPrivateKey := uuid.NewString()
  666. folderID := uuid.NewString()
  667. const certificateName = "certificateName"
  668. certificateID, oldVersionID := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  669. folderID, certificateName,
  670. &certificatemanager.GetCertificateContentResponse{
  671. CertificateChain: []string{oldCertificate1, oldCertificate2},
  672. PrivateKey: oldPrivateKey,
  673. })
  674. k8sClient := clientfake.NewClientBuilder().Build()
  675. const authorizedKeySecretName = "authorizedKeySecretName"
  676. const authorizedKeySecretKey = "authorizedKeySecretKey"
  677. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  678. tassert.Nil(t, err)
  679. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID)
  680. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  681. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  682. tassert.Nil(t, err)
  683. data, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Version: oldVersionID})
  684. tassert.Nil(t, err)
  685. tassert.Equal(
  686. t,
  687. strings.TrimSpace(strings.Join([]string{oldCertificate1, oldCertificate2, oldPrivateKey}, "\n")),
  688. strings.TrimSpace(string(data)),
  689. )
  690. newCertificate1 := uuid.NewString()
  691. newCertificate2 := uuid.NewString()
  692. newPrivateKey := uuid.NewString()
  693. newVersionID := fakeCertificateManagerServer.AddVersion(certificateID,
  694. &certificatemanager.GetCertificateContentResponse{
  695. CertificateChain: []string{newCertificate1, newCertificate2},
  696. PrivateKey: newPrivateKey,
  697. })
  698. data, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Version: oldVersionID})
  699. tassert.Nil(t, err)
  700. tassert.Equal(
  701. t,
  702. strings.TrimSpace(strings.Join([]string{oldCertificate1, oldCertificate2, oldPrivateKey}, "\n")),
  703. strings.TrimSpace(string(data)),
  704. )
  705. data, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Version: newVersionID})
  706. tassert.Nil(t, err)
  707. tassert.Equal(
  708. t,
  709. strings.TrimSpace(strings.Join([]string{newCertificate1, newCertificate2, newPrivateKey}, "\n")),
  710. strings.TrimSpace(string(data)),
  711. )
  712. }
  713. func TestGetSecretWithByNameFetchingPolicyUnauthorized(t *testing.T) {
  714. ctx := context.Background()
  715. namespace := uuid.NewString()
  716. authorizedKeyA := newFakeAuthorizedKey()
  717. authorizedKeyB := newFakeAuthorizedKey()
  718. fakeClock := clock.NewFakeClock()
  719. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  720. folderID := uuid.NewString()
  721. certificateName := "certificateName"
  722. _, _ = fakeCertificateManagerServer.CreateCertificate(authorizedKeyA,
  723. folderID, certificateName,
  724. &certificatemanager.GetCertificateContentResponse{
  725. CertificateChain: []string{uuid.NewString()},
  726. PrivateKey: uuid.NewString(),
  727. })
  728. k8sClient := clientfake.NewClientBuilder().Build()
  729. const authorizedKeySecretName = "authorizedKeySecretName"
  730. const authorizedKeySecretKey = "authorizedKeySecretKey"
  731. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKeyB))
  732. tassert.Nil(t, err)
  733. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID)
  734. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  735. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  736. tassert.Nil(t, err)
  737. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName})
  738. tassert.EqualError(t, err, errSecretPayloadPermissionDenied)
  739. }
  740. func TestGetSecretWithByNameFetchingPolicyNotFound(t *testing.T) {
  741. ctx := context.Background()
  742. namespace := uuid.NewString()
  743. authorizedKey := newFakeAuthorizedKey()
  744. fakeClock := clock.NewFakeClock()
  745. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  746. folderID := uuid.NewString()
  747. k8sClient := clientfake.NewClientBuilder().Build()
  748. const authorizedKeySecretName = "authorizedKeySecretName"
  749. const authorizedKeySecretKey = "authorizedKeySecretKey"
  750. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  751. tassert.Nil(t, err)
  752. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID)
  753. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  754. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  755. tassert.Nil(t, err)
  756. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: "no-secret-with-this-name"})
  757. tassert.EqualError(t, err, errSecretPayloadNotFound)
  758. certificateName := "certificateName"
  759. _, _ = fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  760. folderID, certificateName,
  761. &certificatemanager.GetCertificateContentResponse{
  762. CertificateChain: []string{uuid.NewString()},
  763. PrivateKey: uuid.NewString(),
  764. })
  765. _, err = secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateName, Version: "no-version-with-this-id"})
  766. tassert.EqualError(t, err, errSecretPayloadVersionNotFound)
  767. }
  768. func TestGetSecretWithByNameFetchingPolicyWithoutFolderID(t *testing.T) {
  769. ctx := context.Background()
  770. namespace := uuid.NewString()
  771. authorizedKey := newFakeAuthorizedKey()
  772. fakeClock := clock.NewFakeClock()
  773. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  774. k8sClient := clientfake.NewClientBuilder().Build()
  775. const authorizedKeySecretName = "authorizedKeySecretName"
  776. const authorizedKeySecretKey = "authorizedKeySecretKey"
  777. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  778. tassert.Nil(t, err)
  779. store := newYandexCertificateManagerSecretStoreWithFetchByName("", namespace, authorizedKeySecretName, authorizedKeySecretKey, "")
  780. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  781. _, err = provider.NewClient(ctx, store, k8sClient, namespace)
  782. tassert.EqualError(t, err, "folderID is required when fetching policy is 'byName'")
  783. }
  784. func TestGetSecretWithByIDFetchingPolicyWithoutProperty(t *testing.T) {
  785. ctx := context.Background()
  786. namespace := uuid.NewString()
  787. authorizedKey := newFakeAuthorizedKey()
  788. fakeClock := clock.NewFakeClock()
  789. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  790. certificate1 := uuid.NewString()
  791. certificate2 := uuid.NewString()
  792. privateKey := uuid.NewString()
  793. certificateID, _ := fakeCertificateManagerServer.CreateCertificate(authorizedKey,
  794. "folderId", "certificateName",
  795. &certificatemanager.GetCertificateContentResponse{
  796. CertificateChain: []string{certificate1, certificate2},
  797. PrivateKey: privateKey,
  798. })
  799. k8sClient := clientfake.NewClientBuilder().Build()
  800. const authorizedKeySecretName = "authorizedKeySecretName"
  801. const authorizedKeySecretKey = "authorizedKeySecretKey"
  802. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  803. tassert.Nil(t, err)
  804. store := newYandexCertificateManagerSecretStoreWithFetchByID("", namespace, authorizedKeySecretName, authorizedKeySecretKey)
  805. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  806. secretsClient, err := provider.NewClient(ctx, store, k8sClient, namespace)
  807. tassert.Nil(t, err)
  808. data, err := secretsClient.GetSecret(ctx, esv1.ExternalSecretDataRemoteRef{Key: certificateID})
  809. tassert.Nil(t, err)
  810. tassert.Equal(
  811. t,
  812. strings.TrimSpace(strings.Join([]string{certificate1, certificate2, privateKey}, "\n")),
  813. strings.TrimSpace(string(data)),
  814. )
  815. }
  816. func TestGetSecretWithInvalidFetchingPolicy(t *testing.T) {
  817. ctx := context.Background()
  818. namespace := uuid.NewString()
  819. authorizedKey := newFakeAuthorizedKey()
  820. fakeClock := clock.NewFakeClock()
  821. fakeCertificateManagerServer := client.NewFakeCertificateManagerServer(fakeClock, time.Hour)
  822. k8sClient := clientfake.NewClientBuilder().Build()
  823. const authorizedKeySecretName = "authorizedKeySecretName"
  824. const authorizedKeySecretKey = "authorizedKeySecretKey"
  825. err := createK8sSecret(ctx, t, k8sClient, namespace, authorizedKeySecretName, authorizedKeySecretKey, toJSON(t, authorizedKey))
  826. tassert.Nil(t, err)
  827. store := &esv1.SecretStore{
  828. ObjectMeta: metav1.ObjectMeta{
  829. Namespace: namespace,
  830. },
  831. Spec: esv1.SecretStoreSpec{
  832. Provider: &esv1.SecretStoreProvider{
  833. YandexCertificateManager: &esv1.YandexCertificateManagerProvider{
  834. APIEndpoint: "",
  835. Auth: esv1.YandexAuth{
  836. AuthorizedKey: esmeta.SecretKeySelector{
  837. Name: authorizedKeySecretName,
  838. Key: authorizedKeySecretKey,
  839. },
  840. },
  841. FetchingPolicy: &esv1.FetchingPolicy{
  842. ByID: nil,
  843. ByName: nil,
  844. },
  845. },
  846. },
  847. },
  848. }
  849. provider := newCertificateManagerProvider(fakeClock, fakeCertificateManagerServer)
  850. _, err = provider.NewClient(ctx, store, k8sClient, namespace)
  851. tassert.EqualError(t, err, "invalid Yandex Certificate Manager SecretStore: requires either 'byName' or 'byID' policy")
  852. }
  853. // helper functions
  854. func newCertificateManagerProvider(clock clock.Clock, fakeCertificateManagerServer *client.FakeCertificateManagerServer) *common.YandexCloudProvider {
  855. return common.InitYandexCloudProvider(
  856. ctrl.Log.WithName("provider").WithName("yandex").WithName("certificatemanager"),
  857. clock,
  858. adaptInput,
  859. func(ctx context.Context, apiEndpoint string, authorizedKey *iamkey.Key, caCertificate []byte) (common.SecretGetter, error) {
  860. return newCertificateManagerSecretGetter(client.NewFakeCertificateManagerClient(fakeCertificateManagerServer))
  861. },
  862. func(ctx context.Context, apiEndpoint string, authorizedKey *iamkey.Key, caCertificate []byte) (*common.IamToken, error) {
  863. return fakeCertificateManagerServer.NewIamToken(authorizedKey), nil
  864. },
  865. 0,
  866. )
  867. }
  868. func newYandexCertificateManagerSecretStore(apiEndpoint, namespace, authorizedKeySecretName, authorizedKeySecretKey string) esv1.GenericStore {
  869. return &esv1.SecretStore{
  870. ObjectMeta: metav1.ObjectMeta{
  871. Namespace: namespace,
  872. },
  873. Spec: esv1.SecretStoreSpec{
  874. Provider: &esv1.SecretStoreProvider{
  875. YandexCertificateManager: &esv1.YandexCertificateManagerProvider{
  876. APIEndpoint: apiEndpoint,
  877. Auth: esv1.YandexAuth{
  878. AuthorizedKey: esmeta.SecretKeySelector{
  879. Name: authorizedKeySecretName,
  880. Key: authorizedKeySecretKey,
  881. },
  882. },
  883. },
  884. },
  885. },
  886. }
  887. }
  888. func newYandexCertificateManagerSecretStoreWithFetchByName(apiEndpoint, namespace, authorizedKeySecretName, authorizedKeySecretKey, folderID string) esv1.GenericStore {
  889. return &esv1.SecretStore{
  890. ObjectMeta: metav1.ObjectMeta{
  891. Namespace: namespace,
  892. },
  893. Spec: esv1.SecretStoreSpec{
  894. Provider: &esv1.SecretStoreProvider{
  895. YandexCertificateManager: &esv1.YandexCertificateManagerProvider{
  896. APIEndpoint: apiEndpoint,
  897. Auth: esv1.YandexAuth{
  898. AuthorizedKey: esmeta.SecretKeySelector{
  899. Name: authorizedKeySecretName,
  900. Key: authorizedKeySecretKey,
  901. },
  902. },
  903. FetchingPolicy: &esv1.FetchingPolicy{
  904. ByName: &esv1.ByName{
  905. FolderID: folderID,
  906. },
  907. },
  908. },
  909. },
  910. },
  911. }
  912. }
  913. func newYandexCertificateManagerSecretStoreWithFetchByID(apiEndpoint, namespace, authorizedKeySecretName, authorizedKeySecretKey string) esv1.GenericStore {
  914. return &esv1.SecretStore{
  915. ObjectMeta: metav1.ObjectMeta{
  916. Namespace: namespace,
  917. },
  918. Spec: esv1.SecretStoreSpec{
  919. Provider: &esv1.SecretStoreProvider{
  920. YandexCertificateManager: &esv1.YandexCertificateManagerProvider{
  921. APIEndpoint: apiEndpoint,
  922. Auth: esv1.YandexAuth{
  923. AuthorizedKey: esmeta.SecretKeySelector{
  924. Name: authorizedKeySecretName,
  925. Key: authorizedKeySecretKey,
  926. },
  927. },
  928. FetchingPolicy: &esv1.FetchingPolicy{
  929. ByID: &esv1.ByID{},
  930. },
  931. },
  932. },
  933. },
  934. }
  935. }
  936. func toJSON(t *testing.T, v any) []byte {
  937. jsonBytes, err := json.Marshal(v)
  938. tassert.Nil(t, err)
  939. return jsonBytes
  940. }
  941. func createK8sSecret(ctx context.Context, t *testing.T, k8sClient k8sclient.Client, namespace, secretName, secretKey string, secretValue []byte) error {
  942. err := k8sClient.Create(ctx, &corev1.Secret{
  943. ObjectMeta: metav1.ObjectMeta{
  944. Namespace: namespace,
  945. Name: secretName,
  946. },
  947. Data: map[string][]byte{secretKey: secretValue},
  948. })
  949. tassert.Nil(t, err)
  950. return nil
  951. }
  952. func newFakeAuthorizedKey() *iamkey.Key {
  953. uniqueLabel := uuid.NewString()
  954. return &iamkey.Key{
  955. Id: uniqueLabel,
  956. Subject: &iamkey.Key_ServiceAccountId{
  957. ServiceAccountId: uniqueLabel,
  958. },
  959. PrivateKey: uniqueLabel,
  960. }
  961. }