diff --git a/pkg/util/pki/csr.go b/pkg/util/pki/csr.go index 43653af36..dbc54c142 100644 --- a/pkg/util/pki/csr.go +++ b/pkg/util/pki/csr.go @@ -27,6 +27,7 @@ import ( "fmt" "math/big" "net" + "net/netip" "net/url" "strings" @@ -34,6 +35,7 @@ import ( v1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1" ) +// DEPRECATED: this function will be removed in a future release. func IPAddressesForCertificate(crt *v1.Certificate) []net.IP { var ipAddresses []net.IP var ip net.IP @@ -46,6 +48,7 @@ func IPAddressesForCertificate(crt *v1.Certificate) []net.IP { return ipAddresses } +// DEPRECATED: this function will be removed in a future release. func URIsForCertificate(crt *v1.Certificate) ([]*url.URL, error) { uris, err := URLsFromStrings(crt.Spec.URIs) if err != nil { @@ -55,6 +58,7 @@ func URIsForCertificate(crt *v1.Certificate) ([]*url.URL, error) { return uris, nil } +// DEPRECATED: this function will be removed in a future release. func DNSNamesForCertificate(crt *v1.Certificate) ([]string, error) { _, err := URLsFromStrings(crt.Spec.DNSNames) if err != nil { @@ -95,6 +99,22 @@ func IPAddressesToString(ipAddresses []net.IP) []string { return ipNames } +func IPAddressesFromStrings(ipStrings []string) ([]net.IP, error) { + var ipAddresses []net.IP + for _, ipString := range ipStrings { + ip, err := netip.ParseAddr(ipString) + if err != nil || ip.Zone() != "" { + return nil, err + } + addr := ip.AsSlice() + if len(addr) == 0 { + return nil, fmt.Errorf("failed to parse IP address %q", ipString) + } + ipAddresses = append(ipAddresses, net.IP(addr)) + } + return ipAddresses, nil +} + func URLsToString(uris []*url.URL) []string { var uriStrs []string for _, uri := range uris { @@ -111,6 +131,7 @@ func URLsToString(uris []*url.URL) []string { // OrganizationForCertificate will return the Organization to set for the // Certificate resource. // If an Organization is not specifically set, a default will be used. +// DEPRECATED: this function will be removed in a future release. func OrganizationForCertificate(crt *v1.Certificate) []string { if crt.Spec.Subject == nil { return nil @@ -198,35 +219,51 @@ func GenerateCSR(crt *v1.Certificate, optFuncs ...GenerateCSROption) (*x509.Cert opt(opts) } - var ( - commonName = crt.Spec.CommonName - err error - ) - - if opts.UseLiteralSubject { - commonName, err = extractCommonNameFromLiteralSubject(crt.Spec) + // Generate the Subject field for the CSR. + var commonName string + var rdnSubject pkix.RDNSequence + if opts.UseLiteralSubject && len(crt.Spec.LiteralSubject) > 0 { + subjectRDNSequence, err := UnmarshalSubjectStringToRDNSequence(crt.Spec.LiteralSubject) if err != nil { return nil, err } + commonName = ExtractCommonNameFromRDNSequence(subjectRDNSequence) + rdnSubject = subjectRDNSequence + } else { + subject := SubjectForCertificate(crt) + + commonName = crt.Spec.CommonName + rdnSubject = pkix.Name{ + Country: subject.Countries, + Organization: subject.Organizations, + OrganizationalUnit: subject.OrganizationalUnits, + Locality: subject.Localities, + Province: subject.Provinces, + StreetAddress: subject.StreetAddresses, + PostalCode: subject.PostalCodes, + SerialNumber: subject.SerialNumber, + CommonName: commonName, + }.ToRDNSequence() } - iPAddresses := IPAddressesForCertificate(crt) - organization := OrganizationForCertificate(crt) - subject := SubjectForCertificate(crt) - - dnsNames, err := DNSNamesForCertificate(crt) + // Generate the SANs for the CSR. + ipAddresses, err := IPAddressesFromStrings(crt.Spec.IPAddresses) if err != nil { return nil, err } - uriNames, err := URIsForCertificate(crt) + uris, err := URLsFromStrings(crt.Spec.URIs) if err != nil { return nil, err } - if len(commonName) == 0 && len(dnsNames) == 0 && len(uriNames) == 0 && len(crt.Spec.EmailAddresses) == 0 && len(crt.Spec.IPAddresses) == 0 { - return nil, fmt.Errorf("no common name, DNS name, URI SAN, Email SAN or IP address specified on certificate") + if len(commonName) == 0 && + len(crt.Spec.EmailAddresses) == 0 && + len(crt.Spec.DNSNames) == 0 && + len(uris) == 0 && + len(ipAddresses) == 0 { + return nil, fmt.Errorf("no common name, DNS name, URI SAN, Email SAN, IP or OtherName SAN specified on certificate") } pubKeyAlgo, sigAlgo, err := SignatureAlgorithm(crt) @@ -234,22 +271,43 @@ func GenerateCSR(crt *v1.Certificate, optFuncs ...GenerateCSROption) (*x509.Cert return nil, err } + asn1Subject, err := MarshalRDNSequenceToRawDERBytes(rdnSubject) + if err != nil { + return nil, err + } + var extraExtensions []pkix.Extension + if crt.Spec.EncodeUsagesInRequest == nil || *crt.Spec.EncodeUsagesInRequest { - extraExtensions, err = buildKeyUsagesExtensionsForCertificate(crt) + ku, ekus, err := KeyUsagesForCertificateOrCertificateRequest(crt.Spec.Usages, crt.Spec.IsCA) if err != nil { - return nil, err + return nil, fmt.Errorf("failed to build key usages: %w", err) + } + + usage, err := MarshalKeyUsage(ku) + if err != nil { + return nil, fmt.Errorf("failed to asn1 encode usages: %w", err) + } + extraExtensions = append(extraExtensions, usage) + + // Only add extended usages if they are specified. + if len(ekus) > 0 { + extendedUsages, err := MarshalExtKeyUsage(ekus, nil) + if err != nil { + return nil, fmt.Errorf("failed to asn1 encode extended usages: %w", err) + } + extraExtensions = append(extraExtensions, extendedUsages) } } // NOTE(@inteon): opts.EncodeBasicConstraintsInRequest is a temporary solution and will // be removed/ replaced in a future release. if opts.EncodeBasicConstraintsInRequest { - extension, err := MarshalBasicConstraints(crt.Spec.IsCA, nil) + basicExtension, err := MarshalBasicConstraints(crt.Spec.IsCA, nil) if err != nil { return nil, err } - extraExtensions = append(extraExtensions, extension) + extraExtensions = append(extraExtensions, basicExtension) } cr := &x509.CertificateRequest{ @@ -259,60 +317,18 @@ func GenerateCSR(crt *v1.Certificate, optFuncs ...GenerateCSROption) (*x509.Cert Version: 0, SignatureAlgorithm: sigAlgo, PublicKeyAlgorithm: pubKeyAlgo, - DNSNames: dnsNames, - IPAddresses: iPAddresses, - URIs: uriNames, - EmailAddresses: crt.Spec.EmailAddresses, + RawSubject: asn1Subject, ExtraExtensions: extraExtensions, - } - if opts.UseLiteralSubject && len(crt.Spec.LiteralSubject) > 0 { - rawSubject, err := ParseSubjectStringToRawDERBytes(crt.Spec.LiteralSubject) - if err != nil { - return nil, err - } - - cr.RawSubject = rawSubject - } else { - cr.Subject = pkix.Name{ - Country: subject.Countries, - Organization: organization, - OrganizationalUnit: subject.OrganizationalUnits, - Locality: subject.Localities, - Province: subject.Provinces, - StreetAddress: subject.StreetAddresses, - PostalCode: subject.PostalCodes, - SerialNumber: subject.SerialNumber, - CommonName: commonName, - } + DNSNames: crt.Spec.DNSNames, + EmailAddresses: crt.Spec.EmailAddresses, + IPAddresses: ipAddresses, + URIs: uris, } return cr, nil } -func buildKeyUsagesExtensionsForCertificate(crt *v1.Certificate) ([]pkix.Extension, error) { - ku, ekus, err := KeyUsagesForCertificateOrCertificateRequest(crt.Spec.Usages, crt.Spec.IsCA) - if err != nil { - return nil, fmt.Errorf("failed to build key usages: %w", err) - } - - usage, err := MarshalKeyUsage(ku) - if err != nil { - return nil, fmt.Errorf("failed to asn1 encode usages: %w", err) - } - - // if no extended usages are specified, return early - if len(ekus) == 0 { - return []pkix.Extension{usage}, nil - } - - extendedUsages, err := MarshalExtKeyUsage(ekus, nil) - if err != nil { - return nil, fmt.Errorf("failed to asn1 encode extended usages: %w", err) - } - return []pkix.Extension{usage, extendedUsages}, nil -} - // SignCertificate returns a signed *x509.Certificate given a template // *x509.Certificate crt and an issuer. // publicKey is the public key of the signee, and signerKey is the private @@ -464,26 +480,3 @@ func SignatureAlgorithm(crt *v1.Certificate) (x509.PublicKeyAlgorithm, x509.Sign } return pubKeyAlgo, sigAlgo, nil } - -func extractCommonNameFromLiteralSubject(spec v1.CertificateSpec) (string, error) { - if spec.LiteralSubject == "" { - return spec.CommonName, nil - } - commonName := "" - sequence, err := UnmarshalSubjectStringToRDNSequence(spec.LiteralSubject) - if err != nil { - return "", err - } - - for _, rdns := range sequence { - for _, atv := range rdns { - if atv.Type.Equal(OIDConstants.CommonName) { - if str, ok := atv.Value.(string); ok { - commonName = str - } - } - } - } - - return commonName, nil -} diff --git a/pkg/util/pki/csr_test.go b/pkg/util/pki/csr_test.go index f4a09e8a8..1d7835fa7 100644 --- a/pkg/util/pki/csr_test.go +++ b/pkg/util/pki/csr_test.go @@ -34,15 +34,6 @@ import ( "github.com/cert-manager/cert-manager/pkg/util" ) -func buildCertificate(cn string, dnsNames ...string) *cmapi.Certificate { - return &cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - CommonName: cn, - DNSNames: dnsNames, - }, - } -} - func TestKeyUsagesForCertificate(t *testing.T) { type testT struct { name string @@ -118,112 +109,6 @@ func TestKeyUsagesForCertificate(t *testing.T) { } } -func TestCommonNameForCertificate(t *testing.T) { - type testT struct { - name string - crtCN string - crtDNSNames []string - expectedCN string - } - tests := []testT{ - { - name: "certificate with CommonName set", - crtCN: "test", - expectedCN: "test", - }, - { - name: "certificate with one DNS name set", - crtDNSNames: []string{"dnsname"}, - expectedCN: "", - }, - { - name: "certificate with both common name and dnsName set", - crtCN: "cn", - crtDNSNames: []string{"dnsname"}, - expectedCN: "cn", - }, - { - name: "certificate with multiple dns names set", - crtDNSNames: []string{"dnsname1", "dnsname2"}, - expectedCN: "", - }, - } - testFn := func(test testT) func(*testing.T) { - return func(t *testing.T) { - actualCN := buildCertificate(test.crtCN, test.crtDNSNames...).Spec.CommonName - if actualCN != test.expectedCN { - t.Errorf("expected %q but got %q", test.expectedCN, actualCN) - return - } - } - } - for _, test := range tests { - t.Run(test.name, testFn(test)) - } -} - -func TestDNSNamesForCertificate(t *testing.T) { - type testT struct { - name string - crtCN string - crtDNSNames []string - expectDNSNames []string - } - tests := []testT{ - { - name: "certificate with CommonName set", - crtCN: "test", - expectDNSNames: []string{}, - }, - { - name: "certificate with one DNS name set", - crtDNSNames: []string{"dnsname"}, - expectDNSNames: []string{"dnsname"}, - }, - { - name: "certificate with both common name and dnsName set", - crtCN: "cn", - crtDNSNames: []string{"dnsname"}, - expectDNSNames: []string{"dnsname"}, - }, - { - name: "certificate with multiple dns names set", - crtDNSNames: []string{"dnsname1", "dnsname2"}, - expectDNSNames: []string{"dnsname1", "dnsname2"}, - }, - { - name: "certificate with dnsName[0] set to equal common name", - crtCN: "cn", - crtDNSNames: []string{"cn", "dnsname"}, - expectDNSNames: []string{"cn", "dnsname"}, - }, - { - name: "certificate with a dnsName equal to cn", - crtCN: "cn", - crtDNSNames: []string{"dnsname", "cn"}, - expectDNSNames: []string{"dnsname", "cn"}, - }, - } - testFn := func(test testT) func(*testing.T) { - return func(t *testing.T) { - actualDNSNames := buildCertificate(test.crtCN, test.crtDNSNames...).Spec.DNSNames - if len(actualDNSNames) != len(test.expectDNSNames) { - t.Errorf("expected %q but got %q", test.expectDNSNames, actualDNSNames) - return - } - for i, actual := range actualDNSNames { - if test.expectDNSNames[i] != actual { - t.Errorf("expected %q but got %q", test.expectDNSNames, actualDNSNames) - return - } - } - } - } - for _, test := range tests { - t.Run(test.name, testFn(test)) - } -} - func TestSignatureAlgorithmForCertificate(t *testing.T) { type testT struct { name string @@ -413,20 +298,25 @@ func TestGenerateCSR(t *testing.T) { }, } - asn1ExtKeyUsage, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageIPSECEndSystem}) + // 0xa0 = DigitalSignature and Encipherment usage + asn1DefaultKeyUsage, err := asn1.Marshal(asn1.BitString{Bytes: []byte{0xa0}, BitLength: asn1BitLength([]byte{0xa0})}) if err != nil { t.Fatal(err) } - ipsecExtraExtensions := []pkix.Extension{ - { - Id: OIDExtensionKeyUsage, - Value: asn1KeyUsage, - Critical: true, - }, - { - Id: OIDExtensionExtendedKeyUsage, - Value: asn1ExtKeyUsage, - }, + + asn1ClientAuth, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageClientAuth}) + if err != nil { + t.Fatal(err) + } + + asn1ServerClientAuth, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageServerAuth, oidExtKeyUsageClientAuth}) + if err != nil { + t.Fatal(err) + } + + asn1ExtKeyUsage, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageIPSECEndSystem}) + if err != nil { + t.Fatal(err) } basicConstraintsGenerator := func(isCA bool) ([]byte, error) { @@ -437,6 +327,14 @@ func TestGenerateCSR(t *testing.T) { }) } + subjectGenerator := func(t *testing.T, name pkix.Name) []byte { + data, err := MarshalRDNSequenceToRawDERBytes(name.ToRDNSequence()) + if err != nil { + t.Fatal(err) + } + return data + } + basicConstraintsWithCA, err := basicConstraintsGenerator(true) if err != nil { t.Fatal(err) @@ -482,6 +380,7 @@ func TestGenerateCSR(t *testing.T) { PublicKeyAlgorithm: x509.RSA, DNSNames: []string{"example.org"}, ExtraExtensions: defaultExtraExtensions, + RawSubject: subjectGenerator(t, pkix.Name{}), }, }, { @@ -491,8 +390,8 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, ExtraExtensions: defaultExtraExtensions, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, }, { @@ -502,7 +401,6 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, ExtraExtensions: []pkix.Extension{ { Id: OIDExtensionKeyUsage, @@ -510,6 +408,7 @@ func TestGenerateCSR(t *testing.T) { Critical: true, }, }, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, }, { @@ -519,7 +418,6 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, ExtraExtensions: []pkix.Extension{ { Id: OIDExtensionKeyUsage, @@ -532,6 +430,7 @@ func TestGenerateCSR(t *testing.T) { Critical: true, }, }, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, basicConstraintsFeatureEnabled: true, }, @@ -542,7 +441,6 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, ExtraExtensions: []pkix.Extension{ { Id: OIDExtensionKeyUsage, @@ -555,6 +453,7 @@ func TestGenerateCSR(t *testing.T) { Critical: true, }, }, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, basicConstraintsFeatureEnabled: true, }, @@ -565,8 +464,18 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, - ExtraExtensions: ipsecExtraExtensions, + ExtraExtensions: []pkix.Extension{ + { + Id: OIDExtensionKeyUsage, + Value: asn1KeyUsage, + Critical: true, + }, + { + Id: OIDExtensionExtendedKeyUsage, + Value: asn1ExtKeyUsage, + }, + }, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, }, { @@ -576,8 +485,8 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - Subject: pkix.Name{CommonName: "example.org"}, ExtraExtensions: defaultExtraExtensions, + RawSubject: subjectGenerator(t, pkix.Name{CommonName: "example.org"}), }, }, { @@ -592,8 +501,8 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - RawSubject: rawExampleLiteralSubject, ExtraExtensions: defaultExtraExtensions, + RawSubject: rawExampleLiteralSubject, }, literalCertificateSubjectFeatureEnabled: true, }, @@ -604,8 +513,8 @@ func TestGenerateCSR(t *testing.T) { Version: 0, SignatureAlgorithm: x509.SHA256WithRSA, PublicKeyAlgorithm: x509.RSA, - RawSubject: rawExampleMultiValueRDNLiteralSubject, ExtraExtensions: defaultExtraExtensions, + RawSubject: rawExampleMultiValueRDNLiteralSubject, }, literalCertificateSubjectFeatureEnabled: true, }, @@ -615,6 +524,81 @@ func TestGenerateCSR(t *testing.T) { wantErr: true, literalCertificateSubjectFeatureEnabled: true, }, + { + name: "KeyUsages and ExtendedKeyUsages: no usages set", + crt: &cmapi.Certificate{Spec: cmapi.CertificateSpec{DNSNames: []string{"example.org"}}}, + want: &x509.CertificateRequest{ + Version: 0, + SignatureAlgorithm: x509.SHA256WithRSA, + PublicKeyAlgorithm: x509.RSA, + DNSNames: []string{"example.org"}, + ExtraExtensions: []pkix.Extension{ + { + Id: OIDExtensionKeyUsage, + Value: asn1DefaultKeyUsage, + Critical: true, + }, + }, + RawSubject: subjectGenerator(t, pkix.Name{}), + }, + wantErr: false, + }, + { + name: "KeyUsages and ExtendedKeyUsages: client auth extended usage set", + crt: &cmapi.Certificate{ + Spec: cmapi.CertificateSpec{ + DNSNames: []string{"example.org"}, + Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth}, + }, + }, + want: &x509.CertificateRequest{ + Version: 0, + SignatureAlgorithm: x509.SHA256WithRSA, + PublicKeyAlgorithm: x509.RSA, + DNSNames: []string{"example.org"}, + ExtraExtensions: []pkix.Extension{ + { + Id: OIDExtensionKeyUsage, + Value: asn1DefaultKeyUsage, + Critical: true, + }, + { + Id: OIDExtensionExtendedKeyUsage, + Value: asn1ClientAuth, + }, + }, + RawSubject: subjectGenerator(t, pkix.Name{}), + }, + wantErr: false, + }, + { + name: "KeyUsages and ExtendedKeyUsages: server + client auth extended usage set", + crt: &cmapi.Certificate{ + Spec: cmapi.CertificateSpec{ + DNSNames: []string{"example.org"}, + Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageServerAuth, cmapi.UsageClientAuth}, + }, + }, + want: &x509.CertificateRequest{ + Version: 0, + SignatureAlgorithm: x509.SHA256WithRSA, + PublicKeyAlgorithm: x509.RSA, + DNSNames: []string{"example.org"}, + ExtraExtensions: []pkix.Extension{ + { + Id: OIDExtensionKeyUsage, + Value: asn1DefaultKeyUsage, + Critical: true, + }, + { + Id: OIDExtensionExtendedKeyUsage, + Value: asn1ServerClientAuth, + }, + }, + RawSubject: subjectGenerator(t, pkix.Name{}), + }, + wantErr: false, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -634,96 +618,6 @@ func TestGenerateCSR(t *testing.T) { } } -func Test_buildKeyUsagesExtensionsForCertificate(t *testing.T) { - // 0xa0 = DigitalSignature and Encipherment usage - asn1DefaultKeyUsage, err := asn1.Marshal(asn1.BitString{Bytes: []byte{0xa0}, BitLength: asn1BitLength([]byte{0xa0})}) - if err != nil { - t.Fatal(err) - } - - asn1ClientAuth, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageClientAuth}) - if err != nil { - t.Fatal(err) - } - - asn1ServerClientAuth, err := asn1.Marshal([]asn1.ObjectIdentifier{oidExtKeyUsageServerAuth, oidExtKeyUsageClientAuth}) - if err != nil { - t.Fatal(err) - } - - tests := []struct { - name string - crt *cmapi.Certificate - want []pkix.Extension - wantErr bool - }{ - { - name: "Test no usages set", - crt: &cmapi.Certificate{}, - want: []pkix.Extension{ - { - Id: OIDExtensionKeyUsage, - Value: asn1DefaultKeyUsage, - Critical: true, - }, - }, - wantErr: false, - }, - { - name: "Test client auth extended usage set", - crt: &cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageClientAuth}, - }, - }, - want: []pkix.Extension{ - { - Id: OIDExtensionKeyUsage, - Value: asn1DefaultKeyUsage, - Critical: true, - }, - { - Id: OIDExtensionExtendedKeyUsage, - Value: asn1ClientAuth, - }, - }, - wantErr: false, - }, - { - name: "Test server + client auth extended usage set", - crt: &cmapi.Certificate{ - Spec: cmapi.CertificateSpec{ - Usages: []cmapi.KeyUsage{cmapi.UsageDigitalSignature, cmapi.UsageKeyEncipherment, cmapi.UsageServerAuth, cmapi.UsageClientAuth}, - }, - }, - want: []pkix.Extension{ - { - Id: OIDExtensionKeyUsage, - Value: asn1DefaultKeyUsage, - Critical: true, - }, - { - Id: OIDExtensionExtendedKeyUsage, - Value: asn1ServerClientAuth, - }, - }, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := buildKeyUsagesExtensionsForCertificate(tt.crt) - if (err != nil) != tt.wantErr { - t.Errorf("buildKeyUsagesExtensionsForCertificate() error = %v, wantErr %v", err, tt.wantErr) - return - } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("buildKeyUsagesExtensionsForCertificate() got = %v, want %v", got, tt.want) - } - }) - } -} - func TestSignCSRTemplate(t *testing.T) { // We want to test the behavior of SignCSRTemplate in various contexts; // for that, we construct a chain of four certificates: diff --git a/pkg/util/pki/subject.go b/pkg/util/pki/subject.go index da70494c6..11e636839 100644 --- a/pkg/util/pki/subject.go +++ b/pkg/util/pki/subject.go @@ -104,6 +104,21 @@ func UnmarshalRawDerBytesToRDNSequence(der []byte) (rdnSequence pkix.RDNSequence } } +func ExtractCommonNameFromRDNSequence(rdns pkix.RDNSequence) string { + for _, rdn := range rdns { + for _, atv := range rdn { + if atv.Type.Equal(OIDConstants.CommonName) { + if str, ok := atv.Value.(string); ok { + return str + } + } + } + } + + return "" +} + +// DEPRECATED: this function will be removed in a future release. func ParseSubjectStringToRawDERBytes(subject string) ([]byte, error) { rdnSequence, err := UnmarshalSubjectStringToRDNSequence(subject) if err != nil {