Merge pull request #6535 from inteon/cleanup_generate_csr

Refactor GenerateCSR and deprecate the helper functions
This commit is contained in:
jetstack-bot 2023-12-07 13:15:05 +01:00 committed by GitHub
commit 5484a92df8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 216 additions and 314 deletions

View File

@ -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
}

View File

@ -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:

View File

@ -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 {