From b2f988dbfeca5109eee667982b60c715361d354d Mon Sep 17 00:00:00 2001 From: Jack Henschel Date: Tue, 7 Mar 2023 10:23:58 +0100 Subject: [PATCH] Verify that certificate is valid for Route hostname Signed-off-by: Jack Henschel --- README.md | 9 +++++++++ internal/controller/sync.go | 5 +++++ internal/controller/sync_test.go | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+) diff --git a/README.md b/README.md index 0b84b2e..bdf498e 100644 --- a/README.md +++ b/README.md @@ -106,6 +106,15 @@ The route's TLS certificate will be rotated 2/3 of the way through the certifica Now the website can be called: https://app.service.clustername.domain.com +## Development + +The source code for the controller can be found in the `./internal/` folder. +After modifying the source code, you can execute the tests with: + +```sh +go test ./... +``` + # Why is This a Separate Project? We do not wish to support non Kubernetes (or kubernetes-sigs) APIs in cert-manager core. This adds diff --git a/internal/controller/sync.go b/internal/controller/sync.go index 4d936ee..aae6373 100644 --- a/internal/controller/sync.go +++ b/internal/controller/sync.go @@ -144,6 +144,11 @@ func (r *Route) hasValidCertificate(route *routev1.Route) bool { r.eventRecorder.Event(route, corev1.EventTypeNormal, ReasonIssuing, "Issuing cert as the public key does not match the certificate") return false } + // Cert matches Route hostname? + if err := cert.VerifyHostname(route.Spec.Host); err != nil { + r.eventRecorder.Event(route, corev1.EventTypeNormal, ReasonIssuing, "Issuing cert as the hostname does not match the certificate") + return false + } // Still not after the renew-before window? if metav1.HasAnnotation(route.ObjectMeta, cmapi.RenewBeforeAnnotationKey) { renewBeforeDuration, err := time.ParseDuration(route.Annotations[cmapi.RenewBeforeAnnotationKey]) diff --git a/internal/controller/sync_test.go b/internal/controller/sync_test.go index 169835a..b9d8d04 100644 --- a/internal/controller/sync_test.go +++ b/internal/controller/sync_test.go @@ -284,6 +284,29 @@ SOME GARBAGE want: false, wantedEvents: []string{"Normal Issuing Issuing cert as no TLS is configured"}, }, + { + name: "changed route hostname triggers new certificate", + route: &routev1.Route{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-route", + Namespace: "some-namespace", + CreationTimestamp: metav1.Time{Time: time.Now().Add(-time.Hour * 24 * 30)}, + Annotations: map[string]string{cmapi.IssuerNameAnnotationKey: "some-issuer"}, + }, + Spec: routev1.RouteSpec{ + Host: "some-other-host.some-domain.tld", + TLS: &routev1.TLSConfig{ + Termination: routev1.TLSTerminationEdge, + Certificate: string(validEcdsaCertPEM), + Key: string(ecdsaKeyPEM), + CACertificate: string(validEcdsaCertPEM), + InsecureEdgeTerminationPolicy: routev1.InsecureEdgeTerminationPolicyRedirect, + }, + }, + }, + want: false, + wantedEvents: []string{"Normal Issuing Issuing cert as the hostname does not match the certificate"}, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) {