|
@@ -2,17 +2,70 @@ package cwhub
|
|
|
|
|
|
import (
|
|
|
"fmt"
|
|
|
+ "path/filepath"
|
|
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
|
|
+ "github.com/crowdsecurity/crowdsec/pkg/cwversion"
|
|
|
"github.com/enescakir/emoji"
|
|
|
+ "github.com/pkg/errors"
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
+ "golang.org/x/mod/semver"
|
|
|
)
|
|
|
|
|
|
+// pick a hub branch corresponding to the current crowdsec version.
|
|
|
+func chooseHubBranch() (string, error) {
|
|
|
+ latest, err := cwversion.Latest()
|
|
|
+ if err != nil {
|
|
|
+ return "master", err
|
|
|
+ }
|
|
|
+
|
|
|
+ csVersion := cwversion.VersionStrip()
|
|
|
+ if csVersion == latest {
|
|
|
+ return "master", nil
|
|
|
+ }
|
|
|
+
|
|
|
+ // if current version is greater than the latest we are in pre-release
|
|
|
+ if semver.Compare(csVersion, latest) == 1 {
|
|
|
+ log.Debugf("Your current crowdsec version seems to be a pre-release (%s)", csVersion)
|
|
|
+ return "master", nil
|
|
|
+ }
|
|
|
+
|
|
|
+ if csVersion == "" {
|
|
|
+ log.Warningf("Crowdsec version is not set, using master branch for the hub")
|
|
|
+ return "master", nil
|
|
|
+ }
|
|
|
+
|
|
|
+ log.Warnf("Crowdsec is not the latest version. "+
|
|
|
+ "Current version is '%s' and the latest stable version is '%s'. Please update it!",
|
|
|
+ csVersion, latest)
|
|
|
+ log.Warnf("As a result, you will not be able to use parsers/scenarios/collections "+
|
|
|
+ "added to Crowdsec Hub after CrowdSec %s", latest)
|
|
|
+ return csVersion, nil
|
|
|
+}
|
|
|
+
|
|
|
+// SetHubBranch sets the package variable that points to the hub branch.
|
|
|
+func SetHubBranch() error {
|
|
|
+ // a branch is already set, or specified from the flags
|
|
|
+ if HubBranch != "" {
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+
|
|
|
+ // use the branch corresponding to the crowdsec version
|
|
|
+ branch, err := chooseHubBranch()
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+ HubBranch = branch
|
|
|
+ log.Debugf("Using branch '%s' for the hub", HubBranch)
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
func InstallItem(csConfig *csconfig.Config, name string, obtype string, force bool, downloadOnly bool) error {
|
|
|
it := GetItem(obtype, name)
|
|
|
if it == nil {
|
|
|
- return fmt.Errorf("unable to retrieve item : %s", name)
|
|
|
+ return fmt.Errorf("unable to retrieve item: %s", name)
|
|
|
}
|
|
|
+
|
|
|
item := *it
|
|
|
if downloadOnly && item.Downloaded && item.UpToDate {
|
|
|
log.Warningf("%s is already downloaded and up-to-date", item.Name)
|
|
@@ -20,69 +73,85 @@ func InstallItem(csConfig *csconfig.Config, name string, obtype string, force bo
|
|
|
return nil
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
item, err := DownloadLatest(csConfig.Hub, item, force, true)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("error while downloading %s : %v", item.Name, err)
|
|
|
+ return errors.Wrapf(err, "while downloading %s", item.Name)
|
|
|
}
|
|
|
+
|
|
|
if err := AddItem(obtype, item); err != nil {
|
|
|
- return fmt.Errorf("error while adding %s : %v", item.Name, err)
|
|
|
+ return errors.Wrapf(err, "while adding %s", item.Name)
|
|
|
}
|
|
|
+
|
|
|
if downloadOnly {
|
|
|
- log.Infof("Downloaded %s to %s", item.Name, csConfig.Hub.HubDir+"/"+item.RemotePath)
|
|
|
+ log.Infof("Downloaded %s to %s", item.Name, filepath.Join(csConfig.Hub.HubDir, item.RemotePath))
|
|
|
return nil
|
|
|
}
|
|
|
+
|
|
|
item, err = EnableItem(csConfig.Hub, item)
|
|
|
if err != nil {
|
|
|
- return fmt.Errorf("error while enabling %s : %v.", item.Name, err)
|
|
|
+ return errors.Wrapf(err, "while enabling %s", item.Name)
|
|
|
}
|
|
|
+
|
|
|
if err := AddItem(obtype, item); err != nil {
|
|
|
- return fmt.Errorf("error while adding %s : %v", item.Name, err)
|
|
|
+ return errors.Wrapf(err, "while adding %s", item.Name)
|
|
|
}
|
|
|
+
|
|
|
log.Infof("Enabled %s", item.Name)
|
|
|
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
+// XXX this must return errors instead of log.Fatal
|
|
|
func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all bool, purge bool, forceAction bool) {
|
|
|
- var err error
|
|
|
- var disabled int
|
|
|
+ var (
|
|
|
+ err error
|
|
|
+ disabled int
|
|
|
+ )
|
|
|
+
|
|
|
if name != "" {
|
|
|
it := GetItem(itemType, name)
|
|
|
if it == nil {
|
|
|
log.Fatalf("unable to retrieve: %s", name)
|
|
|
}
|
|
|
+
|
|
|
item := *it
|
|
|
item, err = DisableItem(csConfig.Hub, item, purge, forceAction)
|
|
|
if err != nil {
|
|
|
log.Fatalf("unable to disable %s : %v", item.Name, err)
|
|
|
}
|
|
|
+
|
|
|
if err := AddItem(itemType, item); err != nil {
|
|
|
log.Fatalf("unable to add %s: %v", item.Name, err)
|
|
|
}
|
|
|
return
|
|
|
- } else if name == "" && all {
|
|
|
- for _, v := range GetItemMap(itemType) {
|
|
|
- v, err = DisableItem(csConfig.Hub, v, purge, forceAction)
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("unable to disable %s : %v", v.Name, err)
|
|
|
- }
|
|
|
- if err := AddItem(itemType, v); err != nil {
|
|
|
- log.Fatalf("unable to add %s: %v", v.Name, err)
|
|
|
- }
|
|
|
- disabled++
|
|
|
- }
|
|
|
}
|
|
|
- if name != "" && !all {
|
|
|
- log.Errorf("%s not found", name)
|
|
|
- return
|
|
|
+
|
|
|
+ if !all {
|
|
|
+ log.Fatal("removing item: no item specified")
|
|
|
+ }
|
|
|
+
|
|
|
+ // remove all
|
|
|
+ for _, v := range GetItemMap(itemType) {
|
|
|
+ v, err = DisableItem(csConfig.Hub, v, purge, forceAction)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("unable to disable %s : %v", v.Name, err)
|
|
|
+ }
|
|
|
+
|
|
|
+ if err := AddItem(itemType, v); err != nil {
|
|
|
+ log.Fatalf("unable to add %s: %v", v.Name, err)
|
|
|
+ }
|
|
|
+ disabled++
|
|
|
}
|
|
|
log.Infof("Disabled %d items", disabled)
|
|
|
}
|
|
|
|
|
|
func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, force bool) {
|
|
|
- var err error
|
|
|
- var updated int
|
|
|
- var found bool
|
|
|
+ var (
|
|
|
+ err error
|
|
|
+ updated int
|
|
|
+ found bool
|
|
|
+ )
|
|
|
|
|
|
for _, v := range GetItemMap(itemType) {
|
|
|
if name != "" && name != v.Name {
|
|
@@ -100,6 +169,7 @@ func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, forc
|
|
|
}
|
|
|
|
|
|
found = true
|
|
|
+
|
|
|
if v.UpToDate {
|
|
|
log.Infof("%s : up-to-date", v.Name)
|
|
|
|
|
@@ -111,10 +181,12 @@ func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, forc
|
|
|
continue
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
v, err = DownloadLatest(csConfig.Hub, v, force, true)
|
|
|
if err != nil {
|
|
|
log.Fatalf("%s : download failed : %v", v.Name, err)
|
|
|
}
|
|
|
+
|
|
|
if !v.UpToDate {
|
|
|
if v.Tainted {
|
|
|
log.Infof("%v %s is tainted, --force to overwrite", emoji.Warning, v.Name)
|
|
@@ -125,10 +197,12 @@ func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, forc
|
|
|
log.Infof("%v %s : updated", emoji.Package, v.Name)
|
|
|
updated++
|
|
|
}
|
|
|
+
|
|
|
if err := AddItem(itemType, v); err != nil {
|
|
|
log.Fatalf("unable to add %s: %v", v.Name, err)
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
if !found && name == "" {
|
|
|
log.Infof("No %s installed, nothing to upgrade", itemType)
|
|
|
} else if !found {
|
|
@@ -142,5 +216,4 @@ func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, forc
|
|
|
} else if updated != 0 {
|
|
|
log.Infof("Upgraded %d items", updated)
|
|
|
}
|
|
|
-
|
|
|
}
|