diff --git a/cmd/climc/shell/identity/policies.go b/cmd/climc/shell/identity/policies.go index 991523b690..8c24eb14b8 100644 --- a/cmd/climc/shell/identity/policies.go +++ b/cmd/climc/shell/identity/policies.go @@ -24,6 +24,7 @@ import ( "yunion.io/x/jsonutils" "yunion.io/x/log" + api "yunion.io/x/onecloud/pkg/apis/identity" "yunion.io/x/onecloud/pkg/cloudcommon/consts" "yunion.io/x/onecloud/pkg/cloudcommon/policy" "yunion.io/x/onecloud/pkg/mcclient" @@ -240,6 +241,21 @@ func init() { return nil }) + type PolicyBindRoleOptions struct { + POLICY string `json:"-" help:"policy Id or name"` + api.PolicyBindRoleInput + } + R(&PolicyBindRoleOptions{}, "policy-bind-role", "Policy bind role", func(s *mcclient.ClientSession, args *PolicyBindRoleOptions) error { + params := jsonutils.Marshal(args) + log.Debugf("params: %s", params) + result, err := modules.Policies.PerformAction(s, args.POLICY, "bind-role", params) + if err != nil { + return err + } + printObject(result) + return nil + }) + type PolicyAdminCapableOptions struct { User string `help:"For user"` UserDomain string `help:"Domain for user"` diff --git a/pkg/apis/identity/policy.go b/pkg/apis/identity/policy.go index bdf02a7ae3..ad94684972 100644 --- a/pkg/apis/identity/policy.go +++ b/pkg/apis/identity/policy.go @@ -22,3 +22,12 @@ type PolicyDetails struct { SPolicy } + +type PolicyBindRoleInput struct { + // 角色ID + RoleId string `json:"role_id"` + // 项目ID + ProjectId string `json:"project_id"` + // IP白名单 + Ips []string `json:"ips"` +} diff --git a/pkg/keystone/models/policies.go b/pkg/keystone/models/policies.go index aaab43e6d4..6d438730a9 100644 --- a/pkg/keystone/models/policies.go +++ b/pkg/keystone/models/policies.go @@ -23,6 +23,7 @@ import ( "yunion.io/x/pkg/errors" "yunion.io/x/pkg/gotypes" "yunion.io/x/pkg/tristate" + "yunion.io/x/pkg/util/netutils" "yunion.io/x/sqlchemy" "yunion.io/x/onecloud/pkg/apis" @@ -585,3 +586,47 @@ func (policy *SPolicy) fetchMatchableRoles() ([]SRole, error) { } return roles, nil } + +func (policy *SPolicy) AllowPerformBindRole(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) bool { + return true +} + +// 绑定角色 +func (policy *SPolicy) PerformBindRole(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.PolicyBindRoleInput) (jsonutils.JSONObject, error) { + var projectId string + prefList := make([]netutils.IPV4Prefix, 0) + for _, ipStr := range input.Ips { + pref, err := netutils.NewIPV4Prefix(ipStr) + if err != nil { + return nil, errors.Wrapf(httperrors.ErrInputParameter, "invalid prefix %s", ipStr) + } + prefList = append(prefList, pref) + } + if len(input.ProjectId) > 0 { + proj, err := ProjectManager.FetchByIdOrName(userCred, input.ProjectId) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrNotFound, "%s %s", ProjectManager.Keyword(), input.ProjectId) + } else { + return nil, errors.Wrap(err, "ProjectManager.FetchByIdOrName") + } + } + projectId = proj.GetId() + } + if len(input.RoleId) == 0 { + return nil, errors.Wrap(httperrors.ErrInputParameter, "missing role_id") + } + role, err := RoleManager.FetchByIdOrName(userCred, input.RoleId) + if err != nil { + if errors.Cause(err) == sql.ErrNoRows { + return nil, errors.Wrapf(httperrors.ErrNotFound, "%s %s", RoleManager.Keyword(), input.RoleId) + } else { + return nil, errors.Wrap(err, "RoleManager.FetchByIdOrName") + } + } + err = RolePolicyManager.newRecord(ctx, role.GetId(), projectId, policy.Id, tristate.True, prefList) + if err != nil { + return nil, errors.Wrap(err, "newRecord") + } + return nil, nil +} diff --git a/pkg/keystone/models/roles.go b/pkg/keystone/models/roles.go index b154a536c9..b14a19b444 100644 --- a/pkg/keystone/models/roles.go +++ b/pkg/keystone/models/roles.go @@ -149,6 +149,8 @@ func (manager *SRoleManager) initSysRole(ctx context.Context) error { // insert role := SRole{} role.Name = api.SystemAdminRole + role.IsPublic = true + role.PublicScope = string(rbacutils.ScopeSystem) role.DomainId = api.DEFAULT_DOMAIN_ID role.Description = "Boostrap system default admin role" role.SetModelManager(manager, &role) diff --git a/pkg/keystone/policy/defaults.go b/pkg/keystone/policy/defaults.go index f2283c5ad9..7e952f9407 100644 --- a/pkg/keystone/policy/defaults.go +++ b/pkg/keystone/policy/defaults.go @@ -154,6 +154,36 @@ var ( Action: PolicyActionPerform, Result: rbacutils.Allow, }, + { + Service: api.SERVICE_TYPE, + Resource: "roles", + Action: PolicyActionCreate, + Result: rbacutils.Allow, + }, + { + Service: api.SERVICE_TYPE, + Resource: "roles", + Action: PolicyActionUpdate, + Result: rbacutils.Allow, + }, + { + Service: api.SERVICE_TYPE, + Resource: "roles", + Action: PolicyActionGet, + Result: rbacutils.Allow, + }, + { + Service: api.SERVICE_TYPE, + Resource: "roles", + Action: PolicyActionList, + Result: rbacutils.Allow, + }, + { + Service: api.SERVICE_TYPE, + Resource: "roles", + Action: PolicyActionPerform, + Result: rbacutils.Allow, + }, }, }, }