ldap_test.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  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=users", OrgRole: "Admin"},
  44. },
  45. })
  46. sc.userQueryReturns(nil)
  47. result, err := ldapAuther.getGrafanaUserFor(&ldapUserInfo{
  48. Username: "torkelo",
  49. Email: "my@email.com",
  50. MemberOf: []string{"cn=users"},
  51. })
  52. So(err, ShouldBeNil)
  53. Convey("Should create new user", func() {
  54. So(sc.createUserCmd.Login, ShouldEqual, "torkelo")
  55. So(sc.createUserCmd.Email, ShouldEqual, "my@email.com")
  56. })
  57. Convey("Should return new user", func() {
  58. So(result.Login, ShouldEqual, "torkelo")
  59. })
  60. })
  61. })
  62. Convey("When syncing ldap groups to grafana org roles", t, func() {
  63. ldapAutherScenario("given no current user orgs", func(sc *scenarioContext) {
  64. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  65. LdapGroups: []*LdapGroupToOrgRole{
  66. {GroupDN: "cn=users", OrgRole: "Admin"},
  67. },
  68. })
  69. sc.userOrgsQueryReturns([]*m.UserOrgDTO{})
  70. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  71. MemberOf: []string{"cn=users"},
  72. })
  73. Convey("Should create new org user", func() {
  74. So(err, ShouldBeNil)
  75. So(sc.addOrgUserCmd, ShouldNotBeNil)
  76. So(sc.addOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  77. })
  78. })
  79. ldapAutherScenario("given different current org role", func(sc *scenarioContext) {
  80. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  81. LdapGroups: []*LdapGroupToOrgRole{
  82. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Admin"},
  83. },
  84. })
  85. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  86. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  87. MemberOf: []string{"cn=users"},
  88. })
  89. Convey("Should update org role", func() {
  90. So(err, ShouldBeNil)
  91. So(sc.updateOrgUserCmd, ShouldNotBeNil)
  92. So(sc.updateOrgUserCmd.Role, ShouldEqual, m.ROLE_ADMIN)
  93. })
  94. })
  95. ldapAutherScenario("given current org role is removed in ldap", func(sc *scenarioContext) {
  96. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  97. LdapGroups: []*LdapGroupToOrgRole{
  98. {GroupDN: "cn=users", OrgId: 1, OrgRole: "Admin"},
  99. },
  100. })
  101. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_EDITOR}})
  102. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  103. MemberOf: []string{"cn=other"},
  104. })
  105. Convey("Should remove org role", func() {
  106. So(err, ShouldBeNil)
  107. So(sc.removeOrgUserCmd, ShouldNotBeNil)
  108. })
  109. })
  110. ldapAutherScenario("given multiple matching ldap groups", func(sc *scenarioContext) {
  111. ldapAuther := NewLdapAuthenticator(&LdapServerConf{
  112. LdapGroups: []*LdapGroupToOrgRole{
  113. {GroupDN: "cn=admins", OrgId: 1, OrgRole: "Admin"},
  114. {GroupDN: "*", OrgId: 1, OrgRole: "Viewer"},
  115. },
  116. })
  117. sc.userOrgsQueryReturns([]*m.UserOrgDTO{{OrgId: 1, Role: m.ROLE_ADMIN}})
  118. err := ldapAuther.syncOrgRoles(&m.User{}, &ldapUserInfo{
  119. MemberOf: []string{"cn=admins"},
  120. })
  121. Convey("Should take first match, and ignore subsequent matches", func() {
  122. So(err, ShouldBeNil)
  123. So(sc.updateOrgUserCmd, ShouldBeNil)
  124. })
  125. })
  126. })
  127. }
  128. func ldapAutherScenario(desc string, fn scenarioFunc) {
  129. Convey(desc, func() {
  130. defer bus.ClearBusHandlers()
  131. sc := &scenarioContext{}
  132. bus.AddHandler("test", func(cmd *m.CreateUserCommand) error {
  133. sc.createUserCmd = cmd
  134. sc.createUserCmd.Result = m.User{Login: cmd.Login}
  135. return nil
  136. })
  137. bus.AddHandler("test", func(cmd *m.AddOrgUserCommand) error {
  138. sc.addOrgUserCmd = cmd
  139. return nil
  140. })
  141. bus.AddHandler("test", func(cmd *m.UpdateOrgUserCommand) error {
  142. sc.updateOrgUserCmd = cmd
  143. return nil
  144. })
  145. bus.AddHandler("test", func(cmd *m.RemoveOrgUserCommand) error {
  146. sc.removeOrgUserCmd = cmd
  147. return nil
  148. })
  149. fn(sc)
  150. })
  151. }
  152. type scenarioContext struct {
  153. createUserCmd *m.CreateUserCommand
  154. addOrgUserCmd *m.AddOrgUserCommand
  155. updateOrgUserCmd *m.UpdateOrgUserCommand
  156. removeOrgUserCmd *m.RemoveOrgUserCommand
  157. }
  158. func (sc *scenarioContext) userQueryReturns(user *m.User) {
  159. bus.AddHandler("test", func(query *m.GetUserByLoginQuery) error {
  160. if user == nil {
  161. return m.ErrUserNotFound
  162. } else {
  163. query.Result = user
  164. return nil
  165. }
  166. })
  167. }
  168. func (sc *scenarioContext) userOrgsQueryReturns(orgs []*m.UserOrgDTO) {
  169. bus.AddHandler("test", func(query *m.GetUserOrgListQuery) error {
  170. query.Result = orgs
  171. return nil
  172. })
  173. }
  174. type scenarioFunc func(c *scenarioContext)