@@ -27,6 +27,8 @@ const (
27
27
DefaultCertMinFresh = time .Hour * 24
28
28
// DefaultCertValidFor is the default duration a cert can be valid for - 2 years
29
29
DefaultCertValidFor = time .Hour * 24 * 730
30
+ // OLMCAPEMKey is the CAPEM
31
+ OLMCAPEMKey = "olmCAKey"
30
32
// OLMCAHashAnnotationKey is the label key used to store the hash of the CA cert
31
33
OLMCAHashAnnotationKey = "olmcahash"
32
34
// Organization is the organization name used in the generation of x509 certs
@@ -185,25 +187,28 @@ func (i *StrategyDeploymentInstaller) installCertRequirements(strategy Strategy)
185
187
}
186
188
187
189
// Update the deployment for each certResource
188
- newDepSpec , err := i .installCertRequirementsForDeployment (sddSpec .Name , ca , rotateAt , sddSpec .Spec , getServicePorts (certResources ))
190
+ newDepSpec , caPEM , err := i .installCertRequirementsForDeployment (sddSpec .Name , ca , rotateAt , sddSpec .Spec , getServicePorts (certResources ))
189
191
if err != nil {
190
192
return nil , err
191
193
}
192
194
193
- caPEM , _ , err := ca .ToPEM ()
194
- if err != nil {
195
- logger .Warnf ("unable to convert CA certificate to PEM format for Deployment %s" , sddSpec .Name )
196
- return nil , err
197
- }
198
-
199
195
i .updateCertResourcesForDeployment (sddSpec .Name , caPEM )
200
196
201
197
strategyDetailsDeployment .DeploymentSpecs [n ].Spec = * newDepSpec
202
198
}
203
199
return strategyDetailsDeployment , nil
204
200
}
205
201
206
- func (i * StrategyDeploymentInstaller ) installCertRequirementsForDeployment (deploymentName string , ca * certs.KeyPair , rotateAt time.Time , depSpec appsv1.DeploymentSpec , ports []corev1.ServicePort ) (* appsv1.DeploymentSpec , error ) {
202
+ func ShouldRotateCerts (csv * v1alpha1.ClusterServiceVersion ) bool {
203
+ now := metav1 .Now ()
204
+ if ! csv .Status .CertsRotateAt .IsZero () && csv .Status .CertsRotateAt .Before (& now ) {
205
+ return true
206
+ }
207
+
208
+ return false
209
+ }
210
+
211
+ func (i * StrategyDeploymentInstaller ) installCertRequirementsForDeployment (deploymentName string , ca * certs.KeyPair , rotateAt time.Time , depSpec appsv1.DeploymentSpec , ports []corev1.ServicePort ) (* appsv1.DeploymentSpec , []byte , error ) {
207
212
logger := log .WithFields (log.Fields {})
208
213
209
214
// Create a service for the deployment
@@ -215,27 +220,27 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
215
220
}
216
221
service .SetName (ServiceName (deploymentName ))
217
222
service .SetNamespace (i .owner .GetNamespace ())
223
+ ownerutil .AddNonBlockingOwner (service , i .owner )
218
224
219
225
existingService , err := i .strategyClient .GetOpLister ().CoreV1 ().ServiceLister ().Services (i .owner .GetNamespace ()).Get (service .GetName ())
220
226
if err == nil {
221
227
if ! ownerutil .Adoptable (i .owner , existingService .GetOwnerReferences ()) {
222
- return nil , fmt .Errorf ("service %s not safe to replace: extraneous ownerreferences found" , service .GetName ())
228
+ return nil , nil , fmt .Errorf ("service %s not safe to replace: extraneous ownerreferences found" , service .GetName ())
223
229
}
224
230
service .SetOwnerReferences (existingService .GetOwnerReferences ())
225
231
226
232
// Delete the Service to replace
227
233
deleteErr := i .strategyClient .GetOpClient ().DeleteService (service .GetNamespace (), service .GetName (), & metav1.DeleteOptions {})
228
234
if err != nil && ! k8serrors .IsNotFound (deleteErr ) {
229
- return nil , fmt .Errorf ("could not delete existing service %s" , service .GetName ())
235
+ return nil , nil , fmt .Errorf ("could not delete existing service %s" , service .GetName ())
230
236
}
231
237
}
232
- ownerutil .AddNonBlockingOwner (service , i .owner )
233
238
234
239
// Attempt to create the Service
235
240
_ , err = i .strategyClient .GetOpClient ().CreateService (service )
236
241
if err != nil {
237
242
logger .Warnf ("could not create service %s" , service .GetName ())
238
- return nil , fmt .Errorf ("could not create service %s: %s" , service .GetName (), err .Error ())
243
+ return nil , nil , fmt .Errorf ("could not create service %s: %s" , service .GetName (), err .Error ())
239
244
}
240
245
241
246
// Create signed serving cert
@@ -246,33 +251,34 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
246
251
servingPair , err := certs .CreateSignedServingPair (rotateAt , Organization , ca , hosts )
247
252
if err != nil {
248
253
logger .Warnf ("could not generate signed certs for hosts %v" , hosts )
249
- return nil , err
254
+ return nil , nil , err
250
255
}
251
256
252
257
// Create Secret for serving cert
253
258
certPEM , privPEM , err := servingPair .ToPEM ()
254
259
if err != nil {
255
260
logger .Warnf ("unable to convert serving certificate and private key to PEM format for Service %s" , service .GetName ())
256
- return nil , err
261
+ return nil , nil , err
257
262
}
258
263
264
+ // Add olmcahash as a label to the caPEM
265
+ caPEM , _ , err := ca .ToPEM ()
266
+ if err != nil {
267
+ logger .Warnf ("unable to convert CA certificate to PEM format for Service %s" , service )
268
+ return nil , nil , err
269
+ }
270
+ caHash := certs .PEMSHA256 (caPEM )
271
+
259
272
secret := & corev1.Secret {
260
273
Data : map [string ][]byte {
261
- "tls.crt" : certPEM ,
262
- "tls.key" : privPEM ,
274
+ "tls.crt" : certPEM ,
275
+ "tls.key" : privPEM ,
276
+ OLMCAPEMKey : caPEM ,
263
277
},
264
278
Type : corev1 .SecretTypeTLS ,
265
279
}
266
280
secret .SetName (SecretName (service .GetName ()))
267
281
secret .SetNamespace (i .owner .GetNamespace ())
268
-
269
- // Add olmcahash as a label to the caPEM
270
- caPEM , _ , err := ca .ToPEM ()
271
- if err != nil {
272
- logger .Warnf ("unable to convert CA certificate to PEM format for Service %s" , service )
273
- return nil , err
274
- }
275
- caHash := certs .PEMSHA256 (caPEM )
276
282
secret .SetAnnotations (map [string ]string {OLMCAHashAnnotationKey : caHash })
277
283
278
284
existingSecret , err := i .strategyClient .GetOpLister ().CoreV1 ().SecretLister ().Secrets (i .owner .GetNamespace ()).Get (secret .GetName ())
@@ -283,20 +289,27 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
283
289
}
284
290
285
291
// Attempt an update
286
- if _ , err := i .strategyClient .GetOpClient ().UpdateSecret (secret ); err != nil {
292
+ // TODO: Check that the secret was not modified
293
+ if existingCAPEM , ok := existingSecret .Data [OLMCAPEMKey ]; ok && ! ShouldRotateCerts (i .owner .(* v1alpha1.ClusterServiceVersion )) {
294
+ logger .Warnf ("reusing existing cert %s" , secret .GetName ())
295
+ secret = existingSecret
296
+ caPEM = existingCAPEM
297
+ caHash = certs .PEMSHA256 (caPEM )
298
+ } else if _ , err := i .strategyClient .GetOpClient ().UpdateSecret (secret ); err != nil {
287
299
logger .Warnf ("could not update secret %s" , secret .GetName ())
288
- return nil , err
300
+ return nil , nil , err
289
301
}
302
+
290
303
} else if k8serrors .IsNotFound (err ) {
291
304
// Create the secret
292
305
ownerutil .AddNonBlockingOwner (secret , i .owner )
293
306
_ , err = i .strategyClient .GetOpClient ().CreateSecret (secret )
294
307
if err != nil {
295
308
log .Warnf ("could not create secret %s" , secret .GetName ())
296
- return nil , err
309
+ return nil , nil , err
297
310
}
298
311
} else {
299
- return nil , err
312
+ return nil , nil , err
300
313
}
301
314
302
315
// create Role and RoleBinding to allow the deployment to mount the Secret
@@ -323,18 +336,18 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
323
336
// Attempt an update
324
337
if _ , err := i .strategyClient .GetOpClient ().UpdateRole (secretRole ); err != nil {
325
338
logger .Warnf ("could not update secret role %s" , secretRole .GetName ())
326
- return nil , err
339
+ return nil , nil , err
327
340
}
328
341
} else if k8serrors .IsNotFound (err ) {
329
342
// Create the role
330
343
ownerutil .AddNonBlockingOwner (secretRole , i .owner )
331
344
_ , err = i .strategyClient .GetOpClient ().CreateRole (secretRole )
332
345
if err != nil {
333
346
log .Warnf ("could not create secret role %s" , secretRole .GetName ())
334
- return nil , err
347
+ return nil , nil , err
335
348
}
336
349
} else {
337
- return nil , err
350
+ return nil , nil , err
338
351
}
339
352
340
353
if depSpec .Template .Spec .ServiceAccountName == "" {
@@ -369,18 +382,18 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
369
382
// Attempt an update
370
383
if _ , err := i .strategyClient .GetOpClient ().UpdateRoleBinding (secretRoleBinding ); err != nil {
371
384
logger .Warnf ("could not update secret rolebinding %s" , secretRoleBinding .GetName ())
372
- return nil , err
385
+ return nil , nil , err
373
386
}
374
387
} else if k8serrors .IsNotFound (err ) {
375
388
// Create the role
376
389
ownerutil .AddNonBlockingOwner (secretRoleBinding , i .owner )
377
390
_ , err = i .strategyClient .GetOpClient ().CreateRoleBinding (secretRoleBinding )
378
391
if err != nil {
379
392
log .Warnf ("could not create secret rolebinding with dep spec: %#v" , depSpec )
380
- return nil , err
393
+ return nil , nil , err
381
394
}
382
395
} else {
383
- return nil , err
396
+ return nil , nil , err
384
397
}
385
398
386
399
// create ClusterRoleBinding to system:auth-delegator Role
@@ -407,27 +420,27 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
407
420
if ownerutil .AdoptableLabels (existingAuthDelegatorClusterRoleBinding .GetLabels (), true , i .owner ) {
408
421
logger .WithFields (log.Fields {"obj" : "authDelegatorCRB" , "labels" : existingAuthDelegatorClusterRoleBinding .GetLabels ()}).Debug ("adopting" )
409
422
if err := ownerutil .AddOwnerLabels (authDelegatorClusterRoleBinding , i .owner ); err != nil {
410
- return nil , err
423
+ return nil , nil , err
411
424
}
412
425
}
413
426
414
427
// Attempt an update.
415
428
if _ , err := i .strategyClient .GetOpClient ().UpdateClusterRoleBinding (authDelegatorClusterRoleBinding ); err != nil {
416
429
logger .Warnf ("could not update auth delegator clusterrolebinding %s" , authDelegatorClusterRoleBinding .GetName ())
417
- return nil , err
430
+ return nil , nil , err
418
431
}
419
432
} else if k8serrors .IsNotFound (err ) {
420
433
// Create the role.
421
434
if err := ownerutil .AddOwnerLabels (authDelegatorClusterRoleBinding , i .owner ); err != nil {
422
- return nil , err
435
+ return nil , nil , err
423
436
}
424
437
_ , err = i .strategyClient .GetOpClient ().CreateClusterRoleBinding (authDelegatorClusterRoleBinding )
425
438
if err != nil {
426
439
log .Warnf ("could not create auth delegator clusterrolebinding %s" , authDelegatorClusterRoleBinding .GetName ())
427
- return nil , err
440
+ return nil , nil , err
428
441
}
429
442
} else {
430
- return nil , err
443
+ return nil , nil , err
431
444
}
432
445
433
446
// Create RoleBinding to extension-apiserver-authentication-reader Role in the kube-system namespace.
@@ -455,26 +468,26 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
455
468
if ownerutil .AdoptableLabels (existingAuthReaderRoleBinding .GetLabels (), true , i .owner ) {
456
469
logger .WithFields (log.Fields {"obj" : "existingAuthReaderRB" , "labels" : existingAuthReaderRoleBinding .GetLabels ()}).Debug ("adopting" )
457
470
if err := ownerutil .AddOwnerLabels (authReaderRoleBinding , i .owner ); err != nil {
458
- return nil , err
471
+ return nil , nil , err
459
472
}
460
473
}
461
474
// Attempt an update.
462
475
if _ , err := i .strategyClient .GetOpClient ().UpdateRoleBinding (authReaderRoleBinding ); err != nil {
463
476
logger .Warnf ("could not update auth reader role binding %s" , authReaderRoleBinding .GetName ())
464
- return nil , err
477
+ return nil , nil , err
465
478
}
466
479
} else if k8serrors .IsNotFound (err ) {
467
480
// Create the role.
468
481
if err := ownerutil .AddOwnerLabels (authReaderRoleBinding , i .owner ); err != nil {
469
- return nil , err
482
+ return nil , nil , err
470
483
}
471
484
_ , err = i .strategyClient .GetOpClient ().CreateRoleBinding (authReaderRoleBinding )
472
485
if err != nil {
473
486
log .Warnf ("could not create auth reader role binding %s" , authReaderRoleBinding .GetName ())
474
- return nil , err
487
+ return nil , nil , err
475
488
}
476
489
} else {
477
- return nil , err
490
+ return nil , nil , err
478
491
}
479
492
480
493
// Update deployment with secret volume mount.
@@ -539,5 +552,5 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
539
552
// is used by the apiserver if not hot reloading.
540
553
depSpec .Template .ObjectMeta .SetAnnotations (map [string ]string {OLMCAHashAnnotationKey : caHash })
541
554
542
- return & depSpec , nil
555
+ return & depSpec , caPEM , nil
543
556
}
0 commit comments