forked from TrueCloudLab/certificates
Add initial version of time duration support in sign requests.
This commit is contained in:
parent
7b1f4a43cf
commit
00fed1c538
3 changed files with 124 additions and 6 deletions
13
api/api.go
13
api/api.go
|
@ -36,6 +36,15 @@ type Authority interface {
|
||||||
GetFederation() ([]*x509.Certificate, error)
|
GetFederation() ([]*x509.Certificate, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TimeDuration is an alias of provisioner.TimeDuration
|
||||||
|
type TimeDuration = provisioner.TimeDuration
|
||||||
|
|
||||||
|
// ParseTimeDuration returns a new TimeDuration parsing the RFC 3339 time or
|
||||||
|
// time.Duration string.
|
||||||
|
func ParseTimeDuration(s string) (TimeDuration, error) {
|
||||||
|
return provisioner.ParseTimeDuration(s)
|
||||||
|
}
|
||||||
|
|
||||||
// Certificate wraps a *x509.Certificate and adds the json.Marshaler interface.
|
// Certificate wraps a *x509.Certificate and adds the json.Marshaler interface.
|
||||||
type Certificate struct {
|
type Certificate struct {
|
||||||
*x509.Certificate
|
*x509.Certificate
|
||||||
|
@ -154,8 +163,8 @@ type RootResponse struct {
|
||||||
type SignRequest struct {
|
type SignRequest struct {
|
||||||
CsrPEM CertificateRequest `json:"csr"`
|
CsrPEM CertificateRequest `json:"csr"`
|
||||||
OTT string `json:"ott"`
|
OTT string `json:"ott"`
|
||||||
NotAfter time.Time `json:"notAfter"`
|
NotAfter TimeDuration `json:"notAfter"`
|
||||||
NotBefore time.Time `json:"notBefore"`
|
NotBefore TimeDuration `json:"notBefore"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// ProvisionersResponse is the response object that returns the list of
|
// ProvisionersResponse is the response object that returns the list of
|
||||||
|
|
|
@ -14,8 +14,8 @@ import (
|
||||||
|
|
||||||
// Options contains the options that can be passed to the Sign method.
|
// Options contains the options that can be passed to the Sign method.
|
||||||
type Options struct {
|
type Options struct {
|
||||||
NotAfter time.Time `json:"notAfter"`
|
NotAfter TimeDuration `json:"notAfter"`
|
||||||
NotBefore time.Time `json:"notBefore"`
|
NotBefore TimeDuration `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
|
||||||
|
@ -55,7 +55,7 @@ func (v profileWithOption) Option(Options) x509util.WithOption {
|
||||||
type profileDefaultDuration time.Duration
|
type profileDefaultDuration time.Duration
|
||||||
|
|
||||||
func (v profileDefaultDuration) Option(so Options) x509util.WithOption {
|
func (v profileDefaultDuration) Option(so Options) x509util.WithOption {
|
||||||
return x509util.WithNotBeforeAfterDuration(so.NotBefore, so.NotAfter, time.Duration(v))
|
return x509util.WithNotBeforeAfterDuration(so.NotBefore.Time(), so.NotAfter.Time(), time.Duration(v))
|
||||||
}
|
}
|
||||||
|
|
||||||
// emailOnlyIdentity is a CertificateRequestValidator that checks that the only
|
// emailOnlyIdentity is a CertificateRequestValidator that checks that the only
|
||||||
|
@ -228,6 +228,6 @@ func createProvisionerExtension(typ int, name, credentialID string) (pkix.Extens
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Avoid deadcode warning in profileWithOption
|
// Avoid dead-code warning in profileWithOption
|
||||||
_ = profileWithOption(nil)
|
_ = profileWithOption(nil)
|
||||||
}
|
}
|
||||||
|
|
109
authority/provisioner/timeduration.go
Normal file
109
authority/provisioner/timeduration.go
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
package provisioner
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TimeDuration is a type that represents a time but the JSON unmarshaling can
|
||||||
|
// use a time using the RFC 3339 format or a time.Duration string. If a duration
|
||||||
|
// is used, the time will be set on the first call to TimeDuration.Time.
|
||||||
|
type TimeDuration struct {
|
||||||
|
t time.Time
|
||||||
|
d time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseTimeDuration returns a new TimeDuration parsing the RFC 3339 time or
|
||||||
|
// time.Duration string.
|
||||||
|
func ParseTimeDuration(s string) (TimeDuration, error) {
|
||||||
|
if s == "" {
|
||||||
|
return TimeDuration{}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use the unquoted RFC 3339 format
|
||||||
|
var t time.Time
|
||||||
|
if err := t.UnmarshalText([]byte(s)); err == nil {
|
||||||
|
return TimeDuration{t: t}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use the time.Duration string format
|
||||||
|
if d, err := time.ParseDuration(s); err == nil {
|
||||||
|
return TimeDuration{d: d}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return TimeDuration{}, errors.Errorf("failed to parse %s", s)
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetDuration initializes the TimeDuration with the given duration string. If
|
||||||
|
// the time was set it will re-set to zero.
|
||||||
|
func (t *TimeDuration) SetDuration(d time.Duration) {
|
||||||
|
t.t, t.d = time.Time{}, d
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetTime initializes the TimeDuration with the given time. If the duration is
|
||||||
|
// set it will be re-set to zero.
|
||||||
|
func (t *TimeDuration) SetTime(tt time.Time) {
|
||||||
|
t.t, t.d = tt, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalJSON implements the json.Marshaler interface. If the time is set it
|
||||||
|
// will return the time in RFC 3339 format if not it will return the duration
|
||||||
|
// string.
|
||||||
|
func (t *TimeDuration) MarshalJSON() ([]byte, error) {
|
||||||
|
switch {
|
||||||
|
case t == nil:
|
||||||
|
return []byte("null"), nil
|
||||||
|
case t.t.IsZero():
|
||||||
|
if t.d == 0 {
|
||||||
|
return []byte("null"), nil
|
||||||
|
}
|
||||||
|
return json.Marshal(t.d.String())
|
||||||
|
default:
|
||||||
|
return t.t.MarshalJSON()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON implements the json.Unmarshaler interface. The time is expected
|
||||||
|
// to be a quoted string in RFC 3339 format or a quoted time.Duration string.
|
||||||
|
func (t *TimeDuration) UnmarshalJSON(data []byte) error {
|
||||||
|
var s string
|
||||||
|
if err := json.Unmarshal(data, &s); err != nil {
|
||||||
|
return errors.Wrapf(err, "error unmarshaling %s", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Empty TimeDuration
|
||||||
|
if s == "" {
|
||||||
|
*t = TimeDuration{}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use the unquoted RFC 3339 format
|
||||||
|
var tt time.Time
|
||||||
|
if err := tt.UnmarshalText([]byte(s)); err == nil {
|
||||||
|
*t = TimeDuration{t: tt}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to use the time.Duration string format
|
||||||
|
if d, err := time.ParseDuration(s); err == nil {
|
||||||
|
*t = TimeDuration{d: d}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return errors.Errorf("failed to parse %s", data)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Time set once the embedded time and returns it.
|
||||||
|
func (t *TimeDuration) Time() time.Time {
|
||||||
|
switch {
|
||||||
|
case t == nil:
|
||||||
|
return time.Time{}
|
||||||
|
case t.t.IsZero():
|
||||||
|
t.t = time.Now().UTC().Add(t.d)
|
||||||
|
return t.t
|
||||||
|
default:
|
||||||
|
return t.t
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue