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  }