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  }