crowdsec/pkg/cwhub/hub.go
2023-10-19 14:19:37 +02:00

128 lines
3.1 KiB
Go

package cwhub
import (
"encoding/json"
"fmt"
"strings"
log "github.com/sirupsen/logrus"
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
)
const (
HubIndexFile = ".index.json"
// managed item types
COLLECTIONS = "collections"
PARSERS = "parsers"
POSTOVERFLOWS = "postoverflows"
SCENARIOS = "scenarios"
WAAP_RULES = "waap-rules"
)
var (
// XXX: The order is important, as it is used to range over sub-items in collections
ItemTypes = []string{PARSERS, POSTOVERFLOWS, SCENARIOS, WAAP_RULES, COLLECTIONS}
)
type HubItems map[string]map[string]Item
// Hub represents the runtime status of the hub (parsed items, etc.)
type Hub struct {
Items HubItems
cfg *csconfig.HubCfg
skippedLocal int
skippedTainted int
}
var theHub *Hub
// GetHub returns the hub singleton
// it returns an error if it's not initialized to avoid nil dereference
func GetHub() (*Hub, error) {
if theHub == nil {
return nil, fmt.Errorf("hub not initialized")
}
return theHub, nil
}
func (h Hub) GetDataDir() string {
return h.cfg.InstallDataDir
}
// displaySummary prints a total count of the hub items
func (h Hub) displaySummary() {
msg := "Loaded: "
for itemType := range h.Items {
msg += fmt.Sprintf("%d %s, ", len(h.Items[itemType]), itemType)
}
log.Info(strings.Trim(msg, ", "))
if h.skippedLocal > 0 || h.skippedTainted > 0 {
log.Infof("unmanaged items: %d local, %d tainted", h.skippedLocal, h.skippedTainted)
}
}
// DisplaySummary prints a total count of the hub items.
// It is a wrapper around HubIndex.displaySummary() to avoid exporting the hub singleton
// XXX: to be removed later
func DisplaySummary() error {
hub, err := GetHub()
if err != nil {
return err
}
hub.displaySummary()
return nil
}
// ParseIndex takes the content of a .index.json file and returns the map of associated parsers/scenarios/collections
func ParseIndex(buff []byte) (HubItems, error) {
var (
RawIndex HubItems
missingItems []string
)
if err := json.Unmarshal(buff, &RawIndex); err != nil {
return nil, fmt.Errorf("failed to unmarshal index: %w", err)
}
log.Debugf("%d item types in hub index", len(ItemTypes))
// Iterate over the different types to complete the struct
for _, itemType := range ItemTypes {
log.Tracef("%s: %d items", itemType, len(RawIndex[itemType]))
for name, item := range RawIndex[itemType] {
item.Name = name
item.Type = itemType
x := strings.Split(item.RemotePath, "/")
item.FileName = x[len(x)-1]
RawIndex[itemType][name] = item
if itemType != COLLECTIONS {
continue
}
// if it's a collection, check its sub-items are present
// XXX should be done later
for idx, ptr := range [][]string{item.Parsers, item.PostOverflows, item.Scenarios, item.WaapRules, item.Collections} {
ptrtype := ItemTypes[idx]
for _, p := range ptr {
if _, ok := RawIndex[ptrtype][p]; !ok {
log.Errorf("Referred %s %s in collection %s doesn't exist.", ptrtype, p, item.Name)
missingItems = append(missingItems, p)
}
}
}
}
}
if len(missingItems) > 0 {
return RawIndex, fmt.Errorf("%q: %w", missingItems, ErrMissingReference)
}
return RawIndex, nil
}