@@ -179,28 +179,29 @@ func hasLTPAConfigResourceSuffixesEnv(instance *olv1.OpenLibertyApplication) (st
179
179
}
180
180
181
181
// Create or use an existing LTPA Secret identified by LTPA metadata for the OpenLibertyApplication instance
182
- func (r * ReconcileOpenLiberty ) reconcileLTPAKeys (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata ) (string , string , error ) {
182
+ func (r * ReconcileOpenLiberty ) reconcileLTPAKeys (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata ) (string , string , string , error ) {
183
183
var err error
184
184
ltpaSecretName := ""
185
+ ltpaKeysLastRotation := ""
185
186
if r .isLTPAKeySharingEnabled (instance ) {
186
- ltpaSecretName , err = r .generateLTPAKeys (instance , ltpaKeysMetadata )
187
+ ltpaSecretName , ltpaKeysLastRotation , err = r .generateLTPAKeys (instance , ltpaKeysMetadata )
187
188
if err != nil {
188
- return "Failed to generate the shared LTPA keys Secret" , ltpaSecretName , err
189
+ return "Failed to generate the shared LTPA keys Secret" , ltpaSecretName , ltpaKeysLastRotation , err
189
190
}
190
191
} else {
191
192
err := r .RemoveLeaderTrackerReference (instance , LTPA_RESOURCE_SHARING_FILE_NAME )
192
193
if err != nil {
193
- return "Failed to remove leader tracking reference to the LTPA keys" , ltpaSecretName , err
194
+ return "Failed to remove leader tracking reference to the LTPA keys" , ltpaSecretName , ltpaKeysLastRotation , err
194
195
}
195
196
}
196
- return "" , ltpaSecretName , nil
197
+ return "" , ltpaSecretName , ltpaKeysLastRotation , nil
197
198
}
198
199
199
200
// Create or use an existing LTPA Secret identified by LTPA metadata for the OpenLibertyApplication instance
200
- func (r * ReconcileOpenLiberty ) reconcileLTPAConfig (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata , ltpaConfigMetadata * lutils.LTPAMetadata , passwordEncryptionMetadata * lutils.PasswordEncryptionMetadata ) (string , error ) {
201
+ func (r * ReconcileOpenLiberty ) reconcileLTPAConfig (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata , ltpaConfigMetadata * lutils.LTPAMetadata , passwordEncryptionMetadata * lutils.PasswordEncryptionMetadata , ltpaKeysLastRotation string ) (string , error ) {
201
202
var err error
202
203
if r .isLTPAKeySharingEnabled (instance ) {
203
- err = r .generateLTPAConfig (instance , ltpaKeysMetadata , ltpaConfigMetadata , passwordEncryptionMetadata )
204
+ err = r .generateLTPAConfig (instance , ltpaKeysMetadata , ltpaConfigMetadata , passwordEncryptionMetadata , ltpaKeysLastRotation )
204
205
if err != nil {
205
206
return "Failed to generate the shared LTPA keys Secret" , err
206
207
}
@@ -247,7 +248,7 @@ func (r *ReconcileOpenLiberty) restartLTPAKeysGeneration(instance *olv1.OpenLibe
247
248
}
248
249
249
250
// Generates the LTPA keys file and returns the name of the Secret storing its metadata
250
- func (r * ReconcileOpenLiberty ) generateLTPAKeys (instance * olv1.OpenLibertyApplication , ltpaMetadata * lutils.LTPAMetadata ) (string , error ) {
251
+ func (r * ReconcileOpenLiberty ) generateLTPAKeys (instance * olv1.OpenLibertyApplication , ltpaMetadata * lutils.LTPAMetadata ) (string , string , error ) {
251
252
// Initialize LTPA resources
252
253
passwordEncryptionMetadata := & lutils.PasswordEncryptionMetadata {Name : "" }
253
254
@@ -330,11 +331,11 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
330
331
if err != nil && kerrors .IsNotFound (err ) {
331
332
leaderName , thisInstanceIsLeader , _ , err := r .reconcileLeader (instance , ltpaMetadata , LTPA_RESOURCE_SHARING_FILE_NAME , true )
332
333
if err != nil {
333
- return "" , err
334
+ return "" , "" , err
334
335
}
335
336
// If this instance is not the leader, exit the reconcile loop
336
337
if ! thisInstanceIsLeader {
337
- return "" , fmt .Errorf ("Waiting for OpenLibertyApplication instance '" + leaderName + "' to generate the shared LTPA keys file for the namespace '" + instance .Namespace + "'." )
338
+ return "" , "" , fmt .Errorf ("Waiting for OpenLibertyApplication instance '" + leaderName + "' to generate the shared LTPA keys file for the namespace '" + instance .Namespace + "'." )
338
339
}
339
340
340
341
err = r .GetClient ().Get (context .TODO (), types.NamespacedName {Name : ltpaJobRequest .Name , Namespace : ltpaJobRequest .Namespace }, ltpaJobRequest )
@@ -344,47 +345,47 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
344
345
// Clear all LTPA-related resources from a prior reconcile
345
346
err = r .DeleteResource (ltpaXMLSecret )
346
347
if err != nil {
347
- return "" , err
348
+ return "" , "" , err
348
349
}
349
350
err = r .DeleteResource (ltpaXMLMountSecret )
350
351
if err != nil {
351
- return "" , err
352
+ return "" , "" , err
352
353
}
353
354
err = r .DeleteResource (ltpaKeysCreationScriptConfigMap )
354
355
if err != nil {
355
- return "" , err
356
+ return "" , "" , err
356
357
}
357
358
err = r .GetClient ().Delete (context .TODO (), generateLTPAKeysJob , & client.DeleteOptions {PropagationPolicy : & deletePropagationBackground })
358
359
if err != nil && ! kerrors .IsNotFound (err ) {
359
- return "" , err
360
+ return "" , "" , err
360
361
}
361
362
err := r .CreateOrUpdate (ltpaJobRequest , nil , func () error {
362
363
return nil
363
364
})
364
365
if err != nil {
365
- return "" , fmt .Errorf ("Failed to create ConfigMap " + ltpaJobRequest .Name )
366
+ return "" , "" , fmt .Errorf ("Failed to create ConfigMap " + ltpaJobRequest .Name )
366
367
}
367
368
} else {
368
- return "" , fmt .Errorf ("Failed to get ConfigMap " + ltpaJobRequest .Name )
369
+ return "" , "" , fmt .Errorf ("Failed to get ConfigMap " + ltpaJobRequest .Name )
369
370
}
370
371
} else {
371
372
// Create the ServiceAccount
372
373
if err := r .CreateOrUpdate (ltpaServiceAccount , nil , func () error {
373
374
return nil
374
375
}); err != nil && ! kerrors .IsNotFound (err ) {
375
- return "" , fmt .Errorf ("Failed to create ServiceAccount " + ltpaServiceAccount .Name )
376
+ return "" , "" , fmt .Errorf ("Failed to create ServiceAccount " + ltpaServiceAccount .Name )
376
377
}
377
378
378
379
// Create the Role/RoleBinding
379
380
if err := r .CreateOrUpdate (ltpaRole , nil , func () error {
380
381
return nil
381
382
}); err != nil && ! kerrors .IsNotFound (err ) {
382
- return "" , fmt .Errorf ("Failed to create Role " + ltpaRole .Name )
383
+ return "" , "" , fmt .Errorf ("Failed to create Role " + ltpaRole .Name )
383
384
}
384
385
if err := r .CreateOrUpdate (ltpaRoleBinding , nil , func () error {
385
386
return nil
386
387
}); err != nil && ! kerrors .IsNotFound (err ) {
387
- return "" , fmt .Errorf ("Failed to create RoleBinding " + ltpaRoleBinding .Name )
388
+ return "" , "" , fmt .Errorf ("Failed to create RoleBinding " + ltpaRoleBinding .Name )
388
389
}
389
390
390
391
// Create a ConfigMap to store the internal/controller/assets/create_ltpa_keys.sh script
@@ -393,7 +394,7 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
393
394
ltpaKeysCreationScriptConfigMap .Data = make (map [string ]string )
394
395
script , err := os .ReadFile ("internal/controller/assets/" + lutils .LTPAKeysCreationScriptFileName )
395
396
if err != nil {
396
- return "" , err
397
+ return "" , "" , err
397
398
}
398
399
ltpaKeysCreationScriptConfigMap .Data [lutils .LTPAKeysCreationScriptFileName ] = string (script )
399
400
// prevent script from being modified
@@ -410,22 +411,22 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
410
411
// Compare the bundle script against the ltpaKeysCreationScriptConfigMap's saved script
411
412
script , err := os .ReadFile ("internal/controller/assets/" + lutils .LTPAKeysCreationScriptFileName )
412
413
if err != nil {
413
- return "" , err
414
+ return "" , "" , err
414
415
}
415
416
savedScript , found := ltpaKeysCreationScriptConfigMap .Data [lutils .LTPAKeysCreationScriptFileName ]
416
417
// Delete ltpaKeysCreationScriptConfigMap if it is missing the data key
417
418
if ! found {
418
419
if err := r .DeleteResource (ltpaKeysCreationScriptConfigMap ); err != nil {
419
- return "" , err
420
+ return "" , "" , err
420
421
}
421
- return "" , fmt .Errorf ("the LTPA Keys Creation ConfigMap is missing key " + lutils .LTPAKeysCreationScriptFileName )
422
+ return "" , "" , fmt .Errorf ("the LTPA Keys Creation ConfigMap is missing key " + lutils .LTPAKeysCreationScriptFileName )
422
423
}
423
424
// Delete ltpaKeysCreationScriptConfigMap if the file contents do not match
424
425
if string (script ) != savedScript {
425
426
if err := r .DeleteResource (ltpaKeysCreationScriptConfigMap ); err != nil {
426
- return "" , err
427
+ return "" , "" , err
427
428
}
428
- return "" , fmt .Errorf ("the LTPA Keys Creation ConfigMap key '" + lutils .LTPAKeysCreationScriptFileName + "' is out of sync" )
429
+ return "" , "" , fmt .Errorf ("the LTPA Keys Creation ConfigMap key '" + lutils .LTPAKeysCreationScriptFileName + "' is out of sync" )
429
430
}
430
431
// Run the Kubernetes Job to generate the shared ltpa.keys file and LTPA Secret
431
432
err = r .GetClient ().Get (context .TODO (), types.NamespacedName {Name : generateLTPAKeysJob .Name , Namespace : generateLTPAKeysJob .Namespace }, generateLTPAKeysJob )
@@ -446,7 +447,7 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
446
447
return nil
447
448
})
448
449
if err != nil {
449
- return "" , fmt .Errorf ("Failed to create Job %s: %s" + generateLTPAKeysJob .Name , err )
450
+ return "" , "" , fmt .Errorf ("Failed to create Job %s: %s" + generateLTPAKeysJob .Name , err )
450
451
}
451
452
} else if err == nil {
452
453
// If the LTPA Secret is not yet created (LTPA Job has not successfully completed)
@@ -455,61 +456,61 @@ func (r *ReconcileOpenLiberty) generateLTPAKeys(instance *olv1.OpenLibertyApplic
455
456
// Delete the Job request to restart the entire LTPA generation process (i.e. reloading the script, ltpa.xml, and Job)
456
457
err = r .DeleteResource (ltpaJobRequest )
457
458
if err != nil {
458
- return ltpaSecret .Name , err
459
+ return ltpaSecret .Name , "" , err
459
460
}
460
461
}
461
462
} else {
462
- return "" , fmt .Errorf ("Failed to get Job " + generateLTPAKeysJob .Name )
463
+ return "" , "" , fmt .Errorf ("Failed to get Job " + generateLTPAKeysJob .Name )
463
464
}
464
465
}
465
466
}
466
467
467
468
// Reconcile the Job
468
469
err = r .GetClient ().Get (context .TODO (), types.NamespacedName {Name : generateLTPAKeysJob .Name , Namespace : generateLTPAKeysJob .Namespace }, generateLTPAKeysJob )
469
470
if err != nil && kerrors .IsNotFound (err ) {
470
- return "" , fmt .Errorf ("Waiting for the LTPA key to be generated by Job '" + generateLTPAKeysJob .Name + "'." )
471
+ return "" , "" , fmt .Errorf ("Waiting for the LTPA key to be generated by Job '" + generateLTPAKeysJob .Name + "'." )
471
472
} else if err != nil {
472
- return "" , fmt .Errorf ("Failed to get Job " + generateLTPAKeysJob .Name )
473
+ return "" , "" , fmt .Errorf ("Failed to get Job " + generateLTPAKeysJob .Name )
473
474
}
474
475
if len (generateLTPAKeysJob .Status .Conditions ) > 0 && generateLTPAKeysJob .Status .Conditions [0 ].Type == v1 .JobFailed {
475
- return "" , fmt .Errorf ("Job " + generateLTPAKeysJob .Name + " has failed. Manually clean up hung resources by setting .spec.manageLTPA to false in the " + leaderName + " instance." )
476
+ return "" , "" , fmt .Errorf ("Job " + generateLTPAKeysJob .Name + " has failed. Manually clean up hung resources by setting .spec.manageLTPA to false in the " + leaderName + " instance." )
476
477
}
477
- return "" , fmt .Errorf ("Waiting for the LTPA key to be generated by Job '" + generateLTPAKeysJob .Name + "'." )
478
+ return "" , "" , fmt .Errorf ("Waiting for the LTPA key to be generated by Job '" + generateLTPAKeysJob .Name + "'." )
478
479
} else if err != nil {
479
- return "" , err
480
- } else {
481
- _ , thisInstanceIsLeader , _ , err := r .reconcileLeader (instance , ltpaMetadata , LTPA_RESOURCE_SHARING_FILE_NAME , true )
482
- if err != nil {
483
- return "" , err
484
- }
485
- if ! thisInstanceIsLeader {
486
- return ltpaSecret . Name , nil
487
- }
480
+ return "" , "" , err
481
+ }
482
+ _ , thisInstanceIsLeader , _ , err := r .reconcileLeader (instance , ltpaMetadata , LTPA_RESOURCE_SHARING_FILE_NAME , true )
483
+ if err != nil {
484
+ return "" , "" , err
485
+ }
486
+ lastRotation := string ( ltpaSecret . Data [ "lastRotation" ])
487
+ if ! thisInstanceIsLeader {
488
+ return ltpaSecret . Name , lastRotation , nil
488
489
}
489
490
490
491
// The LTPA Secret is created (in other words, the LTPA Job has completed) so delete the Job request
491
492
err = r .DeleteResource (ltpaJobRequest )
492
493
if err != nil {
493
- return ltpaSecret .Name , err
494
+ return ltpaSecret .Name , lastRotation , err
494
495
}
495
496
// The LTPA Secret is created so delete the ServiceAccount, Role and RoleBinding
496
497
err = r .DeleteResource (ltpaServiceAccount )
497
498
if err != nil {
498
- return ltpaSecret .Name , err
499
+ return ltpaSecret .Name , lastRotation , err
499
500
}
500
501
err = r .DeleteResource (ltpaRole )
501
502
if err != nil {
502
- return ltpaSecret .Name , err
503
+ return ltpaSecret .Name , lastRotation , err
503
504
}
504
505
err = r .DeleteResource (ltpaRoleBinding )
505
506
if err != nil {
506
- return ltpaSecret .Name , err
507
+ return ltpaSecret .Name , lastRotation , err
507
508
}
508
- return ltpaSecret .Name , nil
509
+ return ltpaSecret .Name , lastRotation , nil
509
510
}
510
511
511
512
// Generates the LTPA keys file and returns the name of the Secret storing its metadata
512
- func (r * ReconcileOpenLiberty ) generateLTPAConfig (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata , ltpaConfigMetadata * lutils.LTPAMetadata , passwordEncryptionMetadata * lutils.PasswordEncryptionMetadata ) error {
513
+ func (r * ReconcileOpenLiberty ) generateLTPAConfig (instance * olv1.OpenLibertyApplication , ltpaKeysMetadata * lutils.LTPAMetadata , ltpaConfigMetadata * lutils.LTPAMetadata , passwordEncryptionMetadata * lutils.PasswordEncryptionMetadata , ltpaKeysLastRotation string ) error {
513
514
ltpaXMLSecret := & corev1.Secret {}
514
515
ltpaXMLSecretRootName := OperatorShortName + lutils .LTPAServerXMLSuffix
515
516
ltpaXMLSecret .Name = ltpaXMLSecretRootName + ltpaConfigMetadata .Name
@@ -802,6 +803,20 @@ func (r *ReconcileOpenLiberty) generateLTPAConfig(instance *olv1.OpenLibertyAppl
802
803
return err
803
804
}
804
805
806
+ // if the LTPA password is outdated from the LTPA Secret, delete the LTPA password
807
+ lastRotation , found := ltpaConfigSecret .Data ["lastRotation" ]
808
+ if ! found || string (lastRotation ) != string (ltpaKeysLastRotation ) {
809
+ // lastRotation field is not present so the Secret was not initialized correctly
810
+ err := r .DeleteResource (ltpaConfigSecret )
811
+ if err != nil {
812
+ return err
813
+ }
814
+ if ! found {
815
+ return fmt .Errorf ("the LTPA password does not contain field 'lastRotation'" )
816
+ }
817
+ return fmt .Errorf ("the LTPA password is out of sync with the generated LTPA Secret; waiting for a new LTPA password to be generated" )
818
+ }
819
+
805
820
// if using encryption key, check if the key has been rotated and requires a regeneration of the LTPA keyed password
806
821
if isPasswordEncryptionKeySharing {
807
822
internalEncryptionKeySecret , err := r .hasInternalEncryptionKeySecret (instance , passwordEncryptionMetadata )
0 commit comments