| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2021-06-21 13:51:33 +08:00
										 |  |  | 	"context" | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 	"path/filepath" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/accesscontrol" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-15 21:43:20 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/api/response" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/api/routing" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/bus" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/models" | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/auth" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/services/ldap" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/services/multildap" | 
					
						
							|  |  |  | 	"github.com/grafana/grafana/pkg/setting" | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/assert" | 
					
						
							|  |  |  | 	"github.com/stretchr/testify/require" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type LDAPMock struct { | 
					
						
							|  |  |  | 	Results []*models.ExternalUserInfo | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var userSearchResult *models.ExternalUserInfo | 
					
						
							|  |  |  | var userSearchConfig ldap.ServerConfig | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | var userSearchError error | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | var pingResult []*multildap.ServerStatus | 
					
						
							|  |  |  | var pingError error | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m *LDAPMock) Ping() ([]*multildap.ServerStatus, error) { | 
					
						
							|  |  |  | 	return pingResult, pingError | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func (m *LDAPMock) Login(query *models.LoginUserQuery) (*models.ExternalUserInfo, error) { | 
					
						
							|  |  |  | 	return &models.ExternalUserInfo{}, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m *LDAPMock) Users(logins []string) ([]*models.ExternalUserInfo, error) { | 
					
						
							|  |  |  | 	s := []*models.ExternalUserInfo{} | 
					
						
							|  |  |  | 	return s, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (m *LDAPMock) User(login string) (*models.ExternalUserInfo, ldap.ServerConfig, error) { | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	return userSearchResult, userSearchConfig, userSearchError | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | // GetUserFromLDAP tests
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | func getUserFromLDAPContext(t *testing.T, requestURL string) *scenarioContext { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	sc := setupScenarioContext(t, requestURL) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	origLDAP := setting.LDAPEnabled | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 	setting.LDAPEnabled = true | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	t.Cleanup(func() { setting.LDAPEnabled = origLDAP }) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	hs := &HTTPServer{Cfg: setting.NewCfg()} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-15 21:43:20 +08:00
										 |  |  | 	sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		sc.context = c | 
					
						
							|  |  |  | 		return hs.GetUserFromLDAP(c) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.m.Get("/api/admin/ldap/:username", sc.defaultHandler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.resp = httptest.NewRecorder() | 
					
						
							|  |  |  | 	req, _ := http.NewRequest(http.MethodGet, requestURL, nil) | 
					
						
							|  |  |  | 	sc.req = req | 
					
						
							|  |  |  | 	sc.exec() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | func TestGetUserFromLDAPAPIEndpoint_UserNotFound(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 	getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchResult = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := getUserFromLDAPContext(t, "/api/admin/ldap/user-that-does-not-exist") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	require.Equal(t, sc.resp.Code, http.StatusNotFound) | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 	assert.JSONEq(t, "{\"message\":\"No user was found in the LDAP server(s) with that username\"}", sc.resp.Body.String()) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | func TestGetUserFromLDAPAPIEndpoint_OrgNotfound(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	isAdmin := true | 
					
						
							|  |  |  | 	userSearchResult = &models.ExternalUserInfo{ | 
					
						
							|  |  |  | 		Name:           "John Doe", | 
					
						
							|  |  |  | 		Email:          "john.doe@example.com", | 
					
						
							|  |  |  | 		Login:          "johndoe", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 		Groups:         []string{"cn=admins,ou=groups,dc=grafana,dc=org"}, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		OrgRoles:       map[int64]models.RoleType{1: models.ROLE_ADMIN, 2: models.ROLE_VIEWER}, | 
					
						
							|  |  |  | 		IsGrafanaAdmin: &isAdmin, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchConfig = ldap.ServerConfig{ | 
					
						
							|  |  |  | 		Attr: ldap.AttributeMap{ | 
					
						
							|  |  |  | 			Name:     "ldap-name", | 
					
						
							|  |  |  | 			Surname:  "ldap-surname", | 
					
						
							|  |  |  | 			Email:    "ldap-email", | 
					
						
							|  |  |  | 			Username: "ldap-username", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Groups: []*ldap.GroupToOrgRole{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 				OrgId:   1, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 				OrgRole: models.ROLE_ADMIN, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2019-11-01 22:42:22 +08:00
										 |  |  | 				GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 				OrgId:   2, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 				OrgRole: models.ROLE_VIEWER, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mockOrgSearchResult := []*models.OrgDTO{ | 
					
						
							|  |  |  | 		{Id: 1, Name: "Main Org."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 	bus.AddHandler("test", func(ctx context.Context, query *models.SearchOrgsQuery) error { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 	getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := getUserFromLDAPContext(t, "/api/admin/ldap/johndoe") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-01 22:42:22 +08:00
										 |  |  | 	require.Equal(t, http.StatusBadRequest, sc.resp.Code) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-11-05 20:07:06 +08:00
										 |  |  | 		"error": "unable to find organization with ID '2'", | 
					
						
							| 
									
										
										
										
											2020-06-01 23:11:25 +08:00
										 |  |  | 		"message": "An organization was not found - Please verify your LDAP configuration" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | func TestGetUserFromLDAPAPIEndpoint(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	isAdmin := true | 
					
						
							|  |  |  | 	userSearchResult = &models.ExternalUserInfo{ | 
					
						
							|  |  |  | 		Name:           "John Doe", | 
					
						
							|  |  |  | 		Email:          "john.doe@example.com", | 
					
						
							|  |  |  | 		Login:          "johndoe", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 		Groups:         []string{"cn=admins,ou=groups,dc=grafana,dc=org", "another-group-not-matched"}, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		OrgRoles:       map[int64]models.RoleType{1: models.ROLE_ADMIN}, | 
					
						
							|  |  |  | 		IsGrafanaAdmin: &isAdmin, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchConfig = ldap.ServerConfig{ | 
					
						
							|  |  |  | 		Attr: ldap.AttributeMap{ | 
					
						
							|  |  |  | 			Name:     "ldap-name", | 
					
						
							|  |  |  | 			Surname:  "ldap-surname", | 
					
						
							|  |  |  | 			Email:    "ldap-email", | 
					
						
							|  |  |  | 			Username: "ldap-username", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Groups: []*ldap.GroupToOrgRole{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 				OrgId:   1, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 				OrgRole: models.ROLE_ADMIN, | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2019-11-01 22:42:22 +08:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				GroupDN: "cn=admins2,ou=groups,dc=grafana,dc=org", | 
					
						
							|  |  |  | 				OrgId:   1, | 
					
						
							|  |  |  | 				OrgRole: models.ROLE_ADMIN, | 
					
						
							|  |  |  | 			}, | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mockOrgSearchResult := []*models.OrgDTO{ | 
					
						
							|  |  |  | 		{Id: 1, Name: "Main Org."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 	bus.AddHandler("test", func(ctx context.Context, query *models.SearchOrgsQuery) error { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 	getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := getUserFromLDAPContext(t, "/api/admin/ldap/johndoe") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 	assert.Equal(t, sc.resp.Code, http.StatusOK) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  "name": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-name", "ldapValue": "John" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"surname": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-surname", "ldapValue": "Doe" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"email": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-email", "ldapValue": "john.doe@example.com" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"login": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-username", "ldapValue": "johndoe" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"isGrafanaAdmin": true, | 
					
						
							|  |  |  | 			"isDisabled": false, | 
					
						
							|  |  |  | 			"roles": [ | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 				{ "orgId": 1, "orgRole": "Admin", "orgName": "Main Org.", "groupDN": "cn=admins,ou=groups,dc=grafana,dc=org" }, | 
					
						
							|  |  |  | 				{ "orgId": 0, "orgRole": "", "orgName": "", "groupDN": "another-group-not-matched" } | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 			], | 
					
						
							|  |  |  | 			"teams": null | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | func TestGetUserFromLDAPAPIEndpoint_WithTeamHandler(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 	isAdmin := true | 
					
						
							|  |  |  | 	userSearchResult = &models.ExternalUserInfo{ | 
					
						
							|  |  |  | 		Name:           "John Doe", | 
					
						
							|  |  |  | 		Email:          "john.doe@example.com", | 
					
						
							|  |  |  | 		Login:          "johndoe", | 
					
						
							| 
									
										
										
										
											2019-11-01 22:42:22 +08:00
										 |  |  | 		Groups:         []string{"cn=admins,ou=groups,dc=grafana,dc=org"}, | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 		OrgRoles:       map[int64]models.RoleType{1: models.ROLE_ADMIN}, | 
					
						
							|  |  |  | 		IsGrafanaAdmin: &isAdmin, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchConfig = ldap.ServerConfig{ | 
					
						
							|  |  |  | 		Attr: ldap.AttributeMap{ | 
					
						
							|  |  |  | 			Name:     "ldap-name", | 
					
						
							|  |  |  | 			Surname:  "ldap-surname", | 
					
						
							|  |  |  | 			Email:    "ldap-email", | 
					
						
							|  |  |  | 			Username: "ldap-username", | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		Groups: []*ldap.GroupToOrgRole{ | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org", | 
					
						
							| 
									
										
										
										
											2019-09-19 23:13:38 +08:00
										 |  |  | 				OrgId:   1, | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 				OrgRole: models.ROLE_ADMIN, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mockOrgSearchResult := []*models.OrgDTO{ | 
					
						
							|  |  |  | 		{Id: 1, Name: "Main Org."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 	bus.AddHandler("test", func(ctx context.Context, query *models.SearchOrgsQuery) error { | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 	bus.AddHandler("test", func(ctx context.Context, cmd *models.GetTeamsForLDAPGroupCommand) error { | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 		cmd.Result = []models.TeamOrgGroupDTO{} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 	getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := getUserFromLDAPContext(t, "/api/admin/ldap/johndoe") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	require.Equal(t, sc.resp.Code, http.StatusOK) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		  "name": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-name", "ldapValue": "John" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"surname": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-surname", "ldapValue": "Doe" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"email": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-email", "ldapValue": "john.doe@example.com" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"login": { | 
					
						
							|  |  |  | 				"cfgAttrValue": "ldap-username", "ldapValue": "johndoe" | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 			"isGrafanaAdmin": true, | 
					
						
							|  |  |  | 			"isDisabled": false, | 
					
						
							|  |  |  | 			"roles": [ | 
					
						
							|  |  |  | 				{ "orgId": 1, "orgRole": "Admin", "orgName": "Main Org.", "groupDN": "cn=admins,ou=groups,dc=grafana,dc=org" } | 
					
						
							|  |  |  | 			], | 
					
						
							|  |  |  | 			"teams": [] | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | // GetLDAPStatus tests
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | func getLDAPStatusContext(t *testing.T) *scenarioContext { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	requestURL := "/api/admin/ldap/status" | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	sc := setupScenarioContext(t, requestURL) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ldap := setting.LDAPEnabled | 
					
						
							|  |  |  | 	setting.LDAPEnabled = true | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	t.Cleanup(func() { setting.LDAPEnabled = ldap }) | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	hs := &HTTPServer{Cfg: setting.NewCfg()} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-15 21:43:20 +08:00
										 |  |  | 	sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 		sc.context = c | 
					
						
							|  |  |  | 		return hs.GetLDAPStatus(c) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.m.Get("/api/admin/ldap/status", sc.defaultHandler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.resp = httptest.NewRecorder() | 
					
						
							|  |  |  | 	req, _ := http.NewRequest(http.MethodGet, requestURL, nil) | 
					
						
							|  |  |  | 	sc.req = req | 
					
						
							|  |  |  | 	sc.exec() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | func TestGetLDAPStatusAPIEndpoint(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 	pingResult = []*multildap.ServerStatus{ | 
					
						
							|  |  |  | 		{Host: "10.0.0.3", Port: 361, Available: true, Error: nil}, | 
					
						
							|  |  |  | 		{Host: "10.0.0.3", Port: 362, Available: true, Error: nil}, | 
					
						
							|  |  |  | 		{Host: "10.0.0.5", Port: 361, Available: false, Error: errors.New("something is awfully wrong")}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 	getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := getLDAPStatusContext(t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	require.Equal(t, http.StatusOK, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	[ | 
					
						
							|  |  |  | 		{ "host": "10.0.0.3", "port": 361, "available": true, "error": "" }, | 
					
						
							|  |  |  | 		{ "host": "10.0.0.3", "port": 362, "available": true, "error": "" }, | 
					
						
							|  |  |  | 		{ "host": "10.0.0.5", "port": 361, "available": false, "error": "something is awfully wrong" } | 
					
						
							|  |  |  | 	] | 
					
						
							|  |  |  | 	` | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | // PostSyncUserWithLDAP tests
 | 
					
						
							| 
									
										
										
										
											2020-09-22 22:22:19 +08:00
										 |  |  | // ***
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | func postSyncUserWithLDAPContext(t *testing.T, requestURL string, preHook func(*testing.T, *scenarioContext)) *scenarioContext { | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	sc := setupScenarioContext(t, requestURL) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	ldap := setting.LDAPEnabled | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	t.Cleanup(func() { | 
					
						
							|  |  |  | 		setting.LDAPEnabled = ldap | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	setting.LDAPEnabled = true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	hs := &HTTPServer{ | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 		Cfg:              sc.cfg, | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		AuthTokenService: auth.NewFakeUserAuthTokenService(), | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-01-15 21:43:20 +08:00
										 |  |  | 	sc.defaultHandler = routing.Wrap(func(c *models.ReqContext) response.Response { | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 		sc.context = c | 
					
						
							|  |  |  | 		return hs.PostSyncUserWithLDAP(c) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.m.Post("/api/admin/ldap/sync/:id", sc.defaultHandler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.resp = httptest.NewRecorder() | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 	req, err := http.NewRequest(http.MethodPost, requestURL, nil) | 
					
						
							|  |  |  | 	require.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 	preHook(t, sc) | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	sc.req = req | 
					
						
							|  |  |  | 	sc.exec() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_Success(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34", func(t *testing.T, sc *scenarioContext) { | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 		getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return &ldap.Config{}, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 			return &LDAPMock{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		userSearchResult = &models.ExternalUserInfo{ | 
					
						
							|  |  |  | 			Login: "ldap-daniel", | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, cmd *models.UpsertUserCommand) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, "ldap-daniel", cmd.ExternalUser.Login) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetUserByIdQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.Id, int64(34)) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetAuthInfoQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.UserId, int64(34)) | 
					
						
							|  |  |  | 			require.Equal(t, q.AuthModule, models.AuthModuleLDAP) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Equal(t, http.StatusOK, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"message": "User synced successfully" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_WhenUserNotFound(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34", func(t *testing.T, sc *scenarioContext) { | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 		getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return &ldap.Config{}, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 			return &LDAPMock{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetUserByIdQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.Id, int64(34)) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return models.ErrUserNotFound | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Equal(t, http.StatusNotFound, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-11-05 20:07:06 +08:00
										 |  |  | 		"message": "user not found" | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_WhenGrafanaAdmin(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34", func(t *testing.T, sc *scenarioContext) { | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 		getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return &ldap.Config{}, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 			return &LDAPMock{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		userSearchError = multildap.ErrDidNotFindUser | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 		sc.cfg.AdminUser = "ldap-daniel" | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetUserByIdQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.Id, int64(34)) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetAuthInfoQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.UserId, int64(34)) | 
					
						
							|  |  |  | 			require.Equal(t, q.AuthModule, models.AuthModuleLDAP) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Equal(t, http.StatusBadRequest, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2020-11-05 18:57:20 +08:00
										 |  |  | 		"error": "did not find a user", | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 		"message": "Refusing to sync grafana super admin \"ldap-daniel\" - it would be disabled" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_WhenUserNotInLDAP(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2020-12-16 02:09:04 +08:00
										 |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34", func(t *testing.T, sc *scenarioContext) { | 
					
						
							| 
									
										
										
										
											2020-12-11 18:44:44 +08:00
										 |  |  | 		getLDAPConfig = func(*setting.Cfg) (*ldap.Config, error) { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return &ldap.Config{}, nil | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 			return &LDAPMock{} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 		userSearchResult = nil | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, cmd *models.UpsertUserCommand) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, "ldap-daniel", cmd.ExternalUser.Login) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetUserByIdQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			require.Equal(t, q.Id, int64(34)) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, q *models.GetExternalUserInfoByLoginQuery) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			assert.Equal(t, "ldap-daniel", q.LoginOrEmail) | 
					
						
							|  |  |  | 			q.Result = &models.ExternalUserInfo{IsDisabled: true, UserId: 34} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 		bus.AddHandler("test", func(ctx context.Context, cmd *models.DisableUserCommand) error { | 
					
						
							| 
									
										
										
										
											2020-11-13 16:52:38 +08:00
										 |  |  | 			assert.Equal(t, 34, cmd.UserId) | 
					
						
							|  |  |  | 			return nil | 
					
						
							|  |  |  | 		}) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +08:00
										 |  |  | 	assert.Equal(t, http.StatusBadRequest, sc.resp.Code) | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +08:00
										 |  |  | 		"message": "User not found in LDAP. Disabled the user without updating information" | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | // ***
 | 
					
						
							|  |  |  | // Access control tests for ldap endpoints
 | 
					
						
							|  |  |  | // ***
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestLDAP_AccessControl(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2021-06-14 23:36:48 +08:00
										 |  |  | 	tests := []accessControlTestCase{ | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/reload", | 
					
						
							|  |  |  | 			method:       http.MethodPost, | 
					
						
							|  |  |  | 			desc:         "ReloadLDAPCfg should return 200 for user with correct permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusOK, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: accesscontrol.ActionLDAPConfigReload}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/reload", | 
					
						
							|  |  |  | 			method:       http.MethodPost, | 
					
						
							|  |  |  | 			desc:         "ReloadLDAPCfg should return 403 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusForbidden, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: "wrong"}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/status", | 
					
						
							|  |  |  | 			method:       http.MethodGet, | 
					
						
							|  |  |  | 			desc:         "GetLDAPStatus should return 200 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusOK, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: accesscontrol.ActionLDAPStatusRead}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/status", | 
					
						
							|  |  |  | 			method:       http.MethodGet, | 
					
						
							|  |  |  | 			desc:         "GetLDAPStatus should return 200 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusForbidden, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: "wrong"}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/test", | 
					
						
							|  |  |  | 			method:       http.MethodGet, | 
					
						
							|  |  |  | 			desc:         "GetUserFromLDAP should return 200 for user with required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusOK, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: accesscontrol.ActionLDAPUsersRead}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			url:          "/api/admin/ldap/test", | 
					
						
							|  |  |  | 			method:       http.MethodGet, | 
					
						
							|  |  |  | 			desc:         "GetUserFromLDAP should return 403 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusForbidden, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: "wrong"}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-01-15 00:55:57 +08:00
										 |  |  | 			url:          "/api/admin/ldap/sync/1", | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 			method:       http.MethodPost, | 
					
						
							|  |  |  | 			desc:         "PostSyncUserWithLDAP should return 200 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusOK, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: accesscontrol.ActionLDAPUsersSync}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2022-01-15 00:55:57 +08:00
										 |  |  | 			url:          "/api/admin/ldap/sync/1", | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 			method:       http.MethodPost, | 
					
						
							|  |  |  | 			desc:         "PostSyncUserWithLDAP should return 200 for user without required permissions", | 
					
						
							|  |  |  | 			expectedCode: http.StatusForbidden, | 
					
						
							|  |  |  | 			permissions: []*accesscontrol.Permission{ | 
					
						
							|  |  |  | 				{Action: "wrong"}, | 
					
						
							|  |  |  | 			}, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, test := range tests { | 
					
						
							|  |  |  | 		t.Run(test.desc, func(t *testing.T) { | 
					
						
							|  |  |  | 			enabled := setting.LDAPEnabled | 
					
						
							|  |  |  | 			configFile := setting.LDAPConfigFile | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			t.Cleanup(func() { | 
					
						
							|  |  |  | 				setting.LDAPEnabled = enabled | 
					
						
							|  |  |  | 				setting.LDAPConfigFile = configFile | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			setting.LDAPEnabled = true | 
					
						
							|  |  |  | 			path, err := filepath.Abs("../../conf/ldap.toml") | 
					
						
							|  |  |  | 			assert.NoError(t, err) | 
					
						
							|  |  |  | 			setting.LDAPConfigFile = path | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			cfg := setting.NewCfg() | 
					
						
							|  |  |  | 			cfg.LDAPEnabled = true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-06-14 23:36:48 +08:00
										 |  |  | 			sc, _ := setupAccessControlScenarioContext(t, cfg, test.url, test.permissions) | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 			sc.resp = httptest.NewRecorder() | 
					
						
							|  |  |  | 			sc.req, err = http.NewRequest(test.method, test.url, nil) | 
					
						
							|  |  |  | 			assert.NoError(t, err) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Add minimal setup to pass handler
 | 
					
						
							|  |  |  | 			userSearchResult = &models.ExternalUserInfo{} | 
					
						
							|  |  |  | 			userSearchError = nil | 
					
						
							|  |  |  | 			newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 				return &LDAPMock{} | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 			bus.AddHandler("test", func(ctx context.Context, q *models.GetUserByIdQuery) error { | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 				q.Result = &models.User{} | 
					
						
							|  |  |  | 				return nil | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 			bus.AddHandler("test", func(ctx context.Context, q *models.GetAuthInfoQuery) error { | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 				return nil | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-12-28 23:08:07 +08:00
										 |  |  | 			bus.AddHandler("test", func(ctx context.Context, cmd *models.UpsertUserCommand) error { | 
					
						
							| 
									
										
										
										
											2021-06-11 21:58:18 +08:00
										 |  |  | 				return nil | 
					
						
							|  |  |  | 			}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			sc.exec() | 
					
						
							|  |  |  | 			assert.Equal(t, test.expectedCode, sc.resp.Code) | 
					
						
							|  |  |  | 		}) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |