github.com/vmware/govmomi@v0.37.2/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 := &ltypes.LookupServiceRegistrationFilter{
    81  		ServiceType: &ltypes.LookupServiceRegistrationServiceType{
    82  			Product: "com.vmware.cis",
    83  			Type:    "cs.identity",
    84  		},
    85  		EndpointType: &ltypes.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  }