forked from TrueCloudLab/certificates
Convert x509util.WithOptions to new modifiers.
This commit is contained in:
parent
dcb962bdde
commit
9032018cf2
1 changed files with 84 additions and 106 deletions
|
@ -6,13 +6,14 @@ import (
|
|||
"crypto/x509"
|
||||
"crypto/x509/pkix"
|
||||
"encoding/asn1"
|
||||
"encoding/json"
|
||||
"net"
|
||||
"net/url"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/smallstep/cli/crypto/x509util"
|
||||
"github.com/smallstep/certificates/x509util"
|
||||
"golang.org/x/crypto/ed25519"
|
||||
)
|
||||
|
||||
|
@ -21,6 +22,7 @@ import (
|
|||
type Options struct {
|
||||
NotAfter TimeDuration `json:"notAfter"`
|
||||
NotBefore TimeDuration `json:"notBefore"`
|
||||
UserData json.RawMessage `json:"data"`
|
||||
Backdate time.Duration `json:"-"`
|
||||
}
|
||||
|
||||
|
@ -28,41 +30,30 @@ type Options struct {
|
|||
// Sign method.
|
||||
type SignOption interface{}
|
||||
|
||||
// CertificateValidator is the interface used to validate a X.509 certificate.
|
||||
// CertificateValidator is an interface used to validate a given X.509 certificate.
|
||||
type CertificateValidator interface {
|
||||
SignOption
|
||||
Valid(cert *x509.Certificate, o Options) error
|
||||
Valid(cert *x509.Certificate, opts Options) error
|
||||
}
|
||||
|
||||
// CertificateRequestValidator is the interface used to validate a X.509
|
||||
// certificate request.
|
||||
// CertificateRequestValidator is an interface used to validate a given X.509 certificate request.
|
||||
type CertificateRequestValidator interface {
|
||||
SignOption
|
||||
Valid(req *x509.CertificateRequest) error
|
||||
Valid(cr *x509.CertificateRequest) error
|
||||
}
|
||||
|
||||
// ProfileModifier is the interface used to add custom options to the profile
|
||||
// constructor. The options are used to modify the final certificate.
|
||||
type ProfileModifier interface {
|
||||
SignOption
|
||||
Option(o Options) x509util.WithOption
|
||||
// CertificateModifier is an interface used to modify a given X.509 certificate.
|
||||
// Types implementing this interface will be validated with a
|
||||
// CertificateValidator.
|
||||
type CertificateModifier interface {
|
||||
Modify(cert *x509.Certificate, opts Options) error
|
||||
}
|
||||
|
||||
// CertificateEnforcer is the interface used to modify a certificate after
|
||||
// validation.
|
||||
// CertificateEnforcer is an interface used to modify a given X.509 certificate.
|
||||
// Types implemented this interface will NOT be validated with a
|
||||
// CertificateValidator.
|
||||
type CertificateEnforcer interface {
|
||||
SignOption
|
||||
Enforce(cert *x509.Certificate) error
|
||||
}
|
||||
|
||||
// profileWithOption is a wrapper against x509util.WithOption to conform the
|
||||
// interface.
|
||||
type profileWithOption x509util.WithOption
|
||||
|
||||
func (v profileWithOption) Option(Options) x509util.WithOption {
|
||||
return x509util.WithOption(v)
|
||||
}
|
||||
|
||||
// emailOnlyIdentity is a CertificateRequestValidator that checks that the only
|
||||
// SAN provided is the given email address.
|
||||
type emailOnlyIdentity string
|
||||
|
@ -254,27 +245,26 @@ func (eee ExtraExtsEnforcer) Enforce(cert *x509.Certificate) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// profileDefaultDuration is a wrapper against x509util.WithOption to conform
|
||||
// the SignOption interface.
|
||||
// profileDefaultDuration is a modifier that sets the certificate
|
||||
// duration.
|
||||
type profileDefaultDuration time.Duration
|
||||
|
||||
func (v profileDefaultDuration) Option(so Options) x509util.WithOption {
|
||||
func (v profileDefaultDuration) Modify(cert *x509.Certificate, so Options) error {
|
||||
var backdate time.Duration
|
||||
notBefore := so.NotBefore.Time()
|
||||
if notBefore.IsZero() {
|
||||
notBefore = now()
|
||||
backdate = -1 * so.Backdate
|
||||
|
||||
}
|
||||
notAfter := so.NotAfter.RelativeTime(notBefore)
|
||||
return func(p x509util.Profile) error {
|
||||
fn := x509util.WithNotBeforeAfterDuration(notBefore, notAfter, time.Duration(v))
|
||||
if err := fn(p); err != nil {
|
||||
return err
|
||||
if notAfter.IsZero() {
|
||||
notAfter = notBefore.Add(time.Duration(v))
|
||||
}
|
||||
crt := p.Subject()
|
||||
crt.NotBefore = crt.NotBefore.Add(backdate)
|
||||
|
||||
cert.NotBefore = notBefore.Add(backdate)
|
||||
cert.NotAfter = notAfter
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// profileLimitDuration is an x509 profile option that modifies an x509 validity
|
||||
|
@ -286,13 +276,11 @@ type profileLimitDuration struct {
|
|||
|
||||
// Option returns an x509util option that limits the validity period of a
|
||||
// certificate to one that is superficially imposed.
|
||||
func (v profileLimitDuration) Option(so Options) x509util.WithOption {
|
||||
return func(p x509util.Profile) error {
|
||||
func (v profileLimitDuration) Modify(cert *x509.Certificate, so Options) error {
|
||||
var backdate time.Duration
|
||||
n := now()
|
||||
notBefore := so.NotBefore.Time()
|
||||
if notBefore.IsZero() {
|
||||
notBefore = n
|
||||
notBefore = now()
|
||||
backdate = -1 * so.Backdate
|
||||
}
|
||||
if notBefore.Before(v.notBefore) {
|
||||
|
@ -315,11 +303,10 @@ func (v profileLimitDuration) Option(so Options) x509util.WithOption {
|
|||
notAfter = t
|
||||
}
|
||||
}
|
||||
crt := p.Subject()
|
||||
crt.NotBefore = notBefore.Add(backdate)
|
||||
crt.NotAfter = notAfter
|
||||
|
||||
cert.NotBefore = notBefore.Add(backdate)
|
||||
cert.NotAfter = notAfter
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// validityValidator validates the certificate validity settings.
|
||||
|
@ -385,22 +372,21 @@ func newForceCNOption(forceCN bool) *forceCNOption {
|
|||
return &forceCNOption{forceCN}
|
||||
}
|
||||
|
||||
func (o *forceCNOption) Option(Options) x509util.WithOption {
|
||||
return func(p x509util.Profile) error {
|
||||
func (o *forceCNOption) Modify(cert *x509.Certificate, _ Options) error {
|
||||
if !o.ForceCN {
|
||||
// Forcing CN is disabled, do nothing to certificate
|
||||
return nil
|
||||
}
|
||||
crt := p.Subject()
|
||||
if crt.Subject.CommonName == "" {
|
||||
if len(crt.DNSNames) > 0 {
|
||||
crt.Subject.CommonName = crt.DNSNames[0]
|
||||
|
||||
if cert.Subject.CommonName == "" {
|
||||
if len(cert.DNSNames) > 0 {
|
||||
cert.Subject.CommonName = cert.DNSNames[0]
|
||||
} else {
|
||||
return errors.New("Cannot force CN, DNSNames is empty")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
type provisionerExtensionOption struct {
|
||||
|
@ -419,9 +405,7 @@ func newProvisionerExtensionOption(typ Type, name, credentialID string, keyValue
|
|||
}
|
||||
}
|
||||
|
||||
func (o *provisionerExtensionOption) Option(Options) x509util.WithOption {
|
||||
return func(p x509util.Profile) error {
|
||||
crt := p.Subject()
|
||||
func (o *provisionerExtensionOption) Modify(cert *x509.Certificate, _ Options) error {
|
||||
ext, err := createProvisionerExtension(o.Type, o.Name, o.CredentialID, o.KeyValuePairs...)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -433,9 +417,8 @@ func (o *provisionerExtensionOption) Option(Options) x509util.WithOption {
|
|||
// ExtraExtension. If we were to append (rather than prepend) the correct
|
||||
// stepOIDProvisioner extension, then the resulting certificate would
|
||||
// contain the malicious extension, rather than the one applied by step-ca.
|
||||
crt.ExtraExtensions = append([]pkix.Extension{ext}, crt.ExtraExtensions...)
|
||||
cert.ExtraExtensions = append([]pkix.Extension{ext}, cert.ExtraExtensions...)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
func createProvisionerExtension(typ int, name, credentialID string, keyValuePairs ...string) (pkix.Extension, error) {
|
||||
|
@ -454,8 +437,3 @@ func createProvisionerExtension(typ int, name, credentialID string, keyValuePair
|
|||
Value: b,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
// Avoid dead-code warning in profileWithOption
|
||||
_ = profileWithOption(nil)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue