guardian.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265
  1. package guardian
  2. import (
  3. "errors"
  4. "github.com/grafana/grafana/pkg/bus"
  5. "github.com/grafana/grafana/pkg/infra/log"
  6. m "github.com/grafana/grafana/pkg/models"
  7. "github.com/grafana/grafana/pkg/setting"
  8. )
  9. var (
  10. ErrGuardianPermissionExists = errors.New("Permission already exists")
  11. ErrGuardianOverride = errors.New("You can only override a permission to be higher")
  12. )
  13. // DashboardGuardian to be used for guard against operations without access on dashboard and acl
  14. type DashboardGuardian interface {
  15. CanSave() (bool, error)
  16. CanEdit() (bool, error)
  17. CanView() (bool, error)
  18. CanAdmin() (bool, error)
  19. HasPermission(permission m.PermissionType) (bool, error)
  20. CheckPermissionBeforeUpdate(permission m.PermissionType, updatePermissions []*m.DashboardAcl) (bool, error)
  21. GetAcl() ([]*m.DashboardAclInfoDTO, error)
  22. }
  23. type dashboardGuardianImpl struct {
  24. user *m.SignedInUser
  25. dashId int64
  26. orgId int64
  27. acl []*m.DashboardAclInfoDTO
  28. teams []*m.TeamDTO
  29. log log.Logger
  30. }
  31. // New factory for creating a new dashboard guardian instance
  32. var New = func(dashId int64, orgId int64, user *m.SignedInUser) DashboardGuardian {
  33. return &dashboardGuardianImpl{
  34. user: user,
  35. dashId: dashId,
  36. orgId: orgId,
  37. log: log.New("dashboard.permissions"),
  38. }
  39. }
  40. func (g *dashboardGuardianImpl) CanSave() (bool, error) {
  41. return g.HasPermission(m.PERMISSION_EDIT)
  42. }
  43. func (g *dashboardGuardianImpl) CanEdit() (bool, error) {
  44. if setting.ViewersCanEdit {
  45. return g.HasPermission(m.PERMISSION_VIEW)
  46. }
  47. return g.HasPermission(m.PERMISSION_EDIT)
  48. }
  49. func (g *dashboardGuardianImpl) CanView() (bool, error) {
  50. return g.HasPermission(m.PERMISSION_VIEW)
  51. }
  52. func (g *dashboardGuardianImpl) CanAdmin() (bool, error) {
  53. return g.HasPermission(m.PERMISSION_ADMIN)
  54. }
  55. func (g *dashboardGuardianImpl) HasPermission(permission m.PermissionType) (bool, error) {
  56. if g.user.OrgRole == m.ROLE_ADMIN {
  57. return g.logHasPermissionResult(permission, true, nil)
  58. }
  59. acl, err := g.GetAcl()
  60. if err != nil {
  61. return g.logHasPermissionResult(permission, false, err)
  62. }
  63. result, err := g.checkAcl(permission, acl)
  64. return g.logHasPermissionResult(permission, result, err)
  65. }
  66. func (g *dashboardGuardianImpl) logHasPermissionResult(permission m.PermissionType, hasPermission bool, err error) (bool, error) {
  67. if err != nil {
  68. return hasPermission, err
  69. }
  70. if hasPermission {
  71. g.log.Debug("User granted access to execute action", "userId", g.user.UserId, "orgId", g.orgId, "uname", g.user.Login, "dashId", g.dashId, "action", permission)
  72. } else {
  73. g.log.Debug("User denied access to execute action", "userId", g.user.UserId, "orgId", g.orgId, "uname", g.user.Login, "dashId", g.dashId, "action", permission)
  74. }
  75. return hasPermission, err
  76. }
  77. func (g *dashboardGuardianImpl) checkAcl(permission m.PermissionType, acl []*m.DashboardAclInfoDTO) (bool, error) {
  78. orgRole := g.user.OrgRole
  79. teamAclItems := []*m.DashboardAclInfoDTO{}
  80. for _, p := range acl {
  81. // user match
  82. if !g.user.IsAnonymous && p.UserId > 0 {
  83. if p.UserId == g.user.UserId && p.Permission >= permission {
  84. return true, nil
  85. }
  86. }
  87. // role match
  88. if p.Role != nil {
  89. if *p.Role == orgRole && p.Permission >= permission {
  90. return true, nil
  91. }
  92. }
  93. // remember this rule for later
  94. if p.TeamId > 0 {
  95. teamAclItems = append(teamAclItems, p)
  96. }
  97. }
  98. // do we have team rules?
  99. if len(teamAclItems) == 0 {
  100. return false, nil
  101. }
  102. // load teams
  103. teams, err := g.getTeams()
  104. if err != nil {
  105. return false, err
  106. }
  107. // evaluate team rules
  108. for _, p := range acl {
  109. for _, ug := range teams {
  110. if ug.Id == p.TeamId && p.Permission >= permission {
  111. return true, nil
  112. }
  113. }
  114. }
  115. return false, nil
  116. }
  117. func (g *dashboardGuardianImpl) CheckPermissionBeforeUpdate(permission m.PermissionType, updatePermissions []*m.DashboardAcl) (bool, error) {
  118. acl := []*m.DashboardAclInfoDTO{}
  119. adminRole := m.ROLE_ADMIN
  120. everyoneWithAdminRole := &m.DashboardAclInfoDTO{DashboardId: g.dashId, UserId: 0, TeamId: 0, Role: &adminRole, Permission: m.PERMISSION_ADMIN}
  121. // validate that duplicate permissions don't exists
  122. for _, p := range updatePermissions {
  123. aclItem := &m.DashboardAclInfoDTO{DashboardId: p.DashboardId, UserId: p.UserId, TeamId: p.TeamId, Role: p.Role, Permission: p.Permission}
  124. if aclItem.IsDuplicateOf(everyoneWithAdminRole) {
  125. return false, ErrGuardianPermissionExists
  126. }
  127. for _, a := range acl {
  128. if a.IsDuplicateOf(aclItem) {
  129. return false, ErrGuardianPermissionExists
  130. }
  131. }
  132. acl = append(acl, aclItem)
  133. }
  134. existingPermissions, err := g.GetAcl()
  135. if err != nil {
  136. return false, err
  137. }
  138. // validate overridden permissions to be higher
  139. for _, a := range acl {
  140. for _, existingPerm := range existingPermissions {
  141. if !existingPerm.Inherited {
  142. continue
  143. }
  144. if a.IsDuplicateOf(existingPerm) && a.Permission <= existingPerm.Permission {
  145. return false, ErrGuardianOverride
  146. }
  147. }
  148. }
  149. if g.user.OrgRole == m.ROLE_ADMIN {
  150. return true, nil
  151. }
  152. return g.checkAcl(permission, existingPermissions)
  153. }
  154. // GetAcl returns dashboard acl
  155. func (g *dashboardGuardianImpl) GetAcl() ([]*m.DashboardAclInfoDTO, error) {
  156. if g.acl != nil {
  157. return g.acl, nil
  158. }
  159. query := m.GetDashboardAclInfoListQuery{DashboardId: g.dashId, OrgId: g.orgId}
  160. if err := bus.Dispatch(&query); err != nil {
  161. return nil, err
  162. }
  163. g.acl = query.Result
  164. return g.acl, nil
  165. }
  166. func (g *dashboardGuardianImpl) getTeams() ([]*m.TeamDTO, error) {
  167. if g.teams != nil {
  168. return g.teams, nil
  169. }
  170. query := m.GetTeamsByUserQuery{OrgId: g.orgId, UserId: g.user.UserId}
  171. err := bus.Dispatch(&query)
  172. g.teams = query.Result
  173. return query.Result, err
  174. }
  175. type FakeDashboardGuardian struct {
  176. DashId int64
  177. OrgId int64
  178. User *m.SignedInUser
  179. CanSaveValue bool
  180. CanEditValue bool
  181. CanViewValue bool
  182. CanAdminValue bool
  183. HasPermissionValue bool
  184. CheckPermissionBeforeUpdateValue bool
  185. CheckPermissionBeforeUpdateError error
  186. GetAclValue []*m.DashboardAclInfoDTO
  187. }
  188. func (g *FakeDashboardGuardian) CanSave() (bool, error) {
  189. return g.CanSaveValue, nil
  190. }
  191. func (g *FakeDashboardGuardian) CanEdit() (bool, error) {
  192. return g.CanEditValue, nil
  193. }
  194. func (g *FakeDashboardGuardian) CanView() (bool, error) {
  195. return g.CanViewValue, nil
  196. }
  197. func (g *FakeDashboardGuardian) CanAdmin() (bool, error) {
  198. return g.CanAdminValue, nil
  199. }
  200. func (g *FakeDashboardGuardian) HasPermission(permission m.PermissionType) (bool, error) {
  201. return g.HasPermissionValue, nil
  202. }
  203. func (g *FakeDashboardGuardian) CheckPermissionBeforeUpdate(permission m.PermissionType, updatePermissions []*m.DashboardAcl) (bool, error) {
  204. return g.CheckPermissionBeforeUpdateValue, g.CheckPermissionBeforeUpdateError
  205. }
  206. func (g *FakeDashboardGuardian) GetAcl() ([]*m.DashboardAclInfoDTO, error) {
  207. return g.GetAclValue, nil
  208. }
  209. func MockDashboardGuardian(mock *FakeDashboardGuardian) {
  210. New = func(dashId int64, orgId int64, user *m.SignedInUser) DashboardGuardian {
  211. mock.OrgId = orgId
  212. mock.DashId = dashId
  213. mock.User = user
  214. return mock
  215. }
  216. }