diff --git a/README.md b/README.md index 964a9fd..e9e9719 100644 --- a/README.md +++ b/README.md @@ -103,6 +103,7 @@ metadata: cert-manager.io/alt-names: "mycooldomain.com,mysecondarydomain.com" # Optional, no default cert-manager.io/ip-sans: "10.20.30.40,192.168.192.168" # Optional, no default cert-manager.io/uri-sans: "spiffe://trustdomain/workload" # Optional, no default + cert-manager.io/email-sans: "me@example.com,you@example.com" # Optional, no default cert-manager.io/private-key-algorithm: "ECDSA" # Optional, defaults to RSA spec: host: app.service.clustername.domain.com # will be added to the Subject Alternative Names of the CertificateRequest diff --git a/internal/controller/sync.go b/internal/controller/sync.go index 431d720..44f584e 100644 --- a/internal/controller/sync.go +++ b/internal/controller/sync.go @@ -388,6 +388,10 @@ func (r *Route) buildNextCR(ctx context.Context, route *routev1.Route, revision uriSans = append(uriSans, ur) } } + emailSans := []string{} + if metav1.HasAnnotation(route.ObjectMeta, cmapi.EmailsAnnotationKey) { + emailSans = strings.Split(route.Annotations[cmapi.EmailsAnnotationKey], ",") + } privateKeyAlgorithm, found := route.Annotations[cmapi.PrivateKeyAlgorithmAnnotationKey] if !found { @@ -446,9 +450,10 @@ func (r *Route) buildNextCR(ctx context.Context, route *routev1.Route, revision Subject: pkix.Name{ CommonName: route.Annotations[cmapi.CommonNameAnnotationKey], }, - DNSNames: dnsNames, - IPAddresses: ipSans, - URIs: uriSans, + DNSNames: dnsNames, + IPAddresses: ipSans, + URIs: uriSans, + EmailAddresses: emailSans, }, key, ) diff --git a/internal/controller/sync_test.go b/internal/controller/sync_test.go index 6c4b311..546964d 100644 --- a/internal/controller/sync_test.go +++ b/internal/controller/sync_test.go @@ -1136,6 +1136,65 @@ func TestRoute_buildNextCR(t *testing.T) { }, wantErr: nil, }, + { + name: "With subject alternative names", + revision: 1337, + route: generateRouteStatus(&routev1.Route{ + ObjectMeta: metav1.ObjectMeta{ + Name: "some-route", + Namespace: "some-namespace", + Annotations: map[string]string{ + cmapi.IsNextPrivateKeySecretLabelKey: string(rsaPEM), + cmapi.AltNamesAnnotationKey: "mycooldomain.com,mysecondarydomain.com", + cmapi.IPSANAnnotationKey: "10.20.30.40,192.168.192.168", + cmapi.URISANAnnotationKey: "spiffe://trustdomain/workload", + cmapi.EmailsAnnotationKey: "me@example.com,you@example.com", + }, + }, + Spec: routev1.RouteSpec{ + Host: "some-host.some-domain.tld", + }, + Status: routev1.RouteStatus{ + Ingress: []routev1.RouteIngress{ + { + Host: "some-host.some-domain.tld", + Conditions: []routev1.RouteIngressCondition{ + { + Type: "Admitted", + Status: "True", + }, + }, + }, + }, + }, + }, + true), + want: &cmapi.CertificateRequest{ + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "some-route-", + Namespace: "some-namespace", + Annotations: map[string]string{ + cmapi.CertificateRequestRevisionAnnotationKey: "1338", + }, + }, + Spec: cmapi.CertificateRequestSpec{ + Usages: []cmapi.KeyUsage{cmapi.UsageServerAuth, cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment}, + Duration: &metav1.Duration{Duration: DefaultCertificateDuration}, + }, + }, + wantCSR: &x509.CertificateRequest{ + SignatureAlgorithm: x509.SHA256WithRSA, + PublicKeyAlgorithm: x509.RSA, + Subject: pkix.Name{ + CommonName: "", + }, + DNSNames: []string{"some-host.some-domain.tld", "mycooldomain.com", "mysecondarydomain.com"}, + IPAddresses: []net.IP{net.IPv4(10, 20, 30, 40), net.IPv4(192, 168, 192, 168)}, + URIs: []*url.URL{{Scheme: "spiffe", Host: "trustdomain", Path: "workload"}}, + EmailAddresses: []string{"me@example.com", "you@example.com"}, + }, + wantErr: nil, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -1176,6 +1235,7 @@ func TestRoute_buildNextCR(t *testing.T) { assert.NoError(t, err) assert.Equal(t, tt.wantCSR.DNSNames, parsedCSR.DNSNames) assert.Equal(t, tt.wantCSR.IPAddresses, parsedCSR.IPAddresses) + assert.Equal(t, tt.wantCSR.EmailAddresses, parsedCSR.EmailAddresses) assert.Equal(t, tt.wantCSR.PublicKeyAlgorithm, parsedCSR.PublicKeyAlgorithm) assert.Equal(t, tt.wantCSR.SignatureAlgorithm, parsedCSR.SignatureAlgorithm) assert.Equal(t, tt.wantCSR.Subject.CommonName, parsedCSR.Subject.CommonName)