reduce.go 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package rbacutils
  15. import (
  16. "sort"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/log"
  19. "yunion.io/x/pkg/errors"
  20. "yunion.io/x/onecloud/pkg/util/stringutils2"
  21. )
  22. type sRbacNode struct {
  23. defNode *sRbacNode
  24. downStream map[string]*sRbacNode
  25. result *TRbacResult
  26. level int
  27. }
  28. func newRbacNode(level int) *sRbacNode {
  29. return &sRbacNode{
  30. downStream: make(map[string]*sRbacNode),
  31. level: level,
  32. }
  33. }
  34. func (n *sRbacNode) AddRule(rule SRbacRule) {
  35. n.addRule(rule, levelService)
  36. }
  37. func (n *sRbacNode) addRule(rule SRbacRule, level int) {
  38. if level <= levelAction || len(rule.Extra) > level-levelExtra {
  39. if n.result != nil {
  40. // node is a leaf
  41. if n.defNode != nil {
  42. log.Fatalf("illegal state, result != nil and defNode != nil")
  43. }
  44. n.defNode = newRbacNode(n.level + 1)
  45. n.defNode.result = n.result
  46. n.result = nil
  47. }
  48. var key string
  49. if level == levelService {
  50. key = rule.Service
  51. } else if level == levelResource {
  52. key = rule.Resource
  53. } else if level == levelAction {
  54. key = rule.Action
  55. } else {
  56. key = rule.Extra[level-levelExtra]
  57. }
  58. if len(key) == 0 || key == WILD_MATCH {
  59. next := n.defNode
  60. if n.defNode == nil {
  61. next = newRbacNode(level + 1)
  62. n.defNode = next
  63. }
  64. next.addRule(rule, level+1)
  65. } else {
  66. next, ok := n.downStream[key]
  67. if !ok {
  68. next = newRbacNode(level + 1)
  69. n.downStream[key] = next
  70. }
  71. next.addRule(rule, level+1)
  72. }
  73. } else {
  74. if n.result != nil {
  75. log.Warningf("node has been occupide!!!")
  76. }
  77. n.result = &rule.Result
  78. }
  79. }
  80. func (n *sRbacNode) isLeaf() bool {
  81. return n.result != nil && n.defNode == nil && len(n.downStream) == 0
  82. }
  83. func (n *sRbacNode) reduceDownstream() {
  84. allowKey := make([]string, 0)
  85. denyKey := make([]string, 0)
  86. skipKey := make([]string, 0)
  87. for k, v := range n.downStream {
  88. if v.result == nil {
  89. skipKey = append(skipKey, k)
  90. continue
  91. }
  92. if *v.result == Allow {
  93. allowKey = append(allowKey, k)
  94. } else {
  95. denyKey = append(denyKey, k)
  96. }
  97. }
  98. if len(allowKey)+len(denyKey) > 0 {
  99. var result TRbacResult
  100. var keys []string
  101. if n.defNode != nil {
  102. if n.defNode.isLeaf() {
  103. if *n.defNode.result == Allow {
  104. keys = allowKey
  105. result = Allow
  106. } else {
  107. keys = denyKey
  108. result = Deny
  109. }
  110. }
  111. } else {
  112. if len(allowKey) >= len(denyKey) {
  113. keys = allowKey
  114. result = Allow
  115. } else {
  116. keys = denyKey
  117. result = Deny
  118. }
  119. if len(allowKey) == 0 || len(denyKey) == 0 {
  120. // reduce whole downStream
  121. needBranch := false
  122. if n.level == levelAction {
  123. sort.Strings(keys)
  124. if !stringutils2.Contains(stringutils2.SSortedStrings(keys), AllSortedActions) {
  125. // not a complete set of action, cancel reduce
  126. needBranch = true
  127. }
  128. } else if n.level >= levelExtra {
  129. if len(keys) <= 1 {
  130. needBranch = true
  131. }
  132. }
  133. if needBranch {
  134. keys = nil
  135. if result == Allow {
  136. result = Deny
  137. } else {
  138. result = Allow
  139. }
  140. // add a default branch
  141. n.defNode = newRbacNode(n.level + 1)
  142. n.defNode.result = &result
  143. }
  144. }
  145. }
  146. if len(keys) > 0 {
  147. for _, k := range keys {
  148. delete(n.downStream, k)
  149. }
  150. if n.defNode == nil {
  151. n.defNode = newRbacNode(n.level + 1)
  152. }
  153. n.defNode.result = &result
  154. }
  155. }
  156. if len(n.downStream) == 0 && n.defNode != nil && n.defNode.isLeaf() {
  157. n.result = n.defNode.result
  158. n.defNode = nil
  159. }
  160. }
  161. func (n *sRbacNode) reduce() {
  162. if n.defNode != nil {
  163. n.defNode.reduce()
  164. }
  165. for k := range n.downStream {
  166. n.downStream[k].reduce()
  167. }
  168. if n.level == levelService || n.level == levelResource {
  169. return
  170. }
  171. n.reduceDownstream()
  172. }
  173. func (n *sRbacNode) GetRules() []SRbacRule {
  174. return n.getRules(SRbacRule{Service: WILD_MATCH}, levelService)
  175. }
  176. func (n *sRbacNode) getRules(seed SRbacRule, level int) []SRbacRule {
  177. result := make([]SRbacRule, 0)
  178. if n.result != nil {
  179. rule := seed.clone()
  180. rule.Result = *n.result
  181. return []SRbacRule{rule}
  182. } else {
  183. if n.defNode != nil {
  184. rule := seed.clone()
  185. if level == levelService {
  186. rule.Service = WILD_MATCH
  187. } else if level == levelResource {
  188. rule.Resource = WILD_MATCH
  189. } else if level == levelAction {
  190. rule.Action = WILD_MATCH
  191. } else if level >= levelExtra {
  192. rule.Extra = append(rule.Extra, WILD_MATCH)
  193. }
  194. newRules := n.defNode.getRules(rule, level+1)
  195. result = append(result, newRules...)
  196. }
  197. for k := range n.downStream {
  198. rule := seed.clone()
  199. if level == levelService {
  200. rule.Service = k
  201. } else if level == levelResource {
  202. rule.Resource = k
  203. } else if level == levelAction {
  204. rule.Action = k
  205. } else if level >= levelExtra {
  206. rule.Extra = append(rule.Extra, k)
  207. }
  208. newRules := n.downStream[k].getRules(rule, level+1)
  209. result = append(result, newRules...)
  210. }
  211. }
  212. return result
  213. }
  214. func reduceRules(rules []SRbacRule) []SRbacRule {
  215. root := newRbacNode(levelService)
  216. for _, r := range rules {
  217. root.AddRule(r)
  218. }
  219. root.reduce()
  220. return root.GetRules()
  221. }
  222. func rules2Json(rules []SRbacRule) jsonutils.JSONObject {
  223. root := newRbacNode(levelService)
  224. for _, r := range rules {
  225. root.AddRule(r)
  226. }
  227. // root.reduce()
  228. return root.json()
  229. }
  230. func json2Rules(json jsonutils.JSONObject) ([]SRbacRule, error) {
  231. root := newRbacNode(levelService)
  232. err := root.parseJson(json)
  233. if err != nil {
  234. return nil, errors.Wrap(err, "root.parseJson")
  235. }
  236. // root.reduce()
  237. return root.GetRules(), nil
  238. }
  239. func (n *sRbacNode) json() jsonutils.JSONObject {
  240. var result jsonutils.JSONObject
  241. if n.result != nil {
  242. return jsonutils.NewString(string(*n.result))
  243. } else {
  244. result = jsonutils.NewDict()
  245. if n.defNode != nil {
  246. result.(*jsonutils.JSONDict).Add(n.defNode.json(), "*")
  247. }
  248. for k := range n.downStream {
  249. result.(*jsonutils.JSONDict).Add(n.downStream[k].json(), k)
  250. }
  251. }
  252. return result
  253. }
  254. func (n *sRbacNode) parseJson(input jsonutils.JSONObject) error {
  255. switch val := input.(type) {
  256. case *jsonutils.JSONString:
  257. ruleStr, err := val.GetString()
  258. if err != nil {
  259. return errors.Wrap(err, "val.GetString")
  260. }
  261. var result TRbacResult
  262. switch ruleStr {
  263. case string(Allow), string(AdminAllow), string(OwnerAllow), string(UserAllow), string(GuestAllow):
  264. result = Allow
  265. default:
  266. result = Deny
  267. }
  268. n.result = &result
  269. case *jsonutils.JSONDict:
  270. ruleJsonDict, err := val.GetMap()
  271. if err != nil {
  272. return errors.Wrap(err, "val.GetMap")
  273. }
  274. for key, ruleJson := range ruleJsonDict {
  275. if key == WILD_MATCH {
  276. n.defNode = newRbacNode(n.level + 1)
  277. err := n.defNode.parseJson(ruleJson)
  278. if err != nil {
  279. return errors.Wrap(err, "n.defNode.parseJson")
  280. }
  281. } else {
  282. n.downStream[key] = newRbacNode(n.level + 1)
  283. err := n.downStream[key].parseJson(ruleJson)
  284. if err != nil {
  285. return errors.Wrap(err, "n.downStream[key].parseJson")
  286. }
  287. }
  288. }
  289. default:
  290. return errors.Wrap(ErrUnsuportRuleData, input.String())
  291. }
  292. return nil
  293. }