| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- // 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 identity
- import (
- "fmt"
- "yunion.io/x/jsonutils"
- "yunion.io/x/pkg/errors"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/utils"
- "yunion.io/x/onecloud/pkg/httperrors"
- "yunion.io/x/onecloud/pkg/mcclient"
- "yunion.io/x/onecloud/pkg/mcclient/modulebase"
- "yunion.io/x/onecloud/pkg/mcclient/modules"
- )
- type RoleAssignmentManagerV3 struct {
- modulebase.ResourceManager
- }
- type role struct {
- id string
- name string
- domain struct {
- id string
- name string
- }
- }
- type projectRoles struct {
- id string
- name string
- domain struct {
- id string
- name string
- }
- typ string
- roles []role
- }
- func newProjectRoles(projectId, projectName, projectDomainId, projectDomainName, roleId, roleName, roleDomainId, roleDomainName, typ string) *projectRoles {
- r := role{
- id: roleId,
- name: roleName,
- }
- r.domain.id = roleDomainId
- r.domain.name = roleDomainName
- pr := &projectRoles{id: projectId, name: projectName, typ: typ, roles: []role{r}}
- pr.domain.id = projectDomainId
- pr.domain.name = projectDomainName
- return pr
- }
- func (this *projectRoles) add(roleId, roleName, roleDomainId, roleDomainName string) {
- r := role{id: roleId, name: roleName}
- r.domain.id = roleDomainId
- r.domain.name = roleDomainName
- this.roles = append(this.roles, r)
- }
- func (this *projectRoles) json() jsonutils.JSONObject {
- obj := jsonutils.NewDict()
- obj.Add(jsonutils.NewString(this.id), "id")
- obj.Add(jsonutils.NewString(this.name), "name")
- obj.Add(jsonutils.NewString(this.domain.id), "domain", "id")
- obj.Add(jsonutils.NewString(this.domain.name), "domain", "name")
- obj.Add(jsonutils.NewString(this.typ), "type")
- roles := jsonutils.NewArray()
- for _, r := range this.roles {
- role := jsonutils.NewDict()
- role.Add(jsonutils.NewString(r.id), "id")
- role.Add(jsonutils.NewString(r.name), "name")
- role.Add(jsonutils.NewString(r.domain.id), "domain", "id")
- role.Add(jsonutils.NewString(r.domain.name), "domain", "name")
- roles.Add(role)
- }
- obj.Add(roles, "roles")
- return obj
- }
- type sRole struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Domain struct {
- Id string `json:"id"`
- Name string `json:"name"`
- } `json:"domain"`
- }
- type sGroupRole struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Domain struct {
- Id string `json:"id"`
- Name string `json:"name"`
- } `json:"domain"`
- Roles []sRole `json:"roles"`
- Policies struct {
- Project []string `json:"project"`
- Domain []string `json:"domain"`
- System []string `json:"system"`
- } `json:"policies"`
- }
- type sProjectGroupRole struct {
- Id string `json:"id"`
- Name string `json:"name"`
- Metadata map[string]string `json:"metadata"`
- Domain struct {
- Id string `json:"id"`
- Name string `json:"name"`
- } `json:"domain"`
- Groups []sGroupRole `json:"groups"`
- }
- func (pgr *sProjectGroupRole) add(groupId, groupName, groupDomainId, groupDomainName, roleId, roleName, roleDomainId, roleDomainName string, projectPolicies, domainPolicies, systemPolicies []string) {
- groupIdx := -1
- for i := range pgr.Groups {
- if pgr.Groups[i].Id == groupId {
- groupIdx = i
- break
- }
- }
- if groupIdx < 0 {
- groupIdx = len(pgr.Groups)
- gr := sGroupRole{
- Id: groupId,
- Name: groupName,
- }
- gr.Domain.Id = groupDomainId
- gr.Domain.Name = groupDomainName
- pgr.Groups = append(pgr.Groups, gr)
- }
- pgr.Groups[groupIdx].add(roleId, roleName, roleDomainId, roleDomainName, projectPolicies, domainPolicies, systemPolicies)
- }
- func (gr *sGroupRole) add(roleId, roleName, roleDomainId, roleDomainName string, projectPolicies, domainPolicies, systemPolicies []string) {
- sr := sRole{
- Id: roleId,
- Name: roleName,
- }
- sr.Domain.Id = roleDomainId
- sr.Domain.Name = roleDomainName
- gr.Roles = append(gr.Roles, sr)
- for _, p := range projectPolicies {
- if !utils.IsInStringArray(p, gr.Policies.Project) {
- gr.Policies.Project = append(gr.Policies.Project, p)
- }
- }
- for _, p := range domainPolicies {
- if !utils.IsInStringArray(p, gr.Policies.Domain) {
- gr.Policies.Domain = append(gr.Policies.Domain, p)
- }
- }
- for _, p := range systemPolicies {
- if !utils.IsInStringArray(p, gr.Policies.System) {
- gr.Policies.System = append(gr.Policies.System, p)
- }
- }
- }
- var (
- RoleAssignments RoleAssignmentManagerV3
- )
- // get users for given project
- func (this *RoleAssignmentManagerV3) GetProjectUsers(s *mcclient.ClientSession, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- query := jsonutils.NewDict()
- if params.Contains("effective") {
- query.Add(jsonutils.JSONNull, "effective")
- }
- if jsonutils.QueryBoolean(params, "system", false) {
- query.Add(jsonutils.JSONNull, "include_system")
- }
- resource, e := params.GetString("resource")
- if e != nil {
- return jsonutils.JSONNull, e
- }
- scope := false
- switch resource {
- case "domain",
- "project":
- {
- scope = true
- }
- case "user",
- "group",
- "role":
- {
- scope = false
- }
- default:
- return jsonutils.JSONNull, fmt.Errorf("not allowed resource %s", resource)
- }
- query.Add(jsonutils.JSONNull, "include_names")
- if scope {
- query.Add(jsonutils.NewString(id), "scope", resource, "id")
- } else {
- query.Add(jsonutils.NewString(id), resource, "id")
- }
- query.Add(jsonutils.JSONNull, "include_policies")
- result, err := this.List(s, query)
- if err != nil {
- return jsonutils.JSONNull, err
- }
- projects := make(map[string]*projectRoles)
- for _, roleAssign := range result.Data {
- typ := "user"
- roleId, _ := roleAssign.GetString("role", "id")
- roleName, _ := roleAssign.GetString("role", "name")
- roleDomainId, _ := roleAssign.GetString("role", "domain", "id")
- roleDomainName, _ := roleAssign.GetString("role", "domain", "name")
- userId, _ := roleAssign.GetString("user", "id")
- userName, _ := roleAssign.GetString("user", "name")
- userDomainId, _ := roleAssign.GetString("user", "domain", "id")
- userDomainName, _ := roleAssign.GetString("user", "domain", "name")
- if len(userName) == 0 {
- typ = "group"
- userName, _ = roleAssign.GetString("group", "name")
- userId, _ = roleAssign.GetString("group", "id")
- userDomainId, _ = roleAssign.GetString("group", "domain", "id")
- userDomainName, _ = roleAssign.GetString("group", "domain", "name")
- }
- _, ok := projects[userId]
- if ok {
- projects[userId].add(roleId, roleName, roleDomainId, roleDomainName)
- } else {
- projects[userId] = newProjectRoles(userId, userName, userDomainId, userDomainName, roleId, roleName, roleDomainId, roleDomainName, typ)
- }
- }
- projJson := jsonutils.NewArray()
- for _, proj := range projects {
- projJson.Add(proj.json())
- }
- data := jsonutils.NewDict()
- data.Add(projJson, "data")
- data.Add(jsonutils.NewInt(int64(len(projects))), "total")
- return data, nil
- }
- // get projects-roles for given resource, like domain, project, user, group, role
- func (this *RoleAssignmentManagerV3) GetProjectRole(s *mcclient.ClientSession, id string, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
- data := jsonutils.NewDict()
- query := jsonutils.NewDict()
- if params.Contains("effective") {
- query.Add(jsonutils.JSONNull, "effective")
- }
- if jsonutils.QueryBoolean(params, "system", false) {
- query.Add(jsonutils.JSONNull, "include_system")
- }
- resource, err := params.GetString("resource")
- if err != nil {
- return jsonutils.JSONNull, err
- }
- scope := false
- switch resource {
- case "domain",
- "project":
- {
- scope = true
- }
- case "user",
- "group",
- "role":
- {
- }
- default:
- return jsonutils.JSONNull, fmt.Errorf("not allowed resource %s", resource)
- }
- // search by project id or name
- searchProjs := jsonutils.GetQueryStringArray(params, "projects")
- if len(searchProjs) > 0 {
- query.Add(jsonutils.NewStringArray(searchProjs), "projects")
- }
- // search by user id or name
- searchUsers := jsonutils.GetQueryStringArray(params, "users")
- if len(searchUsers) > 0 {
- query.Add(jsonutils.NewStringArray(searchUsers), "users")
- }
- groupBy, _ := params.GetString("group_by")
- if len(groupBy) == 0 {
- groupBy = "project"
- }
- if groupBy == "project" {
- } else if groupBy == "user" {
- } else {
- return nil, errors.Wrapf(httperrors.ErrInputParameter, "unsupported group_by value %s", groupBy)
- }
- query.Add(jsonutils.JSONNull, "include_names")
- if scope {
- query.Add(jsonutils.NewString(id), "scope", resource, "id")
- } else {
- query.Add(jsonutils.NewString(id), resource, "id")
- }
- query.Add(jsonutils.JSONNull, "include_policies")
- result, err := this.List(s, query)
- if err != nil {
- return jsonutils.JSONNull, err
- }
- lines := make([]sProjectGroupRole, 0)
- for _, roleAssign := range result.Data {
- roleId, _ := roleAssign.GetString("role", "id")
- roleName, _ := roleAssign.GetString("role", "name")
- roleDomainId, _ := roleAssign.GetString("role", "domain", "id")
- roleDomainName, _ := roleAssign.GetString("role", "domain", "name")
- var groupById, groupByName, groupByDomainId, groupByDomainName string
- metadatas := map[string]string{}
- if groupBy == "project" {
- groupById, _ = roleAssign.GetString("scope", "project", "id")
- groupByName, _ = roleAssign.GetString("scope", "project", "name")
- roleAssign.Unmarshal(&metadatas, "scope", "project", "metadata")
- groupByDomainId, _ = roleAssign.GetString("scope", "project", "domain", "id")
- groupByDomainName, _ = roleAssign.GetString("scope", "project", "domain", "name")
- } else if groupBy == "user" {
- groupById, _ = roleAssign.GetString("user", "id")
- groupByName, _ = roleAssign.GetString("user", "name")
- groupByDomainId, _ = roleAssign.GetString("user", "domain", "id")
- groupByDomainName, _ = roleAssign.GetString("user", "domain", "name")
- }
- groupId, _ := roleAssign.GetString("group", "id")
- groupName, _ := roleAssign.GetString("group", "name")
- groupDomainId, _ := roleAssign.GetString("group", "domain", "id")
- groupDomainName, _ := roleAssign.GetString("group", "domain", "name")
- projPolicies, _ := jsonutils.GetStringArray(roleAssign, "policies", "project")
- domPolicies, _ := jsonutils.GetStringArray(roleAssign, "policies", "domain")
- sysPolicies, _ := jsonutils.GetStringArray(roleAssign, "policies", "system")
- lineIdx := -1
- for i := range lines {
- if lines[i].Id == groupById {
- lineIdx = i
- break
- }
- }
- if lineIdx < 0 {
- lineIdx = len(lines)
- pgr := sProjectGroupRole{
- Id: groupById,
- Name: groupByName,
- Metadata: metadatas,
- }
- pgr.Domain.Id = groupByDomainId
- pgr.Domain.Name = groupByDomainName
- lines = append(lines, pgr)
- }
- lines[lineIdx].add(groupId, groupName, groupDomainId, groupDomainName, roleId, roleName, roleDomainId, roleDomainName, projPolicies, domPolicies, sysPolicies)
- }
- lineJson := jsonutils.NewArray()
- for _, line := range lines {
- lineJson.Add(jsonutils.Marshal(line))
- }
- data.Add(lineJson, "data")
- data.Add(jsonutils.NewInt(int64(len(lines))), "total")
- return data, nil
- }
- func (man *RoleAssignmentManagerV3) GetUserIdsByRolesInScope(s *mcclient.ClientSession, roleIds []string, roleScope rbacscope.TRbacScope, scopeId string) ([]string, error) {
- query := jsonutils.NewDict()
- query.Set("roles", jsonutils.Marshal(roleIds))
- query.Set("effective", jsonutils.JSONTrue)
- switch roleScope {
- case rbacscope.ScopeSystem:
- case rbacscope.ScopeDomain:
- if scopeId == "" {
- return nil, errors.Errorf("need projectDomainId")
- }
- query.Set("project_domain_id", jsonutils.NewString(scopeId))
- case rbacscope.ScopeProject:
- if scopeId == "" {
- return nil, errors.Errorf("need projectId")
- }
- query.Add(jsonutils.NewString(scopeId), "scope", "project", "id")
- }
- ret, err := man.List(s, query)
- if err != nil {
- return nil, errors.Wrapf(err, "list RoleAssignments with query %s", query.String())
- }
- users := make([]string, 0)
- for i := range ret.Data {
- ras := ret.Data[i]
- user, err := ras.Get("user")
- if err == nil {
- id, err := user.GetString("id")
- if err != nil {
- return nil, errors.Wrap(err, "unable to get user.id from result of RoleAssignments.List")
- }
- users = append(users, id)
- }
- }
- return users, nil
- }
- func init() {
- RoleAssignments = RoleAssignmentManagerV3{modules.NewIdentityV3Manager("role_assignment", "role_assignments",
- []string{"Scope", "User", "Group", "Role", "Policies"},
- []string{})}
- modules.Register(&RoleAssignments)
- }
|