| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | package api | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	"net/http" | 
					
						
							|  |  |  | 	"net/http/httptest" | 
					
						
							|  |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | //***
 | 
					
						
							|  |  |  | // GetUserFromLDAP tests
 | 
					
						
							|  |  |  | //***
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | func getUserFromLDAPContext(t *testing.T, requestURL string) *scenarioContext { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := setupScenarioContext(requestURL) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | 	ldap := setting.LDAPEnabled | 
					
						
							|  |  |  | 	setting.LDAPEnabled = true | 
					
						
							|  |  |  | 	defer func() { setting.LDAPEnabled = ldap }() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 01:34:44 +08:00
										 |  |  | 	hs := &HTTPServer{Cfg: setting.NewCfg()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.defaultHandler = Wrap(func(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGetUserFromLDAPApiEndpoint_UserNotFound(t *testing.T) { | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGetUserFromLDAPApiEndpoint_OrgNotfound(t *testing.T) { | 
					
						
							|  |  |  | 	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."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(query *models.SearchOrgsQuery) error { | 
					
						
							|  |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		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 := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"error": "Unable to find organization with ID '2'", | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | 		"message": "An oganization 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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGetUserFromLDAPApiEndpoint(t *testing.T) { | 
					
						
							|  |  |  | 	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."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(query *models.SearchOrgsQuery) error { | 
					
						
							|  |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-08 18:48:47 +08:00
										 |  |  | func TestGetUserFromLDAPApiEndpoint_WithTeamHandler(t *testing.T) { | 
					
						
							|  |  |  | 	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."}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(query *models.SearchOrgsQuery) error { | 
					
						
							|  |  |  | 		query.Result = mockOrgSearchResult | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(cmd *models.GetTeamsForLDAPGroupCommand) error { | 
					
						
							|  |  |  | 		cmd.Result = []models.TeamOrgGroupDTO{} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-09-04 22:29:14 +08:00
										 |  |  | //***
 | 
					
						
							|  |  |  | // GetLDAPStatus tests
 | 
					
						
							|  |  |  | //***
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getLDAPStatusContext(t *testing.T) *scenarioContext { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	requestURL := "/api/admin/ldap/status" | 
					
						
							|  |  |  | 	sc := setupScenarioContext(requestURL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldap := setting.LDAPEnabled | 
					
						
							|  |  |  | 	setting.LDAPEnabled = true | 
					
						
							|  |  |  | 	defer func() { setting.LDAPEnabled = ldap }() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hs := &HTTPServer{Cfg: setting.NewCfg()} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.defaultHandler = Wrap(func(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 		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 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestGetLDAPStatusApiEndpoint(t *testing.T) { | 
					
						
							|  |  |  | 	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")}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		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()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //***
 | 
					
						
							|  |  |  | // PostSyncUserWithLDAP tests
 | 
					
						
							|  |  |  | //***
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func postSyncUserWithLDAPContext(t *testing.T, requestURL string) *scenarioContext { | 
					
						
							|  |  |  | 	t.Helper() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := setupScenarioContext(requestURL) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ldap := setting.LDAPEnabled | 
					
						
							|  |  |  | 	setting.LDAPEnabled = true | 
					
						
							|  |  |  | 	defer func() { setting.LDAPEnabled = ldap }() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +08:00
										 |  |  | 	hs := &HTTPServer{Cfg: setting.NewCfg(), AuthTokenService: auth.NewFakeUserAuthTokenService()} | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sc.defaultHandler = Wrap(func(c *models.ReqContext) Response { | 
					
						
							|  |  |  | 		sc.context = c | 
					
						
							|  |  |  | 		return hs.PostSyncUserWithLDAP(c) | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.m.Post("/api/admin/ldap/sync/:id", sc.defaultHandler) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc.resp = httptest.NewRecorder() | 
					
						
							|  |  |  | 	req, _ := http.NewRequest(http.MethodPost, requestURL, nil) | 
					
						
							|  |  |  | 	sc.req = req | 
					
						
							|  |  |  | 	sc.exec() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return sc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_Success(t *testing.T) { | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchResult = &models.ExternalUserInfo{ | 
					
						
							|  |  |  | 		Login: "ldap-daniel", | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(cmd *models.UpsertUserCommand) error { | 
					
						
							|  |  |  | 		require.Equal(t, "ldap-daniel", cmd.ExternalUser.Login) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetUserByIdQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.Id, int64(34)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetAuthInfoQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.UserId, int64(34)) | 
					
						
							|  |  |  | 		require.Equal(t, q.AuthModule, models.AuthModuleLDAP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	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) { | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetUserByIdQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.Id, int64(34)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return models.ErrUserNotFound | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Equal(t, http.StatusNotFound, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		"message": "User not found" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.JSONEq(t, expected, sc.resp.Body.String()) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestPostSyncUserWithLDAPAPIEndpoint_WhenGrafanaAdmin(t *testing.T) { | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +08:00
										 |  |  | 	userSearchError = multildap.ErrDidNotFindUser | 
					
						
							| 
									
										
										
										
											2019-09-13 23:26:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	admin := setting.AdminUser | 
					
						
							|  |  |  | 	setting.AdminUser = "ldap-daniel" | 
					
						
							|  |  |  | 	defer func() { setting.AdminUser = admin }() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetUserByIdQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.Id, int64(34)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetAuthInfoQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.UserId, int64(34)) | 
					
						
							|  |  |  | 		require.Equal(t, q.AuthModule, models.AuthModuleLDAP) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	assert.Equal(t, http.StatusBadRequest, sc.resp.Code) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	expected := ` | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2019-11-07 21:31:44 +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) { | 
					
						
							|  |  |  | 	getLDAPConfig = func() (*ldap.Config, error) { | 
					
						
							|  |  |  | 		return &ldap.Config{}, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP { | 
					
						
							|  |  |  | 		return &LDAPMock{} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	userSearchResult = nil | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(cmd *models.UpsertUserCommand) error { | 
					
						
							|  |  |  | 		require.Equal(t, "ldap-daniel", cmd.ExternalUser.Login) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetUserByIdQuery) error { | 
					
						
							|  |  |  | 		require.Equal(t, q.Id, int64(34)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		q.Result = &models.User{Login: "ldap-daniel", Id: 34} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(q *models.GetExternalUserInfoByLoginQuery) error { | 
					
						
							|  |  |  | 		assert.Equal(t, "ldap-daniel", q.LoginOrEmail) | 
					
						
							|  |  |  | 		q.Result = &models.ExternalUserInfo{IsDisabled: true, UserId: 34} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bus.AddHandler("test", func(cmd *models.DisableUserCommand) error { | 
					
						
							|  |  |  | 		assert.Equal(t, 34, cmd.UserId) | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := postSyncUserWithLDAPContext(t, "/api/admin/ldap/sync/34") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } |