Build RA token using SANs from the template

This commit updates the RA token to use the SANs coming from the
template instead of the CSR.

Note that this PR might break some admin tokens.
pull/1608/head
Mariano Cano 7 months ago
parent ef2b43d888
commit 6705b7dde4
No known key found for this signature in database

@ -71,6 +71,8 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
switch { switch {
case req.CSR == nil: case req.CSR == nil:
return nil, errors.New("createCertificateRequest `csr` cannot be nil") return nil, errors.New("createCertificateRequest `csr` cannot be nil")
case req.Template == nil:
return nil, errors.New("createCertificateRequest `template` cannot be nil")
case req.Lifetime == 0: case req.Lifetime == 0:
return nil, errors.New("createCertificateRequest `lifetime` cannot be 0") return nil, errors.New("createCertificateRequest `lifetime` cannot be 0")
} }
@ -87,7 +89,7 @@ func (s *StepCAS) CreateCertificate(req *apiv1.CreateCertificateRequest) (*apiv1
info.ProvisionerName = p.Name info.ProvisionerName = p.Name
} }
cert, chain, err := s.createCertificate(req.CSR, req.Lifetime, info) cert, chain, err := s.createCertificate(req.CSR, req.Template, req.Lifetime, info)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -167,18 +169,18 @@ func (s *StepCAS) GetCertificateAuthority(*apiv1.GetCertificateAuthorityRequest)
}, nil }, nil
} }
func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, lifetime time.Duration, raInfo *raInfo) (*x509.Certificate, []*x509.Certificate, error) { func (s *StepCAS) createCertificate(cr *x509.CertificateRequest, template *x509.Certificate, lifetime time.Duration, raInfo *raInfo) (*x509.Certificate, []*x509.Certificate, error) {
sans := make([]string, 0, len(cr.DNSNames)+len(cr.EmailAddresses)+len(cr.IPAddresses)+len(cr.URIs)) sans := make([]string, 0, len(template.DNSNames)+len(template.EmailAddresses)+len(template.IPAddresses)+len(template.URIs))
sans = append(sans, cr.DNSNames...) sans = append(sans, template.DNSNames...)
sans = append(sans, cr.EmailAddresses...) sans = append(sans, template.EmailAddresses...)
for _, ip := range cr.IPAddresses { for _, ip := range template.IPAddresses {
sans = append(sans, ip.String()) sans = append(sans, ip.String())
} }
for _, u := range cr.URIs { for _, u := range template.URIs {
sans = append(sans, u.String()) sans = append(sans, u.String())
} }
commonName := cr.Subject.CommonName commonName := template.Subject.CommonName
if commonName == "" && len(sans) > 0 { if commonName == "" && len(sans) > 0 {
commonName = sans[0] commonName = sans[0]
} }

@ -23,6 +23,7 @@ import (
"github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/ca" "github.com/smallstep/certificates/ca"
"github.com/smallstep/certificates/cas/apiv1" "github.com/smallstep/certificates/cas/apiv1"
"github.com/stretchr/testify/require"
"go.step.sm/crypto/jose" "go.step.sm/crypto/jose"
"go.step.sm/crypto/pemutil" "go.step.sm/crypto/pemutil"
"go.step.sm/crypto/randutil" "go.step.sm/crypto/randutil"
@ -631,6 +632,17 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
jwkEnc := testJWKIssuer(t, caURL, testPassword) jwkEnc := testJWKIssuer(t, caURL, testPassword)
x5cBad := testX5CIssuer(t, caURL, "bad-password") x5cBad := testX5CIssuer(t, caURL, "bad-password")
testTemplate := &x509.Certificate{
Subject: testCR.Subject,
DNSNames: testCR.DNSNames,
EmailAddresses: testCR.EmailAddresses,
IPAddresses: testCR.IPAddresses,
URIs: testCR.URIs,
}
testOtherCR, err := x509util.CreateCertificateRequest("Test Certificate", []string{"test.example.com"}, testKey)
require.NoError(t, err)
type fields struct { type fields struct {
iss stepIssuer iss stepIssuer
client *ca.Client client *ca.Client
@ -648,6 +660,15 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}{ }{
{"ok", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{
Certificate: testCrt,
CertificateChain: []*x509.Certificate{testIssCrt},
}, false},
{"ok with different CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testOtherCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
Certificate: testCrt, Certificate: testCrt,
@ -655,6 +676,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"ok with password", fields{x5cEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok with password", fields{x5cEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
Certificate: testCrt, Certificate: testCrt,
@ -662,6 +684,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"ok jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok jwk", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
Certificate: testCrt, Certificate: testCrt,
@ -669,6 +692,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"ok jwk with password", fields{jwkEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok jwk with password", fields{jwkEnc, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
Certificate: testCrt, Certificate: testCrt,
@ -676,6 +700,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"ok with provisioner", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok with provisioner", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
Provisioner: &apiv1.ProvisionerInfo{ID: "provisioner-id", Type: "ACME"}, Provisioner: &apiv1.ProvisionerInfo{ID: "provisioner-id", Type: "ACME"},
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
@ -684,6 +709,7 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"ok with server cert", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"ok with server cert", fields{jwk, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR, CSR: testCR,
Template: testTemplate,
Lifetime: time.Hour, Lifetime: time.Hour,
IsCAServerCert: true, IsCAServerCert: true,
}}, &apiv1.CreateCertificateResponse{ }}, &apiv1.CreateCertificateResponse{
@ -692,6 +718,12 @@ func TestStepCAS_CreateCertificate(t *testing.T) {
}, false}, }, false},
{"fail CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"fail CSR", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: nil, CSR: nil,
Template: testTemplate,
Lifetime: time.Hour,
}}, nil, true},
{"fail Template", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{
CSR: testCR,
Template: nil,
Lifetime: time.Hour, Lifetime: time.Hour,
}}, nil, true}, }}, nil, true},
{"fail lifetime", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{ {"fail lifetime", fields{x5c, client, testRootFingerprint}, args{&apiv1.CreateCertificateRequest{

Loading…
Cancel
Save