-
Notifications
You must be signed in to change notification settings - Fork 454
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
[RFC] Implement ACME RFC 8555, challenge retries #181
Conversation
Hi all,
Will also write unit tests after cementing desired steps :) |
Codecov Report
@@ Coverage Diff @@
## master #181 +/- ##
==========================================
- Coverage 73.85% 73.56% -0.29%
==========================================
Files 75 69 -6
Lines 8501 8041 -460
==========================================
- Hits 6278 5915 -363
+ Misses 1899 1814 -85
+ Partials 324 312 -12
Continue to review full report at Codecov.
|
If the client calls retry, rate limit permitting, the server should reset its retry state, and clear the invalid challenge state, and then begin the challenge process anew.
I'd say a 5 minute exponential backoff retry mechanism is probably fine. After the timeout, the state becomes "invalid", yes. |
Committed an approach to automated retries, would appreciate any feedback. |
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.
Looking good so far. Few questions (:
acme/authority.go
Outdated
if err != nil { | ||
return nil, Wrap(err, "error attempting challenge validation") | ||
|
||
for i:=0; i < 10; i++ { |
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.
Do we want to loop here until the challenge's status lands on a terminal value or while the retry.Active field is not true rather than counting to 10? The challenge's respective validate funcs already count the number of retries and then declare the challenge invalid after the attempts has expired. Not using a fixed 10 would also allow for certain types of challenges to define longer retry periods. However it means a faulty challenge implementation would hang this loop forever. Another option would be to pull the logic out of the challenge validation funcs and just centralize it here, updating the status to invalid only after 10 tries. What were your thoughts while implementing this?
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.
My initial thought was similar - I was trying to avoid a scenario where multiple calls to ValidateChallenge() would loop forever. I think "while retry.active" should get the job done, especially with the lock on that loop. The for range(10) was implemented just in case the retry object state was being modified by any other objects, but I'm seeing that is highly unlikely.
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.
Implemented with while retry.Active
acme/challenge.go
Outdated
upd.Status = StatusInvalid | ||
upd.Retry.Backoffs *= 2 | ||
upd.Retry.Active = false | ||
upd.Retry.Called = 0 |
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.
What's the point of zeroing this?
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.
"Called" to me represented how many times the challenge validation retry was performed on a specific client call. Resetting to 0 was designed to signal that the current process retrying validation had terminated, and the next retry process should start. Called is also used in computing the retry-after header (alongside the backoffs count).
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.
Implemented an updated version of this in the latest commit - let me know of any thoughts
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.
This is looking really good. What's up with all the additional/unrelated removals, though? Would rebasing the branch help ensure we're not reverting anything with a merge?
return hc, nil | ||
} | ||
if hc.getStatus() == StatusInvalid { | ||
// TODO: Resolve segfault on upd.save |
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.
Is this still happening?
@@ -615,3 +678,20 @@ func getChallenge(db nosql.DB, id string) (challenge, error) { | |||
} | |||
return ch, nil | |||
} | |||
|
|||
// iterateRetry iterates a challenge's retry and error objects upon a failed validation attempt | |||
func (bc *baseChallenge) iterateRetry(db nosql.DB, error *Error) 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.
Do you mean increment retry? (:
I'm picking this up #242 |
Summary
(Fixes #168)
Implements section 8.2 in the ACME protocol spec. Describes how client and server retries should be handled during a challenge validation.
Specifically, automates server validation retries, throttles retry attempts, includes error information about the result of each attempted validation, and sets appropriate retry-after headers on the challenge resource response.