go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/sshd.go (about) 1 // copyright: 2019, Dominik Richter and Christoph Hartmann 2 // author: Dominik Richter 3 // author: Christoph Hartmann 4 5 package resources 6 7 import ( 8 "errors" 9 "fmt" 10 "strings" 11 12 "go.mondoo.com/cnquery/llx" 13 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 14 "go.mondoo.com/cnquery/providers/os/connection/shared" 15 "go.mondoo.com/cnquery/providers/os/resources/sshd" 16 ) 17 18 func initSshdConfig(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 19 if x, ok := args["path"]; ok { 20 path, ok := x.Value.(string) 21 if !ok { 22 return nil, nil, errors.New("wrong type for 'path' in sshd.config initialization, it must be a string") 23 } 24 25 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 26 "path": llx.StringData(path), 27 }) 28 if err != nil { 29 return nil, nil, err 30 } 31 args["file"] = llx.ResourceData(f, "file") 32 33 delete(args, "path") 34 } 35 36 return args, nil, nil 37 } 38 39 const defaultSshdConfig = "/etc/ssh/sshd_config" 40 41 func (s *mqlSshdConfig) id() (string, error) { 42 file := s.GetFile() 43 if file.Error != nil { 44 return "", file.Error 45 } 46 47 return file.Data.Path.Data, nil 48 } 49 50 func (s *mqlSshdConfig) file() (*mqlFile, error) { 51 f, err := CreateResource(s.MqlRuntime, "file", map[string]*llx.RawData{ 52 "path": llx.StringData(defaultSshdConfig), 53 }) 54 if err != nil { 55 return nil, err 56 } 57 return f.(*mqlFile), nil 58 } 59 60 func (s *mqlSshdConfig) files(file *mqlFile) ([]interface{}, error) { 61 if !file.GetExists().Data { 62 return nil, errors.New("sshd config does not exist in " + file.GetPath().Data) 63 } 64 65 conn := s.MqlRuntime.Connection.(shared.Connection) 66 allFiles, err := sshd.GetAllSshdIncludedFiles(file.Path.Data, conn) 67 if err != nil { 68 return nil, err 69 } 70 71 // Return a list of lumi files 72 lumiFiles := make([]interface{}, len(allFiles)) 73 for i, path := range allFiles { 74 lumiFile, err := CreateResource(s.MqlRuntime, "file", map[string]*llx.RawData{ 75 "path": llx.StringData(path), 76 }) 77 if err != nil { 78 return nil, err 79 } 80 81 lumiFiles[i] = lumiFile.(*mqlFile) 82 } 83 84 return lumiFiles, nil 85 } 86 87 func (s *mqlSshdConfig) content(files []interface{}) (string, error) { 88 // TODO: this can be heavily improved once we do it right, since this is constantly 89 // re-registered as the file changes 90 91 // files is in the "dependency" order that files were discovered while 92 // parsing the base/root config file. We will essentially re-parse the 93 // config and insert the contents of those dependent files in-place where 94 // they appear in the base/root config. 95 if len(files) < 1 { 96 return "", fmt.Errorf("no base sshd config file to read") 97 } 98 99 lumiFiles := make([]*mqlFile, len(files)) 100 for i, file := range files { 101 lumiFile, ok := file.(*mqlFile) 102 if !ok { 103 return "", fmt.Errorf("failed to type assert list of files to File interface") 104 } 105 lumiFiles[i] = lumiFile 106 } 107 108 // The first entry in our list is the base/root of the sshd configuration tree 109 baseConfigFilePath := lumiFiles[0].Path.Data 110 111 conn := s.MqlRuntime.Connection.(shared.Connection) 112 fullContent, err := sshd.GetSshdUnifiedContent(baseConfigFilePath, conn) 113 if err != nil { 114 return "", err 115 } 116 117 return fullContent, nil 118 } 119 120 func (s *mqlSshdConfig) params(content string) (map[string]interface{}, error) { 121 params, err := sshd.Params(content) 122 if err != nil { 123 return nil, err 124 } 125 126 // convert map 127 res := map[string]interface{}{} 128 for k, v := range params { 129 res[k] = v 130 } 131 132 return res, nil 133 } 134 135 func (s *mqlSshdConfig) parseConfigEntrySlice(raw interface{}) ([]interface{}, error) { 136 strCipher, ok := raw.(string) 137 if !ok { 138 return nil, errors.New("value is not a valid string") 139 } 140 141 res := []interface{}{} 142 entries := strings.Split(strCipher, ",") 143 for i := range entries { 144 val := strings.TrimSpace(entries[i]) 145 res = append(res, val) 146 } 147 148 return res, nil 149 } 150 151 func (s *mqlSshdConfig) ciphers(params map[string]interface{}) ([]interface{}, error) { 152 rawCiphers, ok := params["Ciphers"] 153 if !ok { 154 return nil, nil 155 } 156 157 return s.parseConfigEntrySlice(rawCiphers) 158 } 159 160 func (s *mqlSshdConfig) macs(params map[string]interface{}) ([]interface{}, error) { 161 rawMacs, ok := params["MACs"] 162 if !ok { 163 return nil, nil 164 } 165 166 return s.parseConfigEntrySlice(rawMacs) 167 } 168 169 func (s *mqlSshdConfig) kexs(params map[string]interface{}) ([]interface{}, error) { 170 rawkexs, ok := params["KexAlgorithms"] 171 if !ok { 172 return nil, nil 173 } 174 175 return s.parseConfigEntrySlice(rawkexs) 176 } 177 178 func (s *mqlSshdConfig) hostkeys(params map[string]interface{}) ([]interface{}, error) { 179 rawHostKeys, ok := params["HostKey"] 180 if !ok { 181 return nil, nil 182 } 183 184 return s.parseConfigEntrySlice(rawHostKeys) 185 }