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

Integrate tenant authentication #92

Merged
merged 4 commits into from Jan 19, 2023
Merged

Integrate tenant authentication #92

merged 4 commits into from Jan 19, 2023

Conversation

pdeziel
Copy link
Contributor

@pdeziel pdeziel commented Jan 18, 2023

Scope of changes

This integrates the quarterdeck authentication and authorization middlewares implemented in a previous PR into the tenant server.

There is a fair bit of related changes made, mostly to get the tests to a working state again after the integration.

Fixes SC-10289

Type of change

  • new feature
  • bug fix
  • documentation
  • testing
  • technical debt
  • other (describe)

Acceptance criteria

Tests should still run with the configured middleware and I believe the docker compose should at least start all the services.

Author checklist

  • I have manually tested the change and/or added automation in the form of unit tests or integration tests
  • I have updated the dependencies list
  • I have recompiled and included new protocol buffers to reflect changes I made
  • I have added new test fixtures as needed to support added tests
  • Check this box if a reviewer can merge this pull request after approval (leave it unchecked if you want to do it yourself)
  • I have moved the associated Shortcut story to "Ready for Review"

Reviewer(s) checklist

  • Permissions - do we need to open an additional story to clean those up / figure out which ones we need?
  • Middleware is added as described in SC-10289

@shortcut-integration
Copy link

srv.Shutdown()
<-stopped
logger.ResetLogger()
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird deadlock that only occurred when this test errored out. Previously the <-stopped was declared in the cleanup earlier in the method which caused a hang because the channel was never written to if the test errored.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

// API Keys management
ReadAPIKey = "read:key"
WriteAPIKey = "write:key"
DeleteAPIKey = "delete:key"
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First crack at the permissions but do we want to have create and update as well?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I'll post the permissions that quarterdeck has right now into the engineering channel; then we can figure out what is needed here.

Do you think Quarterdeck needs an API endpoint (possibly unauthenticated) that lists its permissions?

Copy link
Contributor

@bbengfort bbengfort left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! The endpoints are very well organized now and I think it will make it more maintainable in the future. Potentially we should move the setupRoutes function to a routes.go file as an easier reference in the future, but that's not something we have to do now.

Also thank you for going above and beyond and dealing with the tests as well - I really appreciate your hard work on this story!

Comment on lines +861 to +866
// SetCSRFProtect is a helper function to set CSRF cookies on the client. This is not
// possible in a browser because of the HttpOnly flag. This method should only be used
// for testing purposes and an error is returned if the URL is not localhost. For live
// clients - the server should set these cookies. If protect is false, then the cookies
// are removed from the client by setting the cookies to an empty slice.
func (c *APIv1) SetCSRFProtect(protect bool) error {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this implementation from the Admin API or is it different?

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's from the BFF API

Comment on lines +854 to +859
// SetCredentials is a helper function for external users to override credentials at
// runtime by directly passing in the token, which is useful for testing.
// TODO: Pass in a credentials interface instead of the token string.
func (c *APIv1) SetCredentials(token string) {
c.creds = token
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good stub!

// API Keys management
ReadAPIKey = "read:key"
WriteAPIKey = "write:key"
DeleteAPIKey = "delete:key"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I'll post the permissions that quarterdeck has right now into the engineering channel; then we can figure out what is needed here.

Do you think Quarterdeck needs an API endpoint (possibly unauthenticated) that lists its permissions?

srv.Shutdown()
<-stopped
logger.ResetLogger()
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

Comment on lines 189 to 191
// In maintenance mode authentication is disabled
var authenticator gin.HandlerFunc
if !s.conf.Maintenance {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Were you getting a test error with authenticate in maintenance mode? I was hoping that we wouldn't have to worry about that here because the Available middleware comes before the Authenticate middleware, so it should stop processing before any authenticated endpoint. I'm worried that this logic might create a nil middleware accidentally in the future.

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 think the problem was that the maintenance mode test wasn't starting an authtest server so the code here was returning an error. However if we're worried about the nil middleware I can just update the test instead of having the check here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, I'd prefer that we update the test - thank you!

{
apikeys.GET("", mw.Authorize(ReadAPIKey), s.APIKeyList)
apikeys.POST("", csrf, mw.Authorize(WriteAPIKey), s.APIKeyCreate)
apikeys.GET("/:apiKeyID", mw.Authorize(ReadAPIKey), s.APIKeyDetail)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The linter seems to be complaining about missing methods TopicCreate and APIKeyCreate would you mind either creating stub handlers that return http.StatusNotImplemented to appease the linter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I think we just ran into some merge conflicts from Danielle's PR.

Comment on lines 338 to 351
// Set the maximum age of login protection cookies.
const doubleCookiesMaxAge = time.Minute * 10

// ProtectLogin prepares the front-end for login by setting the double cookie
// tokens for CSRF protection.
func (s *Server) ProtectLogin(c *gin.Context) {
expiresAt := time.Now().Add(doubleCookiesMaxAge)
if err := mw.SetDoubleCookieToken(c, s.conf.Auth.CookieDomain, expiresAt); err != nil {
log.Error().Err(err).Msg("could not set cookies")
c.JSON(http.StatusInternalServerError, api.ErrorResponse("could not set cookies"))
return
}
c.JSON(http.StatusOK, &api.Reply{Success: true})
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for porting this over! Would you mind adding this to an auth.go file? Tenant will have login and register routes in the future so that file will be the starting place for it.

@pdeziel pdeziel merged commit e92f513 into main Jan 19, 2023
@pdeziel pdeziel deleted the sc-10289 branch January 19, 2023 15:50
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.

None yet

2 participants