ldap_test.go 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. package login
  2. import (
  3. "testing"
  4. "github.com/grafana/grafana/pkg/bus"
  5. m "github.com/grafana/grafana/pkg/models"
  6. . "github.com/smartystreets/goconvey/convey"
  7. )
  8. func TestLdapAuther(t *testing.T) {
  9. Convey("When translating ldap user to grafana user", t, func() {
  10. Convey("Given no ldap group map match", func() {
  11. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  12. LdapGroups: []*LdapGroupToOrgRole{{}},
  13. })
  14. _, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{})
  15. So(err, ShouldEqual, ErrInvalidCredentials)
  16. })
  17. var user1 = &m.User{}
  18. ldapAutherScenario("Given wildcard group match", func(sc *scenarioContext) {
  19. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  20. LdapGroups: []*LdapGroupToOrgRole{
  21. {GroupDN: "*", OrgRole: "Admin"},
  22. },
  23. })
  24. sc.userQueryReturns(user1)
  25. result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{})
  26. So(err, ShouldBeNil)
  27. So(result, ShouldEqual, user1)
  28. })
  29. ldapAutherScenario("Given exact group match", func(sc *scenarioContext) {
  30. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  31. LdapGroups: []*LdapGroupToOrgRole{
  32. {GroupDN: "cn=users", OrgRole: "Admin"},
  33. },
  34. })
  35. sc.userQueryReturns(user1)
  36. result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{MemberOf: []string{"cn=users"}})
  37. So(err, ShouldBeNil)
  38. So(result, ShouldEqual, user1)
  39. })
  40. ldapAutherScenario("Given no existing grafana user", func(sc *scenarioContext) {
  41. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  42. LdapGroups: []*LdapGroupToOrgRole{
  43. {GroupDN: "cn=admin", OrgRole: "Admin"},
  44. {GroupDN: "cn=editor", OrgRole: "Editor"},
  45. {GroupDN: "*", OrgRole: "Viewer"},
  46. },
  47. })
  48. sc.userQueryReturns(nil)
  49. result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{
  50. Username: "torkelo",
  51. Email: "my@email.com",
  52. MemberOf: []string{"cn=editor"},
  53. })
  54. So(err, ShouldBeNil)
  55. Convey("Should create new user", func() {
  56. So(sc.createUserCmd.Login, ShouldEqual, "torkelo")
  57. So(sc.createUserCmd.Email, ShouldEqual, "my@email.com")
  58. })
  59. Convey("Should return new user", func() {
  60. So(result.Login, ShouldEqual, "torkelo")
  61. })
  62. })
  63. })
  64. Convey("When syncing ldap groups to grafana org roles", t, func() {
  65. ldapAutherScenario("given no current user orgs", func(sc *scenarioContext) {
  66. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  67. LdapGroups: []*LdapGroupToOrgRole{
  68. {GroupDN: "cn=users", OrgRole: "Admin"},
  69. },
  70. })
  71. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  72. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  73. MemberOf: []string{"cn=users"},
  74. })
  75. Convey("Should create new org user", func() {
  76. So(err, ShouldBeNil)
  77. So(sc.addOrgUserCmd, ShouldNotBeNil)
  78. So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  79. })
  80. })
  81. ldapAutherScenario("given different current org role", func(sc *scenarioContext) {
  82. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  83. LdapGroups: []*LdapGroupToOrgRole{
  84. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Admin"},
  85. },
  86. })
  87. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  88. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  89. MemberOf: []string{"cn=users"},
  90. })
  91. Convey("Should update org role", func() {
  92. So(err, ShouldBeNil)
  93. So(sc.updateOrgUserCmd, ShouldNotBeNil)
  94. So(sc.updateOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  95. })
  96. })
  97. ldapAutherScenario("given current org role is removed in ldap", func(sc *scenarioContext) {
  98. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  99. LdapGroups: []*LdapGroupToOrgRole{
  100. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Admin"},
  101. },
  102. })
  103. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  104. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  105. MemberOf: []string{"cn=other"},
  106. })
  107. Convey("Should remove org role", func() {
  108. So(err, ShouldBeNil)
  109. So(sc.removeOrgUserCmd, ShouldNotBeNil)
  110. })
  111. })
  112. ldapAutherScenario("given org role is updated in config", func(sc *scenarioContext) {
  113. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  114. LdapGroups: []*LdapGroupToOrgRole{
  115. {GroupDN: "cn=admin", OrgId: 1, OrgRole: "Admin"},
  116. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Viewer"},
  117. },
  118. })
  119. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  120. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  121. MemberOf: []string{"cn=users"},
  122. })
  123. Convey("Should update org role", func() {
  124. So(err, ShouldBeNil)
  125. So(sc.removeOrgUserCmd, ShouldBeNil)
  126. So(sc.updateOrgUserCmd, ShouldNotBeNil)
  127. })
  128. })
  129. ldapAutherScenario("given multiple matching ldap groups", func(sc *scenarioContext) {
  130. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  131. LdapGroups: []*LdapGroupToOrgRole{
  132. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin"},
  133. {GroupDN: "*", OrgId: 1, OrgRole: "Viewer"},
  134. },
  135. })
  136. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_ADMIN}})
  137. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  138. MemberOf: []string{"cn=admins"},
  139. })
  140. Convey("Should take first match, and ignore subsequent matches", func() {
  141. So(err, ShouldBeNil)
  142. So(sc.updateOrgUserCmd, ShouldBeNil)
  143. })
  144. })
  145. ldapAutherScenario("given multiple matching ldap groups and no existing groups", func(sc *scenarioContext) {
  146. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  147. LdapGroups: []*LdapGroupToOrgRole{
  148. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin"},
  149. {GroupDN: "*", OrgId: 1, OrgRole: "Viewer"},
  150. },
  151. })
  152. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  153. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  154. MemberOf: []string{"cn=admins"},
  155. })
  156. Convey("Should take first match, and ignore subsequent matches", func() {
  157. So(err, ShouldBeNil)
  158. So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  159. })
  160. })
  161. })
  162. }
  163. func ldapAutherScenario(desc string, fn scenarioFunc) {
  164. Convey(desc, func() {
  165. defer bus.ClearBusHandlers()
  166. sc := &scenarioContext{}
  167. bus.AddHandler("test", func(cmd *m.CreateUserCommand) error {
  168. sc.createUserCmd = cmd
  169. sc.createUserCmd.Result = m.User{Login: cmd.Login}
  170. return nil
  171. })
  172. bus.AddHandler("test", func(cmd *m.AddOrgUserCommand) error {
  173. sc.addOrgUserCmd = cmd
  174. return nil
  175. })
  176. bus.AddHandler("test", func(cmd *m.UpdateOrgUserCommand) error {
  177. sc.updateOrgUserCmd = cmd
  178. return nil
  179. })
  180. bus.AddHandler("test", func(cmd *m.RemoveOrgUserCommand) error {
  181. sc.removeOrgUserCmd = cmd
  182. return nil
  183. })
  184. fn(sc)
  185. })
  186. }
  187. type scenarioContext struct {
  188. createUserCmd *m.CreateUserCommand
  189. addOrgUserCmd *m.AddOrgUserCommand
  190. updateOrgUserCmd *m.UpdateOrgUserCommand
  191. removeOrgUserCmd *m.RemoveOrgUserCommand
  192. }
  193. func (sc *scenarioContext) userQueryReturns(user *m.User) {
  194. bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
  195. if user == nil {
  196. return m.ErrUserNotFound
  197. } else {
  198. query.Result = user
  199. return nil
  200. }
  201. })
  202. }
  203. func (sc *scenarioContext) userOrgsQueryReturns(orgs []*m.UserOrgDTO) {
  204. bus.AddHandler("test", func(query *m.GetUserOrgListQuery) error {
  205. query.Result = orgs
  206. return nil
  207. })
  208. }
  209. type scenarioFunc func(c *scenarioContext)