simulation for local scenarios (#3010)

This commit is contained in:
mmetc 2024-05-16 11:13:39 +02:00 committed by GitHub
parent ccf08e56d9
commit b6253d567b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 40 additions and 73 deletions

View file

@ -17,11 +17,12 @@ import (
// Hub is the main structure for the package.
type Hub struct {
items HubItems // Items read from HubDir and InstallDir
local *csconfig.LocalHubCfg
remote *RemoteHubCfg
logger *logrus.Logger
Warnings []string // Warnings encountered during sync
items HubItems // Items read from HubDir and InstallDir
pathIndex map[string]*Item
local *csconfig.LocalHubCfg
remote *RemoteHubCfg
logger *logrus.Logger
Warnings []string // Warnings encountered during sync
}
// GetDataDir returns the data directory, where data sets are installed.
@ -43,9 +44,10 @@ func NewHub(local *csconfig.LocalHubCfg, remote *RemoteHubCfg, updateIndex bool,
}
hub := &Hub{
local: local,
remote: remote,
logger: logger,
local: local,
remote: remote,
logger: logger,
pathIndex: make(map[string]*Item, 0),
}
if updateIndex {
@ -137,7 +139,7 @@ func (h *Hub) ItemStats() []string {
}
ret := []string{
fmt.Sprintf("Loaded: %s", loaded),
"Loaded: " + loaded,
}
if local > 0 || tainted > 0 {
@ -169,6 +171,7 @@ func (h *Hub) addItem(item *Item) {
}
h.items[item.Type][item.Name] = item
h.pathIndex[item.State.LocalPath] = item
}
// GetItemMap returns the map of items for a given type.
@ -181,6 +184,11 @@ func (h *Hub) GetItem(itemType string, itemName string) *Item {
return h.GetItemMap(itemType)[itemName]
}
// GetItemByPath returns an item from hub based on its (absolute) local path.
func (h *Hub) GetItemByPath(itemPath string) *Item {
return h.pathIndex[itemPath]
}
// GetItemFQ returns an item from hub based on its type and name (type:author/name).
func (h *Hub) GetItemFQ(itemFQName string) (*Item, error) {
// type and name are separated by a colon

View file

@ -1,53 +0,0 @@
package cwhub
// Resolve a symlink to find the hub item it points to.
// This file is used only by pkg/leakybucket
import (
"fmt"
"os"
"path/filepath"
"strings"
)
// itemKey extracts the map key of an item (i.e. author/name) from its pathname. Follows a symlink if necessary.
func itemKey(itemPath string) (string, error) {
f, err := os.Lstat(itemPath)
if err != nil {
return "", fmt.Errorf("while performing lstat on %s: %w", itemPath, err)
}
if f.Mode()&os.ModeSymlink == 0 {
// it's not a symlink, so the filename itsef should be the key
return filepath.Base(itemPath), nil
}
// resolve the symlink to hub file
pathInHub, err := os.Readlink(itemPath)
if err != nil {
return "", fmt.Errorf("while reading symlink of %s: %w", itemPath, err)
}
author := filepath.Base(filepath.Dir(pathInHub))
fname := filepath.Base(pathInHub)
fname = strings.TrimSuffix(fname, ".yaml")
fname = strings.TrimSuffix(fname, ".yml")
return fmt.Sprintf("%s/%s", author, fname), nil
}
// GetItemByPath retrieves an item from the hub index based on its local path.
func (h *Hub) GetItemByPath(itemType string, itemPath string) (*Item, error) {
itemKey, err := itemKey(itemPath)
if err != nil {
return nil, err
}
item := h.GetItem(itemType, itemKey)
if item == nil {
return nil, fmt.Errorf("%s not found in %s", itemKey, itemType)
}
return item, nil
}

View file

@ -9,9 +9,10 @@ import (
"strings"
"github.com/Masterminds/semver/v3"
"github.com/crowdsecurity/go-cs-lib/downloader"
"github.com/sirupsen/logrus"
"gopkg.in/yaml.v3"
"github.com/crowdsecurity/go-cs-lib/downloader"
)
func isYAMLFileName(path string) bool {
@ -271,6 +272,8 @@ func (h *Hub) itemVisit(path string, f os.DirEntry, err error) error {
return err
}
h.pathIndex[path] = item
return nil
}

View file

@ -253,7 +253,7 @@ func LoadBuckets(cscfg *csconfig.CrowdsecServiceCfg, hub *cwhub.Hub, files []str
ok, err := cwversion.Satisfies(bucketFactory.FormatVersion, cwversion.Constraint_scenario)
if err != nil {
return nil, nil, fmt.Errorf("failed to check version : %s", err)
return nil, nil, fmt.Errorf("failed to check version: %w", err)
}
if !ok {
@ -265,20 +265,16 @@ func LoadBuckets(cscfg *csconfig.CrowdsecServiceCfg, hub *cwhub.Hub, files []str
bucketFactory.BucketName = seed.Generate()
bucketFactory.ret = response
hubItem, err := hub.GetItemByPath(cwhub.SCENARIOS, bucketFactory.Filename)
if err != nil {
log.Errorf("scenario %s (%s) couldn't be find in hub (ignore if in unit tests)", bucketFactory.Name, bucketFactory.Filename)
hubItem := hub.GetItemByPath(bucketFactory.Filename)
if hubItem == nil {
log.Errorf("scenario %s (%s) could not be found in hub (ignore if in unit tests)", bucketFactory.Name, bucketFactory.Filename)
} else {
if cscfg.SimulationConfig != nil {
bucketFactory.Simulated = cscfg.SimulationConfig.IsSimulated(hubItem.Name)
}
if hubItem != nil {
bucketFactory.ScenarioVersion = hubItem.State.LocalVersion
bucketFactory.hash = hubItem.State.LocalHash
} else {
log.Errorf("scenario %s (%s) couldn't be find in hub (ignore if in unit tests)", bucketFactory.Name, bucketFactory.Filename)
}
bucketFactory.ScenarioVersion = hubItem.State.LocalVersion
bucketFactory.hash = hubItem.State.LocalHash
}
bucketFactory.wgDumpState = buckets.wgDumpState

View file

@ -62,6 +62,19 @@ setup() {
assert_json '[]'
}
@test "simulated local scenario: expect no decision" {
CONFIG_DIR=$(dirname "$CONFIG_YAML")
HUB_DIR=$(config_get '.config_paths.hub_dir')
rune -0 mkdir -p "$CONFIG_DIR"/scenarios
# replace an installed scenario with a local version
rune -0 cp -r "$HUB_DIR"/scenarios/crowdsecurity/ssh-bf.yaml "$CONFIG_DIR"/scenarios/ssh-bf2.yaml
rune -0 cscli scenarios remove crowdsecurity/ssh-bf --force --purge
rune -0 cscli simulation enable crowdsecurity/ssh-bf
fake_log | "$CROWDSEC" -dsn file:///dev/fd/0 -type syslog -no-api
rune -0 cscli decisions list --no-simu -o json
assert_json '[]'
}
@test "global simulation, listing non-simulated: expect no decision" {
rune -0 cscli simulation disable crowdsecurity/ssh-bf
rune -0 cscli simulation enable --global