| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579 |
- // 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 (
- "context"
- "fmt"
- "io/ioutil"
- "strings"
- "time"
- "yunion.io/x/jsonutils"
- "yunion.io/x/log"
- "yunion.io/x/pkg/util/rbacscope"
- "yunion.io/x/pkg/util/shellutils"
- "yunion.io/x/onecloud/cmd/climc/shell"
- 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"
- "yunion.io/x/onecloud/pkg/mcclient/auth"
- modules "yunion.io/x/onecloud/pkg/mcclient/modules/identity"
- baseoptions "yunion.io/x/onecloud/pkg/mcclient/options"
- options "yunion.io/x/onecloud/pkg/mcclient/options/identity"
- "yunion.io/x/onecloud/pkg/util/fileutils2"
- "yunion.io/x/onecloud/pkg/util/rbacutils"
- "yunion.io/x/onecloud/pkg/util/tagutils"
- )
- func createPolicy(s *mcclient.ClientSession, name string, genName string, policy string, domain string, enabled bool, disabled bool, desc string, scope string, isSystem *bool, objectags, projecttags, domaintags tagutils.TTagSet, orgNodeId []string) error {
- params := jsonutils.NewDict()
- if len(genName) > 0 {
- params.Add(jsonutils.NewString(genName), "generate_name")
- params.Add(jsonutils.NewString(genName), "type")
- } else if len(name) > 0 {
- params.Add(jsonutils.NewString(name), "name")
- params.Add(jsonutils.NewString(name), "type")
- } else {
- return fmt.Errorf("mising name")
- }
- params.Add(jsonutils.NewString(policy), "policy")
- if len(domain) > 0 {
- params.Add(jsonutils.NewString(domain), "project_domain_id")
- }
- if enabled {
- params.Add(jsonutils.JSONTrue, "enabled")
- } else if disabled {
- params.Add(jsonutils.JSONFalse, "enabled")
- }
- if len(desc) > 0 {
- params.Add(jsonutils.NewString(desc), "description")
- }
- if len(scope) > 0 {
- params.Add(jsonutils.NewString(scope), "scope")
- }
- if isSystem != nil {
- if *isSystem {
- params.Add(jsonutils.JSONTrue, "is_system")
- } else {
- params.Add(jsonutils.JSONFalse, "is_system")
- }
- }
- if len(objectags) > 0 {
- params.Add(jsonutils.Marshal(objectags), "object_tags")
- }
- if len(projecttags) > 0 {
- params.Add(jsonutils.Marshal(projecttags), "project_tags")
- }
- if len(domaintags) > 0 {
- params.Add(jsonutils.Marshal(domaintags), "domain_tags")
- }
- if len(orgNodeId) > 0 {
- params.Add(jsonutils.NewStringArray(orgNodeId), "org_node_id")
- }
- result, err := modules.Policies.Create(s, params)
- if err != nil {
- return err
- }
- printObject(result)
- return nil
- }
- func createPolicyFromJson(s *mcclient.ClientSession, old jsonutils.JSONObject, argsName, genName, argsDomain, argsScope string) error {
- policy, _ := old.GetString("policy")
- enabled, _ := old.Bool("enabled")
- desc, _ := old.GetString("description")
- scope, _ := old.GetString("scope")
- if len(argsScope) > 0 {
- scope = argsScope
- }
- isSystem, _ := old.Bool("is_system")
- var objectTags, projectTags, domainTags tagutils.TTagSet
- if old.Contains("object_tags") {
- objectTags = make(tagutils.TTagSet, 0)
- old.Unmarshal(&objectTags, "object_tags")
- }
- if old.Contains("project_tags") {
- projectTags = make(tagutils.TTagSet, 0)
- old.Unmarshal(&projectTags, "project_tags")
- }
- if old.Contains("domain_tags") {
- domainTags = make(tagutils.TTagSet, 0)
- old.Unmarshal(&domainTags, "domain_tags")
- }
- var nodeIds []string
- if old.Contains("org_node_id") {
- nodeIds = make([]string, 0)
- old.Unmarshal(&nodeIds, "org_node_id")
- }
- return createPolicy(s, argsName, genName, policy, argsDomain, enabled, !enabled, desc, scope, &isSystem, objectTags, projectTags, domainTags, nodeIds)
- }
- func init() {
- cmd := shell.NewResourceCmd(&modules.Policies)
- cmd.List(&options.PolicyListOptions{})
- cmd.Perform("user-metadata", &baseoptions.ResourceMetadataOptions{})
- cmd.Perform("set-user-metadata", &baseoptions.ResourceMetadataOptions{})
- cmd.GetProperty(&options.PolicyGetPropertyTagValuePairOptions{})
- cmd.GetProperty(&options.PolicyGetPropertyTagValueTreeOptions{})
- cmd.GetProperty(&options.PolicyGetPropertyDomainTagValuePairOptions{})
- cmd.GetProperty(&options.PolicyGetPropertyDomainTagValueTreeOptions{})
- type PolicyCreateOptions struct {
- Domain string `help:"domain of the policy"`
- NAME string `help:"name of the policy"`
- FILE string `help:"path to policy file"`
- Enabled bool `help:"create policy enabled"`
- Disabled bool `help:"create policy disabled"`
- Desc string `help:"policy description"`
- Scope string `help:"scope of policy"`
- IsSystem *bool `help:"create system policy" negative:"no-system"`
- ProjectTags string `help:"project tags"`
- DomainTags string `help:"domain tags"`
- ObjectTags string `help:"object tags"`
- OrgNodeId []string `help:"node ids of organiazation tree node"`
- }
- R(&PolicyCreateOptions{}, "policy-create", "Create a new policy", func(s *mcclient.ClientSession, args *PolicyCreateOptions) error {
- policyBytes, err := ioutil.ReadFile(args.FILE)
- if err != nil {
- return err
- }
- objectTags := baseoptions.SplitTag(args.ObjectTags)
- projectTags := baseoptions.SplitTag(args.ProjectTags)
- domainTags := baseoptions.SplitTag(args.DomainTags)
- return createPolicy(s, args.NAME, "", string(policyBytes), args.Domain, args.Enabled, args.Disabled, args.Desc, args.Scope, args.IsSystem, objectTags, projectTags, domainTags, args.OrgNodeId)
- })
- type PolicyExportOptions struct {
- ID string `json:"id"`
- }
- R(&PolicyExportOptions{}, "policy-export", "Export a policy", func(s *mcclient.ClientSession, args *PolicyExportOptions) error {
- ret, err := modules.Policies.Get(s, args.ID, nil)
- if err != nil {
- return err
- }
- fmt.Println(ret.PrettyString())
- return nil
- })
- type PolicyImportOptions struct {
- FILE string `json:"id"`
- Domain string `help:"domain of the policy"`
- }
- R(&PolicyImportOptions{}, "policy-import", "Import a policy", func(s *mcclient.ClientSession, args *PolicyImportOptions) error {
- cont, err := ioutil.ReadFile(args.FILE)
- if err != nil {
- return err
- }
- jsonCont, err := jsonutils.Parse(cont)
- if err != nil {
- return err
- }
- name, _ := jsonCont.GetString("name")
- return createPolicyFromJson(s, jsonCont, "", name, args.Domain, "")
- })
- type PolicyCloneOptions struct {
- Scope string `help:"scope of policy"`
- Domain string `help:"domain of the policy"`
- OLD string `help:"name or id of the old policy"`
- NAME string `help:"name of the policy"`
- }
- R(&PolicyCloneOptions{}, "policy-clone", "Clone a policy", func(s *mcclient.ClientSession, args *PolicyCloneOptions) error {
- old, err := modules.Policies.Get(s, args.OLD, nil)
- if err != nil {
- return err
- }
- return createPolicyFromJson(s, old, args.NAME, "", args.Domain, args.Scope)
- })
- type PolicyPatchOptions struct {
- ID string `help:"ID of policy"`
- File string `help:"path to policy file"`
- Type string `help:"policy type"`
- Enabled bool `help:"update policy enabled"`
- Disabled bool `help:"update policy disabled"`
- Desc string `help:"Description"`
- IsSystem bool `help:"is_system"`
- IsNotSystem bool `help:"negative is_system"`
- TagsAction string `help:"how to update tags" choices:"add|remove|replace"`
- ProjectTags string `help:"project tags"`
- DomainTags string `help:"domain tags"`
- ObjectTags string `help:"object tags"`
- OrgNodeId []string `help:"node ids of organiazation tree node"`
- }
- updateFunc := func(s *mcclient.ClientSession, args *PolicyPatchOptions) error {
- policyId, err := modules.Policies.GetId(s, args.ID, nil)
- if err != nil {
- return err
- }
- params := jsonutils.NewDict()
- if len(args.Type) > 0 {
- params.Add(jsonutils.NewString(args.Type), "type")
- }
- if len(args.File) > 0 {
- policyBytes, err := ioutil.ReadFile(args.File)
- if err != nil {
- return err
- }
- params.Add(jsonutils.NewString(string(policyBytes)), "policy")
- }
- if args.Enabled {
- params.Add(jsonutils.JSONTrue, "enabled")
- } else if args.Disabled {
- params.Add(jsonutils.JSONFalse, "enabled")
- }
- if len(args.Desc) > 0 {
- params.Add(jsonutils.NewString(args.Desc), "description")
- }
- if args.IsSystem {
- params.Add(jsonutils.JSONTrue, "is_system")
- }
- if args.IsNotSystem {
- params.Add(jsonutils.JSONFalse, "is_system")
- }
- if len(args.ObjectTags) > 0 {
- tags := baseoptions.SplitTag(args.ObjectTags)
- params.Add(jsonutils.Marshal(tags), "object_tags")
- }
- if len(args.ProjectTags) > 0 {
- tags := baseoptions.SplitTag(args.ProjectTags)
- params.Add(jsonutils.Marshal(tags), "project_tags")
- }
- if len(args.DomainTags) > 0 {
- tags := baseoptions.SplitTag(args.DomainTags)
- params.Add(jsonutils.Marshal(tags), "domain_tags")
- }
- if len(args.TagsAction) > 0 {
- params.Add(jsonutils.NewString(args.TagsAction), "tag_update_policy")
- }
- if len(args.OrgNodeId) > 0 {
- params.Add(jsonutils.NewStringArray(args.OrgNodeId), "org_node_id")
- }
- result, err := modules.Policies.Update(s, policyId, params)
- if err != nil {
- return err
- }
- printObject(result)
- return nil
- }
- R(&PolicyPatchOptions{}, "policy-patch", "Patch policy", updateFunc)
- R(&PolicyPatchOptions{}, "policy-update", "Update policy", updateFunc)
- type PolicyPublicOptions struct {
- ID string `help:"ID of policy to update" json:"-"`
- Scope string `help:"sharing scope" choices:"system|domain"`
- SharedDomains []string `help:"share to domains"`
- }
- R(&PolicyPublicOptions{}, "policy-public", "Mark a policy public", func(s *mcclient.ClientSession, args *PolicyPublicOptions) error {
- params := jsonutils.Marshal(args)
- result, err := modules.Policies.PerformAction(s, args.ID, "public", params)
- if err != nil {
- return err
- }
- printObject(result)
- return nil
- })
- type PolicyPrivateOptions struct {
- ID string `help:"ID of policy to update" json:"-"`
- }
- R(&PolicyPrivateOptions{}, "policy-private", "Mark a policy private", func(s *mcclient.ClientSession, args *PolicyPrivateOptions) 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"`
- }
- R(&PolicyDeleteOptions{}, "policy-delete", "Delete policy", func(s *mcclient.ClientSession, args *PolicyDeleteOptions) error {
- policyId, err := modules.Policies.GetId(s, args.ID, nil)
- if err != nil {
- return err
- }
- result, err := modules.Policies.Delete(s, policyId, nil)
- if err != nil {
- return err
- }
- printObject(result)
- return nil
- })
- type PolicyShowOptions struct {
- ID string `help:"ID of policy"`
- Format string `help:"policy format, default yaml" default:"yaml" choices:"yaml|json"`
- Save string `help:"save policy data into a file"`
- }
- R(&PolicyShowOptions{}, "policy-show", "Show policy", func(s *mcclient.ClientSession, args *PolicyShowOptions) error {
- query := jsonutils.NewDict()
- query.Add(jsonutils.NewString(args.Format), "format")
- result, err := modules.Policies.Get(s, args.ID, query)
- if err != nil {
- return err
- }
- printObject(result)
- if len(args.Save) > 0 {
- if args.Format == "yaml" {
- yaml, _ := result.GetString("policy")
- fileutils2.FilePutContents(args.Save, yaml, false)
- } else {
- p, _ := result.Get("policy")
- fileutils2.FilePutContents(args.Save, p.PrettyString(), false)
- }
- }
- return nil
- })
- type PolicyEditOptions struct {
- ID string `help:"ID of policy"`
- }
- R(&PolicyEditOptions{}, "policy-edit", "Edit and update policy", func(s *mcclient.ClientSession, args *PolicyEditOptions) error {
- query := jsonutils.NewDict()
- query.Add(jsonutils.NewString("yaml"), "format")
- result, err := modules.Policies.Get(s, args.ID, query)
- if err != nil {
- return err
- }
- policyId, err := result.GetString("id")
- if err != nil {
- return err
- }
- yaml, err := result.GetString("policy")
- if err != nil {
- return err
- }
- yaml, err = shellutils.Edit(yaml)
- if err != nil {
- return err
- }
- params := jsonutils.NewDict()
- params.Add(jsonutils.NewString(yaml), "policy")
- result, err = modules.Policies.Patch(s, policyId, params)
- if err != nil {
- return err
- }
- printObject(result)
- 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"`
- Project string `help:"Role assignments for project"`
- ProjectDomain string `help:"Domain for project"`
- Role []string `help:"Role name list"`
- RoleId []string `help:"Role Id list"`
- }
- R(&PolicyAdminCapableOptions{}, "policy-admin-capable", "Check admin capable", func(s *mcclient.ClientSession, args *PolicyAdminCapableOptions) error {
- auth.InitFromClientSession(s)
- policy.EnableGlobalRbac(15*time.Second, false, 1)
- var token mcclient.TokenCredential
- if len(args.User) > 0 {
- token = &mcclient.SSimpleToken{
- Domain: args.UserDomain,
- User: args.User,
- Project: args.Project,
- ProjectDomain: args.ProjectDomain,
- Roles: strings.Join(args.Role, ","),
- RoleIds: strings.Join(args.RoleId, ","),
- }
- } else {
- token = s.GetToken()
- }
- fmt.Println("Token", token)
- for _, scope := range []rbacscope.TRbacScope{
- rbacscope.ScopeSystem,
- rbacscope.ScopeDomain,
- rbacscope.ScopeProject,
- rbacscope.ScopeUser,
- rbacscope.ScopeNone,
- } {
- fmt.Printf("%s: ", scope)
- capable := policy.PolicyManager.IsScopeCapable(token, scope)
- fmt.Println(capable)
- }
- return nil
- })
- type PolicyExplainOptions struct {
- User string `help:"For user"`
- UserDomain string `help:"Domain for user"`
- Project string `help:"Role assignments for project"`
- Role []string `help:"Roles"`
- RoleId []string `help:"Role Id list"`
- Request []string `help:"explain request, in format of key:scope:service:resource:action:extra"`
- Name string `help:"policy name"`
- Debug bool `help:"enable RBAC debug"`
- ProjectDomain string `help:"Domain name"`
- Ip string `help:"login IP"`
- }
- R(&PolicyExplainOptions{}, "policy-explain", "Explain policy result", func(s *mcclient.ClientSession, args *PolicyExplainOptions) error {
- err := log.SetLogLevelByString(log.Logger(), "debug")
- if err != nil {
- log.Fatalf("Set log level %q: %v", "debug", err)
- }
- if args.Debug {
- rbacutils.ShowMatchRuleDebug = true
- }
- auth.InitFromClientSession(s)
- policy.EnableGlobalRbac(15*time.Second, false, 1)
- if args.Debug {
- consts.EnableRbacDebug()
- }
- req := jsonutils.NewDict()
- for i := 0; i < len(args.Request); i += 1 {
- parts := strings.Split(args.Request[i], ":")
- if len(parts) < 3 {
- return fmt.Errorf("invalid request, should be in the form of key:[system|domain|project]:service[:resource:action:extra]")
- }
- key := parts[0]
- data := make([]jsonutils.JSONObject, 0)
- for i := 1; i < len(parts); i += 1 {
- data = append(data, jsonutils.NewString(parts[i]))
- }
- req.Add(jsonutils.NewArray(data...), key)
- }
- fmt.Println("Request:", req.String())
- var token mcclient.TokenCredential
- if len(args.User) > 0 {
- usrParams := jsonutils.NewDict()
- if len(args.UserDomain) > 0 {
- usrDom, err := modules.Domains.Get(s, args.UserDomain, nil)
- if err != nil {
- return fmt.Errorf("search user domain %s fail %s", args.UserDomain, err)
- }
- usrDomId, _ := usrDom.Get("id")
- usrParams.Add(usrDomId, "domain_id")
- }
- usr, err := modules.UsersV3.Get(s, args.User, usrParams)
- if err != nil {
- return fmt.Errorf("search user %s fail %s", args.User, err)
- }
- usrId, _ := usr.GetString("id")
- usrName, _ := usr.GetString("name")
- usrDomId, _ := usr.GetString("domain_id")
- usrDom, _ := usr.GetString("domain")
- projParams := jsonutils.NewDict()
- if len(args.ProjectDomain) > 0 {
- projDom, err := modules.Domains.Get(s, args.ProjectDomain, nil)
- if err != nil {
- return fmt.Errorf("search project domain %s fail %s", args.ProjectDomain, err)
- }
- projDomId, _ := projDom.Get("id")
- projParams.Add(projDomId, "domain_id")
- }
- proj, err := modules.Projects.Get(s, args.Project, projParams)
- if err != nil {
- return fmt.Errorf("search project %s fail %s", args.Project, err)
- }
- projId, _ := proj.GetString("id")
- projName, _ := proj.GetString("name")
- projDom, _ := proj.GetString("domain")
- projDomId, _ := proj.GetString("domain_id")
- token = &mcclient.SSimpleToken{
- Domain: usrDom,
- DomainId: usrDomId,
- User: usrName,
- UserId: usrId,
- Project: projName,
- ProjectId: projId,
- ProjectDomain: projDom,
- ProjectDomainId: projDomId,
- Roles: strings.Join(args.Role, ","),
- RoleIds: strings.Join(args.RoleId, ","),
- Context: mcclient.SAuthContext{
- Ip: args.Ip,
- },
- Token: "faketoken",
- }
- } else {
- token = s.GetToken()
- }
- result, err := policy.ExplainRpc(context.Background(), token, req, args.Name)
- if err != nil {
- return err
- }
- printObject(result)
- /*for _, r := range args.Role {
- fmt.Println("role", r, "matched policies:", policy.PolicyManager.RoleMatchPolicies(r))
- }
- fmt.Println("userCred:", token)
- for _, scope := range []rbacutils.TRbacScope{
- rbacutils.ScopeSystem,
- rbacutils.ScopeDomain,
- rbacutils.ScopeProject,
- rbacutils.ScopeUser,
- rbacutils.ScopeNone,
- } {
- m := policy.PolicyManager.MatchedPolicyNames(scope, token)
- fmt.Println("matched", scope, "policies:", m)
- }
- fmt.Println("all_policies", policy.PolicyManager.AllPolicies())*/
- return nil
- })
- }
|