github.com/vmware/govmomi@v0.51.0/crypto/manager_kmip.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 crypto
     6  
     7  import (
     8  	"context"
     9  	"fmt"
    10  
    11  	"github.com/vmware/govmomi/object"
    12  	"github.com/vmware/govmomi/vim25"
    13  	"github.com/vmware/govmomi/vim25/methods"
    14  	"github.com/vmware/govmomi/vim25/types"
    15  )
    16  
    17  const (
    18  	CheckKeyAvailable   = int32(0x01)
    19  	CheckKeyUsedByVms   = int32(0x02)
    20  	CheckKeyUsedByHosts = int32(0x04)
    21  	CheckKeyUsedByOther = int32(0x08)
    22  )
    23  
    24  type ManagerKmip struct {
    25  	object.Common
    26  }
    27  
    28  // GetManagerKmip wraps NewManager, returning ErrNotSupported when the client is
    29  // not connected to a vCenter instance.
    30  func GetManagerKmip(c *vim25.Client) (*ManagerKmip, error) {
    31  	if c.ServiceContent.CryptoManager == nil {
    32  		return nil, object.ErrNotSupported
    33  	}
    34  	return NewManagerKmip(c), nil
    35  }
    36  
    37  func NewManagerKmip(c *vim25.Client) *ManagerKmip {
    38  	m := ManagerKmip{
    39  		Common: object.NewCommon(c, *c.ServiceContent.CryptoManager),
    40  	}
    41  	return &m
    42  }
    43  
    44  func (m ManagerKmip) ListKmipServers(
    45  	ctx context.Context,
    46  	limit *int32) ([]types.KmipClusterInfo, error) {
    47  
    48  	req := types.ListKmipServers{
    49  		This:  m.Reference(),
    50  		Limit: limit,
    51  	}
    52  	res, err := methods.ListKmipServers(ctx, m.Client(), &req)
    53  	if err != nil {
    54  		return nil, err
    55  	}
    56  	return res.Returnval, nil
    57  }
    58  
    59  func (m ManagerKmip) IsDefaultProviderNative(
    60  	ctx context.Context,
    61  	entity *types.ManagedObjectReference,
    62  	defaultsToParent bool) (bool, error) {
    63  
    64  	defaultProviderID, err := m.GetDefaultKmsClusterID(
    65  		ctx, entity, defaultsToParent)
    66  	if err != nil {
    67  		return false, err
    68  	}
    69  	if defaultProviderID == "" {
    70  		return false, nil
    71  	}
    72  	return m.IsNativeProvider(ctx, defaultProviderID)
    73  }
    74  
    75  func (m ManagerKmip) IsNativeProvider(
    76  	ctx context.Context,
    77  	providerID string) (bool, error) {
    78  
    79  	info, err := m.GetClusterStatus(ctx, providerID)
    80  	if err != nil {
    81  		return false, err
    82  	}
    83  	if info == nil {
    84  		return false, nil
    85  	}
    86  	return info.ManagementType == string(
    87  		types.KmipClusterInfoKmsManagementTypeNativeProvider), nil
    88  }
    89  
    90  func (m ManagerKmip) GetDefaultKmsClusterID(
    91  	ctx context.Context,
    92  	entity *types.ManagedObjectReference,
    93  	defaultsToParent bool) (string, error) {
    94  
    95  	req := types.GetDefaultKmsCluster{
    96  		This:             m.Reference(),
    97  		Entity:           entity,
    98  		DefaultsToParent: &defaultsToParent,
    99  	}
   100  	res, err := methods.GetDefaultKmsCluster(ctx, m.Client(), &req)
   101  	if err != nil {
   102  		return "", err
   103  	}
   104  	if res.Returnval != nil {
   105  		return res.Returnval.Id, nil
   106  	}
   107  	return "", nil
   108  }
   109  
   110  func (m ManagerKmip) GetStatus(
   111  	ctx context.Context,
   112  	clusters ...types.KmipClusterInfo) ([]types.CryptoManagerKmipClusterStatus, error) {
   113  
   114  	req := types.RetrieveKmipServersStatus_Task{
   115  		This:     m.Reference(),
   116  		Clusters: clusters,
   117  	}
   118  	res, err := methods.RetrieveKmipServersStatus_Task(ctx, m.Client(), &req)
   119  	if err != nil {
   120  		return nil, err
   121  	}
   122  
   123  	task := object.NewTask(m.Client(), res.Returnval)
   124  	taskInfo, err := task.WaitForResult(ctx)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  
   129  	if taskInfo.Result == nil {
   130  		return nil, nil
   131  	}
   132  	result, ok := taskInfo.Result.(types.ArrayOfCryptoManagerKmipClusterStatus)
   133  	if !ok {
   134  		return nil, nil
   135  	}
   136  	if len(result.CryptoManagerKmipClusterStatus) == 0 {
   137  		return nil, nil
   138  	}
   139  
   140  	return result.CryptoManagerKmipClusterStatus, nil
   141  }
   142  
   143  func (m ManagerKmip) GetClusterStatus(
   144  	ctx context.Context,
   145  	providerID string) (*types.CryptoManagerKmipClusterStatus, error) {
   146  
   147  	result, err := m.GetStatus(
   148  		ctx,
   149  		types.KmipClusterInfo{
   150  			ClusterId: types.KeyProviderId{
   151  				Id: providerID,
   152  			},
   153  		})
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  	if len(result) == 0 {
   158  		return nil, fmt.Errorf("invalid cluster ID")
   159  	}
   160  	return &result[0], nil
   161  }
   162  
   163  func (m ManagerKmip) GetServerStatus(
   164  	ctx context.Context,
   165  	providerID, serverName string) (*types.CryptoManagerKmipServerStatus, error) {
   166  
   167  	result, err := m.GetStatus(
   168  		ctx,
   169  		types.KmipClusterInfo{
   170  			ClusterId: types.KeyProviderId{
   171  				Id: providerID,
   172  			},
   173  			Servers: []types.KmipServerInfo{
   174  				{
   175  					Name: serverName,
   176  				},
   177  			},
   178  		})
   179  	if err != nil {
   180  		return nil, err
   181  	}
   182  	if len(result) == 0 {
   183  		return nil, fmt.Errorf("invalid cluster ID")
   184  	}
   185  	if len(result[0].Servers) == 0 {
   186  		return nil, fmt.Errorf("invalid server name")
   187  	}
   188  	return &result[0].Servers[0], nil
   189  }
   190  
   191  func (m ManagerKmip) MarkDefault(
   192  	ctx context.Context,
   193  	providerID string) error {
   194  
   195  	req := types.MarkDefault{
   196  		This:      m.Reference(),
   197  		ClusterId: types.KeyProviderId{Id: providerID},
   198  	}
   199  	_, err := methods.MarkDefault(ctx, m.Client(), &req)
   200  	if err != nil {
   201  		return err
   202  	}
   203  	return nil
   204  }
   205  
   206  func (m ManagerKmip) SetDefaultKmsClusterId(
   207  	ctx context.Context,
   208  	providerID string,
   209  	entity *types.ManagedObjectReference) error {
   210  
   211  	req := types.SetDefaultKmsCluster{
   212  		This:   m.Reference(),
   213  		Entity: entity,
   214  	}
   215  	if providerID != "" {
   216  		req.ClusterId = &types.KeyProviderId{
   217  			Id: providerID,
   218  		}
   219  	}
   220  	_, err := methods.SetDefaultKmsCluster(ctx, m.Client(), &req)
   221  	if err != nil {
   222  		return err
   223  	}
   224  	return nil
   225  }
   226  
   227  func (m ManagerKmip) RegisterKmsCluster(
   228  	ctx context.Context,
   229  	providerID string,
   230  	managementType types.KmipClusterInfoKmsManagementType) error {
   231  
   232  	req := types.RegisterKmsCluster{
   233  		This: m.Reference(),
   234  		ClusterId: types.KeyProviderId{
   235  			Id: providerID,
   236  		},
   237  		ManagementType: string(managementType),
   238  	}
   239  	_, err := methods.RegisterKmsCluster(ctx, m.Client(), &req)
   240  	if err != nil {
   241  		return err
   242  	}
   243  	return nil
   244  }
   245  
   246  func (m ManagerKmip) UnregisterKmsCluster(
   247  	ctx context.Context,
   248  	providerID string) error {
   249  
   250  	req := types.UnregisterKmsCluster{
   251  		This: m.Reference(),
   252  		ClusterId: types.KeyProviderId{
   253  			Id: providerID,
   254  		},
   255  	}
   256  	_, err := methods.UnregisterKmsCluster(ctx, m.Client(), &req)
   257  	if err != nil {
   258  		return err
   259  	}
   260  	return nil
   261  }
   262  
   263  func (m ManagerKmip) RegisterKmipServer(
   264  	ctx context.Context,
   265  	server types.KmipServerSpec) error {
   266  
   267  	req := types.RegisterKmipServer{
   268  		This:   m.Reference(),
   269  		Server: server,
   270  	}
   271  	_, err := methods.RegisterKmipServer(ctx, m.Client(), &req)
   272  	if err != nil {
   273  		return err
   274  	}
   275  	return nil
   276  }
   277  
   278  func (m ManagerKmip) UpdateKmipServer(
   279  	ctx context.Context,
   280  	server types.KmipServerSpec) error {
   281  
   282  	req := types.UpdateKmipServer{
   283  		This:   m.Reference(),
   284  		Server: server,
   285  	}
   286  	_, err := methods.UpdateKmipServer(ctx, m.Client(), &req)
   287  	if err != nil {
   288  		return err
   289  	}
   290  	return nil
   291  }
   292  
   293  func (m ManagerKmip) RemoveKmipServer(
   294  	ctx context.Context,
   295  	providerID, serverName string) error {
   296  
   297  	req := types.RemoveKmipServer{
   298  		This: m.Reference(),
   299  		ClusterId: types.KeyProviderId{
   300  			Id: providerID,
   301  		},
   302  		ServerName: serverName,
   303  	}
   304  	_, err := methods.RemoveKmipServer(ctx, m.Client(), &req)
   305  	if err != nil {
   306  		return err
   307  	}
   308  	return nil
   309  }
   310  
   311  func (m ManagerKmip) QueryCryptoKeyStatus(
   312  	ctx context.Context,
   313  	ids []types.CryptoKeyId,
   314  	check int32) ([]types.CryptoManagerKmipCryptoKeyStatus, error) {
   315  
   316  	req := types.QueryCryptoKeyStatus{
   317  		This:           m.Reference(),
   318  		KeyIds:         ids,
   319  		CheckKeyBitMap: check,
   320  	}
   321  
   322  	res, err := methods.QueryCryptoKeyStatus(ctx, m.Client(), &req)
   323  	if err != nil {
   324  		return nil, err
   325  	}
   326  	return res.Returnval, nil
   327  }
   328  
   329  func (m ManagerKmip) ListKeys(
   330  	ctx context.Context,
   331  	limit *int32) ([]types.CryptoKeyId, error) {
   332  
   333  	req := types.ListKeys{
   334  		This:  m.Reference(),
   335  		Limit: limit,
   336  	}
   337  	res, err := methods.ListKeys(ctx, m.Client(), &req)
   338  	if err != nil {
   339  		return nil, err
   340  	}
   341  	return res.Returnval, nil
   342  }
   343  
   344  const keyStateNotActiveOrEnabled = string(types.CryptoManagerKmipCryptoKeyStatusKeyUnavailableReasonKeyStateNotActiveOrEnabled)
   345  
   346  // IsValidKey returns true if QueryCryptoKeyStatus results indicate the key is available or unavailable reason is `KeyStateNotActiveOrEnabled`.
   347  // This method is only valid for standard providers and will always return false for native providers.
   348  func (m ManagerKmip) IsValidKey(
   349  	ctx context.Context,
   350  	providerID,
   351  	keyID string) (bool, error) {
   352  
   353  	id := []types.CryptoKeyId{{
   354  		KeyId: keyID,
   355  		ProviderId: &types.KeyProviderId{
   356  			Id: providerID,
   357  		}},
   358  	}
   359  
   360  	res, err := m.QueryCryptoKeyStatus(ctx, id, CheckKeyAvailable)
   361  	if err != nil {
   362  		return false, err
   363  	}
   364  
   365  	for _, status := range res {
   366  		if status.KeyAvailable != nil && *status.KeyAvailable {
   367  			return true, nil
   368  		}
   369  
   370  		if status.Reason == keyStateNotActiveOrEnabled {
   371  			return true, nil
   372  		}
   373  	}
   374  
   375  	return false, nil
   376  }
   377  
   378  func (m ManagerKmip) IsValidProvider(
   379  	ctx context.Context,
   380  	providerID string) (bool, error) {
   381  
   382  	clusters, err := m.ListKmipServers(ctx, nil)
   383  	if err != nil {
   384  		return false, err
   385  	}
   386  
   387  	for i := range clusters {
   388  		if clusters[i].ClusterId.Id == providerID {
   389  			return true, nil
   390  		}
   391  	}
   392  
   393  	return false, nil
   394  }
   395  
   396  func (m ManagerKmip) IsValidServer(
   397  	ctx context.Context,
   398  	providerID, serverName string) (bool, error) {
   399  
   400  	clusters, err := m.ListKmipServers(ctx, nil)
   401  	if err != nil {
   402  		return false, err
   403  	}
   404  
   405  	for i := range clusters {
   406  		if clusters[i].ClusterId.Id == providerID {
   407  			for j := range clusters[i].Servers {
   408  				if clusters[i].Servers[j].Name == serverName {
   409  					return true, nil
   410  				}
   411  			}
   412  		}
   413  	}
   414  
   415  	return false, nil
   416  }
   417  
   418  func (m ManagerKmip) GenerateKey(
   419  	ctx context.Context,
   420  	providerID string) (string, error) {
   421  
   422  	req := types.GenerateKey{
   423  		This: m.Reference(),
   424  	}
   425  
   426  	if providerID != "" {
   427  		req.KeyProvider = &types.KeyProviderId{
   428  			Id: providerID,
   429  		}
   430  	}
   431  	res, err := methods.GenerateKey(ctx, m.Client(), &req)
   432  	if err != nil {
   433  		return "", err
   434  	}
   435  	if !res.Returnval.Success {
   436  		err := generateKeyError{reason: res.Returnval.Reason}
   437  		if res.Returnval.Fault != nil {
   438  			err.LocalizedMethodFault = *res.Returnval.Fault
   439  		}
   440  		return "", err
   441  	}
   442  	return res.Returnval.KeyId.KeyId, nil
   443  }
   444  
   445  func (m ManagerKmip) RemoveKeys(
   446  	ctx context.Context,
   447  	ids []types.CryptoKeyId,
   448  	force bool) error {
   449  
   450  	req := types.RemoveKeys{
   451  		This:  m.Reference(),
   452  		Keys:  ids,
   453  		Force: force,
   454  	}
   455  
   456  	_, err := methods.RemoveKeys(ctx, m.Client(), &req)
   457  	return err
   458  }
   459  
   460  type generateKeyError struct {
   461  	types.LocalizedMethodFault
   462  	reason string
   463  }
   464  
   465  func (e generateKeyError) Error() string {
   466  
   467  	return e.reason
   468  }
   469  
   470  func (e generateKeyError) GetLocalizedMethodFault() *types.LocalizedMethodFault {
   471  	return &e.LocalizedMethodFault
   472  }