clouduser.go 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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. package azure
  15. import (
  16. "fmt"
  17. "net/url"
  18. "time"
  19. "yunion.io/x/pkg/errors"
  20. api "yunion.io/x/cloudmux/pkg/apis/cloudid"
  21. "yunion.io/x/cloudmux/pkg/cloudprovider"
  22. "yunion.io/x/cloudmux/pkg/multicloud"
  23. )
  24. type SClouduserPasswordProfile struct {
  25. Password string
  26. forceChangePasswordNextLogin bool
  27. enforceChangePasswordPolicy bool
  28. }
  29. type SClouduser struct {
  30. client *SAzureClient
  31. multicloud.SBaseClouduser
  32. OdataType string `json:"odata.type"`
  33. ObjectType string
  34. Id string
  35. DeletionTimestamp string
  36. AccountEnabled bool
  37. AgeGroup string
  38. City string
  39. CompanyName string
  40. ConsentProvidedForMinor string
  41. Country string
  42. CreatedDateTime time.Time
  43. CreationType string
  44. Department string
  45. DirSyncEnabled string
  46. DisplayName string
  47. EmployeeId string
  48. FacsimileTelephoneNumber string
  49. GivenName string
  50. ImmutableId string
  51. IsCompromised string
  52. JobTitle string
  53. LastDirSyncTime string
  54. LegalAgeGroupClassification string
  55. Mail string
  56. MailNickname string
  57. Mobile string
  58. OnPremisesDistinguishedName string
  59. OnPremisesSecurityIdentifier string
  60. PasswordPolicies string
  61. PasswordProfile SClouduserPasswordProfile
  62. PhysicalDeliveryOfficeName string
  63. PostalCode string
  64. PreferredLanguage string
  65. RefreshTokensValidFromDateTime time.Time
  66. ShowInAddressList string
  67. SipProxyAddress string
  68. State string
  69. StreetAddress string
  70. Surname string
  71. TelephoneNumber string
  72. ThumbnailPhotoOdataMediaEditLink string `json:"thumbnailPhoto@odata.mediaEditLink"`
  73. UsageLocation string
  74. UserPrincipalName string
  75. UserState string
  76. UserStateChangedOn string
  77. UserType string
  78. inviteRedeemUrl string
  79. }
  80. func (user *SClouduser) GetName() string {
  81. return user.UserPrincipalName
  82. }
  83. func (user *SClouduser) GetGlobalId() string {
  84. return user.Id
  85. }
  86. func (user *SClouduser) GetEmailAddr() string {
  87. return user.Mail
  88. }
  89. func (user *SClouduser) GetInviteUrl() string {
  90. return user.inviteRedeemUrl
  91. }
  92. func (user *SClouduser) GetICloudpolicies() ([]cloudprovider.ICloudpolicy, error) {
  93. policies, err := user.client.GetPrincipalPolicy(user.Id)
  94. if err != nil {
  95. return nil, errors.Wrapf(err, "GetCloudpolicies(%s)", user.Id)
  96. }
  97. ret := []cloudprovider.ICloudpolicy{}
  98. for i := range policies {
  99. ret = append(ret, &SCloudpolicy{Id: policies[i].RoleDefinitionId})
  100. }
  101. return ret, nil
  102. }
  103. func (user *SClouduser) AttachPolicy(policyId string, policyType api.TPolicyType) error {
  104. return user.client.AssignPolicy(user.Id, policyId)
  105. }
  106. func (user *SClouduser) DetachPolicy(policyId string, policyType api.TPolicyType) error {
  107. policys, err := user.client.GetPrincipalPolicy(user.Id)
  108. if err != nil {
  109. return err
  110. }
  111. for _, policy := range policys {
  112. if policy.RoleDefinitionId == policyId {
  113. return user.client.DeletePrincipalPolicy(policy.Id)
  114. }
  115. }
  116. return nil
  117. }
  118. func (user *SClouduser) IsConsoleLogin() bool {
  119. return true
  120. }
  121. // 需要当前应用有User administrator权限
  122. func (user *SClouduser) Delete() error {
  123. return user.client.DeleteClouduser(user.UserPrincipalName)
  124. }
  125. func (user *SClouduser) ResetPassword(password string) error {
  126. return user.client.ResetClouduserPassword(user.Id, password)
  127. }
  128. func (user *SClouduser) GetICloudgroups() ([]cloudprovider.ICloudgroup, error) {
  129. groups, err := user.client.GetUserGroups(user.Id)
  130. if err != nil {
  131. return nil, errors.Wrap(err, "GetUserGroups")
  132. }
  133. ret := []cloudprovider.ICloudgroup{}
  134. for i := range groups {
  135. groups[i].client = user.client
  136. ret = append(ret, &groups[i])
  137. }
  138. return ret, nil
  139. }
  140. func (self *SAzureClient) GetUserGroups(userId string) ([]SCloudgroup, error) {
  141. resource := fmt.Sprintf("users/%s/memberOf", userId)
  142. resp, err := self._list_v2(SERVICE_GRAPH, resource, "", nil)
  143. if err != nil {
  144. return nil, err
  145. }
  146. groups := []SCloudgroup{}
  147. err = resp.Unmarshal(&groups, "value")
  148. if err != nil {
  149. return nil, err
  150. }
  151. return groups, err
  152. }
  153. func (self *SAzureClient) ResetClouduserPassword(id, password string) error {
  154. body := map[string]interface{}{
  155. "passwordPolicies": "DisablePasswordExpiration, DisableStrongPassword",
  156. "passwordProfile": map[string]interface{}{
  157. "password": password,
  158. },
  159. }
  160. resource := fmt.Sprintf("%s/users/%s", self.tenantId, id)
  161. _, err := self._patch_v2(SERVICE_GRAPH, resource, "", body)
  162. return err
  163. }
  164. func (self *SAzureClient) GetClouduser(name string) (*SClouduser, error) {
  165. users, err := self.GetCloudusers()
  166. if err != nil {
  167. return nil, err
  168. }
  169. for i := range users {
  170. if users[i].DisplayName == name || users[i].UserPrincipalName == name {
  171. users[i].client = self
  172. return &users[i], nil
  173. }
  174. }
  175. return nil, cloudprovider.ErrNotFound
  176. }
  177. func (self *SAzureClient) GetCloudusers() ([]SClouduser, error) {
  178. users := []SClouduser{}
  179. resp, err := self._list_v2(SERVICE_GRAPH, "users", "", url.Values{})
  180. if err != nil {
  181. return nil, err
  182. }
  183. err = resp.Unmarshal(&users, "value")
  184. if err != nil {
  185. return nil, err
  186. }
  187. return users, nil
  188. }
  189. func (self *SAzureClient) DeleteClouduser(id string) error {
  190. _, err := self._delete_v2(SERVICE_GRAPH, "users/"+id, "")
  191. return err
  192. }
  193. func (self *SAzureClient) GetICloudusers() ([]cloudprovider.IClouduser, error) {
  194. users, err := self.GetCloudusers()
  195. if err != nil {
  196. return nil, errors.Wrap(err, "GetCloudusers")
  197. }
  198. ret := []cloudprovider.IClouduser{}
  199. for i := range users {
  200. users[i].client = self
  201. ret = append(ret, &users[i])
  202. }
  203. return ret, nil
  204. }
  205. func (self *SAzureClient) GetIClouduserByName(name string) (cloudprovider.IClouduser, error) {
  206. user, err := self.GetClouduser(name)
  207. if err != nil {
  208. return nil, errors.Wrap(err, "GetCloudusers")
  209. }
  210. return user, nil
  211. }
  212. func (self *SAzureClient) CreateIClouduser(conf *cloudprovider.SClouduserCreateConfig) (cloudprovider.IClouduser, error) {
  213. if conf.UserType == "Guest" {
  214. return self.InviteUser(conf.Email)
  215. }
  216. return self.CreateClouduser(conf.Name, conf.Password)
  217. }
  218. type SDomain struct {
  219. Name string
  220. Id string
  221. AuthenticationType string
  222. AvailabilityStatus string
  223. IsAdminManaged bool
  224. IsDefault bool
  225. IsDefaultForCloudRedirections bool
  226. IsInitial bool
  227. IsRoot bool
  228. IsVerified bool
  229. ForceDeleteState string
  230. State string
  231. PasswordValidityPeriodInDays string
  232. PasswordNotificationWindowInDays string
  233. }
  234. func (self *SAzureClient) GetDomains() ([]SDomain, error) {
  235. domains := []SDomain{}
  236. resp, err := self._list_v2(SERVICE_GRAPH, "domains", "", nil)
  237. if err != nil {
  238. return nil, errors.Wrap(err, "list domains")
  239. }
  240. err = resp.Unmarshal(&domains, "value")
  241. if err != nil {
  242. return nil, err
  243. }
  244. return domains, nil
  245. }
  246. func (self *SAzureClient) GetDefaultDomain() (string, error) {
  247. domains, err := self.GetDomains()
  248. if err != nil {
  249. return "", errors.Wrapf(err, "ListGraphUsers")
  250. }
  251. for i := range domains {
  252. if domains[i].IsDefault && domains[i].IsVerified && domains[i].IsRoot {
  253. return domains[i].Id, nil
  254. }
  255. }
  256. return "", cloudprovider.ErrNotFound
  257. }
  258. func (self *SAzureClient) CreateClouduser(name, password string) (*SClouduser, error) {
  259. passwordProfile := map[string]interface{}{
  260. "password": "Lomo1824",
  261. }
  262. if len(password) > 0 {
  263. passwordProfile["password"] = password
  264. }
  265. params := map[string]interface{}{
  266. "accountEnabled": true,
  267. "displayName": name,
  268. "mailNickname": name,
  269. "passwordProfile": passwordProfile,
  270. "userPrincipalName": name,
  271. }
  272. domain, err := self.GetDefaultDomain()
  273. if err != nil {
  274. return nil, errors.Wrap(err, "GetDefaultDomain")
  275. }
  276. params["userPrincipalName"] = fmt.Sprintf("%s@%s", name, domain)
  277. user := &SClouduser{client: self}
  278. resp, err := self._post_v2(SERVICE_GRAPH, "users", "", params)
  279. if err != nil {
  280. return nil, errors.Wrap(err, "Create")
  281. }
  282. err = resp.Unmarshal(user)
  283. if err != nil {
  284. return nil, err
  285. }
  286. return user, nil
  287. }