From e0cdfd37bfe83dbe733b73e754f463fe375521f0 Mon Sep 17 00:00:00 2001 From: Tim Ramlot <42113979+inteon@users.noreply.github.com> Date: Fri, 14 Jun 2024 15:28:21 +0200 Subject: [PATCH] introduce gen.CSRForCertificate and gen.CSRWithSignerForCertificate and use it to deduplicate test code Signed-off-by: Tim Ramlot <42113979+inteon@users.noreply.github.com> --- .../validation/certificaterequest_test.go | 39 +++------ .../certificates/requestmanager/util_test.go | 31 +------- pkg/util/pki/match_test.go | 79 ++++++++----------- .../certificates/issuing_controller_test.go | 52 +----------- .../revisionmanager_controller_test.go | 20 +---- .../validation/certificaterequest_test.go | 18 +---- test/unit/gen/csr.go | 46 +++++++++++ 7 files changed, 95 insertions(+), 190 deletions(-) diff --git a/internal/apis/certmanager/validation/certificaterequest_test.go b/internal/apis/certmanager/validation/certificaterequest_test.go index 79829b0de..b7ef87c20 100644 --- a/internal/apis/certmanager/validation/certificaterequest_test.go +++ b/internal/apis/certmanager/validation/certificaterequest_test.go @@ -17,11 +17,9 @@ limitations under the License. package validation import ( - "bytes" "crypto/x509" "crypto/x509/pkix" "encoding/asn1" - "encoding/pem" "reflect" "testing" @@ -32,7 +30,6 @@ import ( cminternal "github.com/cert-manager/cert-manager/internal/apis/certmanager" cminternalmeta "github.com/cert-manager/cert-manager/internal/apis/meta" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" - "github.com/cert-manager/cert-manager/pkg/util/pki" utilpki "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/cert-manager/cert-manager/test/unit/gen" ) @@ -572,10 +569,12 @@ func TestValidateCertificateRequest(t *testing.T) { cr: &cminternal.CertificateRequest{ Spec: cminternal.CertificateRequestSpec{ // mustGenerateCSR will set the default usages for us - Request: mustGenerateCSR(t, gen.Certificate("test", gen.SetCertificateDNSNames("example.com")), func(cr *x509.CertificateRequest) { + Request: mustGenerateCSR(t, gen.Certificate("test", gen.SetCertificateDNSNames("example.com")), func(cr *x509.CertificateRequest) error { // manually remove extensions that encode default usages cr.Extensions = nil cr.ExtraExtensions = nil + + return nil }), IssuerRef: validIssuerRef, Usages: []cminternal.KeyUsage{cminternal.UsageKeyEncipherment, cminternal.UsageDigitalSignature}, @@ -588,12 +587,12 @@ func TestValidateCertificateRequest(t *testing.T) { cr: &cminternal.CertificateRequest{ Spec: cminternal.CertificateRequestSpec{ // mustGenerateCSR will set the default usages for us - Request: mustGenerateCSR(t, gen.Certificate("test", gen.SetCertificateDNSNames("example.com")), func(cr *x509.CertificateRequest) { + Request: mustGenerateCSR(t, gen.Certificate("test", gen.SetCertificateDNSNames("example.com")), func(cr *x509.CertificateRequest) error { // manually remove extensions that encode default usages cr.Extensions = nil cr.ExtraExtensions = []pkix.Extension{ { - Id: pki.OIDExtensionKeyUsage, + Id: utilpki.OIDExtensionKeyUsage, Critical: false, Value: func(t *testing.T) []byte { asn1KeyUsage, err := asn1.Marshal(asn1.BitString{Bytes: []byte{}, BitLength: 0}) @@ -605,6 +604,8 @@ func TestValidateCertificateRequest(t *testing.T) { }(t), }, } + + return nil }), IssuerRef: validIssuerRef, Usages: []cminternal.KeyUsage{cminternal.UsageKeyEncipherment, cminternal.UsageDigitalSignature}, @@ -877,30 +878,10 @@ func TestValidateCertificateRequest(t *testing.T) { } } -func mustGenerateCSR(t *testing.T, crt *cmapi.Certificate, modifiers ...func(*x509.CertificateRequest)) []byte { - // Create a new private key - pk, err := utilpki.GenerateRSAPrivateKey(2048) +func mustGenerateCSR(t *testing.T, crt *cmapi.Certificate, modifiers ...gen.CSRModifier) []byte { + csrPEM, _, err := gen.CSRForCertificate(crt, modifiers...) if err != nil { t.Fatal(err) } - - x509CSR, err := utilpki.GenerateCSR(crt) - if err != nil { - t.Fatal(err) - } - for _, modifier := range modifiers { - modifier(x509CSR) - } - csrDER, err := utilpki.EncodeCSR(x509CSR, pk) - if err != nil { - t.Fatal(err) - } - - csrPEM := bytes.NewBuffer([]byte{}) - err = pem.Encode(csrPEM, &pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrDER}) - if err != nil { - t.Fatal(err) - } - - return csrPEM.Bytes() + return csrPEM } diff --git a/pkg/controller/certificates/requestmanager/util_test.go b/pkg/controller/certificates/requestmanager/util_test.go index 2c2fdfadd..475e4703b 100644 --- a/pkg/controller/certificates/requestmanager/util_test.go +++ b/pkg/controller/certificates/requestmanager/util_test.go @@ -19,7 +19,6 @@ package requestmanager import ( "crypto" "crypto/x509" - "encoding/pem" "testing" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -77,7 +76,7 @@ func createCryptoBundle(originalCert *cmapi.Certificate) (*cryptoBundle, error) return nil, err } - privateKey, err := pki.GeneratePrivateKeyForCertificate(crt) + csrPEM, privateKey, err := gen.CSRForCertificate(crt) if err != nil { return nil, err } @@ -87,11 +86,6 @@ func createCryptoBundle(originalCert *cmapi.Certificate) (*cryptoBundle, error) return nil, err } - csrPEM, err := generateCSRImpl(crt, privateKeyBytes) - if err != nil { - return nil, err - } - csr, err := pki.DecodeX509CertificateRequestBytes(csrPEM) if err != nil { return nil, err @@ -173,26 +167,3 @@ func createCryptoBundle(originalCert *cmapi.Certificate) (*cryptoBundle, error) certBytes: certBytes, }, nil } - -func generateCSRImpl(crt *cmapi.Certificate, pk []byte) ([]byte, error) { - csr, err := pki.GenerateCSR(crt) - if err != nil { - return nil, err - } - - signer, err := pki.DecodePrivateKeyBytes(pk) - if err != nil { - return nil, err - } - - csrDER, err := pki.EncodeCSR(csr, signer) - if err != nil { - return nil, err - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - - return csrPEM, nil -} diff --git a/pkg/util/pki/match_test.go b/pkg/util/pki/match_test.go index ea8e11bcf..119bb8408 100644 --- a/pkg/util/pki/match_test.go +++ b/pkg/util/pki/match_test.go @@ -14,14 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -package pki +package pki_test import ( - "bytes" "crypto" "crypto/x509" "encoding/asn1" - "encoding/pem" "reflect" "testing" @@ -29,10 +27,12 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" + "github.com/cert-manager/cert-manager/pkg/util/pki" + "github.com/cert-manager/cert-manager/test/unit/gen" ) func mustGenerateRSA(t *testing.T, keySize int) crypto.PrivateKey { - pk, err := GenerateRSAPrivateKey(keySize) + pk, err := pki.GenerateRSAPrivateKey(keySize) if err != nil { t.Fatal(err) } @@ -40,7 +40,7 @@ func mustGenerateRSA(t *testing.T, keySize int) crypto.PrivateKey { } func mustGenerateECDSA(t *testing.T, keySize int) crypto.PrivateKey { - pk, err := GenerateECPrivateKey(keySize) + pk, err := pki.GenerateECPrivateKey(keySize) if err != nil { t.Fatal(err) } @@ -48,7 +48,7 @@ func mustGenerateECDSA(t *testing.T, keySize int) crypto.PrivateKey { } func mustGenerateEd25519(t *testing.T) crypto.PrivateKey { - pk, err := GenerateEd25519PrivateKey() + pk, err := pki.GenerateEd25519PrivateKey() if err != nil { t.Fatal(err) } @@ -75,18 +75,18 @@ func TestPrivateKeyMatchesSpec(t *testing.T) { violations: []string{"spec.privateKey.size"}, }, "should match if keySize and algorithm are correct (ECDSA)": { - key: mustGenerateECDSA(t, ECCurve256), + key: mustGenerateECDSA(t, pki.ECCurve256), expectedAlgo: cmapi.ECDSAKeyAlgorithm, expectedSize: 256, }, "should not match if ECDSA keySize is incorrect": { - key: mustGenerateECDSA(t, ECCurve256), + key: mustGenerateECDSA(t, pki.ECCurve256), expectedAlgo: cmapi.ECDSAKeyAlgorithm, - expectedSize: ECCurve521, + expectedSize: pki.ECCurve521, violations: []string{"spec.privateKey.size"}, }, "should not match if keyAlgorithm is incorrect": { - key: mustGenerateECDSA(t, ECCurve256), + key: mustGenerateECDSA(t, pki.ECCurve256), expectedAlgo: cmapi.RSAKeyAlgorithm, expectedSize: 2048, violations: []string{"spec.privateKey.algorithm"}, @@ -98,7 +98,7 @@ func TestPrivateKeyMatchesSpec(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - violations, err := PrivateKeyMatchesSpec( + violations, err := pki.PrivateKeyMatchesSpec( test.key, cmapi.CertificateSpec{ PrivateKey: &cmapi.CertificatePrivateKey{ @@ -132,7 +132,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { violations []string }{ "should not report any violation if Certificate otherName(s) match the CertificateRequest's": { - crSpec: MustBuildCertificateRequest(&cmapi.Certificate{Spec: cmapi.CertificateSpec{ + crSpec: mustBuildCertificateRequest(t, &cmapi.Certificate{Spec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ { @@ -140,7 +140,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { UTF8Value: "upn@testdomain.local", }, }, - }}, t), + }}), certSpec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ @@ -153,7 +153,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { err: "", }, "should report violation if Certificate otherName(s) mismatch the CertificateRequest's": { - crSpec: MustBuildCertificateRequest(&cmapi.Certificate{Spec: cmapi.CertificateSpec{ + crSpec: mustBuildCertificateRequest(t, &cmapi.Certificate{Spec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ { @@ -161,7 +161,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { UTF8Value: "upn@testdomain.local", }, }, - }}, t), + }}), certSpec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ @@ -177,7 +177,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { }, }, "should not report violation if Certificate otherName(s) match the CertificateRequest's (with different order)": { - crSpec: MustBuildCertificateRequest(&cmapi.Certificate{Spec: cmapi.CertificateSpec{ + crSpec: mustBuildCertificateRequest(t, &cmapi.Certificate{Spec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ { @@ -189,7 +189,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { UTF8Value: "upn@testdomain.local", }, }, - }}, t), + }}), certSpec: cmapi.CertificateSpec{ CommonName: "cn", OtherNames: []cmapi.OtherName{ @@ -208,7 +208,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - violations, err := RequestMatchesSpec(test.crSpec, test.certSpec) + violations, err := pki.RequestMatchesSpec(test.crSpec, test.certSpec) if err != nil { if test.err == "" { t.Errorf("Unexpected error: %s", err.Error()) @@ -226,12 +226,7 @@ func TestCertificateRequestOtherNamesMatchSpec(t *testing.T) { func TestRequestMatchesSpecSubject(t *testing.T) { createCSRBlob := func(literalSubject string) []byte { - pk, err := GenerateRSAPrivateKey(2048) - if err != nil { - t.Fatal(err) - } - - seq, err := UnmarshalSubjectStringToRDNSequence(literalSubject) + seq, err := pki.UnmarshalSubjectStringToRDNSequence(literalSubject) if err != nil { t.Fatal(err) } @@ -241,16 +236,15 @@ func TestRequestMatchesSpecSubject(t *testing.T) { t.Fatal(err) } - csr := &x509.CertificateRequest{ - RawSubject: asn1Seq, - } - - csrBytes, err := x509.CreateCertificateRequest(bytes.NewBuffer(nil), csr, pk) + pemBytes, _, err := gen.CSR(x509.Ed25519, func(cr *x509.CertificateRequest) error { + cr.RawSubject = asn1Seq + return nil + }) if err != nil { t.Fatal(err) } - return pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csrBytes}) + return pemBytes } tests := []struct { @@ -282,7 +276,7 @@ func TestRequestMatchesSpecSubject(t *testing.T) { for _, test := range tests { test := test t.Run(test.name, func(t *testing.T) { - violations, err := RequestMatchesSpec( + violations, err := pki.RequestMatchesSpec( &cmapi.CertificateRequest{ Spec: cmapi.CertificateRequestSpec{ Request: test.x509CSR, @@ -442,7 +436,7 @@ func TestSecretDataAltNamesMatchSpec(t *testing.T) { } for name, test := range tests { t.Run(name, func(t *testing.T) { - violations, err := SecretDataAltNamesMatchSpec(&corev1.Secret{Data: map[string][]byte{corev1.TLSCertKey: test.data}}, test.spec) + violations, err := pki.SecretDataAltNamesMatchSpec(&corev1.Secret{Data: map[string][]byte{corev1.TLSCertKey: test.data}}, test.spec) switch { case err != nil: if test.err != err.Error() { @@ -461,17 +455,17 @@ func TestSecretDataAltNamesMatchSpec(t *testing.T) { } func selfSignCertificate(t *testing.T, spec cmapi.CertificateSpec) []byte { - pk, err := GenerateRSAPrivateKey(2048) + pk, err := pki.GenerateRSAPrivateKey(2048) if err != nil { t.Fatal(err) } - template, err := CertificateTemplateFromCertificate(&cmapi.Certificate{Spec: spec}) + template, err := pki.CertificateTemplateFromCertificate(&cmapi.Certificate{Spec: spec}) if err != nil { t.Fatal(err) } - pemData, _, err := SignCertificate(template, template, pk.Public(), pk) + pemData, _, err := pki.SignCertificate(template, template, pk.Public(), pk) if err != nil { t.Fatal(err) } @@ -479,23 +473,12 @@ func selfSignCertificate(t *testing.T, spec cmapi.CertificateSpec) []byte { return pemData } -func MustBuildCertificateRequest(crt *cmapi.Certificate, t *testing.T) *cmapi.CertificateRequest { - pk, err := GenerateRSAPrivateKey(2048) +func mustBuildCertificateRequest(t *testing.T, crt *cmapi.Certificate) *cmapi.CertificateRequest { + pemData, _, err := gen.CSRForCertificate(crt) if err != nil { t.Fatal(err) } - csrTemplate, err := GenerateCSR(crt, WithOtherNames(true)) - if err != nil { - t.Fatal(err) - } - - var buffer bytes.Buffer - csr, err := x509.CreateCertificateRequest(&buffer, csrTemplate, pk) - if err != nil { - t.Fatal(err) - } - pemData := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE REQUEST", Bytes: csr}) cr := &cmapi.CertificateRequest{ ObjectMeta: metav1.ObjectMeta{ Name: t.Name(), diff --git a/test/integration/certificates/issuing_controller_test.go b/test/integration/certificates/issuing_controller_test.go index 9a1b7b8ff..d0664de21 100644 --- a/test/integration/certificates/issuing_controller_test.go +++ b/test/integration/certificates/issuing_controller_test.go @@ -148,22 +148,11 @@ func TestIssuingController(t *testing.T) { t.Fatal(err) } - // Create x509 CSR from Certificate - csr, err := utilpki.GenerateCSR(crt) + csrPEM, err := gen.CSRWithSignerForCertificate(crt, sk) if err != nil { t.Fatal(err) } - // Encode CSR - csrDER, err := utilpki.EncodeCSR(csr, sk) - if err != nil { - t.Fatal(err) - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - // Sign Certificate certTemplate, err := utilpki.CertificateTemplateFromCertificate(crt) if err != nil { @@ -371,22 +360,11 @@ func TestIssuingController_PKCS8_PrivateKey(t *testing.T) { t.Fatal(err) } - // Create x509 CSR from Certificate - csr, err := utilpki.GenerateCSR(crt) + csrPEM, err := gen.CSRWithSignerForCertificate(crt, sk) if err != nil { t.Fatal(err) } - // Encode CSR - csrDER, err := utilpki.EncodeCSR(csr, sk) - if err != nil { - t.Fatal(err) - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - // Sign Certificate certTemplate, err := utilpki.CertificateTemplateFromCertificate(crt) if err != nil { @@ -589,22 +567,11 @@ func Test_IssuingController_SecretTemplate(t *testing.T) { t.Fatal(err) } - // Create x509 CSR from Certificate - csr, err := utilpki.GenerateCSR(crt) + csrPEM, err := gen.CSRWithSignerForCertificate(crt, sk) if err != nil { t.Fatal(err) } - // Encode CSR - csrDER, err := utilpki.EncodeCSR(csr, sk) - if err != nil { - t.Fatal(err) - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - // Sign Certificate certTemplate, err := utilpki.CertificateTemplateFromCertificate(crt) if err != nil { @@ -836,22 +803,11 @@ func Test_IssuingController_AdditionalOutputFormats(t *testing.T) { t.Fatal(err) } - // Create x509 CSR from Certificate - csr, err := utilpki.GenerateCSR(crt) + csrPEM, err := gen.CSRWithSignerForCertificate(crt, pk) if err != nil { t.Fatal(err) } - // Encode CSR - csrDER, err := utilpki.EncodeCSR(csr, pk) - if err != nil { - t.Fatal(err) - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - // Sign Certificate certTemplate, err := utilpki.CertificateTemplateFromCertificate(crt) if err != nil { diff --git a/test/integration/certificates/revisionmanager_controller_test.go b/test/integration/certificates/revisionmanager_controller_test.go index a561f5986..9c43ad319 100644 --- a/test/integration/certificates/revisionmanager_controller_test.go +++ b/test/integration/certificates/revisionmanager_controller_test.go @@ -18,7 +18,6 @@ package certificates import ( "context" - "encoding/pem" "strconv" "testing" "time" @@ -36,7 +35,6 @@ import ( "github.com/cert-manager/cert-manager/pkg/controller/certificates/revisionmanager" logf "github.com/cert-manager/cert-manager/pkg/logs" "github.com/cert-manager/cert-manager/pkg/metrics" - utilpki "github.com/cert-manager/cert-manager/pkg/util/pki" "github.com/cert-manager/cert-manager/test/unit/gen" ) @@ -107,27 +105,11 @@ func TestRevisionManagerController(t *testing.T) { t.Fatal(err) } - // Create a new private key - sk, err := utilpki.GenerateRSAPrivateKey(2048) + csrPEM, _, err := gen.CSRForCertificate(crt) if err != nil { t.Fatal(err) } - csr, err := utilpki.GenerateCSR(crt) - if err != nil { - t.Fatal(err) - } - - // Encode CSR - csrDER, err := utilpki.EncodeCSR(csr, sk) - if err != nil { - t.Fatal(err) - } - - csrPEM := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrDER, - }) - // Create 6 CertificateRequests which are owned by this Certificate for i := 0; i < 6; i++ { _, err = cmCl.CertmanagerV1().CertificateRequests(namespace).Create(ctx, &cmapi.CertificateRequest{ diff --git a/test/integration/validation/certificaterequest_test.go b/test/integration/validation/certificaterequest_test.go index f0124e66d..728262c61 100644 --- a/test/integration/validation/certificaterequest_test.go +++ b/test/integration/validation/certificaterequest_test.go @@ -18,7 +18,6 @@ package validation import ( "context" - "encoding/pem" "strings" "testing" "time" @@ -33,7 +32,7 @@ import ( "github.com/cert-manager/cert-manager/pkg/api" cmapi "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" cmmeta "github.com/cert-manager/cert-manager/pkg/apis/meta/v1" - "github.com/cert-manager/cert-manager/pkg/util/pki" + "github.com/cert-manager/cert-manager/test/unit/gen" ) var certGVK = schema.GroupVersionKind{ @@ -200,22 +199,9 @@ func TestValidationCertificateRequests(t *testing.T) { } func mustGenerateCSR(t *testing.T, cert *cmapi.Certificate) []byte { - request, err := pki.GenerateCSR(cert) + csr, _, err := gen.CSRForCertificate(cert) if err != nil { t.Fatal(err) } - - sk, err := pki.GenerateRSAPrivateKey(2048) - if err != nil { - t.Fatal(err) - } - csrBytes, err := pki.EncodeCSR(request, sk) - if err != nil { - t.Fatal(err) - } - csr := pem.EncodeToMemory(&pem.Block{ - Type: "CERTIFICATE REQUEST", Bytes: csrBytes, - }) - return csr } diff --git a/test/unit/gen/csr.go b/test/unit/gen/csr.go index 0e6ff0868..a135c11ce 100644 --- a/test/unit/gen/csr.go +++ b/test/unit/gen/csr.go @@ -28,11 +28,57 @@ import ( "net" "net/url" + v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" "github.com/cert-manager/cert-manager/pkg/util/pki" ) type CSRModifier func(*x509.CertificateRequest) error +var defaultGenerateCSROptions = []pki.GenerateCSROption{ + pki.WithEncodeBasicConstraintsInRequest(true), + pki.WithNameConstraints(true), + pki.WithOtherNames(true), + pki.WithUseLiteralSubject(true), +} + +func CSRForCertificate(crt *v1.Certificate, mods ...CSRModifier) (csr []byte, sk crypto.Signer, err error) { + cr, err := pki.GenerateCSR(crt, defaultGenerateCSROptions...) + if err != nil { + return nil, nil, err + } + + modifiers := []CSRModifier{} + modifiers = append(modifiers, func(c *x509.CertificateRequest) error { + *c = *cr + return nil + }) + modifiers = append(modifiers, mods...) + + return CSR(cr.PublicKeyAlgorithm, modifiers...) +} + +func CSRWithSignerForCertificate(crt *v1.Certificate, sk crypto.Signer, mods ...CSRModifier) (csr []byte, err error) { + cr, err := pki.GenerateCSR(crt, defaultGenerateCSROptions...) + if err != nil { + return nil, err + } + + modifiers := []CSRModifier{} + modifiers = append(modifiers, func(c *x509.CertificateRequest) error { + if c.PublicKeyAlgorithm != cr.PublicKeyAlgorithm { + return fmt.Errorf("public key algorithm mismatch: %s != %s", c.PublicKeyAlgorithm, cr.PublicKeyAlgorithm) + } + if c.SignatureAlgorithm != cr.SignatureAlgorithm { + return fmt.Errorf("signature algorithm mismatch: %s != %s", c.SignatureAlgorithm, cr.SignatureAlgorithm) + } + *c = *cr + return nil + }) + modifiers = append(modifiers, mods...) + + return CSRWithSigner(sk, modifiers...) +} + func CSR(keyAlgorithm x509.PublicKeyAlgorithm, mods ...CSRModifier) (csr []byte, sk crypto.Signer, err error) { switch keyAlgorithm { case x509.RSA: