ldap_debug_test.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. package api
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "net/http"
  6. "net/http/httptest"
  7. "testing"
  8. "github.com/grafana/grafana/pkg/bus"
  9. "github.com/grafana/grafana/pkg/models"
  10. "github.com/grafana/grafana/pkg/services/ldap"
  11. "github.com/grafana/grafana/pkg/services/multildap"
  12. "github.com/grafana/grafana/pkg/setting"
  13. "github.com/stretchr/testify/assert"
  14. "github.com/stretchr/testify/require"
  15. )
  16. type LDAPMock struct {
  17. Results []*models.ExternalUserInfo
  18. }
  19. var userSearchResult *models.ExternalUserInfo
  20. var userSearchConfig ldap.ServerConfig
  21. var pingResult []*multildap.ServerStatus
  22. var pingError error
  23. func (m *LDAPMock) Ping() ([]*multildap.ServerStatus, error) {
  24. return pingResult, pingError
  25. }
  26. func (m *LDAPMock) Login(query *models.LoginUserQuery) (*models.ExternalUserInfo, error) {
  27. return &models.ExternalUserInfo{}, nil
  28. }
  29. func (m *LDAPMock) Users(logins []string) ([]*models.ExternalUserInfo, error) {
  30. s := []*models.ExternalUserInfo{}
  31. return s, nil
  32. }
  33. func (m *LDAPMock) User(login string) (*models.ExternalUserInfo, ldap.ServerConfig, error) {
  34. return userSearchResult, userSearchConfig, nil
  35. }
  36. //***
  37. // GetUserFromLDAP tests
  38. //***
  39. func getUserFromLDAPContext(t *testing.T, requestURL string) *scenarioContext {
  40. t.Helper()
  41. sc := setupScenarioContext(requestURL)
  42. ldap := setting.LDAPEnabled
  43. setting.LDAPEnabled = true
  44. defer func() { setting.LDAPEnabled = ldap }()
  45. hs := &HTTPServer{Cfg: setting.NewCfg()}
  46. sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
  47. sc.context = c
  48. return hs.GetUserFromLDAP(c)
  49. })
  50. sc.m.Get("/api/admin/ldap/:username", sc.defaultHandler)
  51. sc.resp = httptest.NewRecorder()
  52. req, _ := http.NewRequest(http.MethodGet, requestURL, nil)
  53. sc.req = req
  54. sc.exec()
  55. return sc
  56. }
  57. func TestGetUserFromLDAPApiEndpoint_UserNotFound(t *testing.T) {
  58. getLDAPConfig = func() (*ldap.Config, error) {
  59. return &ldap.Config{}, nil
  60. }
  61. newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP {
  62. return &LDAPMock{}
  63. }
  64. userSearchResult = nil
  65. sc := getUserFromLDAPContext(t, "/api/admin/ldap/user-that-does-not-exist")
  66. require.Equal(t, sc.resp.Code, http.StatusNotFound)
  67. responseString, err := getBody(sc.resp)
  68. assert.Nil(t, err)
  69. assert.Equal(t, "{\"message\":\"No user was found on the LDAP server(s)\"}", responseString)
  70. }
  71. func TestGetUserFromLDAPApiEndpoint_OrgNotfound(t *testing.T) {
  72. isAdmin := true
  73. userSearchResult = &models.ExternalUserInfo{
  74. Name: "John Doe",
  75. Email: "john.doe@example.com",
  76. Login: "johndoe",
  77. OrgRoles: map[int64]models.RoleType{1: models.ROLE_ADMIN, 2: models.ROLE_VIEWER},
  78. IsGrafanaAdmin: &isAdmin,
  79. }
  80. userSearchConfig = ldap.ServerConfig{
  81. Attr: ldap.AttributeMap{
  82. Name: "ldap-name",
  83. Surname: "ldap-surname",
  84. Email: "ldap-email",
  85. Username: "ldap-username",
  86. },
  87. Groups: []*ldap.GroupToOrgRole{
  88. {
  89. GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org",
  90. OrgID: 1,
  91. OrgRole: models.ROLE_ADMIN,
  92. },
  93. {
  94. GroupDN: "cn=admins,ou=groups,dc=grafana2,dc=org",
  95. OrgID: 2,
  96. OrgRole: models.ROLE_VIEWER,
  97. },
  98. },
  99. }
  100. mockOrgSearchResult := []*models.OrgDTO{
  101. {Id: 1, Name: "Main Org."},
  102. }
  103. bus.AddHandler("test", func(query *models.SearchOrgsQuery) error {
  104. query.Result = mockOrgSearchResult
  105. return nil
  106. })
  107. getLDAPConfig = func() (*ldap.Config, error) {
  108. return &ldap.Config{}, nil
  109. }
  110. newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP {
  111. return &LDAPMock{}
  112. }
  113. sc := getUserFromLDAPContext(t, "/api/admin/ldap/johndoe")
  114. require.Equal(t, sc.resp.Code, http.StatusBadRequest)
  115. jsonResponse, err := getJSONbody(sc.resp)
  116. assert.Nil(t, err)
  117. expected := `
  118. {
  119. "error": "Unable to find organization with ID '2'",
  120. "message": "Organization not found - Please verify your LDAP configuration"
  121. }
  122. `
  123. var expectedJSON interface{}
  124. _ = json.Unmarshal([]byte(expected), &expectedJSON)
  125. assert.Equal(t, expectedJSON, jsonResponse)
  126. }
  127. func TestGetUserFromLDAPApiEndpoint(t *testing.T) {
  128. isAdmin := true
  129. userSearchResult = &models.ExternalUserInfo{
  130. Name: "John Doe",
  131. Email: "john.doe@example.com",
  132. Login: "johndoe",
  133. OrgRoles: map[int64]models.RoleType{1: models.ROLE_ADMIN},
  134. IsGrafanaAdmin: &isAdmin,
  135. }
  136. userSearchConfig = ldap.ServerConfig{
  137. Attr: ldap.AttributeMap{
  138. Name: "ldap-name",
  139. Surname: "ldap-surname",
  140. Email: "ldap-email",
  141. Username: "ldap-username",
  142. },
  143. Groups: []*ldap.GroupToOrgRole{
  144. {
  145. GroupDN: "cn=admins,ou=groups,dc=grafana,dc=org",
  146. OrgID: 1,
  147. OrgRole: models.ROLE_ADMIN,
  148. },
  149. },
  150. }
  151. mockOrgSearchResult := []*models.OrgDTO{
  152. {Id: 1, Name: "Main Org."},
  153. }
  154. bus.AddHandler("test", func(query *models.SearchOrgsQuery) error {
  155. query.Result = mockOrgSearchResult
  156. return nil
  157. })
  158. getLDAPConfig = func() (*ldap.Config, error) {
  159. return &ldap.Config{}, nil
  160. }
  161. newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP {
  162. return &LDAPMock{}
  163. }
  164. sc := getUserFromLDAPContext(t, "/api/admin/ldap/johndoe")
  165. require.Equal(t, sc.resp.Code, http.StatusOK)
  166. jsonResponse, err := getJSONbody(sc.resp)
  167. assert.Nil(t, err)
  168. expected := `
  169. {
  170. "name": {
  171. "cfgAttrValue": "ldap-name", "ldapValue": "John"
  172. },
  173. "surname": {
  174. "cfgAttrValue": "ldap-surname", "ldapValue": "Doe"
  175. },
  176. "email": {
  177. "cfgAttrValue": "ldap-email", "ldapValue": "john.doe@example.com"
  178. },
  179. "login": {
  180. "cfgAttrValue": "ldap-username", "ldapValue": "johndoe"
  181. },
  182. "isGrafanaAdmin": true,
  183. "isDisabled": false,
  184. "roles": [
  185. { "orgId": 1, "orgRole": "Admin", "orgName": "Main Org.", "groupDN": "cn=admins,ou=groups,dc=grafana,dc=org" }
  186. ],
  187. "teams": null
  188. }
  189. `
  190. var expectedJSON interface{}
  191. _ = json.Unmarshal([]byte(expected), &expectedJSON)
  192. assert.Equal(t, expectedJSON, jsonResponse)
  193. }
  194. //***
  195. // GetLDAPStatus tests
  196. //***
  197. func getLDAPStatusContext(t *testing.T) *scenarioContext {
  198. t.Helper()
  199. requestURL := "/api/admin/ldap/status"
  200. sc := setupScenarioContext(requestURL)
  201. ldap := setting.LDAPEnabled
  202. setting.LDAPEnabled = true
  203. defer func() { setting.LDAPEnabled = ldap }()
  204. hs := &HTTPServer{Cfg: setting.NewCfg()}
  205. sc.defaultHandler = Wrap(func(c *models.ReqContext) Response {
  206. sc.context = c
  207. return hs.GetLDAPStatus(c)
  208. })
  209. sc.m.Get("/api/admin/ldap/status", sc.defaultHandler)
  210. sc.resp = httptest.NewRecorder()
  211. req, _ := http.NewRequest(http.MethodGet, requestURL, nil)
  212. sc.req = req
  213. sc.exec()
  214. return sc
  215. }
  216. func TestGetLDAPStatusApiEndpoint(t *testing.T) {
  217. pingResult = []*multildap.ServerStatus{
  218. {Host: "10.0.0.3", Port: 361, Available: true, Error: nil},
  219. {Host: "10.0.0.3", Port: 362, Available: true, Error: nil},
  220. {Host: "10.0.0.5", Port: 361, Available: false, Error: errors.New("something is awfully wrong")},
  221. }
  222. getLDAPConfig = func() (*ldap.Config, error) {
  223. return &ldap.Config{}, nil
  224. }
  225. newLDAP = func(_ []*ldap.ServerConfig) multildap.IMultiLDAP {
  226. return &LDAPMock{}
  227. }
  228. sc := getLDAPStatusContext(t)
  229. require.Equal(t, http.StatusOK, sc.resp.Code)
  230. jsonResponse, err := getJSONbody(sc.resp)
  231. assert.Nil(t, err)
  232. expected := `
  233. [
  234. { "host": "10.0.0.3", "port": 361, "available": true, "error": "" },
  235. { "host": "10.0.0.3", "port": 362, "available": true, "error": "" },
  236. { "host": "10.0.0.5", "port": 361, "available": false, "error": "something is awfully wrong" }
  237. ]
  238. `
  239. var expectedJSON interface{}
  240. _ = json.Unmarshal([]byte(expected), &expectedJSON)
  241. assert.Equal(t, expectedJSON, jsonResponse)
  242. }