Skip to content

Commit

Permalink
fix: 优化openstack项目认证 (#7398)
Browse files Browse the repository at this point in the history
Co-authored-by: Qu Xuan <quxuan@yunionyun.com>
  • Loading branch information
ioito and Qu Xuan committed Jul 31, 2020
1 parent 5dc8296 commit 65cd074
Show file tree
Hide file tree
Showing 5 changed files with 145 additions and 35 deletions.
50 changes: 15 additions & 35 deletions pkg/multicloud/openstack/openstack.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ import (
api "yunion.io/x/onecloud/pkg/apis/compute"
"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/mcclient"
"yunion.io/x/onecloud/pkg/mcclient/modulebase"
"yunion.io/x/onecloud/pkg/mcclient/modules"
"yunion.io/x/onecloud/pkg/util/httputils"
"yunion.io/x/onecloud/pkg/util/version"
)
Expand Down Expand Up @@ -122,16 +120,6 @@ func (cli *SOpenStackClient) getDefaultRegionName() string {
}

func (cli *SOpenStackClient) getProjectToken(projectId, projectName string) (mcclient.TokenCredential, error) {
s := cli.getDefaultSession("")
roleId, err := modules.RolesV3.GetId(s, "admin", jsonutils.Marshal(map[string]string{}))
if err != nil {
return nil, errors.Wrap(err, "RolesV3.GetId")
}
_, err = modules.RolesV3.PutInContexts(s, roleId, nil, []modulebase.ManagerContext{{InstanceManager: &modules.Projects, InstanceId: projectId}, {InstanceManager: &modules.UsersV3, InstanceId: s.GetUserId()}})
if err != nil {
return nil, errors.Wrap(err, "RolesV3.PutInContexts")
}

client := cli.getDefaultClient()
tokenCredential, err := client.Authenticate(cli.username, cli.password, cli.domainName, projectName, cli.projectDomain)
if err != nil {
Expand Down Expand Up @@ -424,18 +412,6 @@ func (cli *SOpenStackClient) getProjectTokenCredential(projectId string) (mcclie
if err != nil {
return nil, errors.Wrapf(err, "GetProject(%s)", projectId)
}

s := cli.getDefaultSession("")

roleId, err := modules.RolesV3.GetId(s, "admin", jsonutils.Marshal(map[string]string{}))
if err != nil {
return nil, errors.Wrap(err, "RolesV3.GetId")
}
_, err = modules.RolesV3.PutInContexts(s, roleId, nil, []modulebase.ManagerContext{{InstanceManager: &modules.Projects, InstanceId: project.GetId()}, {InstanceManager: &modules.UsersV3, InstanceId: s.GetUserId()}})
if err != nil {
return nil, errors.Wrap(err, "RolesV3.PutInContexts")
}

return cli.getProjectToken(project.Id, project.Name)
}

Expand Down Expand Up @@ -510,23 +486,27 @@ func (cli *SOpenStackClient) CreateIProject(name string) (cloudprovider.ICloudPr
}

func (cli *SOpenStackClient) CreateProject(name, desc string) (*SProject, error) {
s := cli.getDefaultSession("")
params := map[string]string{
"name": name,
"domain_id": s.GetDomainId(),
}
if len(desc) > 0 {
params["description"] = desc
}
result, err := modules.Projects.Create(s, jsonutils.Marshal(params))
params := map[string]interface{}{
"project": map[string]interface{}{
"name": name,
"domain_id": cli.tokenCredential.GetProjectDomainId(),
"enabled": true,
"description": desc,
},
}
resp, err := cli.iamRequest(cli.getDefaultRegionName(), httputils.POST, "/v3/projects", nil, params)
if err != nil {
return nil, errors.Wrap(err, "Projects.Create")
return nil, errors.Wrap(err, "iamRequest")
}
project := SProject{client: cli}
err = result.Unmarshal(&project)
err = resp.Unmarshal(&project, "project")
if err != nil {
return nil, errors.Wrap(err, "result.Unmarshal")
}
err = cli.AssignRoleToUserOnProject(cli.tokenCredential.GetUserId(), project.Id, "admin")
if err != nil {
return nil, errors.Wrap(err, "AssignRoleToUserOnProject")
}
return &project, nil
}

Expand Down
10 changes: 10 additions & 0 deletions pkg/multicloud/openstack/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
package openstack

import (
"fmt"
"net/url"

"yunion.io/x/jsonutils"
Expand Down Expand Up @@ -51,6 +52,9 @@ func (p *SProject) GetName() string {
}

func (p *SProject) GetStatus() string {
if !p.Enabled {
return api.EXTERNAL_PROJECT_STATUS_UNKNOWN
}
_, err := p.getToken()
if err != nil {
log.Errorf("get project %s token error: %v %T", p.Name, err, err)
Expand Down Expand Up @@ -115,3 +119,9 @@ func (cli *SOpenStackClient) GetProjects() ([]SProject, error) {
}
return projects, nil
}

func (cli *SOpenStackClient) DeleteProject(projectId string) error {
resource := fmt.Sprintf("/v3/projects/%s", projectId)
_, err := cli.iamRequest(cli.getDefaultRegionName(), httputils.DELETE, resource, nil, nil)
return err
}
67 changes: 67 additions & 0 deletions pkg/multicloud/openstack/roles.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// 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 openstack

import (
"fmt"
"net/url"

"yunion.io/x/pkg/errors"

"yunion.io/x/onecloud/pkg/cloudprovider"
"yunion.io/x/onecloud/pkg/util/httputils"
)

type SRole struct {
Id string
Name string
}

func (cli *SOpenStackClient) GetRoles(name string) ([]SRole, error) {
resource := "/v3/roles"
query := url.Values{}
if len(name) > 0 {
query.Set("name", name)
}
resp, err := cli.iamRequest(cli.getDefaultRegionName(), httputils.GET, resource, query, nil)
if err != nil {
return nil, errors.Wrap(err, "iamRequest")
}
roles := []SRole{}
err = resp.Unmarshal(&roles, "roles")
if err != nil {
return nil, errors.Wrap(err, "resp.Unmarshal")
}
return roles, nil
}

func (cli *SOpenStackClient) AssignRoleToUserOnProject(userId, projectId, roleName string) error {
if len(roleName) == 0 {
return errors.Error("empty role name")
}
roles, err := cli.GetRoles(roleName)
if err != nil {
return errors.Wrapf(err, "GetRoles(%s)", roleName)
}
if len(roles) == 0 {
return errors.Wrapf(cloudprovider.ErrNotFound, "role %s", roleName)
}
if len(roles) > 1 {
return errors.Wrapf(cloudprovider.ErrDuplicateId, "roles %d for %s", len(roles), roleName)
}
resource := fmt.Sprintf("/v3/projects/%s/users/%s/roles/%s", projectId, userId, roles[0].Id)
_, err = cli.iamRequest(cli.getDefaultRegionName(), httputils.PUT, resource, nil, map[string]string{})
return err
}
8 changes: 8 additions & 0 deletions pkg/multicloud/openstack/shell/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,12 @@ func init() {
return nil
})

type ProjectIdOption struct {
ID string
}

shellutils.R(&ProjectIdOption{}, "project-delete", "Delete project", func(cli *openstack.SRegion, args *ProjectIdOption) error {
return cli.GetClient().DeleteProject(args.ID)
})

}
45 changes: 45 additions & 0 deletions pkg/multicloud/openstack/shell/role.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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 shell

import (
"yunion.io/x/onecloud/pkg/multicloud/openstack"
"yunion.io/x/onecloud/pkg/util/shellutils"
)

func init() {
type RoleListOptions struct {
Name string
}
shellutils.R(&RoleListOptions{}, "role-list", "List roles", func(cli *openstack.SRegion, args *RoleListOptions) error {
roles, err := cli.GetClient().GetRoles(args.Name)
if err != nil {
return err
}
printList(roles, 0, 0, 0, []string{})
return nil
})

type RoleAssignOptions struct {
PROJECT_ID string
USERID string
ROLE string
}

shellutils.R(&RoleAssignOptions{}, "role-assign", "Assign role to user on project", func(cli *openstack.SRegion, args *RoleAssignOptions) error {
return cli.GetClient().AssignRoleToUserOnProject(args.USERID, args.PROJECT_ID, args.ROLE)
})

}

0 comments on commit 65cd074

Please sign in to comment.