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 }