forked from TrueCloudLab/certificates
Remove ACME restrictions and add proper template support.
This commit is contained in:
parent
6a09f11357
commit
a7fe0104c4
4 changed files with 42 additions and 24 deletions
|
@ -18,6 +18,7 @@ type Provisioner interface {
|
|||
AuthorizeSign(ctx context.Context, token string) ([]provisioner.SignOption, error)
|
||||
GetName() string
|
||||
DefaultTLSCertDuration() time.Duration
|
||||
GetOptions() *provisioner.ProvisionerOptions
|
||||
}
|
||||
|
||||
// MockProvisioner for testing
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/certificates/authority/provisioner"
|
||||
"github.com/smallstep/certificates/x509util"
|
||||
"github.com/smallstep/nosql"
|
||||
)
|
||||
|
||||
|
@ -299,23 +300,23 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut
|
|||
orderNames = uniqueLowerNames(orderNames)
|
||||
|
||||
// Validate identifier names against CSR alternative names.
|
||||
//
|
||||
// Note that with certificate templates we are not going to check for the no
|
||||
// presence of other SANs as they will only be set if the templates allows
|
||||
// them.
|
||||
if len(csr.DNSNames) != len(orderNames) {
|
||||
return nil, BadCSRErr(errors.Errorf("CSR names do not match identifiers exactly: CSR names = %v, Order names = %v", csr.DNSNames, orderNames))
|
||||
}
|
||||
|
||||
sans := make([]x509util.SubjectAlternativeName, len(csr.DNSNames))
|
||||
for i := range csr.DNSNames {
|
||||
if csr.DNSNames[i] != orderNames[i] {
|
||||
return nil, BadCSRErr(errors.Errorf("CSR names do not match identifiers exactly: CSR names = %v, Order names = %v", csr.DNSNames, orderNames))
|
||||
}
|
||||
}
|
||||
|
||||
if len(csr.IPAddresses) > 0 {
|
||||
return nil, BadCSRErr(errors.Errorf("CSR contains IP Address SANs, but should only contain DNS Names"))
|
||||
}
|
||||
if len(csr.EmailAddresses) > 0 {
|
||||
return nil, BadCSRErr(errors.Errorf("CSR contains Email Address SANs, but should only contain DNS Names"))
|
||||
}
|
||||
if len(csr.URIs) > 0 {
|
||||
return nil, BadCSRErr(errors.Errorf("CSR contains URI SANs, but should only contain DNS Names"))
|
||||
sans[i] = x509util.SubjectAlternativeName{
|
||||
Type: x509util.DNSType,
|
||||
Value: csr.DNSNames[i],
|
||||
}
|
||||
}
|
||||
|
||||
// Get authorizations from the ACME provisioner.
|
||||
|
@ -325,6 +326,17 @@ func (o *order) finalize(db nosql.DB, csr *x509.CertificateRequest, auth SignAut
|
|||
return nil, ServerInternalErr(errors.Wrapf(err, "error retrieving authorization options from ACME provisioner"))
|
||||
}
|
||||
|
||||
// Template data
|
||||
data := x509util.NewTemplateData()
|
||||
data.SetCommonName(csr.Subject.CommonName)
|
||||
data.Set(x509util.SANsKey, sans)
|
||||
|
||||
templateOptions, err := provisioner.TemplateOptions(p.GetOptions(), data)
|
||||
if err != nil {
|
||||
return nil, ServerInternalErr(errors.Wrapf(err, "error creating template options from ACME provisioner"))
|
||||
}
|
||||
signOps = append(signOps, templateOptions)
|
||||
|
||||
// Create and store a new certificate.
|
||||
certChain, err := auth.Sign(csr, provisioner.Options{
|
||||
NotBefore: provisioner.NewTimeDuration(o.NotBefore),
|
||||
|
|
|
@ -3,12 +3,10 @@ package provisioner
|
|||
import (
|
||||
"context"
|
||||
"crypto/x509"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/certificates/errs"
|
||||
"github.com/smallstep/certificates/x509util"
|
||||
)
|
||||
|
||||
// ACME is the acme provisioner type, an entity that can authorize the ACME
|
||||
|
@ -48,6 +46,11 @@ func (p *ACME) GetEncryptedKey() (string, string, bool) {
|
|||
return "", "", false
|
||||
}
|
||||
|
||||
// GetOptions returns the configured provisioner options.
|
||||
func (p *ACME) GetOptions() *ProvisionerOptions {
|
||||
return p.Options
|
||||
}
|
||||
|
||||
// DefaultTLSCertDuration returns the default TLS cert duration enforced by
|
||||
// the provisioner.
|
||||
func (p *ACME) DefaultTLSCertDuration() time.Duration {
|
||||
|
@ -75,14 +78,7 @@ func (p *ACME) Init(config Config) (err error) {
|
|||
// in the ACME protocol. This method returns a list of modifiers / constraints
|
||||
// on the resulting certificate.
|
||||
func (p *ACME) AuthorizeSign(ctx context.Context, token string) ([]SignOption, error) {
|
||||
// Certificate templates
|
||||
templateOptions, err := TemplateOptions(p.Options, x509util.NewTemplateData())
|
||||
if err != nil {
|
||||
return nil, errs.Wrap(http.StatusInternalServerError, err, "acme.AuthorizeSign")
|
||||
}
|
||||
|
||||
return []SignOption{
|
||||
templateOptions,
|
||||
// modifiers / withOptions
|
||||
newProvisionerExtensionOption(TypeACME, p.Name, ""),
|
||||
newForceCNOption(p.ForceCN),
|
||||
|
|
|
@ -48,6 +48,15 @@ var (
|
|||
ExtKeyUsageMicrosoftKernelCodeSigning = convertName("MicrosoftKernelCodeSigning")
|
||||
)
|
||||
|
||||
// Names used and SubjectAlternativeNames types.
|
||||
const (
|
||||
AutoType = "auto"
|
||||
DNSType = "dns"
|
||||
EmailType = "email"
|
||||
IPType = "ip"
|
||||
URIType = "uri"
|
||||
)
|
||||
|
||||
// Extension is the JSON representation of a raw X.509 extensions.
|
||||
type Extension struct {
|
||||
ID ObjectIdentifier `json:"id"`
|
||||
|
@ -106,21 +115,21 @@ type SubjectAlternativeName struct {
|
|||
|
||||
func (s SubjectAlternativeName) Set(c *x509.Certificate) {
|
||||
switch strings.ToLower(s.Type) {
|
||||
case "dns":
|
||||
case DNSType:
|
||||
c.DNSNames = append(c.DNSNames, s.Value)
|
||||
case "email":
|
||||
case EmailType:
|
||||
c.EmailAddresses = append(c.EmailAddresses, s.Value)
|
||||
case "ip":
|
||||
case IPType:
|
||||
// The validation of the IP would happen in the unmarshaling, but just
|
||||
// to be sure we are only adding valid IPs.
|
||||
if ip := net.ParseIP(s.Value); ip != nil {
|
||||
c.IPAddresses = append(c.IPAddresses, ip)
|
||||
}
|
||||
case "uri":
|
||||
case URIType:
|
||||
if u, err := url.Parse(s.Value); err == nil {
|
||||
c.URIs = append(c.URIs, u)
|
||||
}
|
||||
case "auto", "":
|
||||
case "", AutoType:
|
||||
dnsNames, ips, emails, uris := SplitSANs([]string{s.Value})
|
||||
c.DNSNames = append(c.DNSNames, dnsNames...)
|
||||
c.IPAddresses = append(c.IPAddresses, ips...)
|
||||
|
|
Loading…
Reference in a new issue