Move options to provisioner so we can set the duration of the cert.

This commit is contained in:
Mariano Cano 2019-03-07 15:14:18 -08:00
parent aa8385b8ba
commit a97ea87caa
6 changed files with 35 additions and 44 deletions

View file

@ -18,7 +18,6 @@ import (
"github.com/go-chi/chi" "github.com/go-chi/chi"
"github.com/pkg/errors" "github.com/pkg/errors"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/logging" "github.com/smallstep/certificates/logging"
"github.com/smallstep/cli/crypto/tlsutil" "github.com/smallstep/cli/crypto/tlsutil"
@ -29,7 +28,7 @@ type Authority interface {
Authorize(ott string) ([]provisioner.SignOption, error) Authorize(ott string) ([]provisioner.SignOption, error)
GetTLSOptions() *tlsutil.TLSOptions GetTLSOptions() *tlsutil.TLSOptions
Root(shasum string) (*x509.Certificate, error) Root(shasum string) (*x509.Certificate, error)
Sign(cr *x509.CertificateRequest, signOpts authority.SignOptions, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error)
Renew(peer *x509.Certificate) (*x509.Certificate, *x509.Certificate, error) Renew(peer *x509.Certificate) (*x509.Certificate, *x509.Certificate, error)
GetProvisioners(cursor string, limit int) (provisioner.List, string, error) GetProvisioners(cursor string, limit int) (provisioner.List, string, error)
GetEncryptedKey(kid string) (string, error) GetEncryptedKey(kid string) (string, error)
@ -166,7 +165,7 @@ type ProvisionersResponse struct {
NextCursor string `json:"nextCursor"` NextCursor string `json:"nextCursor"`
} }
// ProvisionerKeyResponse is the response object that returns the encryptoed key // ProvisionerKeyResponse is the response object that returns the encrypted key
// of a provisioner. // of a provisioner.
type ProvisionerKeyResponse struct { type ProvisionerKeyResponse struct {
Key string `json:"key"` Key string `json:"key"`
@ -267,18 +266,18 @@ func (h *caHandler) Sign(w http.ResponseWriter, r *http.Request) {
return return
} }
signOpts := authority.SignOptions{ opts := provisioner.Options{
NotBefore: body.NotBefore, NotBefore: body.NotBefore,
NotAfter: body.NotAfter, NotAfter: body.NotAfter,
} }
extraOpts, err := h.Authority.Authorize(body.OTT) signOpts, err := h.Authority.Authorize(body.OTT)
if err != nil { if err != nil {
WriteError(w, Unauthorized(err)) WriteError(w, Unauthorized(err))
return return
} }
cert, root, err := h.Authority.Sign(body.CsrPEM.CertificateRequest, signOpts, extraOpts...) cert, root, err := h.Authority.Sign(body.CsrPEM.CertificateRequest, opts, signOpts...)
if err != nil { if err != nil {
WriteError(w, Forbidden(err)) WriteError(w, Forbidden(err))
return return

View file

@ -24,7 +24,6 @@ import (
"time" "time"
"github.com/go-chi/chi" "github.com/go-chi/chi"
"github.com/smallstep/certificates/authority"
"github.com/smallstep/certificates/authority/provisioner" "github.com/smallstep/certificates/authority/provisioner"
"github.com/smallstep/certificates/logging" "github.com/smallstep/certificates/logging"
"github.com/smallstep/cli/crypto/tlsutil" "github.com/smallstep/cli/crypto/tlsutil"
@ -414,7 +413,7 @@ type mockAuthority struct {
authorize func(ott string) ([]provisioner.SignOption, error) authorize func(ott string) ([]provisioner.SignOption, error)
getTLSOptions func() *tlsutil.TLSOptions getTLSOptions func() *tlsutil.TLSOptions
root func(shasum string) (*x509.Certificate, error) root func(shasum string) (*x509.Certificate, error)
sign func(cr *x509.CertificateRequest, signOpts authority.SignOptions, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) sign func(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error)
renew func(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error) renew func(cert *x509.Certificate) (*x509.Certificate, *x509.Certificate, error)
getProvisioners func(nextCursor string, limit int) (provisioner.List, string, error) getProvisioners func(nextCursor string, limit int) (provisioner.List, string, error)
getEncryptedKey func(kid string) (string, error) getEncryptedKey func(kid string) (string, error)
@ -443,9 +442,9 @@ func (m *mockAuthority) Root(shasum string) (*x509.Certificate, error) {
return m.ret1.(*x509.Certificate), m.err return m.ret1.(*x509.Certificate), m.err
} }
func (m *mockAuthority) Sign(cr *x509.CertificateRequest, signOpts authority.SignOptions, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) { func (m *mockAuthority) Sign(cr *x509.CertificateRequest, opts provisioner.Options, signOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) {
if m.sign != nil { if m.sign != nil {
return m.sign(cr, signOpts, extraOpts...) return m.sign(cr, opts, signOpts...)
} }
return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err return m.ret1.(*x509.Certificate), m.ret2.(*x509.Certificate), m.err
} }

View file

@ -105,16 +105,14 @@ func (p *JWK) Authorize(token string) ([]SignOption, error) {
return nil, err return nil, err
} }
signOps := []SignOption{ return []SignOption{
commonNameValidator(claims.Subject), commonNameValidator(claims.Subject),
dnsNamesValidator(dnsNames), dnsNamesValidator(dnsNames),
ipAddressesValidator(ips), ipAddressesValidator(ips),
// profileWithOption(x509util.WithNotBeforeAfterDuration(so.NotBefore, so.NotAfter, p.Claims.DefaultTLSCertDuration())), profileDefaultDuration(p.Claims.DefaultTLSCertDuration()),
newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID), newProvisionerExtensionOption(TypeJWK, p.Name, p.Key.KeyID),
newValidityValidator(p.Claims.MinTLSCertDuration(), p.Claims.MaxTLSCertDuration()), newValidityValidator(p.Claims.MinTLSCertDuration(), p.Claims.MaxTLSCertDuration()),
} }, nil
return signOps, nil
} }
// AuthorizeRenewal returns an error if the renewal is disabled. // AuthorizeRenewal returns an error if the renewal is disabled.
@ -130,18 +128,3 @@ func (p *JWK) AuthorizeRenewal(cert *x509.Certificate) error {
func (p *JWK) AuthorizeRevoke(token string) error { func (p *JWK) AuthorizeRevoke(token string) error {
return errors.New("not implemented") return errors.New("not implemented")
} }
// // getTLSApps returns a list of modifiers and validators that will be applied to
// // the certificate.
// func (p *JWT) getTLSApps(so SignOptions) ([]x509util.WithOption, []certClaim, error) {
// c := p.Claims
// return []x509util.WithOption{
// x509util.WithNotBeforeAfterDuration(so.NotBefore, so.NotAfter, c.DefaultTLSCertDuration()),
// withProvisionerOID(p.Name, p.Key.KeyID),
// }, []certClaim{
// &certTemporalClaim{
// min: c.MinTLSCertDuration(),
// max: c.MaxTLSCertDuration(),
// },
// }, nil
// }

View file

@ -156,6 +156,7 @@ func (o *OIDC) Authorize(token string) ([]SignOption, error) {
return []SignOption{ return []SignOption{
emailOnlyIdentity(claims.Email), emailOnlyIdentity(claims.Email),
profileDefaultDuration(o.Claims.DefaultTLSCertDuration()),
newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID), newProvisionerExtensionOption(TypeOIDC, o.Name, o.ClientID),
newValidityValidator(o.Claims.MinTLSCertDuration(), o.Claims.MaxTLSCertDuration()), newValidityValidator(o.Claims.MinTLSCertDuration(), o.Claims.MaxTLSCertDuration()),
}, nil }, nil

View file

@ -12,6 +12,12 @@ import (
"github.com/smallstep/cli/crypto/x509util" "github.com/smallstep/cli/crypto/x509util"
) )
// Options contains the options that can be passed to the Sign method.
type Options struct {
NotAfter time.Time `json:"notAfter"`
NotBefore time.Time `json:"notBefore"`
}
// SignOption is the interface used to collect all extra options used in the // SignOption is the interface used to collect all extra options used in the
// Sign method. // Sign method.
type SignOption interface{} type SignOption interface{}
@ -29,19 +35,29 @@ type CertificateRequestValidator interface {
Valid(req *x509.CertificateRequest) error Valid(req *x509.CertificateRequest) error
} }
// ProfileWithOption is the interface used to add custom options to the profile // ProfileModifier is the interface used to add custom options to the profile
// constructor. The options are used to modify the final certificate. // constructor. The options are used to modify the final certificate.
type ProfileWithOption interface { type ProfileModifier interface {
SignOption SignOption
Option() x509util.WithOption Option(so SignOption) x509util.WithOption
} }
// profileWithOption is a wrapper against x509util.WithOption to conform the
// interface.
type profileWithOption x509util.WithOption type profileWithOption x509util.WithOption
func (v profileWithOption) Option() x509util.WithOption { func (v profileWithOption) Option(Options) x509util.WithOption {
return x509util.WithOption(v) return x509util.WithOption(v)
} }
// profileDefaultDuration is a wrapper against x509util.WithOption to conform the
// interface.
type profileDefaultDuration time.Duration
func (v profileDefaultDuration) Option(so Options) x509util.WithOption {
return x509util.WithNotBeforeAfterDuration(so.NotBefore, so.NotAfter, time.Duration(v))
}
// emailOnlyIdentity is a CertificateRequestValidator that checks that the only // emailOnlyIdentity is a CertificateRequestValidator that checks that the only
// SAN provided is the given email address. // SAN provided is the given email address.
type emailOnlyIdentity string type emailOnlyIdentity string

View file

@ -23,13 +23,6 @@ func (a *Authority) GetTLSOptions() *tlsutil.TLSOptions {
return a.config.TLS return a.config.TLS
} }
// SignOptions contains the options that can be passed to the Authority.Sign
// method.
type SignOptions struct {
NotAfter time.Time `json:"notAfter"`
NotBefore time.Time `json:"notBefore"`
}
var ( var (
stepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64} stepOIDRoot = asn1.ObjectIdentifier{1, 3, 6, 1, 4, 1, 37476, 9000, 64}
stepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(stepOIDRoot, 1)...) stepOIDProvisioner = append(asn1.ObjectIdentifier(nil), append(stepOIDRoot, 1)...)
@ -97,7 +90,7 @@ func withDefaultASN1DN(def *x509util.ASN1DN) x509util.WithOption {
} }
// Sign creates a signed certificate from a certificate signing request. // Sign creates a signed certificate from a certificate signing request.
func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts SignOptions, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) { func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts provisioner.Options, extraOpts ...provisioner.SignOption) (*x509.Certificate, *x509.Certificate, error) {
var ( var (
errContext = context{"csr": csr, "signOptions": signOpts} errContext = context{"csr": csr, "signOptions": signOpts}
mods = []x509util.WithOption{} mods = []x509util.WithOption{}
@ -111,8 +104,8 @@ func (a *Authority) Sign(csr *x509.CertificateRequest, signOpts SignOptions, ext
if err := k.Valid(csr); err != nil { if err := k.Valid(csr); err != nil {
return nil, nil, err return nil, nil, err
} }
case provisioner.ProfileWithOption: case provisioner.ProfileModifier:
mods = append(mods, k.Option()) mods = append(mods, k.Option(signOpts))
default: default:
return nil, nil, &apiError{errors.Errorf("sign: invalid extra option type %T", k), return nil, nil, &apiError{errors.Errorf("sign: invalid extra option type %T", k),
http.StatusInternalServerError, errContext} http.StatusInternalServerError, errContext}