mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	Map OIDC groups to Orgs/Teams (#21441)
Fixes #19555 Test-Instructions: https://github.com/go-gitea/gitea/pull/21441#issuecomment-1419438000 This PR implements the mapping of user groups provided by OIDC providers to orgs teams in Gitea. The main part is a refactoring of the existing LDAP code to make it usable from different providers. Refactorings: - Moved the router auth code from module to service because of import cycles - Changed some model methods to take a `Context` parameter - Moved the mapping code from LDAP to a common location I've tested it with Keycloak but other providers should work too. The JSON mapping format is the same as for LDAP.  --------- Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
This commit is contained in:
		| @@ -112,23 +112,14 @@ func getLDAPServerPort() string { | ||||
| 	return port | ||||
| } | ||||
|  | ||||
| func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupMapParams ...string) { | ||||
| 	groupTeamMapRemoval := "off" | ||||
| 	groupTeamMap := "" | ||||
| 	if len(groupMapParams) == 2 { | ||||
| 		groupTeamMapRemoval = groupMapParams[0] | ||||
| 		groupTeamMap = groupMapParams[1] | ||||
| 	} | ||||
|  | ||||
| func buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval string) map[string]string { | ||||
| 	// Modify user filter to test group filter explicitly | ||||
| 	userFilter := "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))" | ||||
| 	if groupFilter != "" { | ||||
| 		userFilter = "(&(objectClass=inetOrgPerson)(uid=%s))" | ||||
| 	} | ||||
|  | ||||
| 	session := loginUser(t, "user1") | ||||
| 	csrf := GetCSRF(t, session, "/admin/auths/new") | ||||
| 	req := NewRequestWithValues(t, "POST", "/admin/auths/new", map[string]string{ | ||||
| 	return map[string]string{ | ||||
| 		"_csrf":                    csrf, | ||||
| 		"type":                     "2", | ||||
| 		"name":                     "ldap", | ||||
| @@ -154,7 +145,19 @@ func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupM | ||||
| 		"group_team_map":           groupTeamMap, | ||||
| 		"group_team_map_removal":   groupTeamMapRemoval, | ||||
| 		"user_uid":                 "DN", | ||||
| 	}) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func addAuthSourceLDAP(t *testing.T, sshKeyAttribute, groupFilter string, groupMapParams ...string) { | ||||
| 	groupTeamMapRemoval := "off" | ||||
| 	groupTeamMap := "" | ||||
| 	if len(groupMapParams) == 2 { | ||||
| 		groupTeamMapRemoval = groupMapParams[0] | ||||
| 		groupTeamMap = groupMapParams[1] | ||||
| 	} | ||||
| 	session := loginUser(t, "user1") | ||||
| 	csrf := GetCSRF(t, session, "/admin/auths/new") | ||||
| 	req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, sshKeyAttribute, groupFilter, groupTeamMap, groupTeamMapRemoval)) | ||||
| 	session.MakeRequest(t, req, http.StatusSeeOther) | ||||
| } | ||||
|  | ||||
| @@ -202,26 +205,7 @@ func TestLDAPAuthChange(t *testing.T) { | ||||
| 	binddn, _ := doc.Find(`input[name="bind_dn"]`).Attr("value") | ||||
| 	assert.Equal(t, binddn, "uid=gitea,ou=service,dc=planetexpress,dc=com") | ||||
|  | ||||
| 	req = NewRequestWithValues(t, "POST", href, map[string]string{ | ||||
| 		"_csrf":                    csrf, | ||||
| 		"type":                     "2", | ||||
| 		"name":                     "ldap", | ||||
| 		"host":                     getLDAPServerHost(), | ||||
| 		"port":                     "389", | ||||
| 		"bind_dn":                  "uid=gitea,ou=service,dc=planetexpress,dc=com", | ||||
| 		"bind_password":            "password", | ||||
| 		"user_base":                "ou=people,dc=planetexpress,dc=com", | ||||
| 		"filter":                   "(&(objectClass=inetOrgPerson)(memberOf=cn=git,ou=people,dc=planetexpress,dc=com)(uid=%s))", | ||||
| 		"admin_filter":             "(memberOf=cn=admin_staff,ou=people,dc=planetexpress,dc=com)", | ||||
| 		"restricted_filter":        "(uid=leela)", | ||||
| 		"attribute_username":       "uid", | ||||
| 		"attribute_name":           "givenName", | ||||
| 		"attribute_surname":        "sn", | ||||
| 		"attribute_mail":           "mail", | ||||
| 		"attribute_ssh_public_key": "", | ||||
| 		"is_sync_enabled":          "on", | ||||
| 		"is_active":                "on", | ||||
| 	}) | ||||
| 	req = NewRequestWithValues(t, "POST", href, buildAuthSourceLDAPPayload(csrf, "", "", "", "off")) | ||||
| 	session.MakeRequest(t, req, http.StatusSeeOther) | ||||
|  | ||||
| 	req = NewRequest(t, "GET", href) | ||||
| @@ -395,7 +379,7 @@ func TestLDAPGroupTeamSyncAddMember(t *testing.T) { | ||||
| 	} | ||||
| 	defer tests.PrepareTestEnv(t)() | ||||
| 	addAuthSourceLDAP(t, "", "", "on", `{"cn=ship_crew,ou=people,dc=planetexpress,dc=com":{"org26": ["team11"]},"cn=admin_staff,ou=people,dc=planetexpress,dc=com": {"non-existent": ["non-existent"]}}`) | ||||
| 	org, err := organization.GetOrgByName("org26") | ||||
| 	org, err := organization.GetOrgByName(db.DefaultContext, "org26") | ||||
| 	assert.NoError(t, err) | ||||
| 	team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11") | ||||
| 	assert.NoError(t, err) | ||||
| @@ -440,7 +424,7 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) { | ||||
| 	} | ||||
| 	defer tests.PrepareTestEnv(t)() | ||||
| 	addAuthSourceLDAP(t, "", "", "on", `{"cn=dispatch,ou=people,dc=planetexpress,dc=com": {"org26": ["team11"]}}`) | ||||
| 	org, err := organization.GetOrgByName("org26") | ||||
| 	org, err := organization.GetOrgByName(db.DefaultContext, "org26") | ||||
| 	assert.NoError(t, err) | ||||
| 	team, err := organization.GetTeam(db.DefaultContext, org.ID, "team11") | ||||
| 	assert.NoError(t, err) | ||||
| @@ -468,24 +452,15 @@ func TestLDAPGroupTeamSyncRemoveMember(t *testing.T) { | ||||
| 	assert.False(t, isMember, "User membership should have been removed from team") | ||||
| } | ||||
|  | ||||
| // Login should work even if Team Group Map contains a broken JSON | ||||
| func TestBrokenLDAPMapUserSignin(t *testing.T) { | ||||
| func TestLDAPPreventInvalidGroupTeamMap(t *testing.T) { | ||||
| 	if skipLDAPTests() { | ||||
| 		t.Skip() | ||||
| 		return | ||||
| 	} | ||||
| 	defer tests.PrepareTestEnv(t)() | ||||
| 	addAuthSourceLDAP(t, "", "", "on", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`) | ||||
|  | ||||
| 	u := gitLDAPUsers[0] | ||||
|  | ||||
| 	session := loginUserWithPassword(t, u.UserName, u.Password) | ||||
| 	req := NewRequest(t, "GET", "/user/settings") | ||||
| 	resp := session.MakeRequest(t, req, http.StatusOK) | ||||
|  | ||||
| 	htmlDoc := NewHTMLParser(t, resp.Body) | ||||
|  | ||||
| 	assert.Equal(t, u.UserName, htmlDoc.GetInputValueByName("name")) | ||||
| 	assert.Equal(t, u.FullName, htmlDoc.GetInputValueByName("full_name")) | ||||
| 	assert.Equal(t, u.Email, htmlDoc.Find(`label[for="email"]`).Siblings().First().Text()) | ||||
| 	session := loginUser(t, "user1") | ||||
| 	csrf := GetCSRF(t, session, "/admin/auths/new") | ||||
| 	req := NewRequestWithValues(t, "POST", "/admin/auths/new", buildAuthSourceLDAPPayload(csrf, "", "", `{"NOT_A_VALID_JSON"["MISSING_DOUBLE_POINT"]}`, "off")) | ||||
| 	session.MakeRequest(t, req, http.StatusOK) // StatusOK = failed, StatusSeeOther = ok | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user