mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-06-20 11:22:19 +08:00
369 lines
15 KiB
Go
369 lines
15 KiB
Go
// Copyright 2019 Yunion
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
package db
|
|
|
|
import (
|
|
"context"
|
|
|
|
"yunion.io/x/log"
|
|
"yunion.io/x/pkg/errors"
|
|
"yunion.io/x/pkg/util/rbacscope"
|
|
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
|
|
"yunion.io/x/onecloud/pkg/cloudcommon/policy"
|
|
"yunion.io/x/onecloud/pkg/httperrors"
|
|
"yunion.io/x/onecloud/pkg/mcclient"
|
|
"yunion.io/x/onecloud/pkg/util/rbacutils"
|
|
)
|
|
|
|
func IsObjectRbacAllowed(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
|
return isObjectRbacAllowed(ctx, model, userCred, action, extra...)
|
|
}
|
|
|
|
func isObjectRbacAllowed(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
|
_, err := isObjectRbacAllowedResult(ctx, model, userCred, action, extra...)
|
|
return err
|
|
}
|
|
|
|
func isObjectRbacAllowedResult(ctx context.Context, model IModel, userCred mcclient.TokenCredential, action string, extra ...string) (rbacutils.SPolicyResult, error) {
|
|
manager := model.GetModelManager()
|
|
objOwnerId := model.GetOwnerId()
|
|
|
|
var ownerId mcclient.IIdentityProvider
|
|
if userCred != nil {
|
|
ownerId = userCred
|
|
}
|
|
|
|
var requireScope rbacscope.TRbacScope
|
|
resScope := manager.ResourceScope()
|
|
switch resScope {
|
|
case rbacscope.ScopeSystem:
|
|
requireScope = rbacscope.ScopeSystem
|
|
case rbacscope.ScopeDomain:
|
|
if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() && action == policy.PolicyActionGet) {
|
|
requireScope = rbacscope.ScopeUser
|
|
} else if ownerId != nil && objOwnerId != nil && (ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() || objOwnerId.GetProjectDomainId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
case rbacscope.ScopeUser:
|
|
if ownerId != nil && objOwnerId != nil && (ownerId.GetUserId() == objOwnerId.GetUserId() || objOwnerId.GetUserId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
|
|
requireScope = rbacscope.ScopeUser
|
|
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectId() == objOwnerId.GetProjectId() {
|
|
requireScope = rbacscope.ScopeProject
|
|
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
default:
|
|
// objOwnerId should not be nil
|
|
if ownerId != nil && objOwnerId != nil && (ownerId.GetProjectId() == objOwnerId.GetProjectId() || objOwnerId.GetProjectId() == "" || (model.IsSharable(ownerId) && action == policy.PolicyActionGet)) {
|
|
requireScope = rbacscope.ScopeProject
|
|
} else if ownerId != nil && objOwnerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
}
|
|
|
|
scope, result := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
|
|
|
|
if result.Result.IsAllow() && !requireScope.HigherThan(scope) {
|
|
err := objectConfirmPolicyTags(ctx, model, result)
|
|
if err != nil {
|
|
return rbacutils.PolicyDeny, errors.Wrap(err, "objectConfirmPolicyTags")
|
|
}
|
|
return result, nil
|
|
}
|
|
return rbacutils.PolicyDeny, httperrors.NewForbiddenError("not enough privilege (require:%s,allow:%s:resource:%s) [tags:%s]", requireScope, scope, resScope, result.String())
|
|
}
|
|
|
|
func isJointObjectRbacAllowed(ctx context.Context, item IJointModel, userCred mcclient.TokenCredential, action string, extra ...string) error {
|
|
err1 := isObjectRbacAllowed(ctx, JointMaster(item), userCred, action, extra...)
|
|
err2 := isObjectRbacAllowed(ctx, JointSlave(item), userCred, action, extra...)
|
|
if err1 == nil || err2 == nil {
|
|
return nil
|
|
}
|
|
return err1
|
|
}
|
|
|
|
func isClassRbacAllowed(ctx context.Context, manager IModelManager, userCred mcclient.TokenCredential, objOwnerId mcclient.IIdentityProvider, action string, extra ...string) (rbacutils.SPolicyResult, error) {
|
|
var ownerId mcclient.IIdentityProvider
|
|
if userCred != nil {
|
|
ownerId = userCred
|
|
}
|
|
|
|
var requireScope rbacscope.TRbacScope
|
|
resScope := manager.ResourceScope()
|
|
switch resScope {
|
|
case rbacscope.ScopeSystem:
|
|
requireScope = rbacscope.ScopeSystem
|
|
case rbacscope.ScopeDomain:
|
|
// objOwnerId should not be nil
|
|
if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
case rbacscope.ScopeUser:
|
|
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
|
|
requireScope = rbacscope.ScopeUser
|
|
} else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
default:
|
|
// objOwnerId should not be nil
|
|
if ownerId != nil && ownerId.GetProjectId() == objOwnerId.GetProjectId() {
|
|
requireScope = rbacscope.ScopeProject
|
|
} else if ownerId != nil && ownerId.GetProjectDomainId() == objOwnerId.GetProjectDomainId() {
|
|
requireScope = rbacscope.ScopeDomain
|
|
} else {
|
|
requireScope = rbacscope.ScopeSystem
|
|
}
|
|
}
|
|
|
|
allowScope, result := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), action, extra...)
|
|
|
|
if result.Result.IsAllow() && !requireScope.HigherThan(allowScope) {
|
|
err := classConfirmPolicyTags(ctx, manager, objOwnerId, result)
|
|
if err != nil {
|
|
return rbacutils.PolicyDeny, errors.Wrap(err, "classConfirmPolicyTags")
|
|
}
|
|
return result, nil
|
|
}
|
|
return rbacutils.PolicyDeny, httperrors.NewForbiddenError("not enough privilege (require:%s,allow:%s)", requireScope, allowScope)
|
|
}
|
|
|
|
type IResource interface {
|
|
KeywordPlural() string
|
|
}
|
|
|
|
func IsAllowList(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
if userCred == nil {
|
|
return rbacutils.PolicyDeny
|
|
}
|
|
return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
|
|
}
|
|
|
|
func IsAdminAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowList(rbacscope.ScopeSystem, userCred, manager)
|
|
}
|
|
|
|
func IsDomainAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowList(rbacscope.ScopeDomain, userCred, manager)
|
|
}
|
|
|
|
func IsProjectAllowList(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowList(rbacscope.ScopeProject, userCred, manager)
|
|
}
|
|
|
|
func IsAllowCreate(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
if userCred == nil {
|
|
return rbacutils.PolicyDeny
|
|
}
|
|
return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionCreate)
|
|
}
|
|
|
|
func IsAdminAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowCreate(rbacscope.ScopeSystem, userCred, manager)
|
|
}
|
|
|
|
func IsDomainAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowCreate(rbacscope.ScopeDomain, userCred, manager)
|
|
}
|
|
|
|
func IsProjectAllowCreate(userCred mcclient.TokenCredential, manager IResource) rbacutils.SPolicyResult {
|
|
return IsAllowCreate(rbacscope.ScopeProject, userCred, manager)
|
|
}
|
|
|
|
func IsAllowClassPerform(scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
|
|
if userCred == nil {
|
|
return rbacutils.PolicyDeny
|
|
}
|
|
return policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionPerform, action)
|
|
}
|
|
|
|
func IsAdminAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
|
|
return IsAllowClassPerform(rbacscope.ScopeSystem, userCred, manager, action)
|
|
}
|
|
|
|
func IsDomainAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
|
|
return IsAllowClassPerform(rbacscope.ScopeDomain, userCred, manager, action)
|
|
}
|
|
|
|
func IsProjectAllowClassPerform(userCred mcclient.TokenCredential, manager IResource, action string) rbacutils.SPolicyResult {
|
|
return IsAllowClassPerform(rbacscope.ScopeProject, userCred, manager, action)
|
|
}
|
|
|
|
func IsAllowGet(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionGet)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowGet %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowGet(ctx, rbacscope.ScopeSystem, userCred, obj)
|
|
}
|
|
|
|
func IsDomainAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowGet(ctx, rbacscope.ScopeDomain, userCred, obj)
|
|
}
|
|
|
|
func IsProjectAllowGet(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowGet(ctx, rbacscope.ScopeProject, userCred, obj)
|
|
}
|
|
|
|
func IsAllowGetSpec(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionGet, spec)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowGetSpec %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowGetSpec(ctx, rbacscope.ScopeSystem, userCred, obj, spec)
|
|
}
|
|
|
|
func IsDomainAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowGetSpec(ctx, rbacscope.ScopeDomain, userCred, obj, spec)
|
|
}
|
|
|
|
func IsProjectAllowGetSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowGetSpec(ctx, rbacscope.ScopeProject, userCred, obj, spec)
|
|
}
|
|
|
|
func IsAllowPerform(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, action string) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionPerform, action)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowPerform %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
|
|
return IsAllowPerform(ctx, rbacscope.ScopeSystem, userCred, obj, action)
|
|
}
|
|
|
|
func IsDomainAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
|
|
return IsAllowPerform(ctx, rbacscope.ScopeDomain, userCred, obj, action)
|
|
}
|
|
|
|
func IsProjectAllowPerform(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, action string) bool {
|
|
return IsAllowPerform(ctx, rbacscope.ScopeProject, userCred, obj, action)
|
|
}
|
|
|
|
func IsAllowUpdate(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionUpdate)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowUpdate %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowUpdate(ctx, rbacscope.ScopeSystem, userCred, obj)
|
|
}
|
|
|
|
func IsDomainAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowUpdate(ctx, rbacscope.ScopeDomain, userCred, obj)
|
|
}
|
|
|
|
func IsProjectAllowUpdate(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowUpdate(ctx, rbacscope.ScopeProject, userCred, obj)
|
|
}
|
|
|
|
func IsAllowUpdateSpec(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionUpdate, spec)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowUpdateSpec %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowUpdateSpec(ctx, rbacscope.ScopeSystem, userCred, obj, spec)
|
|
}
|
|
|
|
func IsDomainAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowUpdateSpec(ctx, rbacscope.ScopeDomain, userCred, obj, spec)
|
|
}
|
|
|
|
func IsProjectAllowUpdateSpec(ctx context.Context, userCred mcclient.TokenCredential, obj IModel, spec string) bool {
|
|
return IsAllowUpdateSpec(ctx, rbacscope.ScopeProject, userCred, obj, spec)
|
|
}
|
|
|
|
func IsAllowDelete(ctx context.Context, scope rbacscope.TRbacScope, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
if userCred == nil {
|
|
return false
|
|
}
|
|
result := policy.PolicyManager.Allow(scope, userCred, consts.GetServiceType(), obj.KeywordPlural(), policy.PolicyActionDelete)
|
|
err := objectConfirmPolicyTags(ctx, obj, result)
|
|
if err != nil {
|
|
log.Errorf("IsAllowDelete %s", err)
|
|
return false
|
|
} else {
|
|
return true
|
|
}
|
|
}
|
|
|
|
func IsAdminAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowDelete(ctx, rbacscope.ScopeSystem, userCred, obj)
|
|
}
|
|
|
|
func IsDomainAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowDelete(ctx, rbacscope.ScopeDomain, userCred, obj)
|
|
}
|
|
|
|
func IsProjectAllowDelete(ctx context.Context, userCred mcclient.TokenCredential, obj IModel) bool {
|
|
return IsAllowDelete(ctx, rbacscope.ScopeProject, userCred, obj)
|
|
}
|