go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/providers/ssh/config.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package ssh
     5  
     6  import (
     7  	"os"
     8  	"path/filepath"
     9  	"strconv"
    10  	"strings"
    11  
    12  	"github.com/kevinburke/ssh_config"
    13  	homedir "github.com/mitchellh/go-homedir"
    14  	"github.com/rs/zerolog/log"
    15  	"go.mondoo.com/cnquery/motor/providers"
    16  	"go.mondoo.com/cnquery/motor/vault"
    17  )
    18  
    19  func ReadSSHConfig(cc *providers.Config) *providers.Config {
    20  	host := cc.Host
    21  
    22  	home, err := homedir.Dir()
    23  	if err != nil {
    24  		log.Debug().Err(err).Msg("ssh> failed to determine user home directory")
    25  		return cc
    26  	}
    27  
    28  	sshUserConfigPath := filepath.Join(home, ".ssh", "config")
    29  	f, err := os.Open(sshUserConfigPath)
    30  	if err != nil {
    31  		log.Debug().Err(err).Str("file", sshUserConfigPath).Msg("ssh> could not read ssh config")
    32  		return cc
    33  	}
    34  
    35  	cfg, err := ssh_config.Decode(f)
    36  	if err != nil {
    37  		log.Debug().Err(err).Str("file", sshUserConfigPath).Msg("could not parse ssh config")
    38  		return cc
    39  	}
    40  
    41  	// optional step, tries to parse the ssh config to see if additional information
    42  	// is already available
    43  	hostname, err := cfg.Get(host, "HostName")
    44  	if err == nil && len(hostname) > 0 {
    45  		cc.Host = hostname
    46  	}
    47  
    48  	if len(cc.Credentials) == 0 || (len(cc.Credentials) == 1 && cc.Credentials[0].Type == vault.CredentialType_password && len(cc.Credentials[0].Secret) == 0) {
    49  		user, _ := cfg.Get(host, "User")
    50  		port, err := cfg.Get(host, "Port")
    51  		if err == nil {
    52  			portNum, err := strconv.Atoi(port)
    53  			if err != nil {
    54  				log.Debug().Err(err).Str("file", sshUserConfigPath).Str("port", port).Msg("could not parse ssh port")
    55  			} else {
    56  				cc.Port = int32(portNum)
    57  			}
    58  		}
    59  
    60  		entry, err := cfg.Get(host, "IdentityFile")
    61  
    62  		// TODO: the ssh_config uses os/home but instead should be use go-homedir, could become a compile issue
    63  		// TODO: the problem is that the lib returns defaults and we cannot properly distingush
    64  		if err == nil && ssh_config.Default("IdentityFile") != entry {
    65  			// commonly ssh config included paths like ~
    66  			expandedPath, err := homedir.Expand(entry)
    67  			if err == nil {
    68  				log.Debug().Str("key", expandedPath).Str("host", host).Msg("ssh> read ssh identity key from ssh config")
    69  				// NOTE: we ignore the error here for now but this should probably been caught earlier anyway
    70  				credential, _ := vault.NewPrivateKeyCredentialFromPath(user, expandedPath, "")
    71  				// apply the option manually
    72  				if credential != nil {
    73  					cc.AddCredential(credential)
    74  				}
    75  			}
    76  		}
    77  	}
    78  
    79  	// handle disable of strict hostkey checking:
    80  	// Host *
    81  	// StrictHostKeyChecking no
    82  	entry, err := cfg.Get(host, "StrictHostKeyChecking")
    83  	if err == nil && strings.ToLower(entry) == "no" {
    84  		cc.Insecure = true
    85  	}
    86  	return cc
    87  }
    88  
    89  func VerifyConfig(pCfg *providers.Config) error {
    90  	if pCfg.Backend != providers.ProviderType_SSH {
    91  		return providers.ErrProviderTypeDoesNotMatch
    92  	}
    93  
    94  	return nil
    95  }