github.com/juju/juju@v0.0.0-20240430160146-1752b71fcf00/provider/vsphere/errors.go (about)

     1  // Copyright 2018 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package vsphere
     5  
     6  import (
     7  	"strings"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/vmware/govmomi/vim25/soap"
    11  	"github.com/vmware/govmomi/vim25/types"
    12  
    13  	"github.com/juju/juju/environs/context"
    14  	"github.com/juju/juju/provider/common"
    15  )
    16  
    17  const (
    18  	// serverFaultCode is the code on the SOAP fault for an
    19  	// authentication error.
    20  	serverFaultCode = "ServerFaultCode"
    21  
    22  	// loginErrorFragment is what we look for in the message string to
    23  	// determine whether this is a login failure. (Using a fragment
    24  	// instead of the exact string to try to avoid breaking if a
    25  	// 'cosmetic' is made to the message.)
    26  	loginErrorFragment = "incorrect user name or password"
    27  )
    28  
    29  // IsAuthorisationFailure determines whether the given error indicates
    30  // that the vsphere credential used is bad.
    31  func IsAuthorisationFailure(err error) bool {
    32  	baseErr := errors.Cause(err)
    33  	if !soap.IsSoapFault(baseErr) {
    34  		return false
    35  	}
    36  	fault := soap.ToSoapFault(baseErr)
    37  	if fault.Code != serverFaultCode {
    38  		return false
    39  	}
    40  	_, isPermissionError := fault.Detail.Fault.(types.NoPermission)
    41  	if isPermissionError {
    42  		return true
    43  	}
    44  	// Otherwise it could be a login error.
    45  	return strings.Contains(fault.String, loginErrorFragment)
    46  }
    47  
    48  // HandleCredentialError marks the current credential as invalid if
    49  // the passed vsphere error indicates it should be.
    50  func HandleCredentialError(err error, env *sessionEnviron, ctx context.ProviderCallContext) {
    51  	if err == nil {
    52  		return
    53  	}
    54  	// LP #1849194: fell into a situation where we can either have an invalid
    55  	// credential OR user issued a VM spec that has no rights to, e.g. on a
    56  	// Resource Pool that it has no permissions on using "zone" on add-machine.
    57  	// To discover if the credentials are valid, run a command that MUST return
    58  	// OK: find folder defined on vm-folder credentials
    59  	_, errfind := env.client.FindFolder(env.ctx, env.getVMFolder())
    60  	if errfind != nil {
    61  		// This is a credential issue. Now, move to mark credentials as invalid
    62  		common.HandleCredentialError(IsAuthorisationFailure, err, ctx)
    63  	}
    64  }