@@ -16,8 +16,10 @@ import (
16
16
bootstrapv1 "github.com/rancher/cluster-api-provider-rke2/bootstrap/api/v1beta1"
17
17
controlplanev1 "github.com/rancher/cluster-api-provider-rke2/controlplane/api/v1beta1"
18
18
"github.com/rancher/cluster-api-provider-rke2/pkg/rke2"
19
+ "github.com/rancher/cluster-api-provider-rke2/pkg/secret"
19
20
corev1 "k8s.io/api/core/v1"
20
21
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
22
+ "k8s.io/apimachinery/pkg/types"
21
23
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
22
24
"sigs.k8s.io/cluster-api/util/certs"
23
25
"sigs.k8s.io/cluster-api/util/collections"
@@ -212,6 +214,15 @@ var _ = Describe("Reconcile control plane conditions", func() {
212
214
Expect (testEnv .Client .Create (ctx , cluster )).To (Succeed ())
213
215
214
216
rcp = & controlplanev1.RKE2ControlPlane {
217
+ ObjectMeta : metav1.ObjectMeta {
218
+ Name : "test" ,
219
+ Namespace : ns .Name ,
220
+ UID : "foobar" ,
221
+ },
222
+ TypeMeta : metav1.TypeMeta {
223
+ APIVersion : controlplanev1 .GroupVersion .String (),
224
+ Kind : rke2ControlPlaneKind ,
225
+ },
215
226
Status : controlplanev1.RKE2ControlPlaneStatus {
216
227
Initialized : true ,
217
228
},
@@ -220,16 +231,34 @@ var _ = Describe("Reconcile control plane conditions", func() {
220
231
cp , err = rke2 .NewControlPlane (ctx , testEnv .GetClient (), cluster , rcp , collections .FromMachineList (& ml ))
221
232
Expect (err ).ToNot (HaveOccurred ())
222
233
223
- ref := metav1.OwnerReference {
224
- APIVersion : clusterv1 .GroupVersion .String (),
225
- Kind : clusterv1 .ClusterKind ,
226
- UID : cp .Cluster .GetUID (),
227
- Name : cp .Cluster .GetName (),
234
+ // Generate new Secret Cluster CA
235
+ certPEM , _ , err := generateCertAndKey (time .Now ().Add (3650 * 24 * time .Hour )) // 10 years from now
236
+ Expect (err ).ShouldNot (HaveOccurred ())
237
+ caSecret := & corev1.Secret {
238
+ ObjectMeta : metav1.ObjectMeta {
239
+ Name : secret .Name (cluster .Name , secret .ClusterCA ),
240
+ Namespace : ns .Name ,
241
+ },
242
+ StringData : map [string ]string {
243
+ secret .TLSCrtDataName : string (certPEM ),
244
+ },
228
245
}
229
- Expect (testEnv .Client .Create (ctx , kubeconfig .GenerateSecretWithOwner (
230
- client .ObjectKeyFromObject (cp .Cluster ),
231
- kubeconfig .FromEnvTestConfig (testEnv .Config , cp .Cluster ),
232
- ref ))).To (Succeed ())
246
+ Expect (testEnv .Client .Create (ctx , caSecret )).Should (Succeed ())
247
+
248
+ // Generate new Secret Client Cluster CA
249
+ certPEM , keyPEM , err := generateCertAndKey (time .Now ().Add (3650 * 24 * time .Hour )) // 10 years from now
250
+ Expect (err ).ShouldNot (HaveOccurred ())
251
+ ccaSecret := & corev1.Secret {
252
+ ObjectMeta : metav1.ObjectMeta {
253
+ Name : secret .Name (cluster .Name , secret .ClientClusterCA ),
254
+ Namespace : ns .Name ,
255
+ },
256
+ StringData : map [string ]string {
257
+ secret .TLSCrtDataName : string (certPEM ),
258
+ secret .TLSKeyDataName : string (keyPEM ),
259
+ },
260
+ }
261
+ Expect (testEnv .Client .Create (ctx , ccaSecret )).Should (Succeed ())
233
262
})
234
263
235
264
AfterEach (func () {
@@ -244,6 +273,18 @@ var _ = Describe("Reconcile control plane conditions", func() {
244
273
managementCluster : & rke2.Management {Client : testEnv .GetClient (), SecretCachingClient : testEnv .GetClient ()},
245
274
managementClusterUncached : & rke2.Management {Client : testEnv .GetClient ()},
246
275
}
276
+ // Create a new Kubeconfig Secret
277
+ ref := metav1.OwnerReference {
278
+ APIVersion : clusterv1 .GroupVersion .String (),
279
+ Kind : clusterv1 .ClusterKind ,
280
+ UID : cp .Cluster .GetUID (),
281
+ Name : cp .Cluster .GetName (),
282
+ }
283
+ Expect (testEnv .Client .Create (ctx , kubeconfig .GenerateSecretWithOwner (
284
+ client .ObjectKeyFromObject (cp .Cluster ),
285
+ kubeconfig .FromEnvTestConfig (testEnv .Config , cp .Cluster ),
286
+ ref ))).To (Succeed ())
287
+
247
288
_ , err := r .reconcileControlPlaneConditions (ctx , cp )
248
289
Expect (err ).ToNot (HaveOccurred ())
249
290
Expect (testEnv .Get (ctx , client .ObjectKeyFromObject (machine ), machine )).To (Succeed ())
@@ -269,22 +310,34 @@ var _ = Describe("Reconcile control plane conditions", func() {
269
310
clusterName := client.ObjectKey {Namespace : ns .Name , Name : "test" }
270
311
endpoint := clusterv1.APIEndpoint {Host : "1.2.3.4" , Port : 6443 }
271
312
272
- // Create kubeconfig secret with short expiry
273
- shortExpiryDate := time .Now ().Add (24 * time .Hour ) // 1 day from now
274
- secret , err := createKubeconfigSecret (ns .Name , shortExpiryDate )
313
+ // Trigger first reconcile to generate a new Kubeconfig Secret
314
+ _ , err = r .reconcileKubeconfig (ctx , clusterName , endpoint , rcp )
275
315
Expect (err ).ToNot (HaveOccurred ())
276
- Expect (testEnv .Create (ctx , secret )).To (Succeed ())
316
+
317
+ // Fetch the original Kubeconfig Secret
318
+ kubeconfigSecret := & corev1.Secret {}
319
+ Expect (testEnv .Get (ctx , types.NamespacedName {
320
+ Namespace : ns .Name ,
321
+ Name : secret .Name (clusterName .Name , secret .Kubeconfig ),
322
+ }, kubeconfigSecret )).Should (Succeed ())
323
+ originalSecret := kubeconfigSecret .DeepCopy ()
324
+
325
+ // Override the kubeconfig secret with short expiry
326
+ shortExpiryDate := time .Now ().Add (24 * time .Hour ) // 1 day from now
327
+ Expect (updateKubeconfigSecret (kubeconfigSecret , shortExpiryDate )).Should (Succeed ())
328
+ Expect (testEnv .Update (ctx , kubeconfigSecret )).To (Succeed ())
277
329
278
330
// Check that rotation is needed
279
- needsRotation , err := kubeconfig .NeedsClientCertRotation (secret , certs .ClientCertificateRenewalDuration )
331
+ needsRotation , err := kubeconfig .NeedsClientCertRotation (kubeconfigSecret , certs .ClientCertificateRenewalDuration )
280
332
Expect (err ).ToNot (HaveOccurred ())
281
333
Expect (needsRotation ).To (BeTrue ())
282
334
283
335
// Rotate kubeconfig secret
284
336
_ , err = r .reconcileKubeconfig (ctx , clusterName , endpoint , rcp )
285
337
Expect (err ).ToNot (HaveOccurred ())
286
338
287
- Expect (testEnv .Get (ctx , client.ObjectKey {Namespace : ns .Name , Name : secret .Name }, secret )).To (Succeed ())
339
+ Expect (testEnv .Get (ctx , client.ObjectKey {Namespace : ns .Name , Name : kubeconfigSecret .Name }, kubeconfigSecret )).To (Succeed ())
340
+ Expect (kubeconfigSecret .StringData [secret .KubeconfigDataName ]).Should (Equal (originalSecret .StringData [secret .KubeconfigDataName ]), "Kubeconfig data must have been updated" )
288
341
})
289
342
290
343
It ("should not rotate kubeconfig secret if not needed" , func () {
@@ -297,22 +350,38 @@ var _ = Describe("Reconcile control plane conditions", func() {
297
350
clusterName := client.ObjectKey {Namespace : ns .Name , Name : "test" }
298
351
endpoint := clusterv1.APIEndpoint {Host : "1.2.3.4" , Port : 6443 }
299
352
300
- // Create kubeconfig secret with long expiry
301
- longExpiryDate := time .Now ().Add (365 * 24 * time .Hour ) // 1 year from now
302
- secret , err := createKubeconfigSecret (ns .Name , longExpiryDate )
353
+ // Trigger first reconcile to generate a new Kubeconfig Secret
354
+ _ , err = r .reconcileKubeconfig (ctx , clusterName , endpoint , rcp )
303
355
Expect (err ).ToNot (HaveOccurred ())
304
- Expect (testEnv .Create (ctx , secret )).To (Succeed ())
356
+ kubeconfigSecret := & corev1.Secret {}
357
+ Expect (testEnv .Get (ctx , types.NamespacedName {
358
+ Namespace : ns .Name ,
359
+ Name : secret .Name (clusterName .Name , secret .Kubeconfig ),
360
+ }, kubeconfigSecret )).Should (Succeed ())
361
+
362
+ // Override the kubeconfig secret with a long expiry
363
+ longExpiryDate := time .Now ().Add (365 * 24 * time .Hour ) // 1 year from now
364
+ Expect (updateKubeconfigSecret (kubeconfigSecret , longExpiryDate )).Should (Succeed ())
365
+ Expect (testEnv .Update (ctx , kubeconfigSecret )).To (Succeed ())
305
366
306
367
// Check that no rotation is needed
307
- needsRotation , err := kubeconfig .NeedsClientCertRotation (secret , certs .ClientCertificateRenewalDuration )
368
+ needsRotation , err := kubeconfig .NeedsClientCertRotation (kubeconfigSecret , certs .ClientCertificateRenewalDuration )
308
369
Expect (err ).ToNot (HaveOccurred ())
309
370
Expect (needsRotation ).To (BeFalse ())
310
371
372
+ // Fetch the overridden kubeconfigSecret
373
+ Expect (testEnv .Get (ctx , types.NamespacedName {
374
+ Namespace : ns .Name ,
375
+ Name : secret .Name (clusterName .Name , secret .Kubeconfig ),
376
+ }, kubeconfigSecret )).Should (Succeed ())
377
+ updatedSecret := kubeconfigSecret .DeepCopy ()
378
+
311
379
// Ensure no rotation occurs
312
380
_ , err = r .reconcileKubeconfig (ctx , clusterName , endpoint , rcp )
313
381
Expect (err ).ToNot (HaveOccurred ())
314
382
315
- Expect (testEnv .Get (ctx , client.ObjectKey {Namespace : ns .Name , Name : secret .Name }, secret )).To (Succeed ())
383
+ Expect (testEnv .Get (ctx , client.ObjectKey {Namespace : ns .Name , Name : kubeconfigSecret .Name }, kubeconfigSecret )).To (Succeed ())
384
+ Expect (kubeconfigSecret .StringData [secret .KubeconfigDataName ]).Should (Equal (updatedSecret .StringData [secret .KubeconfigDataName ]), "Kubeconfig data must stay the same" )
316
385
})
317
386
})
318
387
@@ -347,20 +416,14 @@ func generateCertAndKey(expiryDate time.Time) ([]byte, []byte, error) {
347
416
return certPEM , keyPEM , nil
348
417
}
349
418
350
- // createKubeconfigSecret creates a Kubernetes secret with a kubeconfig containing a client certificate and key.
351
- func createKubeconfigSecret ( namespace string , expiryDate time.Time ) ( * corev1. Secret , error ) {
419
+ // updateKubeconfigSecret updates a Kubernetes secret with a kubeconfig containing a client certificate and key.
420
+ func updateKubeconfigSecret ( configSecret * corev1. Secret , expiryDate time.Time ) error {
352
421
certPEM , keyPEM , err := generateCertAndKey (expiryDate )
353
422
if err != nil {
354
- return nil , err
423
+ return fmt . Errorf ( "Generating Cert and Key: %w" , err )
355
424
}
356
425
357
- secret := & corev1.Secret {
358
- ObjectMeta : metav1.ObjectMeta {
359
- Name : "test-kubeconfig-secret" ,
360
- Namespace : namespace ,
361
- },
362
- Data : map [string ][]byte {
363
- "value" : []byte (fmt .Sprintf (`
426
+ configSecret .Data [secret .KubeconfigDataName ] = []byte (fmt .Sprintf (`
364
427
apiVersion: v1
365
428
kind: Config
366
429
clusters:
@@ -378,9 +441,7 @@ users:
378
441
user:
379
442
client-certificate-data: %s
380
443
client-key-data: %s
381
- ` , base64 .StdEncoding .EncodeToString (certPEM ), base64 .StdEncoding .EncodeToString (keyPEM ))),
382
- },
383
- }
444
+ ` , base64 .StdEncoding .EncodeToString (certPEM ), base64 .StdEncoding .EncodeToString (keyPEM )))
384
445
385
- return secret , nil
446
+ return nil
386
447
}
0 commit comments