浏览代码

`cscli` hub mgmt improvements (#710)

* avoid this confusing behaviour where 'cscli parsers/scenarios/... upgrade' won't tell a thing if no arguments are given (and won't do anything neither)

* avoid repeating warnings about available update to the user
Thibault "bui" Koechlin 4 年之前
父节点
当前提交
20ef67a699

+ 3 - 0
cmd/crowdsec-cli/collections.go

@@ -98,6 +98,9 @@ func NewCollectionsCmd() *cobra.Command {
 			if all {
 				UpgradeConfig(cwhub.COLLECTIONS, "", forceAction)
 			} else {
+				if len(args) == 0 {
+					log.Fatalf("no target collection to upgrade")
+				}
 				for _, name := range args {
 					UpgradeConfig(cwhub.COLLECTIONS, name, forceAction)
 				}

+ 12 - 1
cmd/crowdsec-cli/hub.go

@@ -40,6 +40,7 @@ cscli hub update # Download list of available configurations from the hub
 		Short: "List installed configs",
 		Args:  cobra.ExactArgs(0),
 		Run: func(cmd *cobra.Command, args []string) {
+
 			if err := csConfig.LoadHub(); err != nil {
 				log.Fatalf(err.Error())
 			}
@@ -47,7 +48,11 @@ cscli hub update # Download list of available configurations from the hub
 				log.Fatalf("Failed to get Hub index : %v", err)
 				log.Infoln("Run 'sudo cscli hub update' to get the hub index")
 			}
-
+			//use LocalSync to get warnings about tainted / outdated items
+			_, warn := cwhub.LocalSync(csConfig.Hub)
+			for _, v := range warn {
+				log.Info(v)
+			}
 			cwhub.DisplaySummary()
 			log.Printf("PARSERS:")
 			ListItem(cwhub.PARSERS, args)
@@ -86,6 +91,11 @@ Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.inde
 			if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
 				log.Fatalf("Failed to get Hub index : %v", err)
 			}
+			//use LocalSync to get warnings about tainted / outdated items
+			_, warn := cwhub.LocalSync(csConfig.Hub)
+			for _, v := range warn {
+				log.Info(v)
+			}
 		},
 	}
 	cmdHub.AddCommand(cmdHubUpdate)
@@ -115,6 +125,7 @@ Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if
 				log.Fatalf("Failed to get Hub index : %v", err)
 				log.Infoln("Run 'sudo cscli hub update' to get the hub index")
 			}
+
 			log.Infof("Upgrading collections")
 			UpgradeConfig(cwhub.COLLECTIONS, "", forceAction)
 			log.Infof("Upgrading parsers")

+ 3 - 0
cmd/crowdsec-cli/parsers.go

@@ -93,6 +93,9 @@ cscli parsers remove crowdsecurity/sshd-logs
 			if all {
 				UpgradeConfig(cwhub.PARSERS, "", forceAction)
 			} else {
+				if len(args) == 0 {
+					log.Fatalf("no target parser to upgrade")
+				}
 				for _, name := range args {
 					UpgradeConfig(cwhub.PARSERS, name, forceAction)
 				}

+ 3 - 0
cmd/crowdsec-cli/postoverflows.go

@@ -92,6 +92,9 @@ func NewPostOverflowsCmd() *cobra.Command {
 			if all {
 				UpgradeConfig(cwhub.PARSERS_OVFLW, "", forceAction)
 			} else {
+				if len(args) == 0 {
+					log.Fatalf("no target postoverflow to upgrade")
+				}
 				for _, name := range args {
 					UpgradeConfig(cwhub.PARSERS_OVFLW, name, forceAction)
 				}

+ 3 - 0
cmd/crowdsec-cli/scenarios.go

@@ -93,6 +93,9 @@ cscli scenarios remove crowdsecurity/ssh-bf
 			if all {
 				UpgradeConfig(cwhub.SCENARIOS, "", forceAction)
 			} else {
+				if len(args) == 0 {
+					log.Fatalf("no target scenario to upgrade")
+				}
 				for _, name := range args {
 					UpgradeConfig(cwhub.SCENARIOS, name, forceAction)
 				}

+ 6 - 0
pkg/cwhub/cwhub.go

@@ -12,6 +12,7 @@ import (
 
 	"github.com/enescakir/emoji"
 	"github.com/pkg/errors"
+	"golang.org/x/mod/semver"
 
 	log "github.com/sirupsen/logrus"
 )
@@ -78,6 +79,11 @@ var skippedTainted = 0
 var ReferenceMissingError = errors.New("Reference(s) missing in collection")
 var MissingHubIndex = errors.New("hub index can't be found")
 
+//GetVersionStatus : semver requires 'v' prefix
+func GetVersionStatus(v *Item) int {
+	return semver.Compare("v"+v.Version, "v"+v.LocalVersion)
+}
+
 // calculate sha256 of a file
 func getSHA256(filepath string) (string, error) {
 	/* Digest of file */

+ 8 - 8
pkg/cwhub/cwhub_test.go

@@ -193,7 +193,7 @@ func testInstallItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 	if err != nil {
 		t.Fatalf("error while downloading %s : %v", item.Name, err)
 	}
-	if err := LocalSync(cfg); err != nil {
+	if err, _ := LocalSync(cfg); err != nil {
 		t.Fatalf("taint: failed to run localSync : %s", err)
 	}
 	if !hubIdx[item.Type][item.Name].UpToDate {
@@ -210,7 +210,7 @@ func testInstallItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 	if err != nil {
 		t.Fatalf("error while enabled %s : %v.", item.Name, err)
 	}
-	if err := LocalSync(cfg); err != nil {
+	if err, _ := LocalSync(cfg); err != nil {
 		t.Fatalf("taint: failed to run localSync : %s", err)
 	}
 	if !hubIdx[item.Type][item.Name].Installed {
@@ -232,7 +232,7 @@ func testTaintItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 	}
 	f.Close()
 	//Local sync and check status
-	if err := LocalSync(cfg); err != nil {
+	if err, _ := LocalSync(cfg); err != nil {
 		t.Fatalf("taint: failed to run localSync : %s", err)
 	}
 	if !hubIdx[item.Type][item.Name].Tainted {
@@ -251,7 +251,7 @@ func testUpdateItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 		t.Fatalf("failed to update %s : %s", item.Name, err)
 	}
 	//Local sync and check status
-	if err := LocalSync(cfg); err != nil {
+	if err, _ := LocalSync(cfg); err != nil {
 		t.Fatalf("failed to run localSync : %s", err)
 	}
 	if !hubIdx[item.Type][item.Name].UpToDate {
@@ -272,8 +272,8 @@ func testDisableItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 		t.Fatalf("failed to disable item : %v", err)
 	}
 	//Local sync and check status
-	if err := LocalSync(cfg); err != nil {
-		t.Fatalf("failed to run localSync : %s", err)
+	if err, warns := LocalSync(cfg); err != nil || len(warns) > 0 {
+		t.Fatalf("failed to run localSync : %s (%+v)", err, warns)
 	}
 	if hubIdx[item.Type][item.Name].Tainted {
 		t.Fatalf("disable: %s should not be tainted anymore", item.Name)
@@ -290,8 +290,8 @@ func testDisableItem(cfg *csconfig.Hub, t *testing.T, item Item) {
 		t.Fatalf("failed to purge item : %v", err)
 	}
 	//Local sync and check status
-	if err := LocalSync(cfg); err != nil {
-		t.Fatalf("failed to run localSync : %s", err)
+	if err, warns := LocalSync(cfg); err != nil || len(warns) > 0 {
+		t.Fatalf("failed to run localSync : %s (%+v)", err, warns)
 	}
 	if hubIdx[item.Type][item.Name].Installed {
 		t.Fatalf("disable: %s should not be installed anymore", item.Name)

+ 1 - 1
pkg/cwhub/download.go

@@ -35,7 +35,7 @@ func UpdateHubIdx(hub *csconfig.Hub) error {
 		}
 	}
 	hubIdx = ret
-	if err := LocalSync(hub); err != nil {
+	if err, _ := LocalSync(hub); err != nil {
 		return errors.Wrap(err, "failed to sync")
 	}
 	return nil

+ 35 - 16
pkg/cwhub/loader.go

@@ -8,6 +8,7 @@ import (
 	"sort"
 
 	"github.com/pkg/errors"
+	"golang.org/x/mod/semver"
 
 	//"log"
 
@@ -101,7 +102,6 @@ func parser_visit(path string, f os.FileInfo, err error) error {
 	//non symlinks are local user files or hub files
 	if f.Mode()&os.ModeSymlink == 0 {
 		local = true
-		skippedLocal++
 		log.Tracef("%s isn't a symlink", path)
 	} else {
 		hubpath, err = os.Readlink(path)
@@ -243,6 +243,12 @@ func parser_visit(path string, f os.FileInfo, err error) error {
 }
 
 func CollecDepsCheck(v *Item) error {
+
+	if GetVersionStatus(v) != 0 { //not up-to-date
+		log.Debugf("%s dependencies not checked : not up-to-date", v.Name)
+		return nil
+	}
+
 	/*if it's a collection, ensure all the items are installed, or tag it as tainted*/
 	if v.Type == COLLECTIONS {
 		log.Tracef("checking submembers of %s installed:%t", v.Name, v.Installed)
@@ -294,10 +300,11 @@ func CollecDepsCheck(v *Item) error {
 	return nil
 }
 
-func SyncDir(hub *csconfig.Hub, dir string) error {
+func SyncDir(hub *csconfig.Hub, dir string) (error, []string) {
 	hubdir = hub.HubDir
 	installdir = hub.ConfigDir
 	indexpath = hub.HubIndexFile
+	warnings := []string{}
 
 	/*For each, scan PARSERS, PARSERS_OVFLW, SCENARIOS and COLLECTIONS last*/
 	for _, scan := range ItemTypes {
@@ -307,33 +314,44 @@ func SyncDir(hub *csconfig.Hub, dir string) error {
 		}
 		err = filepath.Walk(cpath, parser_visit)
 		if err != nil {
-			return err
+			return err, warnings
 		}
 
 	}
 
 	for k, v := range hubIdx[COLLECTIONS] {
-		if err := CollecDepsCheck(&v); err != nil {
-			log.Infof("dependency issue %s : %s", v.Name, err)
+		if v.Installed {
+			versStat := GetVersionStatus(&v)
+			if versStat == 0 { //latest
+				if err := CollecDepsCheck(&v); err != nil {
+					warnings = append(warnings, fmt.Sprintf("dependency of %s : %s", v.Name, err))
+					hubIdx[COLLECTIONS][k] = v
+				}
+			} else if versStat == 1 { //not up-to-date
+				warnings = append(warnings, fmt.Sprintf("update for collection %s available (currently:%s, latest:%s)", v.Name, v.LocalVersion, v.Version))
+			} else { //version is higher than the highest available from hub?
+				warnings = append(warnings, fmt.Sprintf("collection %s is in the future (currently:%s, latest:%s)", v.Name, v.LocalVersion, v.Version))
+			}
+			log.Debugf("installed (%s) - status:%d | installed:%s | latest : %s | full : %+v", v.Name, semver.Compare("v"+v.Version, "v"+v.LocalVersion), v.LocalVersion, v.Version, v.Versions)
 		}
-		hubIdx[COLLECTIONS][k] = v
 	}
-	return nil
+	return nil, warnings
 }
 
 /* Updates the infos from HubInit() with the local state */
-func LocalSync(hub *csconfig.Hub) error {
+func LocalSync(hub *csconfig.Hub) (error, []string) {
 	skippedLocal = 0
 	skippedTainted = 0
 
-	for _, dir := range []string{hub.ConfigDir, hub.HubDir} {
-		log.Debugf("scanning %s", dir)
-		if err := SyncDir(hub, dir); err != nil {
-			return fmt.Errorf("failed to scan %s : %s", dir, err)
-		}
+	err, warnings := SyncDir(hub, hub.ConfigDir)
+	if err != nil {
+		return fmt.Errorf("failed to scan %s : %s", hub.ConfigDir, err), warnings
 	}
-
-	return nil
+	err, _ = SyncDir(hub, hub.HubDir)
+	if err != nil {
+		return fmt.Errorf("failed to scan %s : %s", hub.HubDir, err), warnings
+	}
+	return nil, warnings
 }
 
 func GetHubIdx(hub *csconfig.Hub) error {
@@ -353,7 +371,8 @@ func GetHubIdx(hub *csconfig.Hub) error {
 		return err
 	}
 	hubIdx = ret
-	if err := LocalSync(hub); err != nil {
+	err, _ = LocalSync(hub)
+	if err != nil {
 		log.Fatalf("Failed to sync Hub index with local deployment : %v", err)
 	}
 	return nil