Skip to content

Commit

Permalink
fix: azure 支持权限
Browse files Browse the repository at this point in the history
  • Loading branch information
Qu Xuan committed Jul 14, 2020
1 parent 2643468 commit c003f78
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 68 deletions.
58 changes: 1 addition & 57 deletions pkg/apis/cloudid/cloudgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,15 +108,7 @@ type CloudgroupDetails struct {
type CloudgroupCreateInput struct {
apis.StatusInfrasResourceBaseCreateInput

// 平台
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 支持 |
// | Qcloud | 支持 |
// 平台, 目前支持Qcloud,Google,Azure,Aliyun,Huawei,Aws
Provider string `json:"provider"`

// 权限Id列表, 权限provider必须和权限组provider一致
Expand All @@ -126,84 +118,36 @@ type CloudgroupCreateInput struct {
type CloudgroupAddUserInput struct {

// 用户Id
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 不支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 支持 |
// | 腾讯云 | 支持 |
ClouduserId string `json:"clouduser_id"`
}

type CloudgroupRemoveUserInput struct {

// 用户Id
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 不支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 支持 |
// | 腾讯云 | 支持 |
ClouduserId string `json:"clouduser_id"`
}

type CloudgroupAttachPolicyInput struct {

// 权限Id
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 不支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 不支持 |
// | 腾讯云 | 支持 |
CloudpolicyId string `json:"cloudpolicy_id"`
}

type CloudgroupSetUsersInput struct {

// 公有云子账号Ids
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 支持 |
// | 腾讯云 | 支持 |
ClouduserIds []string `json:"clouduser_ids"`
}

type CloudgroupSetPoliciesInput struct {

// 权限Ids
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 不支持 |
// | 腾讯云 | 支持 |
CloudpolicyIds []string `json:"cloudpolicy_ids"`
}

type CloudgroupDetachPolicyInput struct {

// 权限Id
//
// | 云平台 | 说明 |
// |----------|---------------------------------------------|
// | Google | 不支持 |
// | Aliyun | 支持 |
// | Huawei | 支持 |
// | Azure | 不支持 |
// | 腾讯云 | 支持 |
CloudpolicyId string `json:"cloudpolicy_id"`
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/cloudid/clouduser.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ type ClouduserCreateInput struct {
// | Google | 至少需要一个初始权限 |
// | Aliyun | 支持 |
// | Huawei | 不支持 |
// | Azure | 不支持 |
// | Azure | 支持 |
// | 腾讯云 | 支持 |
CloudpolicyIds []string `json:"cloudpolicy_ids"`

Expand Down
16 changes: 14 additions & 2 deletions pkg/apis/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,23 @@ type ProjectizedResourceListInput struct {

type StatusDomainLevelUserResourceListInput struct {
StatusDomainLevelResourceListInput
UserResourceListInput

// 查询指定的用户(ID或名称)拥有的资源
User string `json:"user"`
// swagger:ignore
// Deprecated
// Filter by userId
UserId string `json:"user_id" "yunion:deprecated-by":"user"`
}

type UserResourceListInput struct {
StatusDomainLevelResourceListInput
StandaloneResourceListInput
ScopedResourceInput

// swagger:ignore
// Is an admin call? equivalent to scope=system
// Deprecated
Admin *bool `json:"admin"`

// 查询指定的用户(ID或名称)拥有的资源
User string `json:"user"`
Expand Down
2 changes: 1 addition & 1 deletion pkg/cloudcommon/db/statusinfrasuserresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (manager *SStatusDomainLevelUserResourceBaseManager) FilterByOwner(q *sqlch
if owner != nil {
switch scope {
case rbacutils.ScopeProject, rbacutils.ScopeUser:
return q.Equals("owner_id", owner.GetProjectDomainId())
return q.Equals("owner_id", owner.GetUserId())
case rbacutils.ScopeDomain:
sq := UserCacheManager.Query("id").Equals("domain_id", owner.GetProjectDomainId())
q = q.Filter(
Expand Down
1 change: 1 addition & 0 deletions pkg/multicloud/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ var DEFAULT_API_VERSION = map[string]string{
"microsoft.insights/eventtypes/management/values": "2017-03-01-preview",
"Microsoft.Authorization/policyDefinitions": "2019-09-01",
"Microsoft.Authorization/policyAssignments": "2019-09-01",
"Microsoft.Authorization": "2018-01-01-preview",
}

var GRAPH_API_VERSION = map[string]string{
Expand Down
34 changes: 30 additions & 4 deletions pkg/multicloud/azure/cloudgroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,15 @@ func (group *SCloudgroup) GetDescription() string {
}

func (group *SCloudgroup) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
return nil, cloudprovider.ErrNotSupported
policies, err := group.client.GetCloudpolicies(group.ObjectId)
if err != nil {
return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", group.ObjectId)
}
ret := []cloudprovider.ICloudpolicy{}
for i := range policies {
ret = append(ret, &policies[i])
}
return ret, nil
}

func (group *SCloudgroup) GetICloudusers() ([]cloudprovider.IClouduser, error) {
Expand All @@ -80,11 +88,24 @@ func (group *SCloudgroup) RemoveUser(name string) error {
}

func (group *SCloudgroup) AttachSystemPolicy(policyId string) error {
return cloudprovider.ErrNotSupported
return group.client.AssignPolicy(group.ObjectId, policyId)
}

func (group *SCloudgroup) DetachSystemPolicy(policyId string) error {
return cloudprovider.ErrNotSupported
assignments, err := group.client.GetAssignments(group.ObjectId)
if err != nil {
return errors.Wrapf(err, "GetAssignments(%s)", group.ObjectId)
}
for _, assignment := range assignments {
role, err := group.client.GetRole(assignment.Properties.RoleDefinitionId)
if err != nil {
return errors.Wrapf(err, "GetRule(%s)", assignment.Properties.RoleDefinitionId)
}
if role.Properties.RoleName == policyId {
return group.client.Delete(assignment.Id)
}
}
return nil
}

func (group *SCloudgroup) Delete() error {
Expand Down Expand Up @@ -179,7 +200,12 @@ func (self *SAzureClient) RemoveGroupUser(id, userName string) error {
}

func (self *SAzureClient) CreateICloudgroup(name, desc string) (cloudprovider.ICloudgroup, error) {
return self.CreateGroup(name, desc)
group, err := self.CreateGroup(name, desc)
if err != nil {
return nil, errors.Wrap(err, "CreateGroup")
}
group.client = self
return group, nil
}

func (self *SAzureClient) AddGroupUser(id, userName string) error {
Expand Down
172 changes: 172 additions & 0 deletions pkg/multicloud/azure/cloudpolicy.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
// 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 azure

import (
"fmt"
"net/url"

"yunion.io/x/jsonutils"
"yunion.io/x/pkg/errors"
"yunion.io/x/pkg/util/stringutils"

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

type SRoleProperties struct {
RoleName string
Type string
Description string
AssignableScopes []string
}

type SCloudpolicy struct {
Id string
Type string
Name string
Properties SRoleProperties
}

func (role *SCloudpolicy) GetName() string {
return role.Properties.RoleName
}

func (role *SCloudpolicy) GetGlobalId() string {
return role.Properties.RoleName
}

func (role *SCloudpolicy) GetDescription() string {
return role.Properties.Description
}

func (cli *SAzureClient) GetRoles(name string) ([]SCloudpolicy, error) {
ret := []SCloudpolicy{}
subscriptionId, err := cli.getDefaultSubscriptionId()
if err != nil {
return nil, errors.Wrap(err, "getDefaultSubscriptionId")
}
params := url.Values{}
if len(name) > 0 {
params.Set("$filter", fmt.Sprintf("roleName eq '%s'", name))
}
resource := "providers/Microsoft.Authorization/roleDefinitions"
if len(params) > 0 {
resource = fmt.Sprintf("%s?%s", resource, params.Encode())
}
err = cli.listSubscriptionResource(subscriptionId, resource, &ret)
if err != nil {
return nil, errors.Wrap(err, "listSubscriptionResource")
}
return ret, nil
}

func (cli *SAzureClient) GetICloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
roles, err := cli.GetRoles("")
if err != nil {
return nil, errors.Wrap(err, "GetRoles")
}
ret := []cloudprovider.ICloudpolicy{}
for i := range roles {
ret = append(ret, &roles[i])
}
return ret, nil
}

func (cli *SAzureClient) AssignPolicy(objectId, roleName string) error {
roles, err := cli.GetRoles(roleName)
if err != nil {
return errors.Wrapf(err, "GetRoles(%s)", roleName)
}
if len(roles) == 0 {
return errors.Wrap(cloudprovider.ErrNotFound, roleName)
}
if len(roles) > 1 {
return errors.Wrap(cloudprovider.ErrDuplicateId, roleName)
}
body := map[string]interface{}{
"properties": map[string]interface{}{
"roleDefinitionId": roles[0].Id,
"principalId": objectId,
},
}

subscriptionId, err := cli.getDefaultSubscriptionId()
if err != nil {
return errors.Wrap(err, "getDefaultSubscriptionId")
}

resource := fmt.Sprintf("subscriptions/%s/providers/Microsoft.Authorization/roleAssignments/%s", subscriptionId, stringutils.UUID4())
return cli.Put(resource, jsonutils.Marshal(body))
}

type SAssignmentProperties struct {
RoleDefinitionId string
PrincipalId string
PrincipalType string
Scope string
}

type SAssignment struct {
Id string
Name string
Type string
Properties SAssignmentProperties
}

func (cli *SAzureClient) GetAssignments(objectId string) ([]SAssignment, error) {
ret := []SAssignment{}
subscriptionId, err := cli.getDefaultSubscriptionId()
if err != nil {
return nil, errors.Wrap(err, "getDefaultSubscriptionId")
}
params := url.Values{}
if len(objectId) > 0 {
params.Set("$filter", fmt.Sprintf("principalId eq '%s'", objectId))
}
resource := "providers/Microsoft.Authorization/roleAssignments"
if len(params) > 0 {
resource = fmt.Sprintf("%s?%s", resource, params.Encode())
}
err = cli.listSubscriptionResource(subscriptionId, resource, &ret)
if err != nil {
return nil, errors.Wrap(err, "listSubscriptionResource")
}
return ret, nil
}

func (cli *SAzureClient) GetRole(roleId string) (*SCloudpolicy, error) {
role := &SCloudpolicy{}
err := cli.Get(roleId, nil, role)
if err != nil {
return nil, errors.Wrapf(err, "GetRole(%s)", roleId)
}
return role, nil
}

func (cli *SAzureClient) GetCloudpolicies(objectId string) ([]SCloudpolicy, error) {
assignments, err := cli.GetAssignments(objectId)
if err != nil {
return nil, errors.Wrapf(err, "GetAssignments(%s)", objectId)
}
ret := []SCloudpolicy{}
for _, assignment := range assignments {
role, err := cli.GetRole(assignment.Properties.RoleDefinitionId)
if err != nil {
return nil, errors.Wrapf(err, "GetRule(%s)", assignment.Properties.RoleDefinitionId)
}
ret = append(ret, *role)
}
return ret, nil
}

0 comments on commit c003f78

Please sign in to comment.