fix: bugs in scope support

This commit is contained in:
Qiu Jian
2019-06-04 23:27:55 +08:00
parent a6207a8ac7
commit 292c2a141c
30 changed files with 338 additions and 238 deletions
+6 -29
View File
@@ -19,41 +19,18 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
func init() {
type GroupListOptions struct {
Admin bool `help:"admin mode"`
Name string `help:"Name of the groups to filter"`
Domain string `help:"Domain to filter"`
Limit int64 `help:"Items per page" default:"20"`
Offset int64 `help:"Offset"`
Search string `help:"search text"`
options.BaseListOptions
Name string `help:"Filter by name"`
}
R(&GroupListOptions{}, "group-list", "List groups", func(s *mcclient.ClientSession, args *GroupListOptions) error {
params := jsonutils.NewDict()
if len(args.Name) > 0 {
params.Add(jsonutils.NewString(args.Name), "name")
}
if len(args.Domain) > 0 {
domainId, e := modules.Domains.GetId(s, args.Domain, nil)
if e != nil {
return e
}
params.Add(jsonutils.NewString(domainId), "domain_id")
params.Add(jsonutils.JSONTrue, "admin")
}
if args.Admin {
params.Add(jsonutils.JSONTrue, "admin")
}
if args.Limit > 0 {
params.Add(jsonutils.NewInt(args.Limit), "limit")
}
if args.Offset > 0 {
params.Add(jsonutils.NewInt(args.Offset), "offset")
}
if len(args.Search) > 0 {
params.Add(jsonutils.NewString(args.Search), "name__icontains")
params, err := options.ListStructToParams(args)
if err != nil {
return err
}
result, err := modules.Groups.List(s, params)
if err != nil {
+22
View File
@@ -40,6 +40,7 @@ func init() {
Type string `help:"filter by type"`
Format string `help:"policy format, default to yaml" default:"yaml" choices:"yaml|json"`
Admin bool `help:"admin mode"`
Scope string `help:""`
}
R(&PolicyListOptions{}, "policy-list", "List all policies", func(s *mcclient.ClientSession, args *PolicyListOptions) error {
params := jsonutils.NewDict()
@@ -136,6 +137,27 @@ func init() {
return nil
})
type PolicyPerformOptions struct {
ID string `help:"ID of policy to update"`
}
R(&PolicyPerformOptions{}, "policy-public", "Mark a policy public", func(s *mcclient.ClientSession, args *PolicyPerformOptions) error {
result, err := modules.Policies.PerformAction(s, args.ID, "public", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
R(&PolicyPerformOptions{}, "policy-private", "Mark a policy private", func(s *mcclient.ClientSession, args *PolicyPerformOptions) error {
result, err := modules.Policies.PerformAction(s, args.ID, "private", nil)
if err != nil {
return err
}
printObject(result)
return nil
})
type PolicyDeleteOptions struct {
ID string `help:"ID of policy"`
}
+5 -1
View File
@@ -26,7 +26,8 @@ type GeneralUsageOptions struct {
Provider []string `help:"Provider" choices:"VMware|Aliyun|Azure|Aws|Qcloud|Huawei|OpenStack|Ucloud|ZStack"`
Project string `help:"show usage of specified project"`
Domain string `help:"show usage of specified domain"`
CloudEnv string `help:"show usage of specified cloudenv, e.g public_cloud/private_cloud/on_premise" choices:"public|private|onpremise"`
CloudEnv string `help:"show usage of specified cloudenv, e.g. public_cloud/private_cloud/on_premise" choices:"public|private|onpremise"`
Scope string `help:"show usage of specified privilege scope, e.g. system/domain/project" choices:"system|domain|project"`
}
func fetchHostTypeOptions(args *GeneralUsageOptions) *jsonutils.JSONDict {
@@ -51,6 +52,9 @@ func init() {
} else if args.Domain != "" {
params.Add(jsonutils.NewString(args.Domain), "domain")
}
if len(args.Scope) > 0 {
params.Add(jsonutils.NewString(args.Scope), "scope")
}
result, err := modules.Usages.GetGeneralUsage(s, params)
if err != nil {
return err
+6 -44
View File
@@ -19,56 +19,18 @@ import (
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/mcclient/options"
)
func init() {
type UserListOptions struct {
System bool `help:"system mode"`
Admin bool `help:"admin mode"`
Domain string `help:"Filter by domain"`
Name string `help:"Filter by name"`
Limit int64 `help:"Limit, default 0, i.e. no limit"`
Offset int64 `help:"Offset, default 0, i.e. no offset"`
Search string `help:"Search by name"`
DefaultProject string `help:"Filter by default_project_id"`
NoDefaultProject bool `help:"Filter users without valid default_project_id"`
options.BaseListOptions
Name string `help:"Filter by name"`
}
R(&UserListOptions{}, "user-list", "List users", func(s *mcclient.ClientSession, args *UserListOptions) error {
params := jsonutils.NewDict()
if len(args.Domain) > 0 {
domainId, err := modules.Domains.GetId(s, args.Domain, nil)
if err != nil {
return err
}
params.Add(jsonutils.NewString(domainId), "domain_id")
params.Add(jsonutils.JSONTrue, "admin")
}
if args.Admin {
params.Add(jsonutils.JSONTrue, "admin")
}
if args.System {
params.Add(jsonutils.JSONTrue, "system")
}
if len(args.Name) > 0 {
params.Add(jsonutils.NewString(args.Name), "name")
}
if len(args.Search) > 0 {
params.Add(jsonutils.NewString(args.Search), "name__icontains")
}
if args.Limit > 0 {
params.Add(jsonutils.NewInt(args.Limit), "limit")
}
if args.Offset > 0 {
params.Add(jsonutils.NewInt(args.Offset), "offset")
}
if len(args.DefaultProject) > 0 {
projId, err := modules.Projects.GetId(s, args.DefaultProject, nil)
if err != nil {
return err
}
params.Add(jsonutils.NewString(projId), "default_project_id")
} else if args.NoDefaultProject {
params.Add(jsonutils.NewString(""), "default_project_id__iempty")
params, err := options.ListStructToParams(args)
if err != nil {
return err
}
result, err := modules.UsersV3.List(s, params)
if err != nil {
+7 -2
View File
@@ -36,8 +36,13 @@ func (manager *SDomainizedResourceBaseManager) ResourceScope() rbacutils.TRbacSc
}
func (manager *SDomainizedResourceBaseManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
if owner != nil && len(owner.GetProjectDomainId()) > 0 {
q = q.Equals("domain_id", owner.GetProjectDomainId())
if owner != nil {
switch scope {
case rbacutils.ScopeDomain:
if len(owner.GetProjectDomainId()) > 0 {
q = q.Equals("domain_id", owner.GetProjectDomainId())
}
}
}
return q
}
+32 -49
View File
@@ -255,7 +255,7 @@ func FetchProjectInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient.
}
return &ownerId, nil
}
return nil, nil
return FetchDomainInfo(ctx, data)
}
func FetchDomainInfo(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
@@ -284,6 +284,10 @@ func (m *sUsageManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeProject
}
func (m *sUsageManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
return FetchProjectInfo(ctx, data)
}
func FetchUsageOwnerScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) (mcclient.IIdentityProvider, rbacutils.TRbacScope, error) {
return FetchQueryOwnerScope(ctx, userCred, data, &sUsageManager{}, policy.PolicyActionGet)
}
@@ -291,6 +295,7 @@ func FetchUsageOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
type IScopedResourceManager interface {
KeywordPlural() string
ResourceScope() rbacutils.TRbacScope
FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error)
}
func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject, manager IScopedResourceManager, action string) (mcclient.IIdentityProvider, rbacutils.TRbacScope, error) {
@@ -315,65 +320,43 @@ func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
}
}
ownerId, err := FetchProjectInfo(ctx, data)
// var ownerId mcclient.IIdentityProvider
// var err error
ownerId, err := manager.FetchOwnerId(ctx, data)
if err != nil {
return nil, queryScope, err
}
if ownerId != nil {
if resScope == rbacutils.ScopeProject {
queryScope = rbacutils.ScopeProject
if ownerId.GetProjectId() == userCred.GetProjectId() {
requireScope = rbacutils.ScopeProject
} else if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
} else if resScope == rbacutils.ScopeDomain {
queryScope = rbacutils.ScopeDomain
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
} else {
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
}
} else {
ownerId, err = FetchUserInfo(ctx, data)
if err != nil {
return nil, queryScope, err
}
if ownerId != nil {
if resScope == rbacutils.ScopeUser {
queryScope = rbacutils.ScopeUser
if ownerId.GetUserId() == userCred.GetUserId() {
requireScope = rbacutils.ScopeUser
switch resScope {
case rbacutils.ScopeProject, rbacutils.ScopeDomain:
if len(ownerId.GetProjectId()) > 0 {
queryScope = rbacutils.ScopeProject
if ownerId.GetProjectId() == userCred.GetProjectId() {
requireScope = rbacutils.ScopeProject
} else if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
} else {
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
}
} else {
ownerId, err = FetchDomainInfo(ctx, data)
if err != nil {
return nil, queryScope, err
}
if ownerId != nil {
if resScope == rbacutils.ScopeDomain {
queryScope = rbacutils.ScopeDomain
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
requireScope = rbacutils.ScopeSystem
}
} else if len(ownerId.GetProjectDomainId()) > 0 {
queryScope = rbacutils.ScopeDomain
if ownerId.GetProjectDomainId() == userCred.GetProjectDomainId() {
requireScope = rbacutils.ScopeDomain
} else {
return nil, queryScope, httperrors.NewInputParameterError("query scope out of resource scope")
requireScope = rbacutils.ScopeSystem
}
}
case rbacutils.ScopeUser:
queryScope = rbacutils.ScopeUser
if ownerId.GetUserId() == userCred.GetUserId() {
requireScope = rbacutils.ScopeUser
} else {
requireScope = rbacutils.ScopeSystem
}
}
}
if ownerId == nil {
ownerId = userCred
reqScopeStr, _ := data.GetString("scope")
@@ -391,7 +374,7 @@ func FetchQueryOwnerScope(ctx context.Context, userCred mcclient.TokenCredential
requireScope = queryScope
}
if requireScope.HigherThan(allowScope) {
return nil, scope, httperrors.NewForbiddenError("not enough privilleges")
return nil, scope, httperrors.NewForbiddenError(fmt.Sprintf("not enough privilleges(require:%s,allow:%s:query:%s)", requireScope, allowScope, queryScope))
}
return ownerId, queryScope, nil
}
+5 -5
View File
@@ -35,11 +35,11 @@ func RegisterModelManager(modelMan IModelManager) {
func mustCheckModelManager(modelMan IModelManager) {
allowedTags := map[string][]string{
"create": {"required", "optional", "admin_required", "admin_optional"},
"search": {"user", "admin"},
"get": {"user", "admin"},
"list": {"user", "admin"},
"update": {"user", "admin"},
"create": {"required", "optional", "domain_required", "domain_optional", "admin_required", "admin_optional"},
"search": {"user", "domain", "admin"},
"get": {"user", "domain", "admin"},
"list": {"user", "domain", "admin"},
"update": {"user", "domain", "admin"},
}
for _, col := range modelMan.TableSpec().Columns() {
tags := col.Tags()
+1 -5
View File
@@ -64,9 +64,5 @@ func (manager *SProjectizedResourceBaseManager) ResourceScope() rbacutils.TRbacS
}
func (manager *SProjectizedResourceBaseManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
ownerId, err := FetchProjectInfo(ctx, data)
if err == nil && ownerId == nil {
ownerId, err = FetchDomainInfo(ctx, data)
}
return nil, nil
return FetchProjectInfo(ctx, data)
}
+5
View File
@@ -21,6 +21,7 @@ import (
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/util/rbacutils"
@@ -56,6 +57,10 @@ func (manager *SQuotaManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeProject
}
func (manager *SQuotaManager) FetchOwnerId(ctx context.Context, data jsonutils.JSONObject) (mcclient.IIdentityProvider, error) {
return db.FetchProjectInfo(ctx, data)
}
func (manager *SQuotaManager) Keyword() string {
return manager.keyword
}
+6 -4
View File
@@ -21,10 +21,6 @@ import (
"yunion.io/x/onecloud/pkg/util/rbacutils"
)
func getListRbacAllowedScope(manager IModelManager, userCred mcclient.TokenCredential) rbacutils.TRbacScope {
return policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
}
func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action string, extra ...string) bool {
manager := model.GetModelManager()
objOwnerId := model.GetOwnerId()
@@ -46,6 +42,12 @@ func isObjectRbacAllowed(model IModel, userCred mcclient.TokenCredential, action
} else {
requireScope = rbacutils.ScopeSystem
}
case rbacutils.ScopeUser:
if ownerId != nil && ownerId.GetUserId() == objOwnerId.GetUserId() {
requireScope = rbacutils.ScopeUser
} else {
requireScope = rbacutils.ScopeSystem
}
default:
// objOwnerId should not be nil
if ownerId != nil && (ownerId.GetProjectId() == objOwnerId.GetProjectId() || (model.IsSharable() && action == policy.PolicyActionGet)) {
+15 -7
View File
@@ -22,6 +22,7 @@ import (
"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"
)
@@ -29,8 +30,8 @@ import (
type SSharableVirtualResourceBase struct {
SVirtualResourceBase
IsPublic bool `default:"false" nullable:"false" index:"true" create:"admin_optional" list:"user" update:"admin"`
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"admin_optional" list:"user" update:"admin"`
IsPublic bool `default:"false" nullable:"false" create:"domain_optional" list:"user"`
PublicScope string `width:"16" charset:"ascii" nullable:"false" default:"system" create:"domain_optional" list:"user"`
}
type SSharableVirtualResourceBaseManager struct {
@@ -90,13 +91,12 @@ func (model *SSharableVirtualResourceBase) AllowPerformPublic(ctx context.Contex
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "public")
}
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
}
func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "public")
if !scope.HigherThan(rbacutils.ScopeProject) {
return nil, httperrors.NewForbiddenError("not enough privilege")
}
if !model.IsPublic {
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), "public")
diff, err := Update(model, func() error {
model.IsPublic = true
model.PublicScope = string(scope)
@@ -110,7 +110,15 @@ func (model *SSharableVirtualResourceBase) PerformPublic(ctx context.Context, us
return nil, nil
}
func (model *SSharableVirtualResourceBase) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return IsAllowPerform(rbacutils.ScopeSystem, userCred, model, "private")
}
func (model *SSharableVirtualResourceBase) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
scope := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), model.GetModelManager().KeywordPlural(), policy.PolicyActionPerform, "private")
if !scope.HigherThan(rbacutils.ScopeProject) {
return nil, httperrors.NewForbiddenError("not enough privilege")
}
if model.IsPublic {
diff, err := Update(model, func() error {
model.IsPublic = false
+4 -1
View File
@@ -103,7 +103,10 @@ func (manager *SVirtualResourceBaseManager) FilterBySystemAttributes(q *sqlchemy
q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system"))))
}
pendingDelete, _ := query.GetString("pending_delete")
var pendingDelete string
if query != nil {
pendingDelete, _ = query.GetString("pending_delete")
}
pendingDeleteLower := strings.ToLower(pendingDelete)
if pendingDeleteLower == "all" || pendingDeleteLower == "any" || utils.ToBool(pendingDeleteLower) {
var isAllow bool
+4
View File
@@ -88,6 +88,8 @@ func parseJsonPolicy(obj jsonutils.JSONObject) (string, *rbacutils.SRbacPolicy,
return "", nil, errors.Wrap(err, "missing domain_id")
}
isPublic := jsonutils.QueryBoolean(obj, "is_public", false)
blob, err := obj.Get("policy")
if err != nil {
log.Errorf("get blob error %s", err)
@@ -102,6 +104,7 @@ func parseJsonPolicy(obj jsonutils.JSONObject) (string, *rbacutils.SRbacPolicy,
}
policy.DomainId = domainId
policy.IsPublic = isPublic
return typeStr, &policy, nil
}
@@ -117,6 +120,7 @@ func remotePolicyFetcher() (map[rbacutils.TRbacScope]map[string]*rbacutils.SRbac
params.Add(jsonutils.NewInt(2048), "limit")
params.Add(jsonutils.NewInt(int64(offset)), "offset")
params.Add(jsonutils.JSONTrue, "admin")
params.Add(jsonutils.JSONTrue, "enabled")
result, err := modules.Policies.List(s, params)
if err != nil {
return nil, errors.Wrap(err, "modules.Policies.List")
+17 -17
View File
@@ -67,37 +67,37 @@ type SCloudaccount struct {
db.SDomainizedResourceBase
SSyncableBaseResource
LastAutoSync time.Time `list:"admin"`
LastAutoSync time.Time `list:"domain"`
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
Account string `width:"128" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
// BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
// BalanceKey string `width:"256" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
IsPublicCloud *bool `nullable:"false" get:"user" create:"optional" list:"user" default:"true"`
IsOnPremise bool `nullable:"false" get:"user" create:"optional" list:"user" default:"false"`
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
Provider string `width:"64" charset:"ascii" list:"domain" create:"domain_required"`
EnableAutoSync bool `default:"false" create:"admin_optional" list:"admin"`
SyncIntervalSeconds int `create:"admin_optional" list:"admin" update:"admin"`
EnableAutoSync bool `default:"false" create:"domain_optional" list:"domain"`
SyncIntervalSeconds int `create:"domain_optional" list:"domain" update:"domain"`
Balance float64 `list:"admin"`
ProbeAt time.Time `list:"admin"`
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"admin"`
Balance float64 `list:"domain"`
ProbeAt time.Time `list:"domain"`
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"domain"`
ErrorCount int `list:"admin"`
ErrorCount int `list:"domain"`
AutoCreateProject bool `list:"admin" create:"admin_optional"`
AutoCreateProject bool `list:"domain" create:"domain_optional"`
Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True)
Version string `width:"32" charset:"ascii" nullable:"true" list:"domain"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
Sysinfo jsonutils.JSONObject `get:"domain"` // Column(JSONEncodedDict, nullable=True)
Brand string `width:"64" charset:"utf8" nullable:"true" list:"admin" create:"optional"`
Brand string `width:"64" charset:"utf8" nullable:"true" list:"domain" create:"optional"`
Options *jsonutils.JSONDict `get:"admin" create:"admin_optional" update:"admin"`
Options *jsonutils.JSONDict `get:"domain" create:"domain_optional" update:"domain"`
}
func (self *SCloudaccountManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
+11 -9
View File
@@ -19,15 +19,17 @@ import (
"database/sql"
"math/rand"
"time"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/httperrors"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/util/timeutils"
"yunion.io/x/sqlchemy"
)
type SCloudproviderregionManager struct {
@@ -57,15 +59,15 @@ type SCloudproviderregion struct {
SSyncableBaseResource
CloudproviderId string `width:"36" charset:"ascii" nullable:"false" list:"admin"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"admin"`
CloudproviderId string `width:"36" charset:"ascii" nullable:"false" list:"domain"` // Column(VARCHAR(36, charset='ascii'), nullable=False)
CloudregionId string `width:"36" charset:"ascii" nullable:"false" list:"domain"`
Enabled bool `nullable:"false" list:"admin" update:"admin"`
Enabled bool `nullable:"false" list:"domain" update:"domain"`
// SyncIntervalSeconds int `list:"admin"`
SyncResults jsonutils.JSONObject `list:"admin"`
// SyncIntervalSeconds int `list:"domain"`
SyncResults jsonutils.JSONObject `list:"domain"`
LastDeepSyncAt time.Time `list:"admin"`
LastDeepSyncAt time.Time `list:"domain"`
}
func (manager *SCloudproviderregionManager) GetMasterFieldName() string {
+9 -9
View File
@@ -69,23 +69,23 @@ type SCloudprovider struct {
SSyncableBaseResource
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"admin"` // 云端服务健康状态。例如欠费、项目冻结都属于不健康状态。
HealthStatus string `width:"16" charset:"ascii" default:"normal" nullable:"false" list:"domain"` // 云端服务健康状态。例如欠费、项目冻结都属于不健康状态。
// Hostname string `width:"64" charset:"ascii" nullable:"true"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
// port = Column(Integer, nullable=False)
// Version string `width:"32" charset:"ascii" nullable:"true" list:"admin"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
// Sysinfo jsonutils.JSONObject `get:"admin"` // Column(JSONEncodedDict, nullable=True)
// Version string `width:"32" charset:"ascii" nullable:"true" list:"domain"` // Column(VARCHAR(32, charset='ascii'), nullable=True)
// Sysinfo jsonutils.JSONObject `get:"domain"` // Column(JSONEncodedDict, nullable=True)
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
Account string `width:"128" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"admin" create:"admin_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
AccessUrl string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
Account string `width:"128" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(64, charset='ascii'), nullable=False)
Secret string `width:"256" charset:"ascii" nullable:"false" list:"domain" create:"domain_required"` // Column(VARCHAR(256, charset='ascii'), nullable=False)
CloudaccountId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
// ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"admin"`
// ProjectId string `name:"tenant_id" width:"128" charset:"ascii" nullable:"true" list:"domain"`
// LastSync time.Time `get:"admin" list:"admin"` // = Column(DateTime, nullable=True)
// LastSync time.Time `get:"domain" list:"domain"` // = Column(DateTime, nullable=True)
Provider string `width:"64" charset:"ascii" list:"admin" create:"admin_required"`
Provider string `width:"64" charset:"ascii" list:"domain" create:"domain_required"`
}
func (self *SCloudproviderManager) AllowListItems(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) bool {
+3 -3
View File
@@ -35,9 +35,9 @@ import (
)
type SSyncableBaseResource struct {
SyncStatus string `width:"10" charset:"ascii" default:"idle" list:"admin"`
LastSync time.Time `list:"admin"` // = Column(DateTime, nullable=True)
LastSyncEndAt time.Time `list:"admin"`
SyncStatus string `width:"10" charset:"ascii" default:"idle" list:"domain"`
LastSync time.Time `list:"domain"` // = Column(DateTime, nullable=True)
LastSyncEndAt time.Time `list:"domain"`
}
func (self *SSyncableBaseResource) CanSync() bool {
+1 -2
View File
@@ -25,11 +25,10 @@ import (
"strings"
"time"
"yunion.io/x/pkg/utils"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/utils"
"yunion.io/x/sqlchemy"
api "yunion.io/x/onecloud/pkg/apis/compute"
+3 -4
View File
@@ -23,7 +23,6 @@ import (
"yunion.io/x/pkg/util/compare"
"yunion.io/x/pkg/utils"
"yunion.io/x/onecloud/pkg/apis/compute"
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
@@ -66,7 +65,7 @@ func init() {
}
func (manager *SSnapshotPolicyManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
input := &compute.SSnapshotPolicyCreateInput{}
input := &api.SSnapshotPolicyCreateInput{}
err := data.Unmarshal(input)
if err != nil {
return nil, httperrors.NewInputParameterError("Unmarshal input failed %s", err)
@@ -114,7 +113,7 @@ func (self *SSnapshotPolicy) StartCreateSnapshotPolicy(ctx context.Context, user
}
func (self *SSnapshotPolicy) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
self.SetStatus(userCred, compute.SNAPSHOT_POLICY_DELETING, "")
self.SetStatus(userCred, api.SNAPSHOT_POLICY_DELETING, "")
return self.StartSnapshotPolicyDeleteTask(ctx, userCred, jsonutils.NewDict(), "")
}
@@ -375,7 +374,7 @@ func (self *SSnapshotPolicy) preCheck(
ctx context.Context, userCred mcclient.TokenCredential,
query jsonutils.JSONObject, data jsonutils.JSONObject,
) ([]string, error) {
if self.Status != compute.SNAPSHOT_POLICY_READY {
if self.Status != api.SNAPSHOT_POLICY_READY {
return nil, httperrors.NewInvalidStatusError("Snapshot policy status %s can't do apply", self.Status)
}
jsonDiskIds, err := data.Get("disks")
+6 -3
View File
@@ -245,11 +245,14 @@ func (domain *SDomain) ValidateDeleteCondition(ctx context.Context) error {
return domain.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
func (domain *SDomain) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
func (domain *SDomain) ValidateUpdateCondition(ctx context.Context) error {
if domain.Id == api.DEFAULT_DOMAIN_ID {
return nil, httperrors.NewForbiddenError("default domain is protected")
return httperrors.NewForbiddenError("default domain is protected")
}
return domain.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
if domain.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return domain.SStandaloneResourceBase.ValidateUpdateCondition(ctx)
}
/*func (domain *SDomain) isReadOnly() bool {
+6 -3
View File
@@ -66,7 +66,7 @@ func init() {
type SGroup struct {
SIdentityBaseResource
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
}
func (manager *SGroupManager) GetContextManagers() [][]db.IModelManager {
@@ -209,8 +209,11 @@ func (manager *SGroupManager) RegisterExternalGroup(ctx context.Context, idpId s
return &group, nil
}
func (group *SGroup) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
return group.SIdentityBaseResource.ValidateUpdateData(ctx, userCred, query, data)
func (group *SGroup) ValidateUpdateCondition(ctx context.Context) error {
if group.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return group.SIdentityBaseResource.ValidateUpdateCondition(ctx)
}
func (manager *SGroupManager) fetchGroupById(gid string) *SGroup {
+3 -11
View File
@@ -77,7 +77,7 @@ func NewEnabledIdentityBaseResourceManager(dt interface{}, tableName string, key
type SEnabledIdentityBaseResource struct {
SIdentityBaseResource
Enabled tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
Enabled tristate.TriState `nullable:"false" default:"true" list:"user" update:"domain" create:"domain_optional"`
}
func (model *SIdentityBaseResource) GetIIdentityModelManager() IIdentityModelManager {
@@ -197,23 +197,15 @@ func (model *SIdentityBaseResource) CustomizeCreate(ctx context.Context, userCre
return model.SStandaloneResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
/*
func (self *SIdentityBaseResource) ValidateDeleteCondition(ctx context.Context) error {
// domain := self.GetDomain()
// if self.GetIIdentityModelManager().IsDomainReadonly(domain) {
// return httperrors.NewForbiddenError("readonly domain")
// }
return self.SStandaloneResourceBase.ValidateDeleteCondition(ctx)
}
func (self *SIdentityBaseResource) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
// if data.Contains("name") {
// domain := self.GetDomain()
// if self.GetIIdentityModelManager().IsDomainReadonly(domain) {
// return nil, httperrors.NewForbiddenError("cannot update name in readonly domain")
// }
// }
return self.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
*/
func (self *SEnabledIdentityBaseResource) ValidateDeleteCondition(ctx context.Context) error {
if self.Enabled.IsTrue() {
+118 -2
View File
@@ -19,11 +19,14 @@ import (
"database/sql"
"yunion.io/x/jsonutils"
"yunion.io/x/sqlchemy"
"yunion.io/x/onecloud/pkg/cloudcommon/consts"
"yunion.io/x/onecloud/pkg/cloudcommon/db"
policyman "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"
)
type SPolicyManager struct {
@@ -58,8 +61,10 @@ func init() {
type SPolicy struct {
SEnabledIdentityBaseResource
Type string `width:"255" charset:"utf8" nullable:"false" list:"user" update:"admin"`
Blob jsonutils.JSONObject `nullable:"false" list:"user" update:"admin"`
Type string `width:"255" charset:"utf8" nullable:"false" list:"user" update:"domain"`
Blob jsonutils.JSONObject `nullable:"false" list:"user" update:"domain"`
IsPublic bool `default:"false" nullable:"false" list:"user"`
}
func (manager *SPolicyManager) InitializeData() error {
@@ -100,9 +105,48 @@ func (manager *SPolicyManager) ValidateCreateData(ctx context.Context, userCred
if !data.Contains("name") {
data.Set("name", jsonutils.NewString(typeStr))
}
blobJson, err := data.Get("blob")
if err != nil {
return nil, httperrors.NewInputParameterError("invalid policy data")
}
policy := rbacutils.SRbacPolicy{}
err = policy.Decode(blobJson)
if err != nil {
return nil, httperrors.NewInputParameterError("fail to decode policy data")
}
if policy.IsSystemWidePolicy() && policyman.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(), manager.KeywordPlural(), policyman.PolicyActionCreate) == rbacutils.Deny {
return nil, httperrors.NewNotSufficientPrivilegeError("not allow to create system-wide policy")
}
return manager.SStandaloneResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, data)
}
func (policy *SPolicy) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if data.Contains("blob") {
blobJson, err := data.Get("blob")
if err != nil {
return nil, httperrors.NewInputParameterError("invalid policy data")
}
p := rbacutils.SRbacPolicy{}
err = p.Decode(blobJson)
if err != nil {
return nil, httperrors.NewInputParameterError("fail to decode policy data")
}
if p.IsSystemWidePolicy() && policyman.PolicyManager.Allow(rbacutils.ScopeSystem, userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionUpdate) == rbacutils.Deny {
return nil, httperrors.NewNotSufficientPrivilegeError("not allow to update system-wide policy")
}
}
if data.Contains("type") {
typeStr, _ := data.GetString("type")
if len(typeStr) == 0 {
return nil, httperrors.NewInputParameterError("empty name")
}
if len(typeStr) > 0 {
data.Set("name", jsonutils.NewString(typeStr))
}
}
return policy.SStandaloneResourceBase.ValidateUpdateData(ctx, userCred, query, data)
}
func (policy *SPolicy) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
policy.SStandaloneResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
policyman.PolicyManager.SyncOnce()
@@ -117,3 +161,75 @@ func (policy *SPolicy) PostDelete(ctx context.Context, userCred mcclient.TokenCr
policy.SStandaloneResourceBase.PostDelete(ctx, userCred)
policyman.PolicyManager.SyncOnce()
}
func (policy *SPolicy) AllowPerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, policy, "public")
}
func (policy *SPolicy) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if policy.IsPublic {
return nil, nil
}
scope := policyman.PolicyManager.AllowScope(userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionPerform, "public")
if scope != rbacutils.ScopeSystem {
return nil, httperrors.NewForbiddenError("not enough privilege")
}
p := rbacutils.SRbacPolicy{}
err := p.Decode(policy.Blob)
if err != nil {
return nil, httperrors.NewInputParameterError("fail to decode policy data")
}
if !p.IsSystemWidePolicy() {
return nil, httperrors.NewInvalidStatusError("only system-wide policy (no roles and projects constraints) is sharable")
}
diff, err := db.Update(policy, func() error {
policy.IsPublic = true
return nil
})
if err == nil {
db.OpsLog.LogEvent(policy, db.ACT_UPDATE, diff, userCred)
}
return nil, err
}
func (policy *SPolicy) AllowPerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
return db.IsAllowPerform(rbacutils.ScopeSystem, userCred, policy, "private")
}
func (policy *SPolicy) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
if !policy.IsPublic {
return nil, nil
}
scope := policyman.PolicyManager.AllowScope(userCred, consts.GetServiceType(), policy.GetModelManager().KeywordPlural(), policyman.PolicyActionPerform, "private")
if scope != rbacutils.ScopeSystem {
return nil, httperrors.NewForbiddenError("not enough privilege")
}
diff, err := db.Update(policy, func() error {
policy.IsPublic = false
return nil
})
if err == nil {
db.OpsLog.LogEvent(policy, db.ACT_UPDATE, diff, userCred)
}
return nil, err
}
func (manager *SPolicyManager) FilterByOwner(q *sqlchemy.SQuery, owner mcclient.IIdentityProvider, scope rbacutils.TRbacScope) *sqlchemy.SQuery {
if owner != nil {
switch scope {
case rbacutils.ScopeDomain:
if len(owner.GetProjectDomainId()) > 0 {
q = q.Filter(sqlchemy.OR(
sqlchemy.Equals(q.Field("domain_id"), owner.GetProjectDomainId()),
sqlchemy.IsTrue(q.Field("is_public")),
))
}
}
}
return q
}
+5 -10
View File
@@ -19,10 +19,9 @@ import (
"database/sql"
"fmt"
"github.com/pkg/errors"
"yunion.io/x/jsonutils"
"yunion.io/x/log"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/tristate"
"yunion.io/x/sqlchemy"
@@ -66,16 +65,12 @@ func init() {
+-------------+-------------+------+-----+---------+-------+
*/
type SBaseProject struct {
type SProject struct {
SIdentityBaseResource
ParentId string `width:"64" charset:"ascii" list:"admin" create:"admin_optional"`
ParentId string `width:"64" charset:"ascii" list:"domain" create:"domain_optional"`
IsDomain tristate.TriState `default:"false" nullable:"false" create:"admin_optional"`
}
type SProject struct {
SBaseProject
IsDomain tristate.TriState `default:"false" nullable:"false" create:"domain_optional"`
}
func (manager *SProjectManager) GetContextManagers() [][]db.IModelManager {
@@ -244,7 +239,7 @@ func (manager *SProjectManager) ListItemFilter(ctx context.Context, q *sqlchemy.
func (model *SProject) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
model.ParentId = ownerId.GetProjectDomainId()
model.IsDomain = tristate.False
return model.SBaseProject.CustomizeCreate(ctx, userCred, ownerId, query, data)
return model.SIdentityBaseResource.CustomizeCreate(ctx, userCred, ownerId, query, data)
}
func (proj *SProject) GetUserCount() (int, error) {
+20 -14
View File
@@ -73,22 +73,22 @@ func init() {
type SUser struct {
SEnabledIdentityBaseResource
Email string `width:"64" charset:"ascii" nullable:"true" index:"true" list:"admin" update:"admin" create:"admin_optional"`
Mobile string `width:"20" charset:"ascii" nullable:"true" index:"true" list:"admin" update:"admin" create:"admin_optional"`
Email string `width:"64" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain" create:"domain_optional"`
Mobile string `width:"20" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain" create:"domain_optional"`
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"admin" update:"admin" create:"admin_optional"`
Displayname string `with:"128" charset:"utf8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
LastActiveAt time.Time `nullable:"true" list:"admin"`
LastActiveAt time.Time `nullable:"true" list:"domain"`
LastLoginIp string `nullable:"true" list:"admin"`
LastLoginSource string `nullable:"true" list:"admin"`
LastLoginIp string `nullable:"true" list:"domain"`
LastLoginSource string `nullable:"true" list:"domain"`
IsSystemAccount tristate.TriState `nullable:"false" default:"false" list:"admin" update:"admin" create:"admin_optional"`
IsSystemAccount tristate.TriState `nullable:"false" default:"false" list:"domain" update:"domain" create:"domain_optional"`
DefaultProjectId string `width:"64" charset:"ascii" nullable:"true"`
AllowWebConsole tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
EnableMfa tristate.TriState `nullable:"false" default:"true" list:"admin" update:"admin" create:"admin_optional"`
AllowWebConsole tristate.TriState `nullable:"false" default:"true" list:"domain" update:"domain" create:"domain_optional"`
EnableMfa tristate.TriState `nullable:"false" default:"true" list:"domain" update:"domain" create:"domain_optional"`
}
func (manager *SUserManager) GetContextManagers() [][]db.IModelManager {
@@ -327,15 +327,21 @@ func (manager *SUserManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQu
}
func (user *SUser) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
if user.IsAdminUser() {
return nil, httperrors.NewForbiddenError("system admin user is protected")
}
if user.IsReadOnly() {
return nil, httperrors.NewForbiddenError("readonly")
if data.Contains("name") {
if user.IsAdminUser() {
return nil, httperrors.NewForbiddenError("cannot alter sysadmin user name")
}
}
return user.SEnabledIdentityBaseResource.ValidateUpdateData(ctx, userCred, query, data)
}
func (user *SUser) ValidateUpdateCondition(ctx context.Context) error {
if user.IsReadOnly() {
return httperrors.NewForbiddenError("readonly")
}
return user.SEnabledIdentityBaseResource.ValidateUpdateCondition(ctx)
}
func (manager *SUserManager) fetchUserById(uid string) (*SUser, error) {
obj, err := manager.FetchById(uid)
if err != nil {
+2 -1
View File
@@ -24,7 +24,8 @@ func init() {
"balance", "error_count", "health_status",
"Sync_Status", "Last_sync",
"guest_count", "domain", "domain_id",
"Provider", "Enable_Auto_Sync", "Sync_Interval_Seconds"},
"Provider", "Brand",
"Enable_Auto_Sync", "Sync_Interval_Seconds"},
[]string{})
registerCompute(&Cloudaccounts)
+2 -2
View File
@@ -29,7 +29,7 @@ var Policies SPolicyManager
func policyReadFilter(session *mcclient.ClientSession, s jsonutils.JSONObject, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
ss := s.(*jsonutils.JSONDict)
ret := ss.CopyIncludes("id", "type", "enabled", "domain_id", "domain", "can_update", "can_delete")
ret := ss.CopyIncludes("id", "type", "enabled", "domain_id", "domain", "can_update", "can_delete", "is_public")
blobJson, _ := ss.Get("blob")
if blobJson != nil {
policy := rbacutils.SRbacPolicy{}
@@ -96,7 +96,7 @@ func policyWriteFilter(session *mcclient.ClientSession, s jsonutils.JSONObject,
func init() {
Policies = SPolicyManager{NewIdentityV3Manager("policy", "policies",
[]string{"id", "type", "policy", "enabled", "domain_id", "domain"},
[]string{"id", "type", "policy", "enabled", "domain_id", "domain", "is_public"},
[]string{})}
Policies.SetReadFilter(policyReadFilter).SetWriteFilter(policyWriteFilter).SetNameField("type")
@@ -90,6 +90,8 @@ type SRbacPolicy struct {
DomainId string
IsPublic bool
Projects []string
Roles []string
Ips []netutils.IPV4Prefix
@@ -550,6 +552,10 @@ type IRbacIdentity interface {
GetLoginIp() string
}
func (policy *SRbacPolicy) IsSystemWidePolicy() bool {
return len(policy.Roles) == 0 && len(policy.Projects) == 0
}
func (policy *SRbacPolicy) Match(userCred IRbacIdentity) bool {
if !policy.Auth && len(policy.Projects) == 0 && len(policy.Roles) == 0 && len(policy.Ips) == 0 {
return true
@@ -557,7 +563,10 @@ func (policy *SRbacPolicy) Match(userCred IRbacIdentity) bool {
if userCred == nil {
return false
}
if (len(policy.Projects) == 0 || (policy.DomainId == userCred.GetProjectDomainId() && contains(policy.Projects, userCred.GetProjectName()))) && (len(policy.Roles) == 0 || (policy.DomainId == userCred.GetProjectDomainId() && intersect(policy.Roles, userCred.GetRoles()))) && (len(policy.Ips) == 0 || containsIp(policy.Ips, userCred.GetLoginIp())) {
if !policy.IsPublic && policy.DomainId != userCred.GetProjectDomainId() {
return false
}
if (len(policy.Projects) == 0 || contains(policy.Projects, userCred.GetProjectName())) && (len(policy.Roles) == 0 || intersect(policy.Roles, userCred.GetRoles())) && (len(policy.Ips) == 0 || containsIp(policy.Ips, userCred.GetLoginIp())) {
return true
}
return false
+4
View File
@@ -169,6 +169,10 @@ func (manager *SParameterManager) NamespaceScope() rbacutils.TRbacScope {
return rbacutils.ScopeUser
}
func (manager *SParameterManager) ResourceScope() rbacutils.TRbacScope {
return rbacutils.ScopeUser
}
func (manager *SParameterManager) AllowCreateItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
if !isAdminQuery(query) {
return true