Skip to content
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

Merged
merged 3 commits into from
Sep 27, 2022

Conversation

dnephin
Copy link
Contributor

@dnephin dnephin commented Sep 23, 2022

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:

  1. we need a function that is able to authorize an API request without a gin.Context that contains a RequestContext. We already had a Can method that was only used as part of the implementation of RequireInfraRole. I repurposed that unused function as the new Authorize function which accepts a RequestContext directly.
  2. we needed a way to pass route settings to other functions. We had route, but it contained generic parameters for the route handler. I extracted a routeSettings struct that we can pass around to functions from wrapRoute, that removes the need to parameterize things that don't call the handler.

Finally this allowed me to combine two very similar functions (authenticateRequest, and validateRequestOrganization) into a single function and move the RequestContext to wrapRoute, so that we don't have to set it from gin.Context. This brings us one step closer to having our routes accept the RequestContext directly (instead of accepting gin.Context).

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
Copy link
Collaborator

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

Copy link
Contributor Author

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
Copy link
Collaborator

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.

Copy link
Collaborator

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.

Copy link
Contributor Author

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 {
Copy link
Collaborator

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?

Copy link
Contributor Author

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?

@dnephin dnephin force-pushed the dnephin/api-separate-transaction-for-middleware branch from b697a95 to ee92dec Compare September 27, 2022 15:20
@dnephin dnephin force-pushed the dnephin/authorize-using-request-context branch 2 times, most recently from f20cdf1 to 28d353f Compare September 27, 2022 15:47
Base automatically changed from dnephin/api-separate-transaction-for-middleware to main September 27, 2022 15:50
@dnephin dnephin force-pushed the dnephin/authorize-using-request-context branch from 28d353f to c63f4c4 Compare September 27, 2022 16:44
internal/access/access.go Outdated Show resolved Hide resolved
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.
@dnephin dnephin force-pushed the dnephin/authorize-using-request-context branch from c63f4c4 to 8420901 Compare September 27, 2022 17:59
@dnephin dnephin merged commit c96ddb4 into main Sep 27, 2022
@dnephin dnephin deleted the dnephin/authorize-using-request-context branch September 27, 2022 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants