genpolicy.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  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 locale
  15. import (
  16. "strings"
  17. "yunion.io/x/jsonutils"
  18. "yunion.io/x/pkg/util/rbacscope"
  19. "yunion.io/x/pkg/utils"
  20. )
  21. var (
  22. allowResult = jsonutils.NewString("allow")
  23. denyResult = jsonutils.NewString("deny")
  24. )
  25. func getAdminPolicy(services map[string][]string) jsonutils.JSONObject {
  26. policy := jsonutils.NewDict()
  27. for k := range services {
  28. resList := services[k]
  29. if len(resList) == 0 {
  30. policy.Add(allowResult, k)
  31. } else {
  32. resPolicy := jsonutils.NewDict()
  33. for i := range resList {
  34. resPolicy.Add(allowResult, resList[i])
  35. }
  36. policy.Add(resPolicy, k)
  37. }
  38. }
  39. return policy
  40. }
  41. func getEditActionPolicy(service, resource string) jsonutils.JSONObject {
  42. p := jsonutils.NewDict()
  43. p.Add(denyResult, "create")
  44. p.Add(denyResult, "delete")
  45. perform := jsonutils.NewDict()
  46. perform.Add(denyResult, "purge")
  47. perform.Add(denyResult, "clone")
  48. perform.Add(denyResult, "disable")
  49. if resActions, ok := adminPerformActions[service]; ok {
  50. if actions, ok := resActions[resource]; ok {
  51. for _, action := range actions {
  52. perform.Add(denyResult, action)
  53. }
  54. }
  55. }
  56. perform.Add(allowResult, "*")
  57. p.Add(perform, "perform")
  58. p.Add(allowResult, "*")
  59. return p
  60. }
  61. func getViewerActionPolicy() jsonutils.JSONObject {
  62. p := jsonutils.NewDict()
  63. p.Add(allowResult, "get")
  64. p.Add(allowResult, "list")
  65. p.Add(denyResult, "*")
  66. return p
  67. }
  68. func getEditorPolicy(services map[string][]string) jsonutils.JSONObject {
  69. policy := jsonutils.NewDict()
  70. if len(services) == 1 {
  71. for k := range services {
  72. if k == "*" {
  73. ns := make(map[string][]string)
  74. ns[k] = services[k]
  75. // expand adminPerformActions
  76. for s, resActions := range adminPerformActions {
  77. resList := make([]string, 0, len(resActions)+1)
  78. resList = append(resList, "*")
  79. for res := range resActions {
  80. resList = append(resList, res)
  81. }
  82. ns[s] = resList
  83. }
  84. services = ns
  85. }
  86. }
  87. }
  88. for k, resList := range services {
  89. resPolicy := jsonutils.NewDict()
  90. if len(resList) == 0 {
  91. resList = []string{"*"}
  92. }
  93. if len(resList) == 1 && resList[0] == "*" {
  94. if resActions, ok := adminPerformActions[k]; ok {
  95. for res := range resActions {
  96. resList = append(resList, res)
  97. }
  98. }
  99. }
  100. for i := range resList {
  101. resPolicy.Add(getEditActionPolicy(k, resList[i]), resList[i])
  102. }
  103. policy.Add(resPolicy, k)
  104. }
  105. return policy
  106. }
  107. func getViewerPolicy(services map[string][]string) jsonutils.JSONObject {
  108. policy := jsonutils.NewDict()
  109. for k, resList := range services {
  110. if len(resList) == 0 {
  111. resList = []string{"*"}
  112. }
  113. resPolicy := jsonutils.NewDict()
  114. for i := range resList {
  115. resPolicy.Add(getViewerActionPolicy(), resList[i])
  116. }
  117. policy.Add(resPolicy, k)
  118. }
  119. return policy
  120. }
  121. func addExtraPolicy(policy *jsonutils.JSONDict, extra map[string]map[string][]string) jsonutils.JSONObject {
  122. for s, resources := range extra {
  123. var resourcePolicy *jsonutils.JSONDict
  124. resPolicy, _ := policy.Get(s)
  125. if resPolicy != nil {
  126. resourcePolicy = resPolicy.(*jsonutils.JSONDict)
  127. } else {
  128. resourcePolicy = jsonutils.NewDict()
  129. }
  130. for r, actions := range resources {
  131. var actionPolicy *jsonutils.JSONDict
  132. actPolicy, _ := resourcePolicy.Get(r)
  133. if actPolicy != nil {
  134. actionPolicy = actPolicy.(*jsonutils.JSONDict)
  135. } else {
  136. actionPolicy = jsonutils.NewDict()
  137. }
  138. for i := range actions {
  139. actionPolicy.Add(allowResult, actions[i])
  140. }
  141. actionPolicy.Add(denyResult, "*")
  142. resourcePolicy.Add(actionPolicy, r)
  143. }
  144. policy.Add(resourcePolicy, s)
  145. }
  146. return policy
  147. }
  148. func GenerateAllPolicies() []SPolicyData {
  149. ret := make([]SPolicyData, 0)
  150. for i := range policyDefinitons {
  151. def := policyDefinitons[i]
  152. for _, scope := range []rbacscope.TRbacScope{
  153. rbacscope.ScopeSystem,
  154. rbacscope.ScopeDomain,
  155. rbacscope.ScopeProject,
  156. } {
  157. if scope.HigherEqual(def.Scope) {
  158. ps := generatePolicies(scope, def)
  159. ret = append(ret, ps...)
  160. }
  161. }
  162. }
  163. ret = append(ret, predefinedPolicyData...)
  164. return ret
  165. }
  166. type SPolicyData struct {
  167. Name string
  168. Scope rbacscope.TRbacScope
  169. Policy jsonutils.JSONObject
  170. Description string
  171. DescriptionCN string
  172. AvailableRoles []string
  173. }
  174. func generatePolicies(scope rbacscope.TRbacScope, def sPolicyDefinition) []SPolicyData {
  175. level := ""
  176. switch scope {
  177. case rbacscope.ScopeSystem:
  178. level = "sys"
  179. if def.Scope == rbacscope.ScopeSystem {
  180. level = ""
  181. }
  182. case rbacscope.ScopeDomain:
  183. level = "domain"
  184. case rbacscope.ScopeProject:
  185. level = "project"
  186. }
  187. type sRoleConf struct {
  188. name string
  189. policyFunc func(services map[string][]string) jsonutils.JSONObject
  190. fullName string
  191. fullNameCN string
  192. }
  193. var roleConfs []sRoleConf
  194. if len(def.Services) > 0 {
  195. if len(def.AvailableRoles) == 0 || utils.IsInStringArray("admin", def.AvailableRoles) {
  196. roleConfs = append(roleConfs, sRoleConf{
  197. name: "admin",
  198. policyFunc: getAdminPolicy,
  199. fullNameCN: "管理",
  200. fullName: "full",
  201. })
  202. }
  203. if len(def.AvailableRoles) == 0 || utils.IsInStringArray("editor", def.AvailableRoles) {
  204. roleConfs = append(roleConfs, sRoleConf{
  205. name: "editor",
  206. policyFunc: getEditorPolicy,
  207. fullNameCN: "编辑/操作",
  208. fullName: "editor/operator",
  209. })
  210. }
  211. if len(def.AvailableRoles) == 0 || utils.IsInStringArray("viewer", def.AvailableRoles) {
  212. roleConfs = append(roleConfs, sRoleConf{
  213. name: "viewer",
  214. policyFunc: getViewerPolicy,
  215. fullNameCN: "只读",
  216. fullName: "read-only",
  217. })
  218. }
  219. } else {
  220. roleConfs = []sRoleConf{
  221. {
  222. name: "",
  223. policyFunc: nil,
  224. fullNameCN: "",
  225. fullName: "",
  226. },
  227. }
  228. }
  229. ret := make([]SPolicyData, 0)
  230. for _, role := range roleConfs {
  231. nameSegs := make([]string, 0)
  232. if len(level) > 0 {
  233. nameSegs = append(nameSegs, level)
  234. }
  235. if len(def.Name) > 0 {
  236. nameSegs = append(nameSegs, def.Name)
  237. }
  238. if len(role.name) > 0 {
  239. nameSegs = append(nameSegs, role.name)
  240. }
  241. name := strings.Join(nameSegs, "-")
  242. if name == "sys-admin" {
  243. name = "sysadmin"
  244. }
  245. var policy jsonutils.JSONObject
  246. if def.Services != nil {
  247. policy = role.policyFunc(def.Services)
  248. } else {
  249. policy = jsonutils.NewDict()
  250. }
  251. policy = addExtraPolicy(policy.(*jsonutils.JSONDict), def.Extra)
  252. desc := ""
  253. descCN := ""
  254. switch scope {
  255. case rbacscope.ScopeSystem:
  256. descCN += "全局"
  257. desc += "System-level"
  258. case rbacscope.ScopeDomain:
  259. descCN += "本域内"
  260. desc += "Domain-level"
  261. case rbacscope.ScopeProject:
  262. descCN += "本项目内"
  263. desc += "Project-level"
  264. }
  265. if len(role.fullName) > 0 {
  266. desc += " " + role.fullName
  267. }
  268. desc += " previlliges for"
  269. if len(def.Desc) > 0 {
  270. desc += " " + def.Desc
  271. }
  272. if len(def.DescCN) > 0 {
  273. descCN += def.DescCN
  274. }
  275. if len(role.fullNameCN) > 0 {
  276. descCN += role.fullNameCN
  277. }
  278. descCN += "权限"
  279. policyJson := jsonutils.NewDict()
  280. policyJson.Add(policy, "policy")
  281. ret = append(ret, SPolicyData{
  282. Name: name,
  283. Scope: scope,
  284. Policy: policyJson,
  285. Description: strings.TrimSpace(desc),
  286. DescriptionCN: strings.TrimSpace(descCN),
  287. })
  288. }
  289. return ret
  290. }