go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/os/resources/npm/yarn.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package npm 5 6 import ( 7 "bufio" 8 "bytes" 9 "errors" 10 "io" 11 "regexp" 12 "strings" 13 14 "github.com/rs/zerolog/log" 15 "go.mondoo.com/cnquery/providers-sdk/v1/upstream/mvd" 16 "sigs.k8s.io/yaml" 17 ) 18 19 type YarnLockEntry struct { 20 Version string 21 Resolved string 22 Dependencies map[string]string 23 } 24 25 func ParseYarnLock(r io.Reader) ([]*mvd.Package, error) { 26 var b bytes.Buffer 27 28 // iterate and convert the format to yaml on the fly 29 scanner := bufio.NewScanner(r) 30 for scanner.Scan() { 31 line := scanner.Text() 32 33 reStr := regexp.MustCompile(`^(\s*.*)\s\"(.*)$`) 34 repStr := "${1}: \"$2" 35 line = reStr.ReplaceAllString(line, repStr) 36 37 b.Write([]byte(line)) 38 b.Write([]byte("\n")) 39 } 40 if err := scanner.Err(); err != nil { 41 return nil, err 42 } 43 44 var yarnLock map[string]YarnLockEntry 45 46 err := yaml.Unmarshal(b.Bytes(), &yarnLock) 47 if err != nil { 48 return nil, err 49 } 50 51 entries := []*mvd.Package{} 52 53 // add all dependencies 54 for k, v := range yarnLock { 55 name, _, err := ParseYarnPackageName(k) 56 if err != nil { 57 log.Error().Str("name", name).Msg("cannot parse yarn package name") 58 continue 59 } 60 entries = append(entries, &mvd.Package{ 61 Name: name, 62 Version: v.Version, 63 Format: "npm", 64 Namespace: "nodejs", 65 }) 66 } 67 68 return entries, nil 69 } 70 71 func ParseYarnPackageName(name string) (string, string, error) { 72 // a yarn package line may include may items 73 pkgNames := strings.Split(name, ",") 74 75 if len(pkgNames) == 0 { 76 // something wrong 77 return "", "", errors.New("cannot parse yarn package name") 78 } 79 80 parse := regexp.MustCompile(`^(.*)@(.*)$`) 81 m := parse.FindStringSubmatch(strings.TrimSpace(pkgNames[0])) 82 return m[1], m[2], nil 83 }