certificatemanager_test.go 45 KB

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