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

@ -47,7 +47,7 @@ func StringArrayVarP(flagset *pflag.FlagSet, ptr *[]string, name string, shortha
def = strings.Split(val, ",")
}
}
flagset.StringArrayVarP(ptr, name, shorthand, def, usage)
flagset.StringArrayVarP(ptr, name, shorthand, def, fmtUsage(usage, env))
}
// Uint8VarP sets a uint8 flag on the given flag set.

View File

@ -82,6 +82,7 @@ func server() *cobra.Command {
oauth2GithubClientID string
oauth2GithubClientSecret string
oauth2GithubAllowedOrganizations []string
oauth2GithubAllowedTeams []string
oauth2GithubAllowSignups bool
telemetryEnable bool
telemetryURL string
@ -264,7 +265,7 @@ func server() *cobra.Command {
}
if oauth2GithubClientSecret != "" {
options.GithubOAuth2Config, err = configureGithubOAuth2(accessURLParsed, oauth2GithubClientID, oauth2GithubClientSecret, oauth2GithubAllowSignups, oauth2GithubAllowedOrganizations)
options.GithubOAuth2Config, err = configureGithubOAuth2(accessURLParsed, oauth2GithubClientID, oauth2GithubClientSecret, oauth2GithubAllowSignups, oauth2GithubAllowedOrganizations, oauth2GithubAllowedTeams)
if err != nil {
return xerrors.Errorf("configure github oauth2: %w", err)
}
@ -535,6 +536,8 @@ func server() *cobra.Command {
"Specifies a client secret to use for oauth2 with GitHub.")
cliflag.StringArrayVarP(root.Flags(), &oauth2GithubAllowedOrganizations, "oauth2-github-allowed-orgs", "", "CODER_OAUTH2_GITHUB_ALLOWED_ORGS", nil,
"Specifies organizations the user must be a member of to authenticate with GitHub.")
cliflag.StringArrayVarP(root.Flags(), &oauth2GithubAllowedTeams, "oauth2-github-allowed-teams", "", "CODER_OAUTH2_GITHUB_ALLOWED_TEAMS", nil,
"Specifies teams inside organizations the user must be a member of to authenticate with GitHub. Formatted as: <organization-name>/<team-slug>.")
cliflag.BoolVarP(root.Flags(), &oauth2GithubAllowSignups, "oauth2-github-allow-signups", "", "CODER_OAUTH2_GITHUB_ALLOW_SIGNUPS", false,
"Specifies whether new users can sign up with GitHub.")
cliflag.BoolVarP(root.Flags(), &telemetryEnable, "telemetry", "", "CODER_TELEMETRY", true, "Specifies whether telemetry is enabled or not. Coder collects anonymized usage data to help improve our product.")
@ -719,11 +722,22 @@ func configureTLS(listener net.Listener, tlsMinVersion, tlsClientAuth, tlsCertFi
return tls.NewListener(listener, tlsConfig), nil
}
func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, allowSignups bool, allowOrgs []string) (*coderd.GithubOAuth2Config, error) {
func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, allowSignups bool, allowOrgs []string, rawTeams []string) (*coderd.GithubOAuth2Config, error) {
redirectURL, err := accessURL.Parse("/api/v2/users/oauth2/github/callback")
if err != nil {
return nil, xerrors.Errorf("parse github oauth callback url: %w", err)
}
allowTeams := make([]coderd.GithubOAuth2Team, 0, len(rawTeams))
for _, rawTeam := range rawTeams {
parts := strings.SplitN(rawTeam, "/", 2)
if len(parts) != 2 {
return nil, xerrors.Errorf("github team allowlist is formatted incorrectly. got %s; wanted <organization>/<team>", rawTeam)
}
allowTeams = append(allowTeams, coderd.GithubOAuth2Team{
Organization: parts[0],
Slug: parts[1],
})
}
return &coderd.GithubOAuth2Config{
OAuth2Config: &oauth2.Config{
ClientID: clientID,
@ -738,6 +752,7 @@ func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, al
},
AllowSignups: allowSignups,
AllowOrganizations: allowOrgs,
AllowTeams: allowTeams,
AuthenticatedUser: func(ctx context.Context, client *http.Client) (*github.User, error) {
user, _, err := github.NewClient(client).Users.Get(ctx, "")
return user, err
@ -749,9 +764,18 @@ func configureGithubOAuth2(accessURL *url.URL, clientID, clientSecret string, al
ListOrganizationMemberships: func(ctx context.Context, client *http.Client) ([]*github.Membership, error) {
memberships, _, err := github.NewClient(client).Organizations.ListOrgMemberships(ctx, &github.ListOrgMembershipsOptions{
State: "active",
ListOptions: github.ListOptions{
PerPage: 100,
},
})
return memberships, err
},
ListTeams: func(ctx context.Context, client *http.Client, org string) ([]*github.Team, error) {
teams, _, err := github.NewClient(client).Teams.ListTeams(ctx, org, &github.ListOptions{
PerPage: 100,
})
return teams, err
},
}, nil
}