Sebastien Blot 2 năm trước cách đây
mục cha
commit
1973aa1a56

+ 1 - 0
cmd/crowdsec-cli/main.go

@@ -254,6 +254,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
 	rootCmd.AddCommand(NewHubTestCmd())
 	rootCmd.AddCommand(NewHubTestCmd())
 	rootCmd.AddCommand(NewNotificationsCmd())
 	rootCmd.AddCommand(NewNotificationsCmd())
 	rootCmd.AddCommand(NewSupportCmd())
 	rootCmd.AddCommand(NewSupportCmd())
+	rootCmd.AddCommand(NewWafRulesCmd())
 
 
 	if fflag.CscliSetup.IsEnabled() {
 	if fflag.CscliSetup.IsEnabled() {
 		rootCmd.AddCommand(NewSetupCmd())
 		rootCmd.AddCommand(NewSetupCmd())

+ 2 - 1
cmd/crowdsec-cli/utils.go

@@ -137,6 +137,8 @@ func compInstalledItems(itemType string, args []string, toComplete string) ([]st
 		items, err = cwhub.GetInstalledPostOverflowsAsString()
 		items, err = cwhub.GetInstalledPostOverflowsAsString()
 	case cwhub.COLLECTIONS:
 	case cwhub.COLLECTIONS:
 		items, err = cwhub.GetInstalledCollectionsAsString()
 		items, err = cwhub.GetInstalledCollectionsAsString()
+	case cwhub.WAF_RULES:
+		items, err = cwhub.GetInstalledWafRulesAsString()
 	default:
 	default:
 		return nil, cobra.ShellCompDirectiveDefault
 		return nil, cobra.ShellCompDirectiveDefault
 	}
 	}
@@ -746,7 +748,6 @@ func getDBClient() (*database.Client, error) {
 	return ret, nil
 	return ret, nil
 }
 }
 
 
-
 func removeFromSlice(val string, slice []string) []string {
 func removeFromSlice(val string, slice []string) []string {
 	var i int
 	var i int
 	var value string
 	var value string

+ 196 - 0
cmd/crowdsec-cli/waf_rules.go

@@ -0,0 +1,196 @@
+package main
+
+import (
+	"fmt"
+
+	"github.com/fatih/color"
+	log "github.com/sirupsen/logrus"
+	"github.com/spf13/cobra"
+
+	"github.com/crowdsecurity/crowdsec/pkg/cwhub"
+)
+
+func NewWafRulesCmd() *cobra.Command {
+	var cmdWafRules = &cobra.Command{
+		Use:   "waf-rules [action] [config]",
+		Short: "Install/Remove/Upgrade/Inspect waf-rule(s) from hub",
+		Example: `cscli waf-rules install crowdsecurity/core-rule-set
+cscli waf-rules inspect crowdsecurity/core-rule-set
+cscli waf-rules upgrade crowdsecurity/core-rule-set
+cscli waf-rules list
+cscli waf-rules remove crowdsecurity/core-rule-set
+`,
+		Args:              cobra.MinimumNArgs(1),
+		Aliases:           []string{"waf-rule"},
+		DisableAutoGenTag: true,
+		PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
+			if err := csConfig.LoadHub(); err != nil {
+				log.Fatal(err)
+			}
+			if csConfig.Hub == nil {
+				return fmt.Errorf("you must configure cli before interacting with hub")
+			}
+
+			if err := cwhub.SetHubBranch(); err != nil {
+				return fmt.Errorf("error while setting hub branch: %s", err)
+			}
+
+			if err := cwhub.GetHubIdx(csConfig.Hub); err != nil {
+				log.Info("Run 'sudo cscli hub update' to get the hub index")
+				log.Fatalf("Failed to get Hub index : %v", err)
+			}
+			return nil
+		},
+		PersistentPostRun: func(cmd *cobra.Command, args []string) {
+			if cmd.Name() == "inspect" || cmd.Name() == "list" {
+				return
+			}
+			log.Infof(ReloadMessage())
+		},
+	}
+
+	cmdWafRules.AddCommand(NewWafRulesInstallCmd())
+	cmdWafRules.AddCommand(NewWafRulesRemoveCmd())
+	cmdWafRules.AddCommand(NewWafRulesUpgradeCmd())
+	cmdWafRules.AddCommand(NewWafRulesInspectCmd())
+	cmdWafRules.AddCommand(NewWafRulesListCmd())
+
+	return cmdWafRules
+}
+
+func NewWafRulesInstallCmd() *cobra.Command {
+	var ignoreError bool
+
+	var cmdWafRulesInstall = &cobra.Command{
+		Use:               "install [config]",
+		Short:             "Install given waf-rule(s)",
+		Long:              `Fetch and install given waf-rule(s) from hub`,
+		Example:           `cscli waf-rules install crowdsec/xxx crowdsec/xyz`,
+		Args:              cobra.MinimumNArgs(1),
+		DisableAutoGenTag: true,
+		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+			return compAllItems(cwhub.WAF_RULES, args, toComplete)
+		},
+		Run: func(cmd *cobra.Command, args []string) {
+			for _, name := range args {
+				t := cwhub.GetItem(cwhub.WAF_RULES, name)
+				if t == nil {
+					nearestItem, score := GetDistance(cwhub.WAF_RULES, name)
+					Suggest(cwhub.WAF_RULES, name, nearestItem.Name, score, ignoreError)
+					continue
+				}
+				if err := cwhub.InstallItem(csConfig, name, cwhub.WAF_RULES, forceAction, downloadOnly); err != nil {
+					if ignoreError {
+						log.Errorf("Error while installing '%s': %s", name, err)
+					} else {
+						log.Fatalf("Error while installing '%s': %s", name, err)
+					}
+				}
+			}
+		},
+	}
+	cmdWafRulesInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable")
+	cmdWafRulesInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files")
+	cmdWafRulesInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple waf rules")
+
+	return cmdWafRulesInstall
+}
+
+func NewWafRulesRemoveCmd() *cobra.Command {
+	var cmdWafRulesRemove = &cobra.Command{
+		Use:               "remove [config]",
+		Short:             "Remove given waf-rule(s)",
+		Long:              `Remove given waf-rule(s) from hub`,
+		Aliases:           []string{"delete"},
+		Example:           `cscli waf-rules remove crowdsec/xxx crowdsec/xyz`,
+		DisableAutoGenTag: true,
+		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+			return compInstalledItems(cwhub.WAF_RULES, args, toComplete)
+		},
+		Run: func(cmd *cobra.Command, args []string) {
+			if all {
+				cwhub.RemoveMany(csConfig, cwhub.WAF_RULES, "", all, purge, forceAction)
+				return
+			}
+
+			if len(args) == 0 {
+				log.Fatalf("Specify at least one waf rule to remove or '--all' flag.")
+			}
+
+			for _, name := range args {
+				cwhub.RemoveMany(csConfig, cwhub.WAF_RULES, name, all, purge, forceAction)
+			}
+		},
+	}
+	cmdWafRulesRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too")
+	cmdWafRulesRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files")
+	cmdWafRulesRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the waf rules")
+
+	return cmdWafRulesRemove
+}
+
+func NewWafRulesUpgradeCmd() *cobra.Command {
+	var cmdWafRulesUpgrade = &cobra.Command{
+		Use:               "upgrade [config]",
+		Short:             "Upgrade given waf-rule(s)",
+		Long:              `Fetch and upgrade given waf-rule(s) from hub`,
+		Example:           `cscli waf-rules upgrade crowdsec/xxx crowdsec/xyz`,
+		DisableAutoGenTag: true,
+		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+			return compInstalledItems(cwhub.WAF_RULES, args, toComplete)
+		},
+		Run: func(cmd *cobra.Command, args []string) {
+			if all {
+				cwhub.UpgradeConfig(csConfig, cwhub.WAF_RULES, "", forceAction)
+			} else {
+				if len(args) == 0 {
+					log.Fatalf("no target waf rule to upgrade")
+				}
+				for _, name := range args {
+					cwhub.UpgradeConfig(csConfig, cwhub.WAF_RULES, name, forceAction)
+				}
+			}
+		},
+	}
+	cmdWafRulesUpgrade.PersistentFlags().BoolVar(&all, "all", false, "Upgrade all the waf rules")
+	cmdWafRulesUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files")
+
+	return cmdWafRulesUpgrade
+}
+
+func NewWafRulesInspectCmd() *cobra.Command {
+	var cmdWafRulesInspect = &cobra.Command{
+		Use:               "inspect [name]",
+		Short:             "Inspect given waf rule",
+		Long:              `Inspect given waf rule`,
+		Example:           `cscli waf-rules inspect crowdsec/xxx`,
+		DisableAutoGenTag: true,
+		Args:              cobra.MinimumNArgs(1),
+		ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
+			return compInstalledItems(cwhub.WAF_RULES, args, toComplete)
+		},
+		Run: func(cmd *cobra.Command, args []string) {
+			InspectItem(args[0], cwhub.WAF_RULES)
+		},
+	}
+	cmdWafRulesInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url")
+
+	return cmdWafRulesInspect
+}
+
+func NewWafRulesListCmd() *cobra.Command {
+	var cmdWafRulesList = &cobra.Command{
+		Use:   "list [name]",
+		Short: "List all waf rules or given one",
+		Long:  `List all waf rules or given one`,
+		Example: `cscli waf-rules list
+cscli waf-rules list crowdsecurity/xxx`,
+		DisableAutoGenTag: true,
+		Run: func(cmd *cobra.Command, args []string) {
+			ListItems(color.Output, []string{cwhub.WAF_RULES}, args, false, true, all)
+		},
+	}
+	cmdWafRulesList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well")
+
+	return cmdWafRulesList
+}

+ 29 - 2
pkg/cwhub/cwhub.go

@@ -201,8 +201,8 @@ func AddItem(itemType string, item Item) error {
 }
 }
 
 
 func DisplaySummary() {
 func DisplaySummary() {
-	log.Printf("Loaded %d collecs, %d parsers, %d scenarios, %d post-overflow parsers", len(hubIdx[COLLECTIONS]),
-		len(hubIdx[PARSERS]), len(hubIdx[SCENARIOS]), len(hubIdx[PARSERS_OVFLW]))
+	log.Printf("Loaded %d collecs, %d parsers, %d scenarios, %d post-overflow parsers, %d waf rules", len(hubIdx[COLLECTIONS]),
+		len(hubIdx[PARSERS]), len(hubIdx[SCENARIOS]), len(hubIdx[PARSERS_OVFLW]), len(hubIdx[WAF_RULES]))
 	if skippedLocal > 0 || skippedTainted > 0 {
 	if skippedLocal > 0 || skippedTainted > 0 {
 		log.Printf("unmanaged items : %d local, %d tainted", skippedLocal, skippedTainted)
 		log.Printf("unmanaged items : %d local, %d tainted", skippedLocal, skippedTainted)
 	}
 	}
@@ -343,6 +343,33 @@ func GetInstalledCollections() ([]Item, error) {
 	return retItems, nil
 	return retItems, nil
 }
 }
 
 
+func GetInstalledWafRules() ([]Item, error) {
+	var retItems []Item
+
+	if _, ok := hubIdx[WAF_RULES]; !ok {
+		return nil, fmt.Errorf("no waf rules in hubIdx")
+	}
+	for _, item := range hubIdx[WAF_RULES] {
+		if item.Installed {
+			retItems = append(retItems, item)
+		}
+	}
+	return retItems, nil
+}
+
+func GetInstalledWafRulesAsString() ([]string, error) {
+	var retStr []string
+
+	items, err := GetInstalledWafRules()
+	if err != nil {
+		return nil, errors.Wrap(err, "while fetching waf rules")
+	}
+	for _, it := range items {
+		retStr = append(retStr, it.Name)
+	}
+	return retStr, nil
+}
+
 // Returns a list of entries for packages : name, status, local_path, local_version, utf8_status (fancy)
 // Returns a list of entries for packages : name, status, local_path, local_version, utf8_status (fancy)
 func GetHubStatusForItemType(itemType string, name string, all bool) []ItemHubStatus {
 func GetHubStatusForItemType(itemType string, name string, all bool) []ItemHubStatus {
 	if _, ok := hubIdx[itemType]; !ok {
 	if _, ok := hubIdx[itemType]; !ok {

+ 2 - 2
pkg/cwhub/loader.go

@@ -102,7 +102,7 @@ func parser_visit(path string, f os.DirEntry, err error) error {
 		when the collection is installed, both files are created
 		when the collection is installed, both files are created
 	*/
 	*/
 	//non symlinks are local user files or hub files
 	//non symlinks are local user files or hub files
-	if f.Type() & os.ModeSymlink == 0 {
+	if f.Type()&os.ModeSymlink == 0 {
 		local = true
 		local = true
 		log.Tracef("%s isn't a symlink", path)
 		log.Tracef("%s isn't a symlink", path)
 	} else {
 	} else {
@@ -406,7 +406,7 @@ func LoadPkgIndex(buff []byte) (map[string]map[string]Item, error) {
 			/*if it's a collection, check its sub-items are present*/
 			/*if it's a collection, check its sub-items are present*/
 			//XX should be done later
 			//XX should be done later
 			if itemType == COLLECTIONS {
 			if itemType == COLLECTIONS {
-				var tmp = [][]string{item.Parsers, item.PostOverflows, item.Scenarios, item.Collections}
+				var tmp = [][]string{item.Parsers, item.PostOverflows, item.Scenarios, item.Collections, item.WafRules}
 				for idx, ptr := range tmp {
 				for idx, ptr := range tmp {
 					ptrtype := ItemTypes[idx]
 					ptrtype := ItemTypes[idx]
 					for _, p := range ptr {
 					for _, p := range ptr {