-
Notifications
You must be signed in to change notification settings - Fork 56
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
Refactor request authentication to remove duplication #3302
Conversation
tx, err := srv.db.Begin(c.Request.Context()) | ||
if err != nil { | ||
return access.Authenticated{}, err | ||
} | ||
defer logError(tx.Rollback, "failed to rollback middleware transaction") | ||
|
||
authned, err := requireAccessKey(c, tx, srv) | ||
if err != nil { | ||
if !route.authenticationOptional && err != nil { | ||
return authned, 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.
We could be suppressing unexpected errors here in the case of an "authentication optional" route
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, true. We were doing that before this change as well with authned, _ := requireAccessKey(...)
. I think either the error is an authentication failed error (which we do want to ignore), or it's some kind of operational error like the database not being available. In the case of an operational error I would expect the next operation to fail in the same way, so we end up not missing anything.
// https://github.com/infrahq/infra/blob/main/docs/dev/organization-request-flow.md | ||
|
||
// TODO: use an explicit setting for this, don't overload EnableSignup | ||
if org == nil && !srv.options.EnableSignup { // is single tenant |
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've been generally hesitant to go down the "single-tenant" path versus everything being multi-tenant but with sign-up disabled. Is there anything stopping us from assuming the default org in any case the org in nil? Seems correct to me, then we can move to request failure once existing sessions for single-tenant deployments have expired.
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.
Oh, looks like this was existing logic, ignore this comment for now.
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 would be fine with serving the default org in all cases. We discussed the options a bunch before and this was what we ended up agreeing on.
} | ||
} | ||
|
||
if authned.User != nil { |
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 check to see if authentication was provided or is it actually looking for the user?
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.
It is checking to see if authentication was provided, but in handleInfraDestinationHeader
which is called below here we also need to user to perform the authorization. So I guess it's both?
b697a95
to
ee92dec
Compare
f20cdf1
to
28d353f
Compare
28d353f
to
c63f4c4
Compare
that uses RequestContext instead of gin.Context. This allows us to start migrating access functions to the new strongly typed context without having to do them all at once.
These two functions were performing very similar operations, one for routes requiring authentication, and one for optional authentication. This PR combines them to remove the duplication. It also extracts a routeSettings struct so that the settings can be passed around without needing the generic parameters on route. Also renames a couple of the settings to be more obvious.
c63f4c4
to
8420901
Compare
Summary
Branched from #3299
This PR resolves a TODO from #3299, and combines the two very similar functions we were using as request "middleware".
Best viewed by individual commit.
To accomplish this I had to make a few changes:
gin.Context
that contains aRequestContext
. We already had aCan
method that was only used as part of the implementation ofRequireInfraRole
. I repurposed that unused function as the newAuthorize
function which accepts aRequestContext
directly.route
, but it contained generic parameters for the route handler. I extracted arouteSettings
struct that we can pass around to functions fromwrapRoute
, that removes the need to parameterize things that don't call the handler.Finally this allowed me to combine two very similar functions (
authenticateRequest
, andvalidateRequestOrganization
) into a single function and move theRequestContext
towrapRoute
, so that we don't have to set it fromgin.Context
. This brings us one step closer to having our routes accept theRequestContext
directly (instead of acceptinggin.Context
).