Automatic merge from release/2.3.0 -> release/2.4.0

* commit '4b4dd155c7b344a14a224e85599d133501e89c52':
  fix format
  修正:增加owner级别权限,放置普通用户可以访问系统资源
This commit is contained in:
邱剑
2018-11-08 19:59:50 +08:00
11 changed files with 222 additions and 112 deletions
+30 -21
View File
@@ -24,6 +24,7 @@ import (
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/logclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type DBModelDispatcher struct {
@@ -265,7 +266,10 @@ func listItemQueryFilters(manager IModelManager, ctx context.Context, q *sqlchem
userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*sqlchemy.SQuery, error) {
if !jsonutils.QueryBoolean(query, "admin", false) {
q = manager.FilterByOwner(q, manager.GetOwnerId(userCred))
ownerId := manager.GetOwnerId(userCred)
if len(ownerId) > 0 {
q = manager.FilterByOwner(q, ownerId)
}
}
q, err := manager.ListItemFilter(ctx, q, userCred, query)
if err != nil {
@@ -500,8 +504,13 @@ func (dispatcher *DBModelDispatcher) List(ctx context.Context, query jsonutils.J
var isAllow bool
if consts.IsRbacEnabled() {
isAdmin := jsonutils.QueryBoolean(query, "admin", false)
isAllow = policy.PolicyManager.Allow(isAdmin, userCred, consts.GetServiceType(),
dispatcher.modelManager.KeywordPlural(), policy.PolicyActionList)
manager := dispatcher.modelManager
jointManager, ok := manager.(IJointModelManager)
if ok {
isAllow = isJointListRbacAllowed(jointManager, userCred, isAdmin)
} else {
isAllow = isListRbacAllowed(manager, userCred, isAdmin)
}
} else {
isAllow = dispatcher.modelManager.AllowListItems(ctx, userCred, query)
}
@@ -611,7 +620,7 @@ func (dispatcher *DBModelDispatcher) Get(ctx context.Context, idStr string, quer
// log.Debugf("Get found %s", model)
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionGet)
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionGet)
} else {
isAllow = model.AllowGetDetails(ctx, userCred, query)
}
@@ -642,7 +651,7 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionGet, spec)
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionGet, spec)
} else {
funcName := fmt.Sprintf("AllowGetDetails%s", specCamel)
@@ -686,21 +695,21 @@ func (dispatcher *DBModelDispatcher) GetSpecific(ctx context.Context, idStr stri
}
}
func fetchOwnerProjectId(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (string, error) {
func fetchOwnerProjectId(ctx context.Context, manager IModelManager, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (string, error) {
var projId string
if data != nil {
projId, _ = data.GetString("project")
if len(projId) == 0 {
projId, _ = data.GetString("tenant")
}
projId = jsonutils.GetAnyString(data, []string{"project", "tenant", "project_id", "tenant_id"})
}
if len(projId) == 0 {
return userCred.GetProjectId(), nil
return manager.GetOwnerId(userCred), nil
}
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = policy.PolicyManager.Allow(true, userCred,
result := policy.PolicyManager.Allow(true, userCred,
consts.GetServiceType(), policy.PolicyDelegation, "")
if result == rbacutils.Allow {
isAllow = true
}
} else {
isAllow = userCred.IsSystemAdmin()
}
@@ -798,7 +807,7 @@ func doCreateItem(manager IModelManager, ctx context.Context, userCred mcclient.
func (dispatcher *DBModelDispatcher) Create(ctx context.Context, query jsonutils.JSONObject, data jsonutils.JSONObject, ctxId string) (jsonutils.JSONObject, error) {
userCred := fetchUserCredential(ctx)
ownerProjId, err := fetchOwnerProjectId(ctx, userCred, data)
ownerProjId, err := fetchOwnerProjectId(ctx, dispatcher.modelManager, userCred, data)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
@@ -821,7 +830,7 @@ func (dispatcher *DBModelDispatcher) Create(ctx context.Context, query jsonutils
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, nil, userCred, policy.PolicyActionCreate)
isAllow = isClassActionRbacAllowed(dispatcher.modelManager, userCred, ownerProjId, policy.PolicyActionCreate)
} else {
isAllow = dispatcher.modelManager.AllowCreateItem(ctx, userCred, query, data)
}
@@ -864,7 +873,7 @@ func expandMultiCreateParams(data jsonutils.JSONObject, count int) ([]jsonutils.
func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query jsonutils.JSONObject, data jsonutils.JSONObject, count int, ctxId string) ([]modules.SubmitResult, error) {
userCred := fetchUserCredential(ctx)
ownerProjId, err := fetchOwnerProjectId(ctx, userCred, data)
ownerProjId, err := fetchOwnerProjectId(ctx, dispatcher.modelManager, userCred, data)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
@@ -885,7 +894,7 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, nil, userCred, policy.PolicyActionCreate)
isAllow = isClassActionRbacAllowed(dispatcher.modelManager, userCred, ownerProjId, policy.PolicyActionCreate)
} else {
isAllow = dispatcher.modelManager.AllowCreateItem(ctx, userCred, query, data)
}
@@ -933,7 +942,7 @@ func (dispatcher *DBModelDispatcher) BatchCreate(ctx context.Context, query json
func (dispatcher *DBModelDispatcher) PerformClassAction(ctx context.Context, action string, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
userCred := fetchUserCredential(ctx)
ownerProjId, err := fetchOwnerProjectId(ctx, userCred, data)
ownerProjId, err := fetchOwnerProjectId(ctx, dispatcher.modelManager, userCred, data)
if err != nil {
return nil, httperrors.NewGeneralError(err)
}
@@ -952,7 +961,7 @@ func (dispatcher *DBModelDispatcher) PerformClassAction(ctx context.Context, act
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(manager, nil, userCred, policy.PolicyActionPerform, action)
isAllow = isClassActionRbacAllowed(manager, userCred, ownerProjId, policy.PolicyActionPerform, action)
} else {
isAllow = manager.AllowPerformCheckCreateData(ctx, userCred, query, data)
}
@@ -1030,7 +1039,7 @@ func objectPerformAction(dispatcher *DBModelDispatcher, model IModel, modelValue
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionPerform, action)
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionPerform, action)
} else {
allowFuncName := "Allow" + funcName
allowFuncValue := modelValue.MethodByName(allowFuncName)
@@ -1142,7 +1151,7 @@ func (dispatcher *DBModelDispatcher) Update(ctx context.Context, idStr string, q
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionUpdate)
isAllow = isObjectRbacAllowed(dispatcher.modelManager, model, userCred, policy.PolicyActionUpdate)
} else {
isAllow = model.AllowUpdateItem(ctx, userCred)
}
@@ -1178,7 +1187,7 @@ func deleteItem(manager IModelManager, model IModel, ctx context.Context, userCr
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isRbacAllowed(manager, model, userCred, policy.PolicyActionDelete)
isAllow = isObjectRbacAllowed(manager, model, userCred, policy.PolicyActionDelete)
} else {
isAllow = model.AllowDeleteItem(ctx, userCred, query, data)
}
+4 -5
View File
@@ -103,8 +103,7 @@ func (dispatcher *DBJointModelDispatcher) _listJoint(ctx context.Context, userCr
var isAllow bool
if consts.IsRbacEnabled() {
isAdmin := jsonutils.QueryBoolean(queryDict, "admin", false)
isAllow = policy.PolicyManager.Allow(isAdmin, userCred, consts.GetServiceType(),
dispatcher.JointModelManager().KeywordPlural(), policy.PolicyActionList)
isAllow = isJointListRbacAllowed(dispatcher.JointModelManager(), userCred, isAdmin)
} else {
isAllow = dispatcher.JointModelManager().AllowListDescendent(ctx, userCred, ctxModel, queryDict)
}
@@ -147,7 +146,7 @@ func (dispatcher *DBJointModelDispatcher) Get(ctx context.Context, id1 string, i
}
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isJointRbacAllowed(dispatcher.JointModelManager(), item, userCred, policy.PolicyActionGet)
isAllow = isJointObjectRbacAllowed(dispatcher.JointModelManager(), item, userCred, policy.PolicyActionGet)
} else {
isAllow = item.AllowGetJointDetails(ctx, userCred, query, item)
}
@@ -161,7 +160,7 @@ func attachItems(dispatcher *DBJointModelDispatcher, master IStandaloneModel, sl
if !dispatcher.JointModelManager().AllowAttach(ctx, userCred, master, slave) {
return nil, httperrors.NewForbiddenError("Not allow to attach")
}
ownerProjId, err := fetchOwnerProjectId(ctx, userCred, data)
ownerProjId, err := fetchOwnerProjectId(ctx, dispatcher.JointModelManager(), userCred, data)
dataDict, ok := data.(*jsonutils.JSONDict)
if !ok {
return nil, fmt.Errorf("body not a json dict")
@@ -218,7 +217,7 @@ func (dispatcher *DBJointModelDispatcher) Update(ctx context.Context, id1 string
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = isJointRbacAllowed(dispatcher.JointModelManager(), item, userCred, policy.PolicyActionUpdate)
isAllow = isJointObjectRbacAllowed(dispatcher.JointModelManager(), item, userCred, policy.PolicyActionUpdate)
} else {
isAllow = item.AllowUpdateJointItem(ctx, userCred, item)
}
+5 -1
View File
@@ -38,7 +38,11 @@ func NewJointResourceBaseManager(dt interface{}, tableName string, keyword strin
log.Errorf(msg)
panic(msg)
}
return SJointResourceBaseManager{SResourceBaseManager: NewResourceBaseManager(dt, tableName, keyword, keywordPlural), _master: master, _slave: slave}
return SJointResourceBaseManager{
SResourceBaseManager: NewResourceBaseManager(dt, tableName, keyword, keywordPlural),
_master: master,
_slave: slave,
}
}
func (manager *SJointResourceBaseManager) GetMasterManager() IStandaloneModelManager {
+12 -9
View File
@@ -16,6 +16,7 @@ import (
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
var _manager *SQuotaManager
@@ -78,8 +79,9 @@ func getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
if len(projectId) == 0 {
projectId = userCred.GetProjectId()
if consts.IsRbacEnabled() {
if !policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet) {
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet)
if result == rbacutils.Deny {
httperrors.ForbiddenError(w, "not allow to get quota")
return
}
@@ -87,8 +89,9 @@ func getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
} else {
isAllow := false
if consts.IsRbacEnabled() {
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
result := policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
policy.PolicyDelegation, policy.PolicyActionGet)
isAllow = result == rbacutils.Allow
} else {
isAllow = userCred.IsSystemAdmin()
}
@@ -97,8 +100,8 @@ func getQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
return
}
if consts.IsRbacEnabled() {
if !policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet) {
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet) != rbacutils.Allow {
httperrors.ForbiddenError(w, "not allow to query quota")
return
}
@@ -135,7 +138,7 @@ func setQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Request
var isAllow bool
if consts.IsRbacEnabled() {
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionUpdate)
"quotas", policy.PolicyActionUpdate) == rbacutils.Allow
} else {
isAllow = userCred.IsSystemAdmin()
}
@@ -198,7 +201,7 @@ func checkQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Reque
isAllow := false
if consts.IsRbacEnabled() {
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
policy.PolicyDelegation, policy.PolicyActionGet)
policy.PolicyDelegation, policy.PolicyActionGet) == rbacutils.Allow
} else {
isAllow = userCred.IsSystemAdmin()
}
@@ -207,8 +210,8 @@ func checkQuotaHanlder(ctx context.Context, w http.ResponseWriter, r *http.Reque
return
}
if consts.IsRbacEnabled() {
if !policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet) {
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"quotas", policy.PolicyActionGet) != rbacutils.Allow {
httperrors.ForbiddenError(w, "not allow to query quota")
return
}
+87 -42
View File
@@ -1,57 +1,102 @@
package db
import (
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
func isRbacAllowed(manager IModelManager, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
var isAllow bool
var isAdmin bool
if model == nil {
_, ok := manager.(IVirtualModelManager)
if ok {
isAdmin = false
}
} else {
virtModel, ok := model.(IVirtualModel)
if ok {
if virtModel.IsOwner(userCred) {
isAdmin = false
} else {
isAdmin = true
}
} else {
isAdmin = true
}
}
if !isAdmin {
isAllow = policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
}
if !isAllow {
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
}
return isAllow
func isListRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential, isAdminMode bool) bool {
return isListRbacAllowedInternal(manager, manager.KeywordPlural(), userCred, isAdminMode)
}
func isJointRbacAllowed(manager IJointModelManager, item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
isAllow := false
isAdmin := true
master := item.Master()
virtualMaster, ok := master.(IVirtualModel)
if ok && virtualMaster.IsOwner(userCred) {
isAdmin = false
func isListRbacAllowedInternal(manager IModelManager, resource string, userCred mcclient.TokenCredential, isAdminMode bool) bool {
log.Debugf("%s %s", manager.KeywordPlural(), resource)
var requireAdmin bool
ownerId := manager.GetOwnerId(userCred)
if len(ownerId) > 0 {
if isAdminMode {
requireAdmin = true
} else {
requireAdmin = false
}
} else {
requireAdmin = true
}
if !isAdmin {
isAllow = policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
resource, policy.PolicyActionList)
log.Debugf("allow list for non-admin %s %v ownerId: %s", result, requireAdmin, ownerId)
if (result == rbacutils.OwnerAllow && !requireAdmin) || (result == rbacutils.Allow && requireAdmin) {
return true
}
if !isAllow {
isAllow = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
result = policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
resource, policy.PolicyActionList)
log.Debugf("allow list for admin %s %v ownerId: %s", result, requireAdmin, ownerId)
return result == rbacutils.Allow
}
func isJointListRbacAllowed(manager IJointModelManager, userCred mcclient.TokenCredential, isAdminMode bool) bool {
return isListRbacAllowedInternal(manager.GetMasterManager(), manager.KeywordPlural(), userCred, isAdminMode)
}
func isClassActionRbacAllowed(manager IModelManager, userCred mcclient.TokenCredential, ownerProjId string, action string, extra ...string) bool {
var requireAdmin bool
ownerId := manager.GetOwnerId(userCred)
if len(ownerId) > 0 {
if ownerProjId == ownerId {
requireAdmin = false
} else {
requireAdmin = true
}
} else {
requireAdmin = true
}
if !requireAdmin {
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
if result == rbacutils.Allow || result == rbacutils.OwnerAllow {
return true
}
}
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
return result == rbacutils.Allow
}
func isObjectRbacAllowed(manager IModelManager, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
var requireAdmin bool
var isOwner bool
ownerId := model.GetModelManager().GetOwnerId(userCred)
if len(ownerId) > 0 {
objOwnerId := model.GetOwnerProjectId()
if ownerId == objOwnerId {
isOwner = true
requireAdmin = false
} else {
isOwner = false
requireAdmin = true
}
} else {
requireAdmin = true
}
if !requireAdmin {
result := policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
if result == rbacutils.Allow || (result == rbacutils.OwnerAllow && isOwner) {
return true
}
}
return isAllow
result := policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
manager.KeywordPlural(), action, extra...)
return result == rbacutils.Allow
}
func isJointObjectRbacAllowed(manager IJointModelManager, item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
return isObjectRbacAllowed(manager, item.Master(), userCred, action, extra...)
}
+1 -1
View File
@@ -37,7 +37,7 @@ func (manager *SResourceBaseManager) RawQuery(fields ...string) *sqlchemy.SQuery
}
func (manager *SResourceBaseManager) DoCreate(ctx context.Context, userCred mcclient.TokenCredential, kwargs jsonutils.JSONObject, data jsonutils.JSONObject, realManager IModelManager) (IModel, error) {
ownerProjId, err := fetchOwnerProjectId(ctx, userCred, kwargs)
ownerProjId, err := fetchOwnerProjectId(ctx, manager, userCred, kwargs)
if err != nil {
return nil, err
}
+13 -16
View File
@@ -135,7 +135,7 @@ func (manager *SPolicyManager) sync() {
time.AfterFunc(PolicyRefreshInterval, manager.sync)
}
func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCredential, service string, resource string, action string, extra ...string) bool {
func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCredential, service string, resource string, action string, extra ...string) rbacutils.TRbacResult {
var policies map[string]rbacutils.SRbacPolicy
if isAdmin {
policies = manager.adminPolicies
@@ -144,29 +144,30 @@ func (manager *SPolicyManager) Allow(isAdmin bool, userCred mcclient.TokenCreden
}
if policies == nil {
log.Warningf("no policies fetched")
return false
return rbacutils.Deny
}
userCredJson := userCred.ToJson()
// log.Debugf("%s", userCredJson)
currentPriv := rbacutils.Deny
for _, p := range policies {
if p.Allow(userCredJson, service, resource, action, extra...) {
return true
result := p.Allow(userCredJson, service, resource, action, extra...)
if result.IsHigherPrivilege(currentPriv) {
currentPriv = result
}
}
return false
return currentPriv
}
func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential, policyReq jsonutils.JSONObject) (bool, error) {
func (manager *SPolicyManager) explainPolicy(userCred mcclient.TokenCredential, policyReq jsonutils.JSONObject) (rbacutils.TRbacResult, error) {
policySeq, err := policyReq.GetArray()
if err != nil {
return false, httperrors.NewInputParameterError("invalid format")
return rbacutils.Deny, httperrors.NewInputParameterError("invalid format")
}
isAdmin, _ := policySeq[0].Bool()
if !consts.IsRbacEnabled() {
if !isAdmin || (isAdmin && userCred.IsSystemAdmin()) {
return true, nil
return rbacutils.Allow, nil
} else {
return false, httperrors.NewForbiddenError("operation not allowed")
return rbacutils.Deny, httperrors.NewForbiddenError("operation not allowed")
}
}
service := rbacutils.WILD_MATCH
@@ -198,15 +199,11 @@ func (manager *SPolicyManager) ExplainRpc(userCred mcclient.TokenCredential, par
}
ret := jsonutils.NewDict()
for key, policyReq := range paramDict {
allow, err := manager.explainPolicy(userCred, policyReq)
result, err := manager.explainPolicy(userCred, policyReq)
if err != nil {
return nil, err
}
if allow {
ret.Add(jsonutils.JSONTrue, key)
} else {
ret.Add(jsonutils.JSONFalse, key)
}
ret.Add(jsonutils.NewString(string(result)), key)
}
return ret, nil
}
+8
View File
@@ -75,6 +75,14 @@ type SCloudprovider struct {
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
}
func (manager *SCloudproviderManager) GetOwnerId(userCred mcclient.IIdentityProvider) string {
return userCred.GetProjectId()
}
func (self *SCloudprovider) GetOwnerProjectId() string {
return self.ProjectId
}
func (self *SCloudprovider) ValidateDeleteCondition(ctx context.Context) error {
if self.Enabled {
return httperrors.NewInvalidStatusError("provider is enabled")
+4 -3
View File
@@ -20,6 +20,7 @@ import (
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/auth"
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
type Usage map[string]interface{}
@@ -271,7 +272,7 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
if consts.IsRbacEnabled() {
if policy.PolicyManager.Allow(true, userCred, consts.GetServiceType(),
"usages", policy.PolicyActionGet) {
"usages", policy.PolicyActionGet) == rbacutils.Allow {
isAdmin = true
}
} else {
@@ -286,8 +287,8 @@ func ReportGeneralUsage(userCred mcclient.TokenCredential, rangeObj db.IStandalo
}
if consts.IsRbacEnabled() {
if !policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
"usages", policy.PolicyActionGet) {
if policy.PolicyManager.Allow(false, userCred, consts.GetServiceType(),
"usages", policy.PolicyActionGet) == rbacutils.Deny {
err = httperrors.NewForbiddenError("not allow to get usages")
return
}
+33 -11
View File
@@ -12,10 +12,32 @@ type TRbacResult string
const (
WILD_MATCH = "*"
Allow = TRbacResult("allow")
OwnerAllow = TRbacResult("owner")
Deny = TRbacResult("deny")
)
func (result TRbacResult) IsHigherPrivilege(r2 TRbacResult) bool {
switch result {
case Allow:
if r2 == Allow {
return false
} else {
return true
}
case OwnerAllow:
if r2 == Deny {
return true
} else {
return false
}
case Deny:
return false
}
return false
}
type SRbacPolicy struct {
Condition string
IsAdmin bool
@@ -185,11 +207,14 @@ func decode(rules jsonutils.JSONObject, decodeRule SRbacRule, level int) ([]SRba
case *jsonutils.JSONString:
ruleJsonStr := rules.(*jsonutils.JSONString)
ruleStr, _ := ruleJsonStr.GetString()
if ruleStr == string(Allow) {
switch ruleStr {
case string(Allow):
decodeRule.Result = Allow
} else if ruleStr == string(Deny) {
case string(OwnerAllow):
decodeRule.Result = OwnerAllow
case string(Deny):
decodeRule.Result = Deny
} else {
default:
return nil, fmt.Errorf("unsupported rule string %s", ruleStr)
}
return []SRbacRule{decodeRule}, nil
@@ -318,23 +343,20 @@ func (policy *SRbacPolicy) Explain(request [][]string) [][]string {
return output
}
func (policy *SRbacPolicy) Allow(userCred jsonutils.JSONObject, service, resource, action string, extra ...string) bool {
func (policy *SRbacPolicy) Allow(userCred jsonutils.JSONObject, service, resource, action string, extra ...string) TRbacResult {
if len(policy.Condition) > 0 {
match, err := conditionparser.Eval(policy.Condition, userCred)
if err != nil {
log.Errorf("eval condition %s fail %s", policy.Condition, err)
return false
return Deny
}
if !match {
return false
return Deny
}
}
rule := policy.GetMatchRule(service, resource, action, extra...)
if rule == nil {
return false
return Deny
}
if rule.Result == Deny {
return false
}
return true
return rule.Result
}
+25 -3
View File
@@ -191,7 +191,7 @@ func TestSRbacPolicy_Allow(t *testing.T) {
cases := []struct {
policy string
ops []string
want bool
want TRbacResult
}{
{
`{
@@ -202,12 +202,12 @@ func TestSRbacPolicy_Allow(t *testing.T) {
}
}`,
[]string{"compute", "servers", "list"},
true,
Allow,
},
{
`{"is_admin":"false","policy":{"*":{"*":{"*":"allow","delete":"deny"}}}}`,
[]string{"compute", "servers", "delete"},
false,
Deny,
},
}
@@ -280,3 +280,25 @@ func TestSRabcPolicy_Explain(t *testing.T) {
t.Logf("%#v", output)
}
func TestTRbacResult_IsHigherPrivilege(t *testing.T) {
cases := []struct {
t1 TRbacResult
t2 TRbacResult
want bool
}{
{Allow, Allow, false},
{Allow, OwnerAllow, true},
{Deny, Deny, false},
{Deny, OwnerAllow, false},
{Deny, Allow, false},
{OwnerAllow, Allow, false},
}
for _, c := range cases {
got := c.t1.IsHigherPrivilege(c.t2)
if got != c.want {
t.Errorf("%s IsHigherPrivilege %s want %v got %v", c.t1, c.t2, c.want, got)
}
}
}