Skip to content
This repository has been archived by the owner on Jan 24, 2019. It is now read-only.

new option: -github-user #318

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ The GitHub auth provider supports two additional parameters to restrict authenti

-github-org="": restrict logins to members of this organisation
-github-team="": restrict logins to members of any of these teams, separated by a comma
-github-user="": restrict logins to any of these users, separated by a comma

If you are using GitHub enterprise, make sure you set the following to the appropriate url:

Expand Down Expand Up @@ -178,6 +179,7 @@ Usage of oauth2_proxy:
-email-domain=: authenticate emails with the specified domain (may be given multiple times). Use * to authenticate any email
-github-org="": restrict logins to members of this organisation
-github-team="": restrict logins to members of this team
-github-user="": restrict logins to these users
-google-admin-email="": the google admin to impersonate for api calls
-google-group=: restrict logins to members of this google group (may be given multiple times).
-google-service-account-json="": the path to the service account json credentials
Expand Down
1 change: 1 addition & 0 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func main() {
flagSet.String("azure-tenant", "common", "go to a tenant-specific or common (tenant-independent) endpoint.")
flagSet.String("github-org", "", "restrict logins to members of this organisation")
flagSet.String("github-team", "", "restrict logins to members of this team")
flagSet.String("github-user", "", "restrict logins to these users")
flagSet.Var(&googleGroups, "google-group", "restrict logins to members of this google group (may be given multiple times).")
flagSet.String("google-admin-email", "", "the google admin to impersonate for api calls")
flagSet.String("google-service-account-json", "", "the path to the service account json credentials")
Expand Down
3 changes: 2 additions & 1 deletion options.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type Options struct {
EmailDomains []string `flag:"email-domain" cfg:"email_domains"`
GitHubOrg string `flag:"github-org" cfg:"github_org"`
GitHubTeam string `flag:"github-team" cfg:"github_team"`
GitHubUser string `flag:"github-user" cfg:"github_user"`
GoogleGroups []string `flag:"google-group" cfg:"google_group"`
GoogleAdminEmail string `flag:"google-admin-email" cfg:"google_admin_email"`
GoogleServiceAccountJSON string `flag:"google-service-account-json" cfg:"google_service_account_json"`
Expand Down Expand Up @@ -228,7 +229,7 @@ func parseProviderInfo(o *Options, msgs []string) []string {
case *providers.AzureProvider:
p.Configure(o.AzureTenant)
case *providers.GitHubProvider:
p.SetOrgTeam(o.GitHubOrg, o.GitHubTeam)
p.SetOrgTeamUser(o.GitHubOrg, o.GitHubTeam, o.GitHubUser)
case *providers.GoogleProvider:
if o.GoogleServiceAccountJSON != "" {
file, err := os.Open(o.GoogleServiceAccountJSON)
Expand Down
60 changes: 59 additions & 1 deletion providers/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type GitHubProvider struct {
*ProviderData
Org string
Team string
User string
}

func NewGitHubProvider(p *ProviderData) *GitHubProvider {
Expand Down Expand Up @@ -46,9 +47,10 @@ func NewGitHubProvider(p *ProviderData) *GitHubProvider {
}
return &GitHubProvider{ProviderData: p}
}
func (p *GitHubProvider) SetOrgTeam(org, team string) {
func (p *GitHubProvider) SetOrgTeamUser(org, team, user string) {
p.Org = org
p.Team = team
p.User = user
if org != "" || team != "" {
p.Scope += " read:org"
}
Expand Down Expand Up @@ -178,6 +180,58 @@ func (p *GitHubProvider) hasOrgAndTeam(accessToken string) (bool, error) {
return false, nil
}

func (p *GitHubProvider) hasUser(accessToken string) (bool, error) {
// https://developer.github.com/v3/users/#get-the-authenticated-user

var user struct {
Login string `json:"login"`
}

params := url.Values{
"access_token": {accessToken},
"limit": {"100"},
}

endpoint := &url.URL{
Scheme: p.ValidateURL.Scheme,
Host: p.ValidateURL.Host,
Path: path.Join(p.ValidateURL.Path, "/user"),
RawQuery: params.Encode(),
}
req, _ := http.NewRequest("GET", endpoint.String(), nil)
req.Header.Set("Accept", "application/vnd.github.v3+json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return false, err
}

body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
return false, err
}
if resp.StatusCode != 200 {
return false, fmt.Errorf(
"got %d from %q %s", resp.StatusCode, stripToken(endpoint.String()), body)
}

if err := json.Unmarshal(body, &user); err != nil {
return false, err
}

presentUsers := []string{user.Login}
us := strings.Split(p.User, ",")
for _, u := range us {
if u == user.Login {
log.Printf("Found Github User: %q", user.Login)
return true, nil
}
}

log.Printf("Missing User:%q in %v", p.User, presentUsers)
return false, nil
}

func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {

var emails []struct {
Expand All @@ -196,6 +250,10 @@ func (p *GitHubProvider) GetEmailAddress(s *SessionState) (string, error) {
return "", err
}
}
} else if p.User != "" {
if ok, err := p.hasUser(s.AccessToken); err != nil || !ok {
return "", err
}
}

params := url.Values{
Expand Down