go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/parse.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 "encoding/json" 9 "errors" 10 "strings" 11 12 "go.mondoo.com/cnquery/checksums" 13 "go.mondoo.com/cnquery/llx" 14 "go.mondoo.com/cnquery/providers-sdk/v1/plugin" 15 "go.mondoo.com/cnquery/providers/os/resources/parsers" 16 "go.mondoo.com/cnquery/providers/os/resources/plist" 17 "sigs.k8s.io/yaml" 18 ) 19 20 func fileFromPathOrContent(runtime *plugin.Runtime, args map[string]*llx.RawData) error { 21 if x, ok := args["path"]; ok { 22 path, ok := x.Value.(string) 23 if !ok { 24 return errors.New("Wrong type for 'path' it must be a string") 25 } 26 27 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 28 "path": llx.StringData(path), 29 }) 30 if err != nil { 31 return err 32 } 33 args["file"] = llx.ResourceData(f, "file") 34 delete(args, "path") 35 } else { 36 if x, ok := args["content"]; ok { 37 content := x.Value.(string) 38 virtualPath := "in-memory://" + checksums.New.Add(content).String() 39 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 40 "path": llx.StringData(virtualPath), 41 "content": llx.StringData(content), 42 "exists": llx.BoolTrue, 43 }) 44 if err != nil { 45 return err 46 } 47 args["file"] = llx.ResourceData(f, "file") 48 } 49 } 50 return nil 51 } 52 53 func initParseIni(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 54 if err := fileFromPathOrContent(runtime, args); err != nil { 55 return nil, nil, err 56 } 57 58 if _, ok := args["delimiter"]; !ok { 59 args["delimiter"] = llx.StringData("=") 60 } 61 62 return args, nil, nil 63 } 64 65 func (s *mqlParseIni) id() (string, error) { 66 if s.File.Data == nil { 67 return "", errors.New("no file provided for parse.ini") 68 } 69 70 file := s.File.Data 71 del := s.Delimiter.Data 72 return file.Path.Data + del, nil 73 } 74 75 func (s *mqlParseIni) content(file *mqlFile) (string, error) { 76 c := file.GetContent() 77 return c.Data, c.Error 78 } 79 80 func (s *mqlParseIni) sections(content string, delimiter string) (map[string]interface{}, error) { 81 ini := parsers.ParseIni(content, delimiter) 82 83 res := make(map[string]interface{}, len(ini.Fields)) 84 for k, v := range ini.Fields { 85 res[k] = v 86 } 87 88 return res, nil 89 } 90 91 func (s *mqlParseIni) params(sections map[string]interface{}) (map[string]interface{}, error) { 92 res := sections[""] 93 if res == nil { 94 return map[string]interface{}{}, nil 95 } 96 return res.(map[string]interface{}), nil 97 } 98 99 func initParseJson(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 100 if err := fileFromPathOrContent(runtime, args); err != nil { 101 return nil, nil, err 102 } 103 104 return args, nil, nil 105 } 106 107 func (s *mqlParseJson) id() (string, error) { 108 if s.File.Data == nil { 109 return "", errors.New("no file provided for parse.json") 110 } 111 112 file := s.File.Data 113 return file.Path.Data, nil 114 } 115 116 func (s *mqlParseJson) content(file *mqlFile) (string, error) { 117 c := file.GetContent() 118 return c.Data, c.Error 119 } 120 121 func (s *mqlParseJson) params(content string) (interface{}, error) { 122 if content == "" { 123 return nil, nil 124 } 125 126 var res interface{} 127 if err := json.Unmarshal([]byte(content), &res); err != nil { 128 return nil, err 129 } 130 return res, nil 131 } 132 133 func initParseYaml(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 134 if err := fileFromPathOrContent(runtime, args); err != nil { 135 return nil, nil, err 136 } 137 138 return args, nil, nil 139 } 140 141 func (s *mqlParseYaml) id() (string, error) { 142 if s.File.Data == nil { 143 return "", errors.New("no file provided for parse.yaml") 144 } 145 146 file := s.File.Data 147 return file.Path.Data, nil 148 } 149 150 func (s *mqlParseYaml) content(file *mqlFile) (string, error) { 151 c := file.GetContent() 152 return c.Data, c.Error 153 } 154 155 func (s *mqlParseYaml) params(content string) (map[string]interface{}, error) { 156 res := make(map[string](interface{})) 157 158 if content == "" { 159 return nil, nil 160 } 161 162 err := yaml.Unmarshal([]byte(content), &res) 163 if err != nil { 164 return nil, err 165 } 166 167 return res, nil 168 } 169 170 func initParsePlist(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 171 if err := fileFromPathOrContent(runtime, args); err != nil { 172 return nil, nil, err 173 } 174 return args, nil, nil 175 } 176 177 func (s *mqlParsePlist) id() (string, error) { 178 if s.File.Data == nil { 179 return "", errors.New("no file provided for parse.plist") 180 } 181 182 file := s.File.Data 183 return file.Path.Data, nil 184 } 185 186 func (s *mqlParsePlist) content(file *mqlFile) (string, error) { 187 c := file.GetContent() 188 return c.Data, c.Error 189 } 190 191 func (s *mqlParsePlist) params(content string) (map[string]interface{}, error) { 192 return plist.Decode(strings.NewReader(content)) 193 } 194 195 func initParseCertificates(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 196 // resolve path to file 197 if x, ok := args["path"]; ok { 198 path, ok := x.Value.(string) 199 if !ok { 200 return nil, nil, errors.New("Wrong type for 'path' in certificates initialization, it must be a string") 201 } 202 203 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 204 "path": llx.StringData(path), 205 }) 206 if err != nil { 207 return nil, nil, err 208 } 209 args["file"] = llx.ResourceData(f, "file") 210 211 } else if x, ok := args["content"]; ok { 212 content := x.Value.(string) 213 virtualPath := "in-memory://" + checksums.New.Add(content).String() 214 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 215 "path": llx.StringData(virtualPath), 216 "content": llx.StringData(content), 217 "exists": llx.BoolTrue, 218 }) 219 if err != nil { 220 return nil, nil, err 221 } 222 args["file"] = llx.ResourceData(f, "file") 223 args["path"] = llx.StringData(virtualPath) 224 } else { 225 return nil, nil, errors.New("missing 'path' or 'content' for parse.json initialization") 226 } 227 228 return args, nil, nil 229 } 230 231 func certificatesid(path string) string { 232 return "certificates:" + path 233 } 234 235 func (a *mqlParseCertificates) id() (string, error) { 236 f := a.File.Data 237 if f == nil { 238 return "", errors.New("missing file in parse certificate") 239 } 240 241 return certificatesid(f.Path.Data), nil 242 } 243 244 func (a *mqlParseCertificates) file() (*mqlFile, error) { 245 f, err := CreateResource(a.MqlRuntime, "file", map[string]*llx.RawData{ 246 "path": llx.StringData(a.Path.Data), 247 }) 248 if err != nil { 249 return nil, err 250 } 251 return f.(*mqlFile), nil 252 } 253 254 func (a *mqlParseCertificates) content(file *mqlFile) (string, error) { 255 res := file.GetContent() 256 return res.Data, res.Error 257 } 258 259 func (p *mqlParseCertificates) list(content string, path string) ([]interface{}, error) { 260 certificates, err := p.MqlRuntime.CreateSharedResource("certificates", map[string]*llx.RawData{ 261 "pem": llx.StringData(content), 262 }) 263 if err != nil { 264 return nil, err 265 } 266 267 list, err := p.MqlRuntime.GetSharedData("certificates", certificates.MqlID(), "list") 268 if err != nil { 269 return nil, err 270 } 271 272 return list.Value.([]interface{}), nil 273 } 274 275 func initParseOpenpgp(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) { 276 // resolve path to file 277 if x, ok := args["path"]; ok { 278 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 279 "path": x, 280 }) 281 if err != nil { 282 return nil, nil, err 283 } 284 args["file"] = llx.ResourceData(f, "file") 285 286 } else if x, ok := args["content"]; ok { 287 content := x.Value.(string) 288 virtualPath := "in-memory://" + checksums.New.Add(content).String() 289 f, err := CreateResource(runtime, "file", map[string]*llx.RawData{ 290 "path": llx.StringData(virtualPath), 291 "content": llx.StringData(content), 292 "exists": llx.BoolTrue, 293 }) 294 if err != nil { 295 return nil, nil, err 296 } 297 args["file"] = llx.ResourceData(f, "file") 298 args["path"] = llx.StringData(virtualPath) 299 300 } else { 301 return nil, nil, errors.New("missing 'path' or 'content' for parse.json initialization") 302 } 303 304 return args, nil, nil 305 } 306 307 func (a *mqlParseOpenpgp) id() (string, error) { 308 if a.File.Error != nil { 309 return "", a.File.Error 310 } 311 312 return a.File.Data.Path.Data, nil 313 } 314 315 func (a *mqlParseOpenpgp) content(file plugin.Resource) (string, error) { 316 res := file.(*mqlFile).GetContent() 317 return res.Data, res.Error 318 } 319 320 func (p *mqlParseOpenpgp) list(content string) ([]interface{}, error) { 321 certificates, err := p.MqlRuntime.CreateSharedResource("openpgp.entities", map[string]*llx.RawData{ 322 "content": llx.StringData(content), 323 }) 324 if err != nil { 325 return nil, err 326 } 327 328 list, err := p.MqlRuntime.GetSharedData("openpgp.entities", certificates.MqlID(), "list") 329 if err != nil { 330 return nil, err 331 } 332 333 return list.Value.([]interface{}), nil 334 }