yunion.io/x/cloudmux@v0.3.10-0-alpha.1/pkg/multicloud/azure/clouduser.go (about)

     1  // Copyright 2019 Yunion
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package azure
    16  
    17  import (
    18  	"fmt"
    19  	"net/url"
    20  	"strings"
    21  	"time"
    22  
    23  	"yunion.io/x/jsonutils"
    24  	"yunion.io/x/pkg/errors"
    25  
    26  	"yunion.io/x/cloudmux/pkg/cloudprovider"
    27  	"yunion.io/x/cloudmux/pkg/multicloud"
    28  	"yunion.io/x/onecloud/pkg/util/httputils"
    29  )
    30  
    31  type SClouduserPasswordProfile struct {
    32  	Password                     string
    33  	forceChangePasswordNextLogin bool
    34  	enforceChangePasswordPolicy  bool
    35  }
    36  
    37  type SClouduser struct {
    38  	client *SAzureClient
    39  	multicloud.SBaseClouduser
    40  
    41  	OdataType                        string `json:"odata.type"`
    42  	ObjectType                       string
    43  	Id                               string
    44  	DeletionTimestamp                string
    45  	AccountEnabled                   bool
    46  	AgeGroup                         string
    47  	City                             string
    48  	CompanyName                      string
    49  	ConsentProvidedForMinor          string
    50  	Country                          string
    51  	CreatedDateTime                  time.Time
    52  	CreationType                     string
    53  	Department                       string
    54  	DirSyncEnabled                   string
    55  	DisplayName                      string
    56  	EmployeeId                       string
    57  	FacsimileTelephoneNumber         string
    58  	GivenName                        string
    59  	ImmutableId                      string
    60  	IsCompromised                    string
    61  	JobTitle                         string
    62  	LastDirSyncTime                  string
    63  	LegalAgeGroupClassification      string
    64  	Mail                             string
    65  	MailNickname                     string
    66  	Mobile                           string
    67  	OnPremisesDistinguishedName      string
    68  	OnPremisesSecurityIdentifier     string
    69  	PasswordPolicies                 string
    70  	PasswordProfile                  SClouduserPasswordProfile
    71  	PhysicalDeliveryOfficeName       string
    72  	PostalCode                       string
    73  	PreferredLanguage                string
    74  	RefreshTokensValidFromDateTime   time.Time
    75  	ShowInAddressList                string
    76  	SipProxyAddress                  string
    77  	State                            string
    78  	StreetAddress                    string
    79  	Surname                          string
    80  	TelephoneNumber                  string
    81  	ThumbnailPhotoOdataMediaEditLink string `json:"thumbnailPhoto@odata.mediaEditLink"`
    82  	UsageLocation                    string
    83  	UserPrincipalName                string
    84  	UserState                        string
    85  	UserStateChangedOn               string
    86  	UserType                         string
    87  
    88  	inviteRedeemUrl string
    89  }
    90  
    91  func (user *SClouduser) GetName() string {
    92  	return user.UserPrincipalName
    93  }
    94  
    95  func (user *SClouduser) GetGlobalId() string {
    96  	return user.Id
    97  }
    98  
    99  func (user *SClouduser) GetEmailAddr() string {
   100  	return user.Mail
   101  }
   102  
   103  func (user *SClouduser) GetInviteUrl() string {
   104  	return user.inviteRedeemUrl
   105  }
   106  
   107  func (user *SClouduser) GetISystemCloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
   108  	policies, err := user.client.GetCloudpolicies(user.Id)
   109  	if err != nil {
   110  		return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id)
   111  	}
   112  	ret := []cloudprovider.ICloudpolicy{}
   113  	for i := range policies {
   114  		if policies[i].Properties.Type == "BuiltInRole" {
   115  			ret = append(ret, &policies[i])
   116  		}
   117  	}
   118  	return ret, nil
   119  }
   120  
   121  func (user *SClouduser) GetICustomCloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
   122  	policies, err := user.client.GetCloudpolicies(user.Id)
   123  	if err != nil {
   124  		return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id)
   125  	}
   126  	ret := []cloudprovider.ICloudpolicy{}
   127  	for i := range policies {
   128  		if policies[i].Properties.Type != "BuiltInRole" {
   129  			ret = append(ret, &policies[i])
   130  		}
   131  	}
   132  	return ret, nil
   133  }
   134  
   135  func (user *SClouduser) AttachSystemPolicy(policyId string) error {
   136  	for _, subscription := range user.client.subscriptions {
   137  		err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId)
   138  		if err != nil {
   139  			return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId)
   140  		}
   141  	}
   142  	return nil
   143  }
   144  
   145  func (user *SClouduser) AttachCustomPolicy(policyId string) error {
   146  	for _, subscription := range user.client.subscriptions {
   147  		err := user.client.AssignPolicy(user.Id, policyId, subscription.SubscriptionId)
   148  		if err != nil {
   149  			return errors.Wrapf(err, "AssignPolicy for subscription %s", subscription.SubscriptionId)
   150  		}
   151  	}
   152  	return nil
   153  }
   154  
   155  func (user *SClouduser) DetachSystemPolicy(policyId string) error {
   156  	assignments, err := user.client.GetAssignments(user.Id)
   157  	if err != nil {
   158  		return errors.Wrapf(err, "GetAssignments(%s)", user.Id)
   159  	}
   160  	for _, assignment := range assignments {
   161  		role, err := user.client.GetRole(assignment.Properties.RoleDefinitionId)
   162  		if err != nil {
   163  			return errors.Wrapf(err, "GetRule(%s)", assignment.Properties.RoleDefinitionId)
   164  		}
   165  		if role.Properties.RoleName == policyId {
   166  			return user.client.gdel(assignment.Id)
   167  		}
   168  	}
   169  	return nil
   170  }
   171  
   172  func (user *SClouduser) DetachCustomPolicy(policyId string) error {
   173  	return user.DetachSystemPolicy(policyId)
   174  }
   175  
   176  func (user *SClouduser) IsConsoleLogin() bool {
   177  	return true
   178  }
   179  
   180  // 需要当前应用有User administrator权限
   181  func (user *SClouduser) Delete() error {
   182  	return user.client.DeleteClouduser(user.UserPrincipalName)
   183  }
   184  
   185  func (user *SClouduser) ResetPassword(password string) error {
   186  	return user.client.ResetClouduserPassword(user.Id, password)
   187  }
   188  
   189  func (user *SClouduser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) {
   190  	groups, err := user.client.GetUserGroups(user.Id)
   191  	if err != nil {
   192  		return nil, errors.Wrap(err, "GetUserGroups")
   193  	}
   194  	ret := []cloudprovider.ICloudgroup{}
   195  	for i := range groups {
   196  		groups[i].client = user.client
   197  		ret = append(ret, &groups[i])
   198  	}
   199  	return ret, nil
   200  }
   201  
   202  func (self *SAzureClient) GetUserGroups(userId string) ([]SCloudgroup, error) {
   203  	resource := fmt.Sprintf("users/%s/memberOf", userId)
   204  	groups := []SCloudgroup{}
   205  	err := self.glist(resource, url.Values{}, &groups)
   206  	return groups, err
   207  }
   208  
   209  func (self *SAzureClient) ResetClouduserPassword(id, password string) error {
   210  	body := jsonutils.Marshal(map[string]interface{}{
   211  		"passwordPolicies": "DisablePasswordExpiration, DisableStrongPassword",
   212  		"passwordProfile": map[string]interface{}{
   213  			"password": password,
   214  		},
   215  	})
   216  	resource := fmt.Sprintf("%s/users/%s", self.tenantId, id)
   217  	_, err := self.gpatch(resource, body)
   218  	return err
   219  }
   220  
   221  func (self *SAzureClient) GetClouduser(name string) (*SClouduser, error) {
   222  	users, err := self.GetCloudusers()
   223  	if err != nil {
   224  		return nil, err
   225  	}
   226  	for i := range users {
   227  		if users[i].DisplayName == name || users[i].UserPrincipalName == name {
   228  			users[i].client = self
   229  			return &users[i], nil
   230  		}
   231  	}
   232  	return nil, cloudprovider.ErrNotFound
   233  }
   234  
   235  func (self *SAzureClient) GetCloudusers() ([]SClouduser, error) {
   236  	users := []SClouduser{}
   237  	params := url.Values{}
   238  	err := self.glist("users", params, &users)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  	return users, nil
   243  }
   244  
   245  func (self *SAzureClient) DeleteClouduser(id string) error {
   246  	_, err := self.msGraphRequest(string(httputils.DELETE), "users/"+id, nil)
   247  	return err
   248  }
   249  
   250  func (self *SAzureClient) GetICloudusers() ([]cloudprovider.IClouduser, error) {
   251  	users, err := self.ListGraphUsers()
   252  	if err != nil {
   253  		return nil, errors.Wrap(err, "ListGraphUsers")
   254  	}
   255  	ret := []cloudprovider.IClouduser{}
   256  	for i := range users {
   257  		users[i].client = self
   258  		ret = append(ret, &users[i])
   259  	}
   260  	return ret, nil
   261  }
   262  
   263  func (self *SAzureClient) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) {
   264  	user, err := self.GetClouduser(name)
   265  	if err != nil {
   266  		return nil, errors.Wrap(err, "GetCloudusers")
   267  	}
   268  	return user, nil
   269  }
   270  
   271  func (self *SAzureClient) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) {
   272  	if conf.UserType == "Guest" {
   273  		return self.InviteUser(conf.Email)
   274  	}
   275  	return self.CreateClouduser(conf.Name, conf.Password)
   276  }
   277  
   278  type SDomain struct {
   279  	Name                             string
   280  	AuthenticationType               string
   281  	AvailabilityStatus               string
   282  	IsAdminManaged                   bool
   283  	IsDefault                        bool
   284  	IsDefaultForCloudRedirections    bool
   285  	IsInitial                        bool
   286  	IsRoot                           bool
   287  	IsVerified                       bool
   288  	ForceDeleteState                 string
   289  	State                            string
   290  	PasswordValidityPeriodInDays     string
   291  	PasswordNotificationWindowInDays string
   292  }
   293  
   294  func (self *SAzureClient) GetDomains() ([]SDomain, error) {
   295  	domains := []SDomain{}
   296  	err := self.glist("domains", nil, &domains)
   297  	if err != nil {
   298  		return nil, errors.Wrap(err, "glist")
   299  	}
   300  	return domains, nil
   301  }
   302  
   303  func (self *SAzureClient) GetDefaultDomain() (string, error) {
   304  	users, err := self.ListGraphUsers()
   305  	if err != nil {
   306  		return "", errors.Wrapf(err, "ListGraphUsers")
   307  	}
   308  	for i := range users {
   309  		idx := strings.Index(users[i].UserPrincipalName, "@")
   310  		if idx > -1 {
   311  			return users[i].UserPrincipalName[idx+1:], nil
   312  		}
   313  	}
   314  	return "", cloudprovider.ErrNotFound
   315  }
   316  
   317  func (self *SAzureClient) CreateClouduser(name, password string) (*SClouduser, error) {
   318  	passwordProfile := map[string]interface{}{
   319  		"password": "Lomo1824",
   320  	}
   321  	if len(password) > 0 {
   322  		passwordProfile["password"] = password
   323  	}
   324  	params := map[string]interface{}{
   325  		"accountEnabled":    true,
   326  		"displayName":       name,
   327  		"mailNickname":      name,
   328  		"passwordProfile":   passwordProfile,
   329  		"userPrincipalName": name,
   330  	}
   331  	domain, err := self.GetDefaultDomain()
   332  	if err != nil {
   333  		return nil, errors.Wrap(err, "GetDefaultDomain")
   334  	}
   335  	params["userPrincipalName"] = fmt.Sprintf("%s@%s", name, domain)
   336  	user := SClouduser{client: self}
   337  	resp, err := self.msGraphRequest(string(httputils.POST), "users", jsonutils.Marshal(params))
   338  	if err != nil {
   339  		return nil, errors.Wrap(err, "Create")
   340  	}
   341  	err = resp.Unmarshal(&user)
   342  	if err != nil {
   343  		return nil, err
   344  	}
   345  	return &user, nil
   346  }
   347  
   348  func (self *SAzureClient) ListGraphUsers() ([]SClouduser, error) {
   349  	resp, err := self.msGraphRequest("GET", "users", nil)
   350  	if err != nil {
   351  		return nil, errors.Wrapf(err, "msGraphRequest.users")
   352  	}
   353  	users := []SClouduser{}
   354  	err = resp.Unmarshal(&users, "value")
   355  	if err != nil {
   356  		return nil, errors.Wrapf(err, "resp.Unmarshal")
   357  	}
   358  	return users, nil
   359  }