-
Notifications
You must be signed in to change notification settings - Fork 656
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
Add clock skew correction on the client #2668
Conversation
Fixes #2321 This change adjusts signing request to account for the difference in time between client and server Caka clock skew). This PR makes values that we know are caused by clock skew retryable by default, and adds logic to classify probable clock skew errors as retryable. This value is set on the client so subsequent requests can read the adjusted time.
5b26861
to
4e03615
Compare
aws/middleware/middleware.go
Outdated
type clockSkew struct{} | ||
|
||
// SetAttemptSkewContext sets the clock skew value on the context | ||
func SetAttemptSkewContext(ctx context.Context, v time.Duration) context.Context { |
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 do this in internal/context
so it can't be picked up on by callers.
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.
Moved to a new internalmiddleware
package
aws/middleware/middleware.go
Outdated
|
||
// AddTimeOffsetDeserializeMiddleware sets the clock skew on the client if it's present on the context | ||
// at the end of the request | ||
type AddTimeOffsetDeserializeMiddleware struct { |
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.
You can actually have one structure implement both phases FYI.
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.
Nice, moved this to be just a single structure
aws/retry/middleware.go
Outdated
return err | ||
} | ||
skew := awsmiddle.GetAttemptSkewContext(ctx) | ||
if !(skew > 4*time.Minute) { |
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.
nit, skew <= 4*time.Minute
?
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.
also probably worth const
ing
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.
const
ed
aws/retry/retryable_error.go
Outdated
// (difference between server time and client time). | ||
// This is returned when there's certain confidence that adjusting the client time | ||
// could allow a retry to succeed | ||
type ProbClockSkewError struct{ Err 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.
Definitely should be unexported, there's no reason to do otherwise.
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.
Changed
} | ||
|
||
private void generateClockSkewInsertMiddleware(GoWriter writer) { | ||
Symbol stackSymbol = SymbolUtils.createPointableSymbolBuilder("Stack", SmithyGoDependency.SMITHY_MIDDLEWARE) |
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.
FYI we are trying to eradicate calls to these garbage createXBuilder
things with extreme prejudice:
SmithyGoDependency.SMITHY_MIDDLEWARE.struct("Stack")
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.
Changed
@@ -3,7 +3,7 @@ package smithy | |||
import ( | |||
"context" | |||
"fmt" | |||
|
|||
"github.com/aws/aws-sdk-go-v2/aws/middleware" |
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.
Are you running gofmt
? It should be putting that blank line here.
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.
Yes. Discussed offline and this separation is actually done via goimports
. Will send a separate PR to add it to our formatter target
aws/middleware/middleware.go
Outdated
) { | ||
v := GetAttemptSkewContext(ctx) | ||
if v != 0 { | ||
m.Offset.Store(v.Nanoseconds()) |
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.
Question: should we be storing skew every time, or just if not previously set?
Definitely something we can change later but don't remember if we discussed it.
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.
Discussed this offline. We could only store this once when we see it, on the assumption that you only need to collect skew once instead of on every call. This could free some of the calls to lock
that atomic
is likely doing behind the scenes.
However, the downside is that if we ever get a bad Date
back from the server, it can end up poisoning the time for all subsequent requests.
Decided it's probably safer to update it every time
aws/middleware/middleware_test.go
Outdated
@@ -187,3 +191,239 @@ func TestAttemptClockSkewHandler(t *testing.T) { | |||
}) | |||
} | |||
} | |||
|
|||
type HTTPClient interface { |
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.
nit, idiomatically all of these test definitions are always unexported.
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.
changed
var possibleSkewCodes = map[string]struct{}{ | ||
"InvalidSignatureException": {}, | ||
"SignatureDoesNotMatch": {}, | ||
"AuthFailure": {}, |
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.
Are RequestTimeTooSkewed
, RequestInTheFuture
and RequestExpired
(added below) omitted here intentionally?
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.
Yes, they were added to the list of definitely retry always
. Moved to a separate list as discussed on comment below
aws/retry/standard.go
Outdated
@@ -51,8 +51,11 @@ var DefaultRetryableHTTPStatusCodes = map[int]struct{}{ | |||
// DefaultRetryableErrorCodes provides the set of API error codes that should | |||
// be retried. | |||
var DefaultRetryableErrorCodes = map[string]struct{}{ | |||
"RequestExpired": {}, |
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.
Thinking we should probably just use these to do the probSkew
wrapping instead of adding them to the default policy.
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 see your point. Was debating between keeping all skew stuff together. Moved them and expanded the probSkew logic to include this
aws/middleware/middleware.go
Outdated
// AddTimeOffsetBuildMiddleware sets a value representing clock skew on the request context. | ||
// This can be read by other operations (such as signing) to correct the date value they send | ||
// on the request | ||
type AddTimeOffsetBuildMiddleware struct { |
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 almost certainly want this under the blanket internal/
as well. In general, we just don't export things unless we know we absolutely need to.
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.
Moved to internal
aws/retry/middleware.go
Outdated
if !errors.As(err, &v) { | ||
return err | ||
} | ||
_, ok := possibleSkewCodes[v.ErrorCode()] |
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.
nit, can shorten
if _, ok := possibleSkewCodes[v.ErrorCode()]; !ok {
return err
}
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.
Shortened
ClientMemberResolver resolver = ClientMemberResolver.builder() | ||
.resolver(TIME_OFFSET_RESOLVER) | ||
.build(); | ||
MiddlewareRegistrar initializeMiddleware = MiddlewareRegistrar.builder() |
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 tend to also static
decl these but this is fine.
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.
OK, moved all definitions to be static
Fixes #2321
This change adjusts signing request to account for the difference in time between client and server (aka clock skew). This PR makes values that we know are caused by clock skew retryable by default, and adds logic to classify probable clock skew errors as retryable.
This value is set on the client so subsequent requests can read the adjusted time.
For changes to files under the
/codegen/aws-models
folder, and manual edits to autogenerated code (e.g./service/s3/api.go
) please create an Issue instead of a PR for those type of changes.Verified by
If the PR addresses an existing bug or feature, please reference it here.
#2321
To help speed up the process and reduce the time to merge please ensure that
Allow edits by maintainers
is checked before submitting your PR. This will allow the project maintainers to make minor adjustments or improvements to the submitted PR, allow us to reduce the roundtrip time for merging your request.