add hub type "context"

This commit is contained in:
Marco Mariani 2023-12-07 09:44:54 +01:00
parent 8fa84e5cd9
commit 18b53128a5
10 changed files with 94 additions and 11 deletions

View file

@ -0,0 +1,40 @@
package main
import (
"github.com/crowdsecurity/crowdsec/pkg/cwhub"
)
func NewContextCLI() *itemCLI {
return &itemCLI{
name: cwhub.CONTEXTS,
singular: "context",
oneOrMore: "context(s)",
help: cliHelp{
example: `cscli contexts list -a
cscli contexts install crowdsecurity/yyy crowdsecurity/zzz
cscli contexts inspect crowdsecurity/yyy crowdsecurity/zzz
cscli contexts upgrade crowdsecurity/yyy crowdsecurity/zzz
cscli contexts remove crowdsecurity/yyy crowdsecurity/zzz
`,
},
installHelp: cliHelp{
example: `cscli contexts install crowdsecurity/yyy crowdsecurity/zzz`,
},
removeHelp: cliHelp{
example: `cscli contexts remove crowdsecurity/yyy crowdsecurity/zzz`,
},
upgradeHelp: cliHelp{
example: `cscli contexts upgrade crowdsecurity/yyy crowdsecurity/zzz`,
},
inspectHelp: cliHelp{
example: `cscli contexts inspect crowdsecurity/yyy crowdsecurity/zzz`,
},
listHelp: cliHelp{
example: `cscli contexts list
cscli contexts list -a
cscli contexts list crowdsecurity/yyy crowdsecurity/zzz
List only enabled contexts unless "-a" or names are specified.`,
},
}
}

View file

@ -93,7 +93,7 @@ func initConfig() {
} }
var validArgs = []string{ var validArgs = []string{
"scenarios", "parsers", "collections", "capi", "lapi", "postoverflows", "machines", "scenarios", "parsers", "collections", "capi", "contexts", "lapi", "postoverflows", "machines",
"metrics", "bouncers", "alerts", "decisions", "simulation", "hub", "dashboard", "metrics", "bouncers", "alerts", "decisions", "simulation", "hub", "dashboard",
"config", "completion", "version", "console", "notifications", "support", "config", "completion", "version", "console", "notifications", "support",
} }
@ -246,6 +246,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
rootCmd.AddCommand(NewParserCLI().NewCommand()) rootCmd.AddCommand(NewParserCLI().NewCommand())
rootCmd.AddCommand(NewScenarioCLI().NewCommand()) rootCmd.AddCommand(NewScenarioCLI().NewCommand())
rootCmd.AddCommand(NewPostOverflowCLI().NewCommand()) rootCmd.AddCommand(NewPostOverflowCLI().NewCommand())
rootCmd.AddCommand(NewContextCLI().NewCommand())
rootCmd.AddCommand(NewAppsecConfigCLI().NewCommand()) rootCmd.AddCommand(NewAppsecConfigCLI().NewCommand())
rootCmd.AddCommand(NewAppsecRuleCLI().NewCommand()) rootCmd.AddCommand(NewAppsecRuleCLI().NewCommand())

View file

@ -37,6 +37,7 @@ const (
SUPPORT_OS_INFO_PATH = "osinfo.txt" SUPPORT_OS_INFO_PATH = "osinfo.txt"
SUPPORT_PARSERS_PATH = "hub/parsers.txt" SUPPORT_PARSERS_PATH = "hub/parsers.txt"
SUPPORT_SCENARIOS_PATH = "hub/scenarios.txt" SUPPORT_SCENARIOS_PATH = "hub/scenarios.txt"
SUPPORT_CONTEXTS_PATH = "hub/scenarios.txt"
SUPPORT_COLLECTIONS_PATH = "hub/collections.txt" SUPPORT_COLLECTIONS_PATH = "hub/collections.txt"
SUPPORT_POSTOVERFLOWS_PATH = "hub/postoverflows.txt" SUPPORT_POSTOVERFLOWS_PATH = "hub/postoverflows.txt"
SUPPORT_BOUNCERS_PATH = "lapi/bouncers.txt" SUPPORT_BOUNCERS_PATH = "lapi/bouncers.txt"
@ -260,6 +261,7 @@ func NewSupportCmd() *cobra.Command {
- Installed parsers list - Installed parsers list
- Installed scenarios list - Installed scenarios list
- Installed postoverflows list - Installed postoverflows list
- Installed context list
- Bouncers list - Bouncers list
- Machines list - Machines list
- CAPI status - CAPI status
@ -309,6 +311,7 @@ cscli support dump -f /tmp/crowdsec-support.zip
infos[SUPPORT_PARSERS_PATH] = []byte(err.Error()) infos[SUPPORT_PARSERS_PATH] = []byte(err.Error())
infos[SUPPORT_SCENARIOS_PATH] = []byte(err.Error()) infos[SUPPORT_SCENARIOS_PATH] = []byte(err.Error())
infos[SUPPORT_POSTOVERFLOWS_PATH] = []byte(err.Error()) infos[SUPPORT_POSTOVERFLOWS_PATH] = []byte(err.Error())
infos[SUPPORT_CONTEXTS_PATH] = []byte(err.Error())
infos[SUPPORT_COLLECTIONS_PATH] = []byte(err.Error()) infos[SUPPORT_COLLECTIONS_PATH] = []byte(err.Error())
} }
@ -344,6 +347,7 @@ cscli support dump -f /tmp/crowdsec-support.zip
infos[SUPPORT_PARSERS_PATH] = collectHubItems(hub, cwhub.PARSERS) infos[SUPPORT_PARSERS_PATH] = collectHubItems(hub, cwhub.PARSERS)
infos[SUPPORT_SCENARIOS_PATH] = collectHubItems(hub, cwhub.SCENARIOS) infos[SUPPORT_SCENARIOS_PATH] = collectHubItems(hub, cwhub.SCENARIOS)
infos[SUPPORT_POSTOVERFLOWS_PATH] = collectHubItems(hub, cwhub.POSTOVERFLOWS) infos[SUPPORT_POSTOVERFLOWS_PATH] = collectHubItems(hub, cwhub.POSTOVERFLOWS)
infos[SUPPORT_CONTEXTS_PATH] = collectHubItems(hub, cwhub.POSTOVERFLOWS)
infos[SUPPORT_COLLECTIONS_PATH] = collectHubItems(hub, cwhub.COLLECTIONS) infos[SUPPORT_COLLECTIONS_PATH] = collectHubItems(hub, cwhub.COLLECTIONS)
} }

View file

@ -320,10 +320,12 @@ config.yaml) each time the container is run.
| `PARSERS` | | Parsers to install, separated by space | | `PARSERS` | | Parsers to install, separated by space |
| `SCENARIOS` | | Scenarios to install, separated by space | | `SCENARIOS` | | Scenarios to install, separated by space |
| `POSTOVERFLOWS` | | Postoverflows to install, separated by space | | `POSTOVERFLOWS` | | Postoverflows to install, separated by space |
| `CONTEXTS` | | Context files to install, separated by space |
| `DISABLE_COLLECTIONS` | | Collections to remove, separated by space: `-e DISABLE_COLLECTIONS="crowdsecurity/linux crowdsecurity/nginx"` | | `DISABLE_COLLECTIONS` | | Collections to remove, separated by space: `-e DISABLE_COLLECTIONS="crowdsecurity/linux crowdsecurity/nginx"` |
| `DISABLE_PARSERS` | | Parsers to remove, separated by space | | `DISABLE_PARSERS` | | Parsers to remove, separated by space |
| `DISABLE_SCENARIOS` | | Scenarios to remove, separated by space | | `DISABLE_SCENARIOS` | | Scenarios to remove, separated by space |
| `DISABLE_POSTOVERFLOWS` | | Postoverflows to remove, separated by space | | `DISABLE_POSTOVERFLOWS` | | Postoverflows to remove, separated by space |
| `DISABLE_POSTOVERFLOWS` | | Context files to remove, separated by space |
| | | | | | | |
| __Log verbosity__ | | | | __Log verbosity__ | | |
| `LEVEL_INFO` | false | Force INFO level for the container log | | `LEVEL_INFO` | false | Force INFO level for the container log |

View file

@ -300,7 +300,7 @@ fi
conf_set_if "$PLUGIN_DIR" '.config_paths.plugin_dir = strenv(PLUGIN_DIR)' conf_set_if "$PLUGIN_DIR" '.config_paths.plugin_dir = strenv(PLUGIN_DIR)'
## Install collections, parsers, scenarios & postoverflows ## Install hub items
cscli hub update cscli hub update
cscli_if_clean collections upgrade crowdsecurity/linux cscli_if_clean collections upgrade crowdsecurity/linux
@ -328,6 +328,11 @@ if [ "$POSTOVERFLOWS" != "" ]; then
cscli_if_clean postoverflows install "$(difference "$POSTOVERFLOWS" "$DISABLE_POSTOVERFLOWS")" cscli_if_clean postoverflows install "$(difference "$POSTOVERFLOWS" "$DISABLE_POSTOVERFLOWS")"
fi fi
if [ "$CONTEXTS" != "" ]; then
# shellcheck disable=SC2086
cscli_if_clean contexts install "$(difference "$CONTEXTS" "$DISABLE_CONTEXTS")"
fi
## Remove collections, parsers, scenarios & postoverflows ## Remove collections, parsers, scenarios & postoverflows
if [ "$DISABLE_COLLECTIONS" != "" ]; then if [ "$DISABLE_COLLECTIONS" != "" ]; then
# shellcheck disable=SC2086 # shellcheck disable=SC2086
@ -349,6 +354,11 @@ if [ "$DISABLE_POSTOVERFLOWS" != "" ]; then
cscli_if_clean postoverflows remove "$DISABLE_POSTOVERFLOWS" --force cscli_if_clean postoverflows remove "$DISABLE_POSTOVERFLOWS" --force
fi fi
if [ "$DISABLE_CONTEXTS" != "" ]; then
# shellcheck disable=SC2086
cscli_if_clean contexts remove "$DISABLE_CONTEXTS" --force
fi
## Register bouncers via env ## Register bouncers via env
for BOUNCER in $(compgen -A variable | grep -i BOUNCER_KEY); do for BOUNCER in $(compgen -A variable | grep -i BOUNCER_KEY); do
KEY=$(printf '%s' "${!BOUNCER}") KEY=$(printf '%s' "${!BOUNCER}")

View file

@ -16,6 +16,7 @@ const (
PARSERS = "parsers" PARSERS = "parsers"
POSTOVERFLOWS = "postoverflows" POSTOVERFLOWS = "postoverflows"
SCENARIOS = "scenarios" SCENARIOS = "scenarios"
CONTEXTS = "contexts"
APPSEC_CONFIGS = "appsec-configs" APPSEC_CONFIGS = "appsec-configs"
APPSEC_RULES = "appsec-rules" APPSEC_RULES = "appsec-rules"
) )
@ -29,7 +30,7 @@ const (
var ( var (
// The order is important, as it is used to range over sub-items in collections. // The order is important, as it is used to range over sub-items in collections.
ItemTypes = []string{PARSERS, POSTOVERFLOWS, SCENARIOS, APPSEC_CONFIGS, APPSEC_RULES, COLLECTIONS} ItemTypes = []string{PARSERS, POSTOVERFLOWS, SCENARIOS, CONTEXTS, APPSEC_CONFIGS, APPSEC_RULES, COLLECTIONS}
) )
type HubItems map[string]map[string]*Item type HubItems map[string]map[string]*Item
@ -120,6 +121,7 @@ type Item struct {
PostOverflows []string `json:"postoverflows,omitempty" yaml:"postoverflows,omitempty"` PostOverflows []string `json:"postoverflows,omitempty" yaml:"postoverflows,omitempty"`
Scenarios []string `json:"scenarios,omitempty" yaml:"scenarios,omitempty"` Scenarios []string `json:"scenarios,omitempty" yaml:"scenarios,omitempty"`
Collections []string `json:"collections,omitempty" yaml:"collections,omitempty"` Collections []string `json:"collections,omitempty" yaml:"collections,omitempty"`
Contexts []string `json:"contexts,omitempty" yaml:"contexts,omitempty"`
AppsecConfigs []string `json:"appsec-configs,omitempty" yaml:"appsec-configs,omitempty"` AppsecConfigs []string `json:"appsec-configs,omitempty" yaml:"appsec-configs,omitempty"`
AppsecRules []string `json:"appsec-rules,omitempty" yaml:"appsec-rules,omitempty"` AppsecRules []string `json:"appsec-rules,omitempty" yaml:"appsec-rules,omitempty"`
} }
@ -231,6 +233,15 @@ func (i *Item) SubItems() []*Item {
sub = append(sub, s) sub = append(sub, s)
} }
for _, name := range i.Contexts {
s := i.hub.GetItem(CONTEXTS, name)
if s == nil {
continue
}
sub = append(sub, s)
}
for _, name := range i.AppsecConfigs { for _, name := range i.AppsecConfigs {
s := i.hub.GetItem(APPSEC_CONFIGS, name) s := i.hub.GetItem(APPSEC_CONFIGS, name)
if s == nil { if s == nil {
@ -284,6 +295,12 @@ func (i *Item) logMissingSubItems() {
} }
} }
for _, subName := range i.Contexts {
if i.hub.GetItem(CONTEXTS, subName) == nil {
log.Errorf("can't find %s in %s, required by %s", subName, CONTEXTS, i.Name)
}
}
for _, subName := range i.AppsecConfigs { for _, subName := range i.AppsecConfigs {
if i.hub.GetItem(APPSEC_CONFIGS, subName) == nil { if i.hub.GetItem(APPSEC_CONFIGS, subName) == nil {
log.Errorf("can't find %s in %s, required by %s", subName, APPSEC_CONFIGS, i.Name) log.Errorf("can't find %s in %s, required by %s", subName, APPSEC_CONFIGS, i.Name)

View file

@ -346,7 +346,7 @@ func (i *Item) checkSubItemVersions() error {
// syncDir scans a directory for items, and updates the Hub state accordingly. // syncDir scans a directory for items, and updates the Hub state accordingly.
func (h *Hub) syncDir(dir string) error { func (h *Hub) syncDir(dir string) error {
// For each, scan PARSERS, POSTOVERFLOWS, SCENARIOS and COLLECTIONS last // For each, scan PARSERS, POSTOVERFLOWS... and COLLECTIONS last
for _, scan := range ItemTypes { for _, scan := range ItemTypes {
// cpath: top-level item directory, either downloaded or installed items. // cpath: top-level item directory, either downloaded or installed items.
// i.e. /etc/crowdsec/parsers, /etc/crowdsec/hub/parsers, ... // i.e. /etc/crowdsec/parsers, /etc/crowdsec/hub/parsers, ...

View file

@ -83,7 +83,7 @@ bats-build: bats-environment
# Create a reusable package with initial configuration + data # Create a reusable package with initial configuration + data
bats-fixture: bats-check-requirements bats-update-tools bats-fixture: bats-check-requirements bats-update-tools
@echo "Creating functional test fixture..." @echo "Creating functional test fixture."
@$(TEST_DIR)/instance-data make @$(TEST_DIR)/instance-data make
# Remove the local crowdsec installation and the fixture config + data # Remove the local crowdsec installation and the fixture config + data

View file

@ -36,7 +36,7 @@ teardown() {
rune -0 cscli hub list rune -0 cscli hub list
assert_output "No items to display" assert_output "No items to display"
rune -0 cscli hub list -o json rune -0 cscli hub list -o json
assert_json '{"appsec-configs":[],"appsec-rules":[],parsers:[],scenarios:[],collections:[],postoverflows:[]}' assert_json '{"appsec-configs":[],"appsec-rules":[],parsers:[],scenarios:[],collections:[],contexts:[],postoverflows:[]}'
rune -0 cscli hub list -o raw rune -0 cscli hub list -o raw
assert_output 'name,status,version,description,type' assert_output 'name,status,version,description,type'
@ -47,6 +47,7 @@ teardown() {
assert_output --regexp ".*PARSERS.*crowdsecurity/whitelists.*SCENARIOS.*crowdsecurity/telnet-bf.*" assert_output --regexp ".*PARSERS.*crowdsecurity/whitelists.*SCENARIOS.*crowdsecurity/telnet-bf.*"
refute_output --partial 'POSTOVERFLOWS' refute_output --partial 'POSTOVERFLOWS'
refute_output --partial 'COLLECTIONS' refute_output --partial 'COLLECTIONS'
rune -0 cscli hub list -o json rune -0 cscli hub list -o json
rune -0 jq -e '(.parsers | length == 1) and (.scenarios | length == 1)' <(output) rune -0 jq -e '(.parsers | length == 1) and (.scenarios | length == 1)' <(output)
rune -0 cscli hub list -o raw rune -0 cscli hub list -o raw
@ -55,8 +56,11 @@ teardown() {
refute_output --partial 'crowdsecurity/iptables' refute_output --partial 'crowdsecurity/iptables'
# all items # all items
mkdir -p "$CONFIG_DIR/contexts"
# there are no contexts yet, so we create a local one
touch "$CONFIG_DIR/contexts/mycontext.yaml"
rune -0 cscli hub list -a rune -0 cscli hub list -a
assert_output --regexp ".*PARSERS.*crowdsecurity/whitelists.*POSTOVERFLOWS.*SCENARIOS.*crowdsecurity/telnet-bf.*COLLECTIONS.*crowdsecurity/iptables.*" assert_output --regexp ".*PARSERS.*crowdsecurity/whitelists.*POSTOVERFLOWS.*SCENARIOS.*crowdsecurity/telnet-bf.*CONTEXTS.*mycontext.yaml.*COLLECTIONS.*crowdsecurity/iptables.*"
rune -0 cscli hub list -a -o json rune -0 cscli hub list -a -o json
rune -0 jq -e '(.parsers | length > 1) and (.scenarios | length > 1)' <(output) rune -0 jq -e '(.parsers | length > 1) and (.scenarios | length > 1)' <(output)
rune -0 cscli hub list -a -o raw rune -0 cscli hub list -a -o raw
@ -107,6 +111,8 @@ teardown() {
assert_stderr --partial "Upgraded 0 postoverflows" assert_stderr --partial "Upgraded 0 postoverflows"
assert_stderr --partial "Upgrading scenarios" assert_stderr --partial "Upgrading scenarios"
assert_stderr --partial "Upgraded 0 scenarios" assert_stderr --partial "Upgraded 0 scenarios"
assert_stderr --partial "Upgrading contexts"
assert_stderr --partial "Upgraded 0 contexts"
assert_stderr --partial "Upgrading collections" assert_stderr --partial "Upgrading collections"
assert_stderr --partial "Upgraded 0 collections" assert_stderr --partial "Upgraded 0 collections"
@ -134,10 +140,11 @@ teardown() {
assert_line "parsers" assert_line "parsers"
assert_line "postoverflows" assert_line "postoverflows"
assert_line "scenarios" assert_line "scenarios"
assert_line "contexts"
assert_line "collections" assert_line "collections"
rune -0 cscli hub types -o human rune -0 cscli hub types -o human
rune -0 yq -o json <(output) rune -0 yq -o json <(output)
assert_json '["parsers","postoverflows","scenarios","appsec-configs","appsec-rules","collections"]' assert_json '["parsers","postoverflows","scenarios","contexts","appsec-configs","appsec-rules","collections"]'
rune -0 cscli hub types -o json rune -0 cscli hub types -o json
assert_json '["parsers","postoverflows","scenarios","appsec-configs","appsec-rules","collections"]' assert_json '["parsers","postoverflows","scenarios","contexts","appsec-configs","appsec-rules","collections"]'
} }

View file

@ -247,12 +247,14 @@ hub_purge_all() {
"$CONFIG_DIR"/collections/* \ "$CONFIG_DIR"/collections/* \
"$CONFIG_DIR"/parsers/*/* \ "$CONFIG_DIR"/parsers/*/* \
"$CONFIG_DIR"/scenarios/* \ "$CONFIG_DIR"/scenarios/* \
"$CONFIG_DIR"/postoverflows/* "$CONFIG_DIR"/postoverflows/* \
"$CONFIG_DIR"/contexts/*
rm -rf \ rm -rf \
"$CONFIG_DIR"/hub/collections/* \ "$CONFIG_DIR"/hub/collections/* \
"$CONFIG_DIR"/hub/parsers/*/* \ "$CONFIG_DIR"/hub/parsers/*/* \
"$CONFIG_DIR"/hub/scenarios/* \ "$CONFIG_DIR"/hub/scenarios/* \
"$CONFIG_DIR"/hub/postoverflows/* "$CONFIG_DIR"/hub/postoverflows/* \
"$CONFIG_DIR"/hub/contexts/*
local DATA_DIR local DATA_DIR
DATA_DIR=$(config_get .config_paths.data_dir) DATA_DIR=$(config_get .config_paths.data_dir)
# should remove everything except the db (find $DATA_DIR -not -name "crowdsec.db*" -delete), # should remove everything except the db (find $DATA_DIR -not -name "crowdsec.db*" -delete),