feat: Add allowlist of GitHub teams for OAuth (#2849)

Fixes #2848.
This commit is contained in:
Kyle Carberry
2022-07-08 21:37:18 -05:00
committed by GitHub
parent c801da45f3
commit dff6e97f83
5 changed files with 134 additions and 3 deletions

View File

@ -17,15 +17,23 @@ import (
"github.com/coder/coder/codersdk"
)
// GithubOAuth2Team represents a team scoped to an organization.
type GithubOAuth2Team struct {
Organization string
Slug string
}
// GithubOAuth2Provider exposes required functions for the Github authentication flow.
type GithubOAuth2Config struct {
httpmw.OAuth2Config
AuthenticatedUser func(ctx context.Context, client *http.Client) (*github.User, error)
ListEmails func(ctx context.Context, client *http.Client) ([]*github.UserEmail, error)
ListOrganizationMemberships func(ctx context.Context, client *http.Client) ([]*github.Membership, error)
ListTeams func(ctx context.Context, client *http.Client, org string) ([]*github.Team, error)
AllowSignups bool
AllowOrganizations []string
AllowTeams []GithubOAuth2Team
}
func (api *API) userAuthMethods(rw http.ResponseWriter, _ *http.Request) {
@ -64,6 +72,41 @@ func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) {
return
}
// The default if no teams are specified is to allow all.
if len(api.GithubOAuth2Config.AllowTeams) > 0 {
teams, err := api.GithubOAuth2Config.ListTeams(r.Context(), oauthClient, *selectedMembership.Organization.Login)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{
Message: "Failed to fetch teams from GitHub.",
Detail: err.Error(),
})
return
}
var allowedTeam *github.Team
for _, team := range teams {
for _, allowTeam := range api.GithubOAuth2Config.AllowTeams {
if allowTeam.Organization != *selectedMembership.Organization.Login {
// This needs to continue because multiple organizations
// could exist in the allow/team listings.
continue
}
if allowTeam.Slug != *team.Slug {
continue
}
allowedTeam = team
break
}
}
if allowedTeam == nil {
httpapi.Write(rw, http.StatusUnauthorized, httpapi.Response{
Message: fmt.Sprintf("You aren't a member of an authorized team in the %s Github organization!", *selectedMembership.Organization.Login),
})
return
}
}
emails, err := api.GithubOAuth2Config.ListEmails(r.Context(), oauthClient)
if err != nil {
httpapi.Write(rw, http.StatusInternalServerError, httpapi.Response{