rbac.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  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 db
  15. import (
  16. "context"
  17. "yunion.io/x/log"
  18. "yunion.io/x/pkg/errors"
  19. "yunion.io/x/pkg/util/rbacscope"
  20. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  21. "yunion.io/x/onecloud/pkg/cloudcommon/policy"
  22. "yunion.io/x/onecloud/pkg/httperrors"
  23. "yunion.io/x/onecloud/pkg/mcclient"
  24. "yunion.io/x/onecloud/pkg/util/rbacutils"
  25. )
  26. func IsObjectRbacAllowed(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
  27. return isObjectRbacAllowed(ctx, model, userCred, action, extra...)
  28. }
  29. func isObjectRbacAllowed(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
  30. _, err := isObjectRbacAllowedResult(ctx, model, userCred, action, extra...)
  31. return err
  32. }
  33. func isObjectRbacAllowedResult(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) (rbacutils.SPolicyResult, error) {
  34. manager := model.GetModelManager()
  35. objOwnerId := model.GetOwnerId()
  36. var ownerId mcclient.IIdentityProvider
  37. if userCred != nil {
  38. ownerId = userCred
  39. }
  40. var requireScope rbacscope.TRbacScope
  41. resScope := manager.ResourceScope()
  42. switch resScope {
  43. case rbacscope.ScopeSystem:
  44. requireScope = rbacscope.ScopeSystem
  45. case rbacscope.ScopeDomain:
  46. if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() && action == policy.PolicyActionGet) {
  47. requireScope = rbacscope.ScopeUser
  48. } else if ownerId != nil && objOwnerId != nil && (ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() || objOwnerId.GetProjectDomainId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
  49. requireScope = rbacscope.ScopeDomain
  50. } else {
  51. requireScope = rbacscope.ScopeSystem
  52. }
  53. case rbacscope.ScopeUser:
  54. if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() || objOwnerId.GetUserId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
  55. requireScope = rbacscope.ScopeUser
  56. } else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectId() == objOwnerId.GetProjectId() {
  57. requireScope = rbacscope.ScopeProject
  58. } else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
  59. requireScope = rbacscope.ScopeDomain
  60. } else {
  61. requireScope = rbacscope.ScopeSystem
  62. }
  63. default:
  64. // objOwnerId should not be nil
  65. if ownerId != nil && objOwnerId != nil && (ownerId.GetProjectId() == objOwnerId.GetProjectId() || objOwnerId.GetProjectId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
  66. requireScope = rbacscope.ScopeProject
  67. } else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
  68. requireScope = rbacscope.ScopeDomain
  69. } else {
  70. requireScope = rbacscope.ScopeSystem
  71. }
  72. }
  73. scope, result := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
  74. if result.Result.IsAllow() && !requireScope.HigherThan(scope) {
  75. err := objectConfirmPolicyTags(ctx, model, result)
  76. if err != nil {
  77. return rbacutils.PolicyDeny, errors.Wrap(err, "objectConfirmPolicyTags")
  78. }
  79. return result, nil
  80. }
  81. return rbacutils.PolicyDeny, httperrors.NewForbiddenError("not enough privilege (require:%s,allow:%s:resource:%s) [tags:%s]", requireScope, scope, resScope, result.String())
  82. }
  83. func isJointObjectRbacAllowed(ctx context.Context, item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
  84. err1 := isObjectRbacAllowed(ctx, JointMaster(item), userCred, action, extra...)
  85. err2 := isObjectRbacAllowed(ctx, JointSlave(item), userCred, action, extra...)
  86. if err1 == nil || err2 == nil {
  87. return nil
  88. }
  89. return err1
  90. }
  91. func isClassRbacAllowed(ctx context.Context, manager IModelManager, userCred mcclient.TokenCredential, objOwnerId mcclient.IIdentityProvider, action string, extra ...string) (rbacutils.SPolicyResult, error) {
  92. var ownerId mcclient.IIdentityProvider
  93. if userCred != nil {
  94. ownerId = userCred
  95. }
  96. var requireScope rbacscope.TRbacScope
  97. resScope := manager.ResourceScope()
  98. switch resScope {
  99. case rbacscope.ScopeSystem:
  100. requireScope = rbacscope.ScopeSystem
  101. case rbacscope.ScopeDomain:
  102. // objOwnerId should not be nil
  103. if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
  104. requireScope = rbacscope.ScopeDomain
  105. } else {
  106. requireScope = rbacscope.ScopeSystem
  107. }
  108. case rbacscope.ScopeUser:
  109. if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
  110. requireScope = rbacscope.ScopeUser
  111. } else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
  112. requireScope = rbacscope.ScopeDomain
  113. } else {
  114. requireScope = rbacscope.ScopeSystem
  115. }
  116. default:
  117. // objOwnerId should not be nil
  118. if ownerId != nil && ownerId.GetProjectId() == objOwnerId.GetProjectId() {
  119. requireScope = rbacscope.ScopeProject
  120. } else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
  121. requireScope = rbacscope.ScopeDomain
  122. } else {
  123. requireScope = rbacscope.ScopeSystem
  124. }
  125. }
  126. allowScope, result := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
  127. if result.Result.IsAllow() && !requireScope.HigherThan(allowScope) {
  128. err := classConfirmPolicyTags(ctx, manager, objOwnerId, result)
  129. if err != nil {
  130. return rbacutils.PolicyDeny, errors.Wrap(err, "classConfirmPolicyTags")
  131. }
  132. return result, nil
  133. }
  134. return rbacutils.PolicyDeny, httperrors.NewForbiddenError("not enough privilege (require:%s,allow:%s)", requireScope, allowScope)
  135. }
  136. type IResource interface {
  137. KeywordPlural() string
  138. }
  139. func IsAllowList(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  140. if userCred == nil {
  141. return rbacutils.PolicyDeny
  142. }
  143. return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
  144. }
  145. func IsAdminAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  146. return IsAllowList(rbacscope.ScopeSystem, userCred, manager)
  147. }
  148. func IsDomainAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  149. return IsAllowList(rbacscope.ScopeDomain, userCred, manager)
  150. }
  151. func IsProjectAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  152. return IsAllowList(rbacscope.ScopeProject, userCred, manager)
  153. }
  154. func IsAllowCreate(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  155. if userCred == nil {
  156. return rbacutils.PolicyDeny
  157. }
  158. return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionCreate)
  159. }
  160. func IsAdminAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  161. return IsAllowCreate(rbacscope.ScopeSystem, userCred, manager)
  162. }
  163. func IsDomainAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  164. return IsAllowCreate(rbacscope.ScopeDomain, userCred, manager)
  165. }
  166. func IsProjectAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
  167. return IsAllowCreate(rbacscope.ScopeProject, userCred, manager)
  168. }
  169. func IsAllowClassPerform(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
  170. if userCred == nil {
  171. return rbacutils.PolicyDeny
  172. }
  173. return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionPerform, action)
  174. }
  175. func IsAdminAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
  176. return IsAllowClassPerform(rbacscope.ScopeSystem, userCred, manager, action)
  177. }
  178. func IsDomainAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
  179. return IsAllowClassPerform(rbacscope.ScopeDomain, userCred, manager, action)
  180. }
  181. func IsProjectAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
  182. return IsAllowClassPerform(rbacscope.ScopeProject, userCred, manager, action)
  183. }
  184. func IsAllowGet(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
  185. if userCred == nil {
  186. return false
  187. }
  188. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionGet)
  189. err := objectConfirmPolicyTags(ctx, obj, result)
  190. if err != nil {
  191. log.Errorf("IsAllowGet %s", err)
  192. return false
  193. } else {
  194. return true
  195. }
  196. }
  197. func IsAdminAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  198. return IsAllowGet(ctx, rbacscope.ScopeSystem, userCred, obj)
  199. }
  200. func IsDomainAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  201. return IsAllowGet(ctx, rbacscope.ScopeDomain, userCred, obj)
  202. }
  203. func IsProjectAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  204. return IsAllowGet(ctx, rbacscope.ScopeProject, userCred, obj)
  205. }
  206. func IsAllowGetSpec(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  207. if userCred == nil {
  208. return false
  209. }
  210. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionGet, spec)
  211. err := objectConfirmPolicyTags(ctx, obj, result)
  212. if err != nil {
  213. log.Errorf("IsAllowGetSpec %s", err)
  214. return false
  215. } else {
  216. return true
  217. }
  218. }
  219. func IsAdminAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  220. return IsAllowGetSpec(ctx, rbacscope.ScopeSystem, userCred, obj, spec)
  221. }
  222. func IsDomainAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  223. return IsAllowGetSpec(ctx, rbacscope.ScopeDomain, userCred, obj, spec)
  224. }
  225. func IsProjectAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  226. return IsAllowGetSpec(ctx, rbacscope.ScopeProject, userCred, obj, spec)
  227. }
  228. func IsAllowPerform(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, action string) bool {
  229. if userCred == nil {
  230. return false
  231. }
  232. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionPerform, action)
  233. err := objectConfirmPolicyTags(ctx, obj, result)
  234. if err != nil {
  235. log.Errorf("IsAllowPerform %s", err)
  236. return false
  237. } else {
  238. return true
  239. }
  240. }
  241. func IsAdminAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
  242. return IsAllowPerform(ctx, rbacscope.ScopeSystem, userCred, obj, action)
  243. }
  244. func IsDomainAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
  245. return IsAllowPerform(ctx, rbacscope.ScopeDomain, userCred, obj, action)
  246. }
  247. func IsProjectAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
  248. return IsAllowPerform(ctx, rbacscope.ScopeProject, userCred, obj, action)
  249. }
  250. func IsAllowUpdate(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
  251. if userCred == nil {
  252. return false
  253. }
  254. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionUpdate)
  255. err := objectConfirmPolicyTags(ctx, obj, result)
  256. if err != nil {
  257. log.Errorf("IsAllowUpdate %s", err)
  258. return false
  259. } else {
  260. return true
  261. }
  262. }
  263. func IsAdminAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  264. return IsAllowUpdate(ctx, rbacscope.ScopeSystem, userCred, obj)
  265. }
  266. func IsDomainAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  267. return IsAllowUpdate(ctx, rbacscope.ScopeDomain, userCred, obj)
  268. }
  269. func IsProjectAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  270. return IsAllowUpdate(ctx, rbacscope.ScopeProject, userCred, obj)
  271. }
  272. func IsAllowUpdateSpec(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  273. if userCred == nil {
  274. return false
  275. }
  276. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionUpdate, spec)
  277. err := objectConfirmPolicyTags(ctx, obj, result)
  278. if err != nil {
  279. log.Errorf("IsAllowUpdateSpec %s", err)
  280. return false
  281. } else {
  282. return true
  283. }
  284. }
  285. func IsAdminAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  286. return IsAllowUpdateSpec(ctx, rbacscope.ScopeSystem, userCred, obj, spec)
  287. }
  288. func IsDomainAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  289. return IsAllowUpdateSpec(ctx, rbacscope.ScopeDomain, userCred, obj, spec)
  290. }
  291. func IsProjectAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
  292. return IsAllowUpdateSpec(ctx, rbacscope.ScopeProject, userCred, obj, spec)
  293. }
  294. func IsAllowDelete(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
  295. if userCred == nil {
  296. return false
  297. }
  298. result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionDelete)
  299. err := objectConfirmPolicyTags(ctx, obj, result)
  300. if err != nil {
  301. log.Errorf("IsAllowDelete %s", err)
  302. return false
  303. } else {
  304. return true
  305. }
  306. }
  307. func IsAdminAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  308. return IsAllowDelete(ctx, rbacscope.ScopeSystem, userCred, obj)
  309. }
  310. func IsDomainAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  311. return IsAllowDelete(ctx, rbacscope.ScopeDomain, userCred, obj)
  312. }
  313. func IsProjectAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
  314. return IsAllowDelete(ctx, rbacscope.ScopeProject, userCred, obj)
  315. }