Skip to content

Commit

Permalink
feat: allow CSR template subject field to be overridden
Browse files Browse the repository at this point in the history
This allows CSR signer to have control over the subject field of the
generated certificate.

Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
(cherry picked from commit c3225ee)
  • Loading branch information
smira committed Sep 7, 2022
1 parent e9df1b8 commit f60380e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 0 deletions.
14 changes: 14 additions & 0 deletions x509/x509.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,9 @@ type Options struct {
NotBefore time.Time
KeyUsage x509.KeyUsage
ExtKeyUsage []x509.ExtKeyUsage

// Used with CSR signing process to override fields in the certificate subject.
OverrideSubject func(*pkix.Name)
}

// Option is the functional option func.
Expand Down Expand Up @@ -219,6 +222,13 @@ func NotBefore(o time.Time) Option {
}
}

// OverrideSubject sets the option to override fields in the certificate subject when signing a CSR.
func OverrideSubject(f func(*pkix.Name)) Option {
return func(opts *Options) {
opts.OverrideSubject = f
}
}

// NewDefaultOptions initializes the Options struct with default values.
func NewDefaultOptions(setters ...Option) *Options {
opts := &Options{
Expand Down Expand Up @@ -535,6 +545,10 @@ func NewCertificateFromCSR(ca *x509.Certificate, key interface{}, csr *x509.Cert
DNSNames: csr.DNSNames,
}

if opts.OverrideSubject != nil {
opts.OverrideSubject(&template.Subject)
}

crtDER, err := x509.CreateCertificate(rand.Reader, template, ca, csr.PublicKey, key)
if err != nil {
return nil, err
Expand Down
26 changes: 26 additions & 0 deletions x509/x509_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package x509_test

import (
stdx509 "crypto/x509"
"crypto/x509/pkix"
"testing"
"time"

Expand Down Expand Up @@ -301,3 +302,28 @@ func TestPEMEncodedKeyECDSA(t *testing.T) {
assert.Equal(t, key.KeyPEM, decodedKey.KeyPEM)
assert.Equal(t, key.PublicKeyPEM, decodedKey.PublicKeyPEM)
}

func TestNewCertificateFromCSR(t *testing.T) {
t.Parallel()

ca, err := x509.NewSelfSignedCertificateAuthority(x509.ECDSA(true))
require.NoError(t, err)

csr, _, err := x509.NewECDSACSRAndIdentity(x509.Organization("os:admin"))
require.NoError(t, err)

// sign the CSR usual way
crt1, err := x509.NewCertificateFromCSRBytes(ca.CrtPEM, ca.KeyPEM, csr.X509CertificateRequestPEM)
require.NoError(t, err)

// sign the CSR with overrides
crt2, err := x509.NewCertificateFromCSRBytes(ca.CrtPEM, ca.KeyPEM, csr.X509CertificateRequestPEM,
x509.OverrideSubject(func(subject *pkix.Name) {
subject.Organization = nil
}),
)
require.NoError(t, err)

assert.Equal(t, []string{"os:admin"}, crt1.X509Certificate.Subject.Organization)
assert.Equal(t, []string(nil), crt2.X509Certificate.Subject.Organization)
}

0 comments on commit f60380e

Please sign in to comment.