-
Notifications
You must be signed in to change notification settings - Fork 252
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Needs-Renewal #496
Needs-Renewal #496
Conversation
Add support for Google CAS v1
needs-renewal is in the commands base now
Works standalone and with flag. Flag currently only check if the given time is > than the time left on the cert
Formatted right
removed comments
Codecov Report
@@ Coverage Diff @@
## megan/expiration #496 +/- ##
====================================================
- Coverage 63.29% 62.80% -0.49%
====================================================
Files 57 58 +1
Lines 6865 6980 +115
====================================================
+ Hits 4345 4384 +39
- Misses 2281 2357 +76
Partials 239 239
Continue to review full report at Codecov.
|
Was left behind on accident when testing
command/certificate/needsRenewal.go
Outdated
''' | ||
$ step certificate needs-renewal ./certificate.crt | ||
''' | ||
Check if certificate will expire within a given time |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add an example using a host and one using percentage (rather than duration)
command/certificate/needsRenewal.go
Outdated
Name: "needs-renewal", | ||
Action: cli.ActionFunc(needsRenewalAction), | ||
Usage: `Check if a certificate needs to be renewed`, | ||
UsageText: `**step certificate needs-renewal** <crt_file> or <host_name> [**--expires-in <duration>]`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't really do this <crt_file> or <host_name>
in other places. Which is not to say that we shouldn't be doing that.
But I think instead let's try <crt_file or host_name>
to make it clear that's it’s one argument.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@dopey are we naming this needs-renewal instead of verdancy?
command/certificate/needsRenewal.go
Outdated
`, | ||
Flags: []cli.Flag{ | ||
cli.StringFlag{ | ||
Name: "expires-in", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See the description of the not-before
flag in command/certificate/create.go
. Use the second part of that description that talks about duration for this flag as well. And additionally, I think we want the option to use a percent for this flag. So if I pass 70%
it should be parsed as a percent. Let's try to make that clear in the description.
So for example -- the beginning of not-before
description starts with <time|duration>
. This description could start with <percent|duration>
.
command/certificate/needsRenewal.go
Outdated
} else if isURL { | ||
peerCertificates, err := getPeerCertificates(addr, serverName, roots, false) | ||
if err != nil { | ||
os.Exit(255) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Returning 255
is technically correct. But we want a bit more than that. What we really want is to return an error type that has an attribute where we can store what the return code should be. And then we need to be able to parse that error type wherever this error is handled.
Think of yourself as the user of the program. You run it and all you see is exit code 255
. Well, a bunch of things probably cause that error code, so how do you figure out what went wrong. That's why we return error types. So there's some context for the user as to what went wrong.
Unfortunately, I'm not sure if we have an error type that you could use for this. We may have to write a new one. @maraino do we return non zero or 1 exit status from anywhere else? If not, should we create a new error type and then check for it in main.go?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We usually just return a wrapped error in these cases. Commands returning an error will print the error and exit with 1. And we can get the trace using STEPDEBUG=1
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We were going for this functionality I believe:
- return 0 if it's a certificate that needs to be renewed
- return 0 if the certificate is expired
- return 1 if it's a certificate that is valid (timewise) but doesn't need to be renewed
- return 255 for any error
Which is why we needed a different error type that would give 255 as an exit code
os.Exit(255) was there in the mean time to make sure the logic worked right until we knew if there was an error type built like that.
For cases where exit code 1 is needed should we continue to use os.Exit(1) or should we change it to some kind of error type which doesn't seem right if its not actually an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See #495 (comment), I think we should be consistent and keep 1
as exit code for an error.
In bash scripts is very easy to differentiate exit errors. Unless systemd is an issue we should keep 1
as an error and use 2
for example to say that the certificate is valid.
var totalValidity = cert.NotAfter.Sub(cert.NotBefore) | ||
var percentUsed = (1 - remainingValidity.Minutes()/totalValidity.Minutes()) * 100 | ||
|
||
if expiresIn != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we want --expires-in
to be either a percent or a duration (#495 (comment)). In order to do that we can try the following logic:
- Check if input string has a
%
sign as it's last index. If it does, then treat the input as a percent. The prefix of the input should be a number in a string. Golang has utilites to parse a int from a string. Parse it and then verify that it is between 0 and 100. If not we'll return an error. - The input does not have a
%
sign and therefore is a duration. Your code already looks correct for this case.
Question for @mmalone: How exactly is the % option supposed to work (it's not as easy to understand as the duration option)? E.g.
step certificate needs-renewal --expires-in 15m
Answers the question: Will this certificate be expired in 15 minutes?
step certificate needs-renewal --expires-in 75%
Do we want to know if the certificate will expire if 75% of it's lifetime passes? If it's already lived past 75% of it's lifetime. It's not very clear.
Also updated examples and usage text
command/certificate/needsRenewal.go
Outdated
} else { | ||
crtBytes, err := ioutil.ReadFile(crtFile) | ||
if err != nil { | ||
os.Exit(255) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should return an error here too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should return wrapped errors here and in all the exit conditions. For example this should be like:
crtBytes, err := ioutil.ReadFile(crtFile)
if err != nil {
return errors.Wrapf(err, "error reading %s", crtFile)
}
Or use the helper errs.FileError(err, crtFile)
command/certificate/needsRenewal.go
Outdated
} | ||
|
||
var ( | ||
block *pem.Block |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To define one variable use just var block *pem.Block
. It looks cleaner to me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make sure to return errors always instead of doing os.Exit(1)
They are now returning custom errors with exit code 255 while also giving a short print out of what went wrong
Changed the os.Exit(0) to return nil. os.Exit(255) is now replaced returning error types with the exit code of 255 Made edits to the examples and usage instructions
Referencing issue #398
step certificate needs-renewal subcommand using exit codes
And having optional flag --expires-in
Example:
step certificate needs-renewal foo.crt
step certificate needs-renewal foo.crt --expires-in 15m
step certificate needs-renewal https://smallstep.com
step certificate needs-renewal https://smallstep.com --expires-in 15m