You've already forked step-ca-cli
mirror of
https://github.com/smallstep/cli.git
synced 2026-10-29 00:17:23 +03:00
Merge pull request #52 from smallstep/mariano/validity
Allow to add custom validity in `step certificate create`
This commit is contained in:
@@ -208,11 +208,11 @@ func signCertificateTokenFlow(ctx *cli.Context, subject string) (string, error)
|
||||
}
|
||||
|
||||
// parse times or durations
|
||||
notBefore, ok := parseTimeOrDuration(ctx.String("not-before"))
|
||||
notBefore, ok := flags.ParseTimeOrDuration(ctx.String("not-before"))
|
||||
if !ok {
|
||||
return "", errs.InvalidFlagValue(ctx, "not-before", ctx.String("not-before"), "")
|
||||
}
|
||||
notAfter, ok := parseTimeOrDuration(ctx.String("not-after"))
|
||||
notAfter, ok := flags.ParseTimeOrDuration(ctx.String("not-after"))
|
||||
if !ok {
|
||||
return "", errs.InvalidFlagValue(ctx, "not-after", ctx.String("not-after"), "")
|
||||
}
|
||||
@@ -232,11 +232,11 @@ func signCertificateRequest(ctx *cli.Context, token string, csr api.CertificateR
|
||||
caURL := ctx.String("ca-url")
|
||||
|
||||
// parse times or durations
|
||||
notBefore, ok := parseTimeOrDuration(ctx.String("not-before"))
|
||||
notBefore, ok := flags.ParseTimeOrDuration(ctx.String("not-before"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-before", ctx.String("not-before"), "")
|
||||
}
|
||||
notAfter, ok := parseTimeOrDuration(ctx.String("not-after"))
|
||||
notAfter, ok := flags.ParseTimeOrDuration(ctx.String("not-after"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-after", ctx.String("not-after"), "")
|
||||
}
|
||||
|
||||
@@ -151,11 +151,11 @@ func newTokenAction(ctx *cli.Context) error {
|
||||
}
|
||||
|
||||
// parse times or durations
|
||||
notBefore, ok := parseTimeOrDuration(ctx.String("not-before"))
|
||||
notBefore, ok := flags.ParseTimeOrDuration(ctx.String("not-before"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-before", ctx.String("not-before"), "")
|
||||
}
|
||||
notAfter, ok := parseTimeOrDuration(ctx.String("not-after"))
|
||||
notAfter, ok := flags.ParseTimeOrDuration(ctx.String("not-after"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-after", ctx.String("not-after"), "")
|
||||
}
|
||||
@@ -360,22 +360,6 @@ func newTokenFlow(ctx *cli.Context, subject, caURL, root, kid, issuer, passwordF
|
||||
return generateToken(subject, kid, issuer, audience, root, notBefore, notAfter, jwk)
|
||||
}
|
||||
|
||||
func parseTimeOrDuration(s string) (time.Time, bool) {
|
||||
if s == "" {
|
||||
return time.Time{}, true
|
||||
}
|
||||
|
||||
var t time.Time
|
||||
if err := t.UnmarshalText([]byte(s)); err != nil {
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
t = time.Now().Add(d)
|
||||
}
|
||||
return t, true
|
||||
}
|
||||
|
||||
// provisionerFilter returns a slice of provisioners that pass the given filter.
|
||||
func provisionerFilter(provisioners []*authority.Provisioner, f func(*authority.Provisioner) bool) []*authority.Provisioner {
|
||||
var result []*authority.Provisioner
|
||||
|
||||
@@ -82,6 +82,14 @@ $ step certificate create foo foo.crt foo.key --profile leaf \
|
||||
--ca ./intermediate-ca.crt --ca-key ./intermediate-ca.key
|
||||
'''
|
||||
|
||||
Create a leaf certificate and key with custom validity:
|
||||
|
||||
'''
|
||||
$ step certificate create foo foo.crt foo.key --profile leaf \
|
||||
--ca ./intermediate-ca.crt --ca-key ./intermediate-ca.key \
|
||||
--not-before 24h --not-after 2160h
|
||||
'''
|
||||
|
||||
Create a root certificate and key with underlying OKP Ed25519:
|
||||
|
||||
'''
|
||||
@@ -193,6 +201,22 @@ unset, default is P-256 for EC keys and Ed25519 for OKP keys.
|
||||
**Ed25519**
|
||||
: Ed25519 Curve
|
||||
`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "not-before",
|
||||
Usage: `The <time|duration> set in the NotBefore property of the certificate. If a
|
||||
<time> is used it is expected to be in RFC 3339 format. If a <duration> is
|
||||
used, it is a sequence of decimal numbers, each with optional fraction and a
|
||||
unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns",
|
||||
"us" (or "µs"), "ms", "s", "m", "h".`,
|
||||
},
|
||||
cli.StringFlag{
|
||||
Name: "not-after",
|
||||
Usage: `The <time|duration> set in the NotAfter property of the certificate. If a
|
||||
<time> is used it is expected to be in RFC 3339 format. If a <duration> is
|
||||
used, it is a sequence of decimal numbers, each with optional fraction and a
|
||||
unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns",
|
||||
"us" (or "µs"), "ms", "s", "m", "h".`,
|
||||
},
|
||||
flags.Force,
|
||||
},
|
||||
@@ -217,6 +241,18 @@ func createAction(ctx *cli.Context) error {
|
||||
return errs.EqualArguments(ctx, "CRT_FILE", "KEY_FILE")
|
||||
}
|
||||
|
||||
notBefore, ok := flags.ParseTimeOrDuration(ctx.String("not-before"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-before", ctx.String("not-before"), "")
|
||||
}
|
||||
notAfter, ok := flags.ParseTimeOrDuration(ctx.String("not-after"))
|
||||
if !ok {
|
||||
return errs.InvalidFlagValue(ctx, "not-after", ctx.String("not-after"), "")
|
||||
}
|
||||
if !notAfter.IsZero() && !notBefore.IsZero() && notBefore.After(notAfter) {
|
||||
return errs.IncompatibleFlagValues(ctx, "not-before", ctx.String("not-before"), "not-after", ctx.String("not-after"))
|
||||
}
|
||||
|
||||
var typ string
|
||||
if ctx.Bool("csr") {
|
||||
typ = "x509-csr"
|
||||
@@ -283,7 +319,8 @@ func createAction(ctx *cli.Context) error {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
profile, err = x509util.NewLeafProfile(subject, issIdentity.Crt,
|
||||
issIdentity.Key, x509util.GenerateKeyPair(kty, crv, size))
|
||||
issIdentity.Key, x509util.GenerateKeyPair(kty, crv, size),
|
||||
x509util.WithNotBeforeAfterDuration(notBefore, notAfter, 0))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
@@ -297,14 +334,16 @@ func createAction(ctx *cli.Context) error {
|
||||
}
|
||||
profile, err = x509util.NewIntermediateProfile(subject,
|
||||
issIdentity.Crt, issIdentity.Key,
|
||||
x509util.GenerateKeyPair(kty, crv, size))
|
||||
x509util.GenerateKeyPair(kty, crv, size),
|
||||
x509util.WithNotBeforeAfterDuration(notBefore, notAfter, 0))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
}
|
||||
case "root-ca":
|
||||
profile, err = x509util.NewRootProfile(subject,
|
||||
x509util.GenerateKeyPair(kty, crv, size))
|
||||
x509util.GenerateKeyPair(kty, crv, size),
|
||||
x509util.WithNotBeforeAfterDuration(notBefore, notAfter, 0))
|
||||
if err != nil {
|
||||
return errors.WithStack(err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package flags
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
@@ -19,3 +21,21 @@ var Force = cli.BoolFlag{
|
||||
Name: "f,force",
|
||||
Usage: "Force the overwrite of files without asking.",
|
||||
}
|
||||
|
||||
// ParseTimeOrDuration is a helper that returns the time or the current time
|
||||
// with an extra duration. It's used in flags like --not-before, --not-after.
|
||||
func ParseTimeOrDuration(s string) (time.Time, bool) {
|
||||
if s == "" {
|
||||
return time.Time{}, true
|
||||
}
|
||||
|
||||
var t time.Time
|
||||
if err := t.UnmarshalText([]byte(s)); err != nil {
|
||||
d, err := time.ParseDuration(s)
|
||||
if err != nil {
|
||||
return time.Time{}, false
|
||||
}
|
||||
t = time.Now().Add(d)
|
||||
}
|
||||
return t, true
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user