Skip to content

Commit 737dc0f

Browse files
Merge pull request #1720 from vrutkovs/certrotation-better-error-messages
NO-JIRA: certrotation: improve error messages
2 parents b941412 + 9a49878 commit 737dc0f

File tree

5 files changed

+42
-18
lines changed

5 files changed

+42
-18
lines changed

pkg/operator/certrotation/cabundle.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ type CABundleConfigMap struct {
4141
EventRecorder events.Recorder
4242
}
4343

44-
func (c CABundleConfigMap) EnsureConfigMapCABundle(ctx context.Context, signingCertKeyPair *crypto.CA) ([]*x509.Certificate, error) {
44+
func (c CABundleConfigMap) EnsureConfigMapCABundle(ctx context.Context, signingCertKeyPair *crypto.CA, signingCertKeyPairLocation string) ([]*x509.Certificate, error) {
4545
// by this point we have current signing cert/key pair. We now need to make sure that the ca-bundle configmap has this cert and
4646
// doesn't have any expired certs
4747
modified := false
@@ -73,7 +73,15 @@ func (c CABundleConfigMap) EnsureConfigMapCABundle(ctx context.Context, signingC
7373
return nil, err
7474
}
7575
if originalCABundleConfigMap == nil || originalCABundleConfigMap.Data == nil || !equality.Semantic.DeepEqual(originalCABundleConfigMap.Data, caBundleConfigMap.Data) {
76-
c.EventRecorder.Eventf("CABundleUpdateRequired", "%q in %q requires a new cert", c.Name, c.Namespace)
76+
reason := ""
77+
if originalCABundleConfigMap == nil {
78+
reason = "configmap doesn't exist"
79+
} else if originalCABundleConfigMap.Data == nil {
80+
reason = "configmap is empty"
81+
} else if !equality.Semantic.DeepEqual(originalCABundleConfigMap.Data, caBundleConfigMap.Data) {
82+
reason = fmt.Sprintf("signer update %s", signingCertKeyPairLocation)
83+
}
84+
c.EventRecorder.Eventf("CABundleUpdateRequired", "%q in %q requires a new cert: %s", c.Name, c.Namespace, reason)
7785
LabelAsManagedConfigMap(caBundleConfigMap, CertificateTypeCABundle)
7886

7987
modified = true

pkg/operator/certrotation/cabundle_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func TestEnsureConfigMapCABundle(t *testing.T) {
236236
if err != nil {
237237
t.Fatal(err)
238238
}
239-
_, err = c.EnsureConfigMapCABundle(context.TODO(), newCA)
239+
_, err = c.EnsureConfigMapCABundle(context.TODO(), newCA, "signer-secret")
240240
switch {
241241
case err != nil && len(test.expectedError) == 0:
242242
t.Error(err)

pkg/operator/certrotation/client_cert_rotation_controller.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,17 @@ func (c CertRotationController) Sync(ctx context.Context, syncCtx factory.SyncCo
121121
return syncErr
122122
}
123123

124+
func (c CertRotationController) getSigningCertKeyPairLocation() string {
125+
return fmt.Sprintf("%s/%s", c.RotatedSelfSignedCertKeySecret.Namespace, c.RotatedSelfSignedCertKeySecret.Name)
126+
}
127+
124128
func (c CertRotationController) SyncWorker(ctx context.Context) error {
125129
signingCertKeyPair, _, err := c.RotatedSigningCASecret.EnsureSigningCertKeyPair(ctx)
126130
if err != nil {
127131
return err
128132
}
129133

130-
cabundleCerts, err := c.CABundleConfigMap.EnsureConfigMapCABundle(ctx, signingCertKeyPair)
134+
cabundleCerts, err := c.CABundleConfigMap.EnsureConfigMapCABundle(ctx, signingCertKeyPair, c.getSigningCertKeyPairLocation())
131135
if err != nil {
132136
return err
133137
}

pkg/operator/certrotation/signer.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ func (c RotatedSigningCASecret) EnsureSigningCertKeyPair(ctx context.Context) (*
6868
if err != nil && !apierrors.IsNotFound(err) {
6969
return nil, false, err
7070
}
71+
var signerExists = true
7172
signingCertKeyPairSecret := originalSigningCertKeyPairSecret.DeepCopy()
7273
if apierrors.IsNotFound(err) {
7374
// create an empty one
@@ -79,7 +80,7 @@ func (c RotatedSigningCASecret) EnsureSigningCertKeyPair(ctx context.Context) (*
7980
),
8081
Type: corev1.SecretTypeTLS,
8182
}
82-
modified = true
83+
signerExists = false
8384
}
8485

8586
applyFn := resourceapply.ApplySecret
@@ -94,7 +95,10 @@ func (c RotatedSigningCASecret) EnsureSigningCertKeyPair(ctx context.Context) (*
9495
modified = needsMetadataUpdate || needsTypeChange || modified
9596

9697
signerUpdated := false
97-
if needed, reason := needNewSigningCertKeyPair(signingCertKeyPairSecret.Annotations, c.Refresh, c.RefreshOnlyWhenExpired); needed {
98+
if needed, reason := needNewSigningCertKeyPair(signingCertKeyPairSecret, c.Refresh, c.RefreshOnlyWhenExpired); needed || !signerExists {
99+
if !signerExists {
100+
reason = "secret doesn't exist"
101+
}
98102
c.EventRecorder.Eventf("SignerUpdateRequired", "%q in %q requires a new signing cert/key pair: %v", c.Name, c.Namespace, reason)
99103
if err := setSigningCertKeyPairSecret(signingCertKeyPairSecret, c.Validity); err != nil {
100104
return nil, false, err
@@ -139,7 +143,8 @@ func ensureOwnerReference(meta *metav1.ObjectMeta, owner *metav1.OwnerReference)
139143
return false
140144
}
141145

142-
func needNewSigningCertKeyPair(annotations map[string]string, refresh time.Duration, refreshOnlyWhenExpired bool) (bool, string) {
146+
func needNewSigningCertKeyPair(secret *corev1.Secret, refresh time.Duration, refreshOnlyWhenExpired bool) (bool, string) {
147+
annotations := secret.Annotations
143148
notBefore, notAfter, reason := getValidityFromAnnotations(annotations)
144149
if len(reason) > 0 {
145150
return true, reason
@@ -156,7 +161,7 @@ func needNewSigningCertKeyPair(annotations map[string]string, refresh time.Durat
156161
validity := notAfter.Sub(notBefore)
157162
at80Percent := notAfter.Add(-validity / 5)
158163
if time.Now().After(at80Percent) {
159-
return true, fmt.Sprintf("past its latest possible time %v", at80Percent)
164+
return true, fmt.Sprintf("past refresh time (80%% of validity): %v", at80Percent)
160165
}
161166

162167
developerSpecifiedRefresh := notBefore.Add(refresh)

pkg/operator/certrotation/target.go

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ type TargetCertCreator interface {
8080
// NewCertificate creates a new key-cert pair with the given signer.
8181
NewCertificate(signer *crypto.CA, validity time.Duration) (*crypto.TLSCertificateConfig, error)
8282
// NeedNewTargetCertKeyPair decides whether a new cert-key pair is needed. It returns a non-empty reason if it is the case.
83-
NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired bool) string
83+
NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired, secretDoesntExist bool) string
8484
// SetAnnotations gives an option to override or set additional annotations
8585
SetAnnotations(cert *crypto.TLSCertificateConfig, annotations map[string]string) map[string]string
8686
}
@@ -97,6 +97,7 @@ func (c RotatedSelfSignedCertKeySecret) EnsureTargetCertKeyPair(ctx context.Cont
9797
// and need to mint one
9898
// TODO do the cross signing thing, but this shows the API consumers want and a very simple impl.
9999

100+
secretDoesntExist := false
100101
modified := false
101102
originalTargetCertKeyPairSecret, err := c.Lister.Secrets(c.Namespace).Get(c.Name)
102103
if err != nil && !apierrors.IsNotFound(err) {
@@ -114,6 +115,7 @@ func (c RotatedSelfSignedCertKeySecret) EnsureTargetCertKeyPair(ctx context.Cont
114115
Type: corev1.SecretTypeTLS,
115116
}
116117
modified = true
118+
secretDoesntExist = true
117119
}
118120

119121
applyFn := resourceapply.ApplySecret
@@ -127,7 +129,7 @@ func (c RotatedSelfSignedCertKeySecret) EnsureTargetCertKeyPair(ctx context.Cont
127129
needsSecretTypeUpdate := ensureSecretTLSTypeSet(targetCertKeyPairSecret)
128130
modified = needsMetadataUpdate || needsSecretTypeUpdate || modified
129131

130-
if reason := c.CertCreator.NeedNewTargetCertKeyPair(targetCertKeyPairSecret, signingCertKeyPair, caBundleCerts, c.Refresh, c.RefreshOnlyWhenExpired); len(reason) > 0 {
132+
if reason := c.CertCreator.NeedNewTargetCertKeyPair(targetCertKeyPairSecret, signingCertKeyPair, caBundleCerts, c.Refresh, c.RefreshOnlyWhenExpired, secretDoesntExist); len(reason) > 0 {
131133
c.EventRecorder.Eventf("TargetUpdateRequired", "%q in %q requires a new target cert/key pair: %v", c.Name, c.Namespace, reason)
132134
if err := setTargetCertKeyPairSecret(targetCertKeyPairSecret, c.Validity, signingCertKeyPair, c.CertCreator, c.AdditionalAnnotations); err != nil {
133135
return nil, err
@@ -149,7 +151,12 @@ func (c RotatedSelfSignedCertKeySecret) EnsureTargetCertKeyPair(ctx context.Cont
149151
return targetCertKeyPairSecret, nil
150152
}
151153

152-
func needNewTargetCertKeyPair(annotations map[string]string, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired bool) string {
154+
func needNewTargetCertKeyPair(secret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired, secretDoesntExist bool) string {
155+
if secretDoesntExist {
156+
return "secret doesn't exist"
157+
}
158+
159+
annotations := secret.Annotations
153160
if reason := needNewTargetCertKeyPairForTime(annotations, signer, refresh, refreshOnlyWhenExpired); len(reason) > 0 {
154161
return reason
155162
}
@@ -206,7 +213,7 @@ func needNewTargetCertKeyPairForTime(annotations map[string]string, signer *cryp
206213
validity := notAfter.Sub(notBefore)
207214
at80Percent := notAfter.Add(-validity / 5)
208215
if time.Now().After(at80Percent) {
209-
return fmt.Sprintf("past its latest possible time %v", at80Percent)
216+
return fmt.Sprintf("past refresh time (80%% of validity): %v", at80Percent)
210217
}
211218

212219
// If Certificate is past its refresh time, we may have action to take. We only do this if the signer is old enough.
@@ -266,8 +273,8 @@ func (r *ClientRotation) NewCertificate(signer *crypto.CA, validity time.Duratio
266273
return signer.MakeClientCertificateForDuration(r.UserInfo, validity)
267274
}
268275

269-
func (r *ClientRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired bool) string {
270-
return needNewTargetCertKeyPair(currentCertSecret.Annotations, signer, caBundleCerts, refresh, refreshOnlyWhenExpired)
276+
func (r *ClientRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired, secretDoesntExist bool) string {
277+
return needNewTargetCertKeyPair(currentCertSecret, signer, caBundleCerts, refresh, refreshOnlyWhenExpired, secretDoesntExist)
271278
}
272279

273280
func (r *ClientRotation) SetAnnotations(cert *crypto.TLSCertificateConfig, annotations map[string]string) map[string]string {
@@ -291,8 +298,8 @@ func (r *ServingRotation) RecheckChannel() <-chan struct{} {
291298
return r.HostnamesChanged
292299
}
293300

294-
func (r *ServingRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired bool) string {
295-
reason := needNewTargetCertKeyPair(currentCertSecret.Annotations, signer, caBundleCerts, refresh, refreshOnlyWhenExpired)
301+
func (r *ServingRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired, secretDoesntExist bool) string {
302+
reason := needNewTargetCertKeyPair(currentCertSecret, signer, caBundleCerts, refresh, refreshOnlyWhenExpired, secretDoesntExist)
296303
if len(reason) > 0 {
297304
return reason
298305
}
@@ -337,8 +344,8 @@ func (r *SignerRotation) NewCertificate(signer *crypto.CA, validity time.Duratio
337344
return crypto.MakeCAConfigForDuration(signerName, validity, signer)
338345
}
339346

340-
func (r *SignerRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired bool) string {
341-
return needNewTargetCertKeyPair(currentCertSecret.Annotations, signer, caBundleCerts, refresh, refreshOnlyWhenExpired)
347+
func (r *SignerRotation) NeedNewTargetCertKeyPair(currentCertSecret *corev1.Secret, signer *crypto.CA, caBundleCerts []*x509.Certificate, refresh time.Duration, refreshOnlyWhenExpired, secretDoesntExist bool) string {
348+
return needNewTargetCertKeyPair(currentCertSecret, signer, caBundleCerts, refresh, refreshOnlyWhenExpired, secretDoesntExist)
342349
}
343350

344351
func (r *SignerRotation) SetAnnotations(cert *crypto.TLSCertificateConfig, annotations map[string]string) map[string]string {

0 commit comments

Comments
 (0)