Skip to content

Commit

Permalink
Add support for setting the raw subject in the templates
Browse files Browse the repository at this point in the history
This commit allows setting the raw subject of the certificate. This
allows for example copying the subject for the CR without changing the
types of some subject fields from UTF8String to PrintableString.

Fixes smallstep/certificates#1917
  • Loading branch information
maraino committed Jul 9, 2024
1 parent 6eaaf7f commit 936b845
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 0 deletions.
2 changes: 2 additions & 0 deletions x509util/certificate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
type Certificate struct {
Version int `json:"version"`
Subject Subject `json:"subject"`
RawSubject []byte `json:"rawSubject"`
Issuer Issuer `json:"issuer"`
SerialNumber SerialNumber `json:"serialNumber"`
DNSNames MultiString `json:"dnsNames"`
Expand Down Expand Up @@ -128,6 +129,7 @@ func (c *Certificate) GetCertificate() *x509.Certificate {
// Unparsed data
cert.PublicKey = c.PublicKey
cert.PublicKeyAlgorithm = c.PublicKeyAlgorithm
cert.RawSubject = c.RawSubject

// Subject
c.Subject.Set(cert)
Expand Down
3 changes: 3 additions & 0 deletions x509util/certificate_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type certificateRequest struct {
type CertificateRequest struct {
Version int `json:"version"`
Subject Subject `json:"subject"`
RawSubject []byte `json:"rawSubject"`
DNSNames MultiString `json:"dnsNames"`
EmailAddresses MultiString `json:"emailAddresses"`
IPAddresses MultiIP `json:"ipAddresses"`
Expand Down Expand Up @@ -115,6 +116,7 @@ func NewCertificateRequestFromX509(cr *x509.CertificateRequest) *CertificateRequ
return &CertificateRequest{
Version: cr.Version,
Subject: newSubject(cr.Subject),
RawSubject: cr.RawSubject,
DNSNames: cr.DNSNames,
EmailAddresses: cr.EmailAddresses,
IPAddresses: cr.IPAddresses,
Expand All @@ -134,6 +136,7 @@ func (c *CertificateRequest) GetCertificateRequest() (*x509.CertificateRequest,
cert := c.GetCertificate().GetCertificate()
asn1Data, err := x509.CreateCertificateRequest(rand.Reader, &x509.CertificateRequest{
Subject: cert.Subject,
RawSubject: cert.RawSubject,
DNSNames: cert.DNSNames,
IPAddresses: cert.IPAddresses,
EmailAddresses: cert.EmailAddresses,
Expand Down
50 changes: 50 additions & 0 deletions x509util/certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.step.sm/crypto/pemutil"
)

func createCertificateRequest(t *testing.T, commonName string, sans []string) (*x509.CertificateRequest, crypto.Signer) {
Expand Down Expand Up @@ -49,6 +50,21 @@ func createCertificateRequest(t *testing.T, commonName string, sans []string) (*
return cr, priv
}

func readCertificateRequest(t *testing.T, filename, keyFilename string) (*x509.CertificateRequest, crypto.Signer) {
t.Helper()

cr, err := pemutil.ReadCertificateRequest(filename)
require.NoError(t, err)

key, err := pemutil.Read(keyFilename)
require.NoError(t, err)

signer, ok := key.(crypto.Signer)
require.True(t, ok)

return cr, signer
}

func createIssuerCertificate(t *testing.T, commonName string) (*x509.Certificate, crypto.Signer) {
t.Helper()
now := time.Now()
Expand Down Expand Up @@ -135,6 +151,8 @@ func TestNewCertificate(t *testing.T) {
return ipNet
}

rawSubjectCR, rawSubjectKey := readCertificateRequest(t, "testdata/rawSubject.csr", "testdata/rawSubject.key")

type args struct {
cr *x509.CertificateRequest
opts []Option
Expand Down Expand Up @@ -283,6 +301,38 @@ func TestNewCertificate(t *testing.T) {
PublicKey: priv.Public(),
PublicKeyAlgorithm: x509.Ed25519,
}, false},
{"okRawSubject", args{rawSubjectCR, []Option{WithTemplateFile("./testdata/rawSubject.tpl", TemplateData{
SANsKey: []SubjectAlternativeName{
{Type: "dns", Value: "foo.com"},
},
CertificateRequestKey: NewCertificateRequestFromX509(rawSubjectCR),
})}}, &Certificate{
Subject: Subject{},
RawSubject: []byte{
0x30, 0x68, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03,
0x55, 0x04, 0x06, 0x13, 0x02, 0x55, 0x53, 0x31,
0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x08,
0x0c, 0x0a, 0x43, 0x61, 0x6c, 0x69, 0x66, 0x6f,
0x72, 0x6e, 0x69, 0x61, 0x31, 0x16, 0x30, 0x14,
0x06, 0x03, 0x55, 0x04, 0x07, 0x0c, 0x0d, 0x53,
0x61, 0x6e, 0x20, 0x46, 0x72, 0x61, 0x6e, 0x63,
0x69, 0x73, 0x63, 0x6f, 0x31, 0x1d, 0x30, 0x1b,
0x06, 0x03, 0x55, 0x04, 0x0a, 0x0c, 0x14, 0x53,
0x6d, 0x61, 0x6c, 0x6c, 0x73, 0x74, 0x65, 0x70,
0x20, 0x4c, 0x61, 0x62, 0x73, 0x2c, 0x20, 0x49,
0x6e, 0x63, 0x2e, 0x31, 0x0d, 0x30, 0x0b, 0x06,
0x03, 0x55, 0x04, 0x03, 0x0c, 0x04, 0x54, 0x65,
0x73, 0x74,
},
SANs: []SubjectAlternativeName{{Type: DNSType, Value: "foo.com"}},
KeyUsage: KeyUsage(x509.KeyUsageDigitalSignature),
ExtKeyUsage: ExtKeyUsage([]x509.ExtKeyUsage{
x509.ExtKeyUsageServerAuth,
x509.ExtKeyUsageClientAuth,
}),
PublicKey: rawSubjectKey.Public(),
PublicKeyAlgorithm: x509.ECDSA,
}, false},
{"badSignature", args{crBadSignateure, nil}, nil, true},
{"failTemplate", args{cr, []Option{WithTemplate(`{{ fail "fatal error }}`, CreateTemplateData("commonName", []string{"foo.com"}))}}, nil, true},
{"missingTemplate", args{cr, []Option{WithTemplateFile("./testdata/missing.tpl", CreateTemplateData("commonName", []string{"foo.com"}))}}, nil, true},
Expand Down
9 changes: 9 additions & 0 deletions x509util/testdata/rawSubject.csr
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIBIjCBygIBADBoMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEW
MBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEdMBsGA1UECgwUU21hbGxzdGVwIExhYnMs
IEluYy4xDTALBgNVBAMMBFRlc3QwWTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAATG
NLZtzv5dcl2Nz66XBV+tq5jKCH9WGPlsuBEq48NNUb1LzecjaVTZsEwe+ZpQbnzk
wTdYXFI68HbovxWc9fDxoAAwCgYIKoZIzj0EAwIDRwAwRAIgODOqVqdeZzSwZOFB
VZuSLoMVvCVoiFng8/2hXfJWJi4CIBNHEt9batonI4Z6Z0kij/qNTeTTWFd5yawX
2DP2+6EP
-----END CERTIFICATE REQUEST-----
5 changes: 5 additions & 0 deletions x509util/testdata/rawSubject.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIK9FBgwqr6Zjsbf2uPmvnDz341AhiJbPLTuq8+/BLbd/oAoGCCqGSM49
AwEHoUQDQgAExjS2bc7+XXJdjc+ulwVfrauYygh/Vhj5bLgRKuPDTVG9S83nI2lU
2bBMHvmaUG585ME3WFxSOvB26L8VnPXw8Q==
-----END EC PRIVATE KEY-----
10 changes: 10 additions & 0 deletions x509util/testdata/rawSubject.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"rawSubject": {{ toJson .Insecure.CR.RawSubject }},
"sans": {{ toJson .SANs }},
{{- if typeIs "*rsa.PublicKey" .Insecure.CR.PublicKey }}
"keyUsage": ["keyEncipherment", "digitalSignature"],
{{- else }}
"keyUsage": ["digitalSignature"],
{{- end }}
"extKeyUsage": ["serverAuth", "clientAuth"]
}

0 comments on commit 936b845

Please sign in to comment.