github.com/vmware/govmomi@v0.51.0/ssoadmin/client.go (about)

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