github.com/vmware/govmomi@v0.37.1/ssoadmin/client.go (about) 1 /* 2 Copyright (c) 2018-2023 VMware, Inc. All Rights Reserved. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package ssoadmin 18 19 import ( 20 "context" 21 "fmt" 22 "math" 23 "path" 24 "reflect" 25 "strings" 26 27 "github.com/vmware/govmomi/internal" 28 "github.com/vmware/govmomi/lookup" 29 ltypes "github.com/vmware/govmomi/lookup/types" 30 "github.com/vmware/govmomi/ssoadmin/methods" 31 "github.com/vmware/govmomi/ssoadmin/types" 32 "github.com/vmware/govmomi/vim25" 33 "github.com/vmware/govmomi/vim25/soap" 34 vim "github.com/vmware/govmomi/vim25/types" 35 ) 36 37 const ( 38 Namespace = "sso" 39 Version = "version2" 40 basePath = "/sso-adminserver" 41 Path = basePath + vim25.Path 42 SystemPath = basePath + "/system-sdk" 43 ) 44 45 var ( 46 ServiceInstance = vim.ManagedObjectReference{ 47 Type: "SsoAdminServiceInstance", 48 Value: "SsoAdminServiceInstance", 49 } 50 ) 51 52 type Client struct { 53 *soap.Client 54 55 RoundTripper soap.RoundTripper 56 ServiceContent types.AdminServiceContent 57 GroupCheck types.GroupcheckServiceContent 58 Domain string 59 Limit int32 60 } 61 62 func init() { 63 // Fault types are not in the ssoadmin.wsdl 64 vim.Add("SsoFaultNotAuthenticated", reflect.TypeOf((*vim.NotAuthenticated)(nil)).Elem()) 65 vim.Add("SsoFaultNoPermission", reflect.TypeOf((*vim.NoPermission)(nil)).Elem()) 66 vim.Add("SsoFaultInvalidCredentials", reflect.TypeOf((*vim.InvalidLogin)(nil)).Elem()) 67 vim.Add("SsoAdminFaultDuplicateSolutionCertificateFaultFault", reflect.TypeOf((*vim.InvalidArgument)(nil)).Elem()) 68 } 69 70 func getEndpointURL(ctx context.Context, c *vim25.Client) string { 71 // Services running on vCenter can bypass lookup service using the 72 // system-sdk path. This avoids the need to lookup the system domain. 73 if useSidecar := internal.UsingEnvoySidecar(c); useSidecar { 74 return fmt.Sprintf("http://%s%s", c.URL().Host, SystemPath) 75 } 76 return getEndpointURLFromLookupService(ctx, c) 77 } 78 79 func getEndpointURLFromLookupService(ctx context.Context, c *vim25.Client) string { 80 filter := <ypes.LookupServiceRegistrationFilter{ 81 ServiceType: <ypes.LookupServiceRegistrationServiceType{ 82 Product: "com.vmware.cis", 83 Type: "cs.identity", 84 }, 85 EndpointType: <ypes.LookupServiceRegistrationEndpointType{ 86 Protocol: "vmomi", 87 Type: "com.vmware.cis.cs.identity.admin", 88 }, 89 } 90 91 return lookup.EndpointURL(ctx, c, Path, filter) 92 } 93 94 func NewClient(ctx context.Context, c *vim25.Client) (*Client, error) { 95 url := getEndpointURL(ctx, c) 96 sc := c.NewServiceClient(url, Namespace) 97 sc.Version = Version 98 99 admin := &Client{ 100 Client: sc, 101 RoundTripper: sc, 102 Domain: "vsphere.local", // Default 103 Limit: math.MaxInt32, 104 } 105 if url != Path && !internal.UsingEnvoySidecar(c) { 106 admin.Domain = path.Base(url) 107 } 108 109 { 110 req := types.SsoAdminServiceInstance{ 111 This: ServiceInstance, 112 } 113 114 res, err := methods.SsoAdminServiceInstance(ctx, sc, &req) 115 if err != nil { 116 return nil, err 117 } 118 119 admin.ServiceContent = res.Returnval 120 } 121 122 { 123 req := types.SsoGroupcheckServiceInstance{ 124 This: vim.ManagedObjectReference{ 125 Type: "SsoGroupcheckServiceInstance", Value: "ServiceInstance", 126 }, 127 } 128 129 res, err := methods.SsoGroupcheckServiceInstance(ctx, sc, &req) 130 if err != nil { 131 return nil, err 132 } 133 134 admin.GroupCheck = res.Returnval 135 } 136 137 return admin, nil 138 } 139 140 // RoundTrip dispatches to the RoundTripper field. 141 func (c *Client) RoundTrip(ctx context.Context, req, res soap.HasFault) error { 142 return c.RoundTripper.RoundTrip(ctx, req, res) 143 } 144 145 func (c *Client) parseID(name string) types.PrincipalId { 146 p := strings.SplitN(name, "@", 2) 147 id := types.PrincipalId{Name: p[0]} 148 if len(p) == 2 { 149 id.Domain = p[1] 150 } else { 151 id.Domain = c.Domain 152 } 153 return id 154 } 155 156 func (c *Client) CreateSolutionUser(ctx context.Context, name string, details types.AdminSolutionDetails) error { 157 req := types.CreateLocalSolutionUser{ 158 This: c.ServiceContent.PrincipalManagementService, 159 UserName: name, 160 UserDetails: details, 161 } 162 163 _, err := methods.CreateLocalSolutionUser(ctx, c, &req) 164 return err 165 } 166 167 func (c *Client) UpdateLocalPasswordPolicy(ctx context.Context, policy types.AdminPasswordPolicy) error { 168 req := types.UpdateLocalPasswordPolicy{ 169 This: c.ServiceContent.PasswordPolicyService, 170 Policy: policy, 171 } 172 173 _, err := methods.UpdateLocalPasswordPolicy(ctx, c, &req) 174 return err 175 } 176 177 func (c *Client) UpdateSolutionUser(ctx context.Context, name string, details types.AdminSolutionDetails) error { 178 req := types.UpdateLocalSolutionUserDetails{ 179 This: c.ServiceContent.PrincipalManagementService, 180 UserName: name, 181 UserDetails: details, 182 } 183 184 _, err := methods.UpdateLocalSolutionUserDetails(ctx, c, &req) 185 return err 186 } 187 188 func (c *Client) DeletePrincipal(ctx context.Context, name string) error { 189 req := types.DeleteLocalPrincipal{ 190 This: c.ServiceContent.PrincipalManagementService, 191 PrincipalName: name, 192 } 193 194 _, err := methods.DeleteLocalPrincipal(ctx, c, &req) 195 return err 196 } 197 198 func (c *Client) AddUsersToGroup(ctx context.Context, groupName string, userIDs ...types.PrincipalId) error { 199 req := types.AddUsersToLocalGroup{ 200 This: c.ServiceContent.PrincipalManagementService, 201 GroupName: groupName, 202 UserIds: userIDs, 203 } 204 205 _, err := methods.AddUsersToLocalGroup(ctx, c, &req) 206 return err 207 } 208 209 func (c *Client) RemoveUsersFromGroup(ctx context.Context, groupName string, userIDs ...types.PrincipalId) error { 210 req := types.RemovePrincipalsFromLocalGroup{ 211 This: c.ServiceContent.PrincipalManagementService, 212 GroupName: groupName, 213 PrincipalsIds: userIDs, 214 } 215 216 _, err := methods.RemovePrincipalsFromLocalGroup(ctx, c, &req) 217 return err 218 } 219 220 func (c *Client) AddGroupsToGroup(ctx context.Context, groupName string, groupIDs ...types.PrincipalId) error { 221 req := types.AddGroupsToLocalGroup{ 222 This: c.ServiceContent.PrincipalManagementService, 223 GroupName: groupName, 224 GroupIds: groupIDs, 225 } 226 227 _, err := methods.AddGroupsToLocalGroup(ctx, c, &req) 228 return err 229 } 230 231 func (c *Client) CreateGroup(ctx context.Context, name string, details types.AdminGroupDetails) error { 232 req := types.CreateLocalGroup{ 233 This: c.ServiceContent.PrincipalManagementService, 234 GroupName: name, 235 GroupDetails: details, 236 } 237 238 _, err := methods.CreateLocalGroup(ctx, c, &req) 239 return err 240 } 241 242 func (c *Client) UpdateGroup(ctx context.Context, name string, details types.AdminGroupDetails) error { 243 req := types.UpdateLocalGroupDetails{ 244 This: c.ServiceContent.PrincipalManagementService, 245 GroupName: name, 246 GroupDetails: details, 247 } 248 249 _, err := methods.UpdateLocalGroupDetails(ctx, c, &req) 250 return err 251 } 252 253 func (c *Client) CreatePersonUser(ctx context.Context, name string, details types.AdminPersonDetails, password string) error { 254 req := types.CreateLocalPersonUser{ 255 This: c.ServiceContent.PrincipalManagementService, 256 UserName: name, 257 UserDetails: details, 258 Password: password, 259 } 260 261 _, err := methods.CreateLocalPersonUser(ctx, c, &req) 262 return err 263 } 264 265 func (c *Client) UpdatePersonUser(ctx context.Context, name string, details types.AdminPersonDetails) error { 266 req := types.UpdateLocalPersonUserDetails{ 267 This: c.ServiceContent.PrincipalManagementService, 268 UserName: name, 269 UserDetails: details, 270 } 271 272 _, err := methods.UpdateLocalPersonUserDetails(ctx, c, &req) 273 return err 274 } 275 276 func (c *Client) ResetPersonPassword(ctx context.Context, name string, password string) error { 277 req := types.ResetLocalPersonUserPassword{ 278 This: c.ServiceContent.PrincipalManagementService, 279 UserName: name, 280 NewPassword: password, 281 } 282 283 _, err := methods.ResetLocalPersonUserPassword(ctx, c, &req) 284 return err 285 } 286 287 func (c *Client) FindSolutionUser(ctx context.Context, name string) (*types.AdminSolutionUser, error) { 288 req := types.FindSolutionUser{ 289 This: c.ServiceContent.PrincipalDiscoveryService, 290 UserName: name, 291 } 292 293 res, err := methods.FindSolutionUser(ctx, c, &req) 294 if err != nil { 295 return nil, err 296 } 297 298 return res.Returnval, nil 299 } 300 301 func (c *Client) FindPersonUser(ctx context.Context, name string) (*types.AdminPersonUser, error) { 302 req := types.FindPersonUser{ 303 This: c.ServiceContent.PrincipalDiscoveryService, 304 UserId: c.parseID(name), 305 } 306 307 res, err := methods.FindPersonUser(ctx, c, &req) 308 if err != nil { 309 return nil, err 310 } 311 312 return res.Returnval, nil 313 } 314 315 func (c *Client) FindUser(ctx context.Context, name string) (*types.AdminUser, error) { 316 req := types.FindUser{ 317 This: c.ServiceContent.PrincipalDiscoveryService, 318 UserId: c.parseID(name), 319 } 320 321 res, err := methods.FindUser(ctx, c, &req) 322 if err != nil { 323 return nil, err 324 } 325 326 return res.Returnval, nil 327 } 328 329 func (c *Client) FindSolutionUsers(ctx context.Context, search string) ([]types.AdminSolutionUser, error) { 330 req := types.FindSolutionUsers{ 331 This: c.ServiceContent.PrincipalDiscoveryService, 332 SearchString: search, 333 Limit: c.Limit, 334 } 335 336 res, err := methods.FindSolutionUsers(ctx, c, &req) 337 if err != nil { 338 return nil, err 339 } 340 341 return res.Returnval, nil 342 } 343 344 func (c *Client) FindPersonUsers(ctx context.Context, search string) ([]types.AdminPersonUser, error) { 345 req := types.FindPersonUsers{ 346 This: c.ServiceContent.PrincipalDiscoveryService, 347 Criteria: types.AdminPrincipalDiscoveryServiceSearchCriteria{ 348 Domain: c.Domain, 349 SearchString: search, 350 }, 351 Limit: c.Limit, 352 } 353 354 res, err := methods.FindPersonUsers(ctx, c, &req) 355 if err != nil { 356 return nil, err 357 } 358 359 return res.Returnval, nil 360 } 361 362 func (c *Client) FindGroup(ctx context.Context, name string) (*types.AdminGroup, error) { 363 req := types.FindGroup{ 364 This: c.ServiceContent.PrincipalDiscoveryService, 365 GroupId: c.parseID(name), 366 } 367 368 res, err := methods.FindGroup(ctx, c, &req) 369 if err != nil { 370 return nil, err 371 } 372 373 return res.Returnval, nil 374 } 375 376 func (c *Client) FindGroups(ctx context.Context, search string) ([]types.AdminGroup, error) { 377 req := types.FindGroups{ 378 This: c.ServiceContent.PrincipalDiscoveryService, 379 Criteria: types.AdminPrincipalDiscoveryServiceSearchCriteria{ 380 Domain: c.Domain, 381 SearchString: search, 382 }, 383 Limit: c.Limit, 384 } 385 386 res, err := methods.FindGroups(ctx, c, &req) 387 if err != nil { 388 return nil, err 389 } 390 391 return res.Returnval, nil 392 } 393 394 func (c *Client) FindUsersInGroup(ctx context.Context, name string, search string) ([]types.AdminUser, error) { 395 req := types.FindUsersInGroup{ 396 This: c.ServiceContent.PrincipalDiscoveryService, 397 GroupId: c.parseID(name), 398 SearchString: search, 399 Limit: c.Limit, 400 } 401 402 res, err := methods.FindUsersInGroup(ctx, c, &req) 403 if err != nil { 404 return nil, err 405 } 406 407 return res.Returnval, nil 408 } 409 410 func (c *Client) FindGroupsInGroup(ctx context.Context, name string, search string) ([]types.AdminGroup, error) { 411 req := types.FindGroupsInGroup{ 412 This: c.ServiceContent.PrincipalDiscoveryService, 413 GroupId: c.parseID(name), 414 SearchString: search, 415 Limit: c.Limit, 416 } 417 418 res, err := methods.FindGroupsInGroup(ctx, c, &req) 419 if err != nil { 420 return nil, err 421 } 422 423 return res.Returnval, nil 424 } 425 426 func (c *Client) FindParentGroups(ctx context.Context, id types.PrincipalId, groups ...types.PrincipalId) ([]types.PrincipalId, error) { 427 if len(groups) == 0 { 428 req := types.FindAllParentGroups{ 429 This: c.GroupCheck.GroupCheckService, 430 UserId: id, 431 } 432 res, err := methods.FindAllParentGroups(ctx, c, &req) 433 if err != nil { 434 return nil, err 435 } 436 return res.Returnval, nil 437 } 438 439 return nil, nil 440 } 441 442 func (c *Client) GetLocalPasswordPolicy(ctx context.Context) (*types.AdminPasswordPolicy, error) { 443 req := types.GetLocalPasswordPolicy{ 444 This: c.ServiceContent.PasswordPolicyService, 445 } 446 447 res, err := methods.GetLocalPasswordPolicy(ctx, c, &req) 448 if err != nil { 449 return nil, err 450 } 451 452 return &res.Returnval, nil 453 } 454 455 func (c *Client) Login(ctx context.Context) error { 456 req := types.Login{ 457 This: c.ServiceContent.SessionManager, 458 } 459 460 _, err := methods.Login(ctx, c, &req) 461 return err 462 } 463 464 func (c *Client) Logout(ctx context.Context) error { 465 req := types.Logout{ 466 This: c.ServiceContent.SessionManager, 467 } 468 469 _, err := methods.Logout(ctx, c, &req) 470 return err 471 } 472 473 func (c *Client) SetRole(ctx context.Context, id types.PrincipalId, role string) (bool, error) { 474 req := types.SetRole{ 475 This: c.ServiceContent.RoleManagementService, 476 UserId: id, 477 Role: role, 478 } 479 480 res, err := methods.SetRole(ctx, c, &req) 481 if err != nil { 482 return false, err 483 } 484 485 return res.Returnval, nil 486 } 487 488 func (c *Client) GrantWSTrustRole(ctx context.Context, id types.PrincipalId, role string) (bool, error) { 489 req := types.GrantWSTrustRole{ 490 This: c.ServiceContent.RoleManagementService, 491 UserId: id, 492 Role: role, 493 } 494 495 res, err := methods.GrantWSTrustRole(ctx, c, &req) 496 if err != nil { 497 return false, err 498 } 499 500 return res.Returnval, nil 501 } 502 503 func (c *Client) RevokeWSTrustRole(ctx context.Context, id types.PrincipalId, role string) (bool, error) { 504 req := types.RevokeWSTrustRole{ 505 This: c.ServiceContent.RoleManagementService, 506 UserId: id, 507 Role: role, 508 } 509 510 res, err := methods.RevokeWSTrustRole(ctx, c, &req) 511 if err != nil { 512 return false, err 513 } 514 515 return res.Returnval, nil 516 } 517 518 func (c *Client) IdentitySources(ctx context.Context) (*types.IdentitySources, error) { 519 req := types.Get{ 520 This: c.ServiceContent.IdentitySourceManagementService, 521 } 522 523 res, err := methods.Get(ctx, c, &req) 524 if err != nil { 525 return nil, err 526 } 527 528 return &res.Returnval, nil 529 } 530 531 func (c *Client) GetDefaultDomains(ctx context.Context) ([]string, error) { 532 req := types.GetDefaultDomains{ 533 This: c.ServiceContent.IdentitySourceManagementService, 534 } 535 536 res, err := methods.GetDefaultDomains(ctx, c, &req) 537 if err != nil { 538 return nil, err 539 } 540 541 return res.Returnval, nil 542 } 543 544 func (c *Client) SetDefaultDomains(ctx context.Context, domain string) error { 545 req := types.SetDefaultDomains{ 546 This: c.ServiceContent.IdentitySourceManagementService, 547 DomainNames: domain, 548 } 549 550 _, err := methods.SetDefaultDomains(ctx, c, &req) 551 return err 552 } 553 554 func (c *Client) RegisterLdap(ctx context.Context, stype string, name string, alias string, details types.LdapIdentitySourceDetails, auth types.SsoAdminIdentitySourceManagementServiceAuthenticationCredentails) error { 555 req := types.RegisterLdap{ 556 This: c.ServiceContent.IdentitySourceManagementService, 557 ServerType: stype, 558 DomainName: name, 559 DomainAlias: alias, 560 Details: details, 561 AuthenticationType: "password", 562 AuthnCredentials: &auth, 563 } 564 565 _, err := methods.RegisterLdap(ctx, c, &req) 566 return err 567 } 568 569 func (c *Client) UpdateLdap(ctx context.Context, name string, details types.LdapIdentitySourceDetails) error { 570 req := types.UpdateLdap{ 571 This: c.ServiceContent.IdentitySourceManagementService, 572 DomainName: name, 573 Details: details, 574 } 575 576 _, err := methods.UpdateLdap(ctx, c, &req) 577 return err 578 } 579 580 func (c *Client) UpdateLdapAuthnType(ctx context.Context, name string, auth types.SsoAdminIdentitySourceManagementServiceAuthenticationCredentails) error { 581 req := types.UpdateLdapAuthnType{ 582 This: c.ServiceContent.IdentitySourceManagementService, 583 DomainName: name, 584 AuthenticationType: "password", 585 AuthnCredentials: &auth, 586 } 587 588 _, err := methods.UpdateLdapAuthnType(ctx, c, &req) 589 return err 590 }