go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers-sdk/v1/inventory/domainlist/domainlist.go (about) 1 // Copyright (c) Mondoo, Inc. 2 // SPDX-License-Identifier: BUSL-1.1 3 4 package domainlist 5 6 import ( 7 "bufio" 8 "io" 9 "net/url" 10 "strconv" 11 "strings" 12 13 "github.com/cockroachdb/errors" 14 "github.com/rs/zerolog/log" 15 "go.mondoo.com/cnquery/providers-sdk/v1/inventory" 16 ) 17 18 func Parse(input io.Reader) (*Inventory, error) { 19 inventory := &Inventory{} 20 scanner := bufio.NewScanner(input) 21 22 for scanner.Scan() { 23 line := scanner.Text() 24 line = strings.TrimSpace(line) 25 26 if strings.HasPrefix(line, "#") || line == "" { 27 continue 28 } 29 30 inventory.Hosts = append(inventory.Hosts, line) 31 } 32 33 if err := scanner.Err(); err != nil { 34 return nil, err 35 } 36 37 return inventory, nil 38 } 39 40 type Inventory struct { 41 Hosts []string 42 } 43 44 func (in *Inventory) ToV1Inventory() *inventory.Inventory { 45 out := inventory.New() 46 47 r := &networkResolver{} 48 49 for i := range in.Hosts { 50 host := in.Hosts[i] 51 name := host 52 53 // prefix with host to ensure the connection parsing works as expected 54 if !strings.Contains(host, "//") { 55 host = "host://" + host 56 } 57 58 tc, err := r.ParseConnectionURL(host, "", "") 59 if err != nil { 60 log.Warn().Err(err).Str("hostname", host).Msg("could not parse hostname") 61 } 62 63 out.Spec.Assets = append(out.Spec.Assets, &inventory.Asset{ 64 Name: name, 65 Connections: []*inventory.Config{tc}, 66 }) 67 } 68 69 return out 70 } 71 72 type networkResolver struct{} 73 74 func (r *networkResolver) ParseConnectionURL(fullUrl string, identityFile string, password string) (*inventory.Config, error) { 75 url, err := url.Parse(fullUrl) 76 if err != nil { 77 return nil, errors.Wrap(err, "failed to parse target URL") 78 } 79 80 // TODO: Processing the family here needs a bit more work. It is unclear 81 // where this will evolve for now, so let's keep watching it. 82 // So far we know: 83 // - all of them are in the `api` family (also their kind is set this way) 84 // - multiple families on one service are possible (eg: http, tls, tcp) 85 res := inventory.Config{ 86 Type: "host", 87 Options: map[string]string{"scheme": url.Scheme}, 88 } 89 90 schemeBits := strings.Split(url.Scheme, "+") 91 for i := range schemeBits { 92 x := strings.ToLower(schemeBits[i]) 93 switch x { 94 case "tls", "tcp", "udp": 95 // FIXME: properly check for schema bits 96 res.Options[x] = "" 97 } 98 } 99 100 hostBits := strings.Split(url.Host, ":") 101 switch len(hostBits) { 102 case 1: 103 res.Host = hostBits[0] 104 case 2: 105 res.Host = hostBits[0] 106 port, err := strconv.Atoi(hostBits[1]) 107 if err != nil { 108 return nil, errors.Wrap(err, "failed to parse port in target URL") 109 } 110 res.Port = int32(port) 111 default: 112 return nil, errors.New("malformed target URL, host cannot be parsed") 113 } 114 115 return &res, nil 116 }