1
0
mirror of https://github.com/oauth2-proxy/oauth2-proxy.git synced 2025-06-21 00:29:44 +02:00

feat: support for multiple github orgs (#3072)

* fix for github teams

* Update github.go

* added errorhandling

* Update github.md

* refactored GitHub provider

refactored hasOrg, hasOrgAndTeams and hasTeam into hasAccess to stay within function limit

* reverted Refactoring

* refactored github.go

- joined hasOrgAndTeamAccess into checkRestrictions

* refactored github.go

- reduced number of returns of function checkRestrictions to 4

* updated GitHub provider to accept legacy team ids

* GoFmt and golangci-lint

Formatted with GoFmt and followed recommendations of GoLint

* added Tests

added Tests for checkRestrictions.

* refactored in maintainer feedback

* Removed code, documentation and tests for legacy ids

* add changelog and update docs

---------

Signed-off-by: Jan Larwig <jan@larwig.com>
Co-authored-by: Jan Larwig <jan@larwig.com>
This commit is contained in:
Daniel Mersch
2025-05-29 18:11:07 +02:00
committed by GitHub
parent fb7e33519a
commit 7731437af4
4 changed files with 201 additions and 26 deletions

View File

@ -39,6 +39,7 @@ func testGitHubBackend(payloads map[string][]string) *httptest.Server {
"/repos/oauth2-proxy/oauth2-proxy/collaborators/mbland": {""},
"/user": {""},
"/user/emails": {""},
"/user/teams": {"page=1&per_page=100", "page=2&per_page=100", "page=3&per_page=100"},
"/user/orgs": {"page=1&per_page=100", "page=2&per_page=100", "page=3&per_page=100"},
// GitHub Enterprise Server API
"/api/v3": {""},
@ -168,6 +169,134 @@ func TestGitHubProvider_getEmailWithOrg(t *testing.T) {
assert.Equal(t, "michael.bland@gsa.gov", session.Email)
}
func TestGitHubProvider_checkRestrictionsOrg(t *testing.T) {
b := testGitHubBackend(map[string][]string{
"/user/emails": {`[ {"email": "john.doe@example", "verified": true, "primary": true} ]`},
"/user/orgs": {
`[ { "login": "test-org-1" } ]`,
`[ { "login": "test-org-2" } ]`,
`[ ]`,
},
"/user/teams": {
`[ { "name":"test-team-1", "slug":"test-team-1", "organization": { "login": "test-org-1" } } ]`,
`[ { "name":"test-team-2", "slug":"test-team-2", "organization": { "login": "test-org-2" } } ]`,
`[ ]`,
},
})
defer b.Close()
// This test should succeed, because of the valid organization.
bURL, _ := url.Parse(b.URL)
p := testGitHubProvider(bURL.Host,
options.GitHubOptions{
Org: "test-org-1",
},
)
var err error
session := CreateAuthorizedSession()
err = p.getOrgAndTeam(context.Background(), session)
assert.NoError(t, err)
err = p.checkRestrictions(context.Background(), session)
assert.NoError(t, err)
// This part should fail, because user is not part of the organization
p = testGitHubProvider(bURL.Host,
options.GitHubOptions{
Org: "test-org-1-fail",
},
)
err = p.checkRestrictions(context.Background(), session)
assert.Error(t, err)
}
func TestGitHubProvider_checkRestrictionsOrgTeam(t *testing.T) {
b := testGitHubBackend(map[string][]string{
"/user/emails": {`[ {"email": "john.doe@example", "verified": true, "primary": true} ]`},
"/user/orgs": {
`[ { "login": "test-org-1" } ]`,
`[ { "login": "test-org-2" } ]`,
`[ ]`,
},
"/user/teams": {
`[ { "name":"test-team-1", "slug":"test-team-1", "organization": { "login": "test-org-1" } } ]`,
`[ { "name":"test-team-2", "slug":"test-team-2", "organization": { "login": "test-org-2" } } ]`,
`[ ]`,
},
})
defer b.Close()
// This test should succeed, because of the valid Org and Team combination.
bURL, _ := url.Parse(b.URL)
p := testGitHubProvider(bURL.Host,
options.GitHubOptions{
Org: "test-org-1",
Team: "test-team-1",
},
)
var err error
session := CreateAuthorizedSession()
err = p.getOrgAndTeam(context.Background(), session)
assert.NoError(t, err)
err = p.checkRestrictions(context.Background(), session)
assert.NoError(t, err)
// This part should fail, because user is not part of the organization and the team
p = testGitHubProvider(bURL.Host,
options.GitHubOptions{
Org: "test-org-1-fail",
Team: "test-team-1-fail",
},
)
err = p.checkRestrictions(context.Background(), session)
assert.Error(t, err)
}
func TestGitHubProvider_checkRestrictionsTeam(t *testing.T) {
b := testGitHubBackend(map[string][]string{
"/user/emails": {`[ {"email": "john.doe@example", "verified": true, "primary": true} ]`},
"/user/orgs": {
`[ { "login": "test-org-1" } ]`,
`[ { "login": "test-org-2" } ]`,
`[ ]`,
},
"/user/teams": {
`[ { "name":"test-team-1", "slug":"test-team-1", "organization": { "login": "test-org-1" } } ]`,
`[ { "name":"test-team-2", "slug":"test-team-2", "organization": { "login": "test-org-2" } } ]`,
`[ ]`,
},
})
defer b.Close()
// This test should succeed, because of the valid org:slug combination.
bURL, _ := url.Parse(b.URL)
p := testGitHubProvider(bURL.Host,
options.GitHubOptions{
Team: "test-org-1:test-team-1, test-org-2:test-team-2-fail",
},
)
var err error
session := CreateAuthorizedSession()
err = p.getOrgAndTeam(context.Background(), session)
assert.NoError(t, err)
err = p.checkRestrictions(context.Background(), session)
assert.NoError(t, err)
// This part should fail, because user is not part of the organization:team combination
p = testGitHubProvider(bURL.Host,
options.GitHubOptions{
Team: "test-org-1-fail:test-team-1-fail, test-org-2-fail:test-team-2-fail",
},
)
err = p.checkRestrictions(context.Background(), session)
assert.Error(t, err)
}
func TestGitHubProvider_getEmailWithWriteAccessToPublicRepo(t *testing.T) {
b := testGitHubBackend(map[string][]string{
"/repo/oauth2-proxy/oauth2-proxy": {`{"permissions": {"pull": true, "push": true}, "private": false}`},