Refact cscli hub/item commands (#2536)

* log.Fatal -> fmt.Errorf
* lint cmd/crowdsec-cli hub items and split collection commands
* cscli collections: add examples
* cscli parsers: avoid globals
* cscli scenarios: avoid globals
* cscli collections, postoverflows: avoid globals
* cscli hub: avoid globals
* remove unused globals
This commit is contained in:
mmetc 2023-10-12 14:53:17 +02:00 committed by Marco Mariani
parent 7db5bf8979
commit 734ba46e6a
11 changed files with 845 additions and 409 deletions

View file

@ -12,11 +12,15 @@ import (
) )
func NewCollectionsCmd() *cobra.Command { func NewCollectionsCmd() *cobra.Command {
var cmdCollections = &cobra.Command{ cmdCollections := &cobra.Command{
Use: "collections [action]", Use: "collections [action]",
Short: "Manage collections from hub", Short: "Install/Remove/Upgrade/Inspect collections from the CrowdSec Hub.",
Long: `Install/Remove/Upgrade/Inspect collections from the CrowdSec Hub.`, Example: `cscli collections install crowdsec/xxx crowdsec/xyz
/*TBD fix help*/ cscli collections inspect crowdsec/xxx crowdsec/xyz
cscli collections upgrade crowdsec/xxx crowdsec/xyz
cscli collections list
cscli collections remove crowdsec/xxx crowdsec/xyz
`,
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
Aliases: []string{"collection"}, Aliases: []string{"collection"},
DisableAutoGenTag: true, DisableAutoGenTag: true,
@ -35,54 +39,99 @@ func NewCollectionsCmd() *cobra.Command {
}, },
} }
var ignoreError bool cmdCollections.AddCommand(NewCollectionsInstallCmd())
cmdCollections.AddCommand(NewCollectionsRemoveCmd())
cmdCollections.AddCommand(NewCollectionsUpgradeCmd())
cmdCollections.AddCommand(NewCollectionsInspectCmd())
cmdCollections.AddCommand(NewCollectionsListCmd())
return cmdCollections
}
func runCollectionsInstall(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
downloadOnly, err := flags.GetBool("download-only")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
ignoreError, err := flags.GetBool("ignore")
if err != nil {
return err
}
var cmdCollectionsInstall = &cobra.Command{
Use: "install collection",
Short: "Install given collection(s)",
Long: `Fetch and install given collection(s) from hub`,
Example: `cscli collections install crowdsec/xxx crowdsec/xyz`,
Args: cobra.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compAllItems(cwhub.COLLECTIONS, args, toComplete)
},
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
for _, name := range args { for _, name := range args {
t := cwhub.GetItem(cwhub.COLLECTIONS, name) t := cwhub.GetItem(cwhub.COLLECTIONS, name)
if t == nil { if t == nil {
nearestItem, score := GetDistance(cwhub.COLLECTIONS, name) nearestItem, score := GetDistance(cwhub.COLLECTIONS, name)
Suggest(cwhub.COLLECTIONS, name, nearestItem.Name, score, ignoreError) Suggest(cwhub.COLLECTIONS, name, nearestItem.Name, score, ignoreError)
continue continue
} }
if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, forceAction, downloadOnly); err != nil {
if err := cwhub.InstallItem(csConfig, name, cwhub.COLLECTIONS, force, downloadOnly); err != nil {
if !ignoreError { if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err) return fmt.Errorf("error while installing '%s': %w", name, err)
} }
log.Errorf("Error while installing '%s': %s", name, err) log.Errorf("Error while installing '%s': %s", name, err)
} }
} }
return nil
},
}
cmdCollectionsInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable")
cmdCollectionsInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files")
cmdCollectionsInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple collections")
cmdCollections.AddCommand(cmdCollectionsInstall)
var cmdCollectionsRemove = &cobra.Command{ return nil
Use: "remove collection", }
Short: "Remove given collection(s)",
Long: `Remove given collection(s) from hub`, func NewCollectionsInstallCmd() *cobra.Command {
Example: `cscli collections remove crowdsec/xxx crowdsec/xyz`, cmdCollectionsInstall := &cobra.Command{
Aliases: []string{"delete"}, Use: "install collection",
Short: "Install given collection(s)",
Long: `Fetch and install given collection(s) from hub`,
Example: `cscli collections install crowdsec/xxx crowdsec/xyz`,
Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true, DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) return compAllItems(cwhub.COLLECTIONS, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runCollectionsInstall,
}
flags := cmdCollectionsInstall.Flags()
flags.BoolP("download-only", "d", false, "Only download packages, don't enable")
flags.Bool("force", false, "Force install : Overwrite tainted and outdated files")
flags.Bool("ignore", false, "Ignore errors when installing multiple collections")
return cmdCollectionsInstall
}
func runCollectionsRemove(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
purge, err := flags.GetBool("purge")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all { if all {
cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, forceAction) err := cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, "", all, purge, force)
if err != nil {
return err
}
return nil return nil
} }
@ -91,7 +140,7 @@ func NewCollectionsCmd() *cobra.Command {
} }
for _, name := range args { for _, name := range args {
if !forceAction { if !force {
item := cwhub.GetItem(cwhub.COLLECTIONS, name) item := cwhub.GetItem(cwhub.COLLECTIONS, name)
if item == nil { if item == nil {
return fmt.Errorf("unable to retrieve: %s", name) return fmt.Errorf("unable to retrieve: %s", name)
@ -102,17 +151,69 @@ func NewCollectionsCmd() *cobra.Command {
continue continue
} }
} }
cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, name, all, purge, forceAction)
}
return nil
},
}
cmdCollectionsRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too")
cmdCollectionsRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files")
cmdCollectionsRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the collections")
cmdCollections.AddCommand(cmdCollectionsRemove)
var cmdCollectionsUpgrade = &cobra.Command{ err := cwhub.RemoveMany(csConfig, cwhub.COLLECTIONS, name, all, purge, force)
if err != nil {
return err
}
}
return nil
}
func NewCollectionsRemoveCmd() *cobra.Command {
cmdCollectionsRemove := &cobra.Command{
Use: "remove collection",
Short: "Remove given collection(s)",
Long: `Remove given collection(s) from hub`,
Example: `cscli collections remove crowdsec/xxx crowdsec/xyz`,
Aliases: []string{"delete"},
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.COLLECTIONS, args, toComplete)
},
RunE: runCollectionsRemove,
}
flags := cmdCollectionsRemove.Flags()
flags.Bool("purge", false, "Delete source file too")
flags.Bool("force", false, "Force remove : Remove tainted and outdated files")
flags.Bool("all", false, "Delete all the collections")
return cmdCollectionsRemove
}
func runCollectionsUpgrade(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all {
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", force)
return nil
}
if len(args) == 0 {
return fmt.Errorf("specify at least one collection to upgrade or '--all'")
}
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, name, force)
}
return nil
}
func NewCollectionsUpgradeCmd() *cobra.Command {
cmdCollectionsUpgrade := &cobra.Command{
Use: "upgrade collection", Use: "upgrade collection",
Short: "Upgrade given collection(s)", Short: "Upgrade given collection(s)",
Long: `Fetch and upgrade given collection(s) from hub`, Long: `Fetch and upgrade given collection(s) from hub`,
@ -121,25 +222,35 @@ func NewCollectionsCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) return compInstalledItems(cwhub.COLLECTIONS, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runCollectionsUpgrade,
if all {
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", forceAction)
} else {
if len(args) == 0 {
return fmt.Errorf("specify at least one collection to upgrade or '--all'")
} }
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, name, forceAction)
}
}
return nil
},
}
cmdCollectionsUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the collections")
cmdCollectionsUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files")
cmdCollections.AddCommand(cmdCollectionsUpgrade)
var cmdCollectionsInspect = &cobra.Command{ flags := cmdCollectionsUpgrade.Flags()
flags.BoolP("all", "a", false, "Upgrade all the collections")
flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files")
return cmdCollectionsUpgrade
}
func runCollectionsInspect(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
var err error
// XXX: set global
prometheusURL, err = flags.GetString("url")
if err != nil {
return err
}
for _, name := range args {
InspectItem(name, cwhub.COLLECTIONS)
}
return nil
}
func NewCollectionsInspectCmd() *cobra.Command {
cmdCollectionsInspect := &cobra.Command{
Use: "inspect collection", Use: "inspect collection",
Short: "Inspect given collection", Short: "Inspect given collection",
Long: `Inspect given collection`, Long: `Inspect given collection`,
@ -149,28 +260,42 @@ func NewCollectionsCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.COLLECTIONS, args, toComplete) return compInstalledItems(cwhub.COLLECTIONS, args, toComplete)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: runCollectionsInspect,
for _, name := range args {
InspectItem(name, cwhub.COLLECTIONS)
} }
},
}
cmdCollectionsInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url")
cmdCollections.AddCommand(cmdCollectionsInspect)
var cmdCollectionsList = &cobra.Command{ flags := cmdCollectionsInspect.Flags()
flags.StringP("url", "u", "", "Prometheus url")
return cmdCollectionsInspect
}
func runCollectionsList(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
all, err := flags.GetBool("all")
if err != nil {
return err
}
// XXX: will happily ignore missing collections
ListItems(color.Output, []string{cwhub.COLLECTIONS}, args, false, true, all)
return nil
}
func NewCollectionsListCmd() *cobra.Command {
cmdCollectionsList := &cobra.Command{
Use: "list collection [-a]", Use: "list collection [-a]",
Short: "List all collections", Short: "List all collections",
Long: `List all collections`, Long: `List all collections`,
Example: `cscli collections list`, Example: `cscli collections list`,
Args: cobra.ExactArgs(0), Args: cobra.ExactArgs(0),
DisableAutoGenTag: true, DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) { RunE: runCollectionsList,
ListItems(color.Output, []string{cwhub.COLLECTIONS}, args, false, true, all)
},
} }
cmdCollectionsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well")
cmdCollections.AddCommand(cmdCollectionsList)
return cmdCollections flags := cmdCollectionsList.Flags()
flags.BoolP("all", "a", false, "List disabled items as well")
return cmdCollectionsList
} }

View file

@ -27,10 +27,7 @@ func silentInstallItem(name string, obtype string) (string, error) {
if item == nil { if item == nil {
return "", fmt.Errorf("error retrieving item") return "", fmt.Errorf("error retrieving item")
} }
if downloadOnly && item.Downloaded && item.UpToDate { err := cwhub.DownloadLatest(csConfig.Hub, item, false, false)
return fmt.Sprintf("%s is already downloaded and up-to-date", item.Name), nil
}
err := cwhub.DownloadLatest(csConfig.Hub, item, forceAction, false)
if err != nil { if err != nil {
return "", fmt.Errorf("error while downloading %s : %v", item.Name, err) return "", fmt.Errorf("error while downloading %s : %v", item.Name, err)
} }
@ -38,9 +35,6 @@ func silentInstallItem(name string, obtype string) (string, error) {
return "", err return "", err
} }
if downloadOnly {
return fmt.Sprintf("Downloaded %s to %s", item.Name, csConfig.Cscli.HubDir+"/"+item.RemotePath), nil
}
err = cwhub.EnableItem(csConfig.Hub, item) err = cwhub.EnableItem(csConfig.Hub, item)
if err != nil { if err != nil {
return "", fmt.Errorf("error while enabling %s : %v", item.Name, err) return "", fmt.Errorf("error while enabling %s : %v", item.Name, err)

View file

@ -45,13 +45,14 @@ cscli hub update # Download list of available configurations from the hub
return cmdHub return cmdHub
} }
func NewHubListCmd() *cobra.Command { func runHubList(cmd *cobra.Command, args []string) error {
var cmdHubList = &cobra.Command{ flags := cmd.Flags()
Use: "list [-a]",
Short: "List installed configs", all, err := flags.GetBool("all")
Args: cobra.ExactArgs(0), if err != nil {
DisableAutoGenTag: true, return err
RunE: func(cmd *cobra.Command, args []string) error { }
if err := require.Hub(csConfig); err != nil { if err := require.Hub(csConfig); err != nil {
return err return err
} }
@ -61,19 +62,56 @@ func NewHubListCmd() *cobra.Command {
for _, v := range warn { for _, v := range warn {
log.Info(v) log.Info(v)
} }
cwhub.DisplaySummary() cwhub.DisplaySummary()
ListItems(color.Output, []string{ ListItems(color.Output, []string{
cwhub.COLLECTIONS, cwhub.PARSERS, cwhub.SCENARIOS, cwhub.PARSERS_OVFLW, cwhub.COLLECTIONS, cwhub.PARSERS, cwhub.SCENARIOS, cwhub.PARSERS_OVFLW,
}, args, true, false, all) }, args, true, false, all)
return nil return nil
},
} }
cmdHubList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well")
func NewHubListCmd() *cobra.Command {
var cmdHubList = &cobra.Command{
Use: "list [-a]",
Short: "List installed configs",
Args: cobra.ExactArgs(0),
DisableAutoGenTag: true,
RunE: runHubList,
}
flags := cmdHubList.Flags()
flags.BoolP("all", "a", false, "List disabled items as well")
return cmdHubList return cmdHubList
} }
func runHubUpdate(cmd *cobra.Command, args []string) error {
if err := csConfig.LoadHub(); err != nil {
return err
}
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
if !errors.Is(err, cwhub.ErrIndexNotFound) {
return fmt.Errorf("failed to get Hub index : %w", err)
}
log.Warnf("Could not find index file for branch '%s', using 'master'", cwhub.HubBranch)
cwhub.HubBranch = "master"
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
return fmt.Errorf("failed to get Hub index after retry: %w", err)
}
}
// use LocalSync to get warnings about tainted / outdated items
warn, _ := cwhub.LocalSync(csConfig.Hub)
for _, v := range warn {
log.Info(v)
}
return nil
}
func NewHubUpdateCmd() *cobra.Command { func NewHubUpdateCmd() *cobra.Command {
var cmdHubUpdate = &cobra.Command{ var cmdHubUpdate = &cobra.Command{
Use: "update", Use: "update",
@ -92,33 +130,36 @@ Fetches the [.index.json](https://github.com/crowdsecurity/hub/blob/master/.inde
return nil return nil
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runHubUpdate,
if err := csConfig.LoadHub(); err != nil {
return err
}
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
if !errors.Is(err, cwhub.ErrIndexNotFound) {
return fmt.Errorf("failed to get Hub index : %w", err)
}
log.Warnf("Could not find index file for branch '%s', using 'master'", cwhub.HubBranch)
cwhub.HubBranch = "master"
if err := cwhub.UpdateHubIdx(csConfig.Hub); err != nil {
return fmt.Errorf("failed to get Hub index after retry: %w", err)
}
}
// use LocalSync to get warnings about tainted / outdated items
warn, _ := cwhub.LocalSync(csConfig.Hub)
for _, v := range warn {
log.Info(v)
}
return nil
},
} }
return cmdHubUpdate return cmdHubUpdate
} }
func runHubUpgrade(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
force, err := flags.GetBool("force")
if err != nil {
return err
}
if err := require.Hub(csConfig); err != nil {
return err
}
log.Infof("Upgrading collections")
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", force)
log.Infof("Upgrading parsers")
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", force)
log.Infof("Upgrading scenarios")
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", force)
log.Infof("Upgrading postoverflows")
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", force)
return nil
}
func NewHubUpgradeCmd() *cobra.Command { func NewHubUpgradeCmd() *cobra.Command {
var cmdHubUpgrade = &cobra.Command{ var cmdHubUpgrade = &cobra.Command{
Use: "upgrade", Use: "upgrade",
@ -137,24 +178,11 @@ Upgrade all configs installed from Crowdsec Hub. Run 'sudo cscli hub update' if
return nil return nil
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runHubUpgrade,
if err := require.Hub(csConfig); err != nil {
return err
} }
log.Infof("Upgrading collections") flags := cmdHubUpgrade.Flags()
cwhub.UpgradeConfig(csConfig, cwhub.COLLECTIONS, "", forceAction) flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files")
log.Infof("Upgrading parsers")
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", forceAction)
log.Infof("Upgrading scenarios")
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", forceAction)
log.Infof("Upgrading postoverflows")
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", forceAction)
return nil
},
}
cmdHubUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files")
return cmdHubUpgrade return cmdHubUpgrade
} }

View file

@ -29,11 +29,6 @@ var dbClient *database.Client
var OutputFormat string var OutputFormat string
var OutputColor string var OutputColor string
var downloadOnly bool
var forceAction bool
var purge bool
var all bool
var prometheusURL string var prometheusURL string
var mergedConfig string var mergedConfig string

View file

@ -12,7 +12,7 @@ import (
) )
func NewParsersCmd() *cobra.Command { func NewParsersCmd() *cobra.Command {
var cmdParsers = &cobra.Command{ cmdParsers := &cobra.Command{
Use: "parsers [action] [config]", Use: "parsers [action] [config]",
Short: "Install/Remove/Upgrade/Inspect parser(s) from hub", Short: "Install/Remove/Upgrade/Inspect parser(s) from hub",
Example: `cscli parsers install crowdsecurity/sshd-logs Example: `cscli parsers install crowdsecurity/sshd-logs
@ -48,10 +48,46 @@ cscli parsers remove crowdsecurity/sshd-logs
return cmdParsers return cmdParsers
} }
func NewParsersInstallCmd() *cobra.Command { func runParsersInstall(cmd *cobra.Command, args []string) error {
var ignoreError bool flags := cmd.Flags()
var cmdParsersInstall = &cobra.Command{ downloadOnly, err := flags.GetBool("download-only")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
ignoreError, err := flags.GetBool("ignore")
if err != nil {
return err
}
for _, name := range args {
t := cwhub.GetItem(cwhub.PARSERS, name)
if t == nil {
nearestItem, score := GetDistance(cwhub.PARSERS, name)
Suggest(cwhub.PARSERS, name, nearestItem.Name, score, ignoreError)
continue
}
if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS, force, downloadOnly); err != nil {
if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err)
}
log.Errorf("Error while installing '%s': %s", name, err)
}
}
return nil
}
func NewParsersInstallCmd() *cobra.Command {
cmdParsersInstall := &cobra.Command{
Use: "install [config]", Use: "install [config]",
Short: "Install given parser(s)", Short: "Install given parser(s)",
Long: `Fetch and install given parser(s) from hub`, Long: `Fetch and install given parser(s) from hub`,
@ -61,32 +97,58 @@ func NewParsersInstallCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compAllItems(cwhub.PARSERS, args, toComplete) return compAllItems(cwhub.PARSERS, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runParsersInstall,
for _, name := range args {
t := cwhub.GetItem(cwhub.PARSERS, name)
if t == nil {
nearestItem, score := GetDistance(cwhub.PARSERS, name)
Suggest(cwhub.PARSERS, name, nearestItem.Name, score, ignoreError)
continue
}
if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS, forceAction, downloadOnly); err != nil {
if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err)
}
log.Errorf("Error while installing '%s': %s", name, err)
}
}
return nil
},
} }
cmdParsersInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") flags := cmdParsersInstall.Flags()
cmdParsersInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") flags.BoolP("download-only", "d", false, "Only download packages, don't enable")
cmdParsersInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple parsers") flags.Bool("force", false, "Force install: Overwrite tainted and outdated files")
flags.Bool("ignore", false, "Ignore errors when installing multiple parsers")
return cmdParsersInstall return cmdParsersInstall
} }
func runParsersRemove(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
purge, err := flags.GetBool("purge")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all {
err := cwhub.RemoveMany(csConfig, cwhub.PARSERS, "", all, purge, force)
if err != nil {
return err
}
return nil
}
if len(args) == 0 {
return fmt.Errorf("specify at least one parser to remove or '--all'")
}
for _, name := range args {
err := cwhub.RemoveMany(csConfig, cwhub.PARSERS, name, all, purge, force)
if err != nil {
return err
}
}
return nil
}
func NewParsersRemoveCmd() *cobra.Command { func NewParsersRemoveCmd() *cobra.Command {
cmdParsersRemove := &cobra.Command{ cmdParsersRemove := &cobra.Command{
Use: "remove [config]", Use: "remove [config]",
@ -98,29 +160,44 @@ func NewParsersRemoveCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS, args, toComplete) return compInstalledItems(cwhub.PARSERS, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runParsersRemove,
}
flags := cmdParsersRemove.Flags()
flags.Bool("purge", false, "Delete source file too")
flags.Bool("force", false, "Force remove: Remove tainted and outdated files")
flags.Bool("all", false, "Delete all the parsers")
return cmdParsersRemove
}
func runParsersUpgrade(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all { if all {
cwhub.RemoveMany(csConfig, cwhub.PARSERS, "", all, purge, forceAction) cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", force)
return nil return nil
} }
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("specify at least one parser to remove or '--all'") return fmt.Errorf("specify at least one parser to upgrade or '--all'")
} }
for _, name := range args { for _, name := range args {
cwhub.RemoveMany(csConfig, cwhub.PARSERS, name, all, purge, forceAction) cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, name, force)
} }
return nil return nil
},
}
cmdParsersRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too")
cmdParsersRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files")
cmdParsersRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the parsers")
return cmdParsersRemove
} }
func NewParsersUpgradeCmd() *cobra.Command { func NewParsersUpgradeCmd() *cobra.Command {
@ -133,62 +210,78 @@ func NewParsersUpgradeCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS, args, toComplete) return compInstalledItems(cwhub.PARSERS, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runParsersUpgrade,
if all {
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, "", forceAction)
} else {
if len(args) == 0 {
return fmt.Errorf("specify at least one parser to upgrade or '--all'")
}
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS, name, forceAction)
}
}
return nil
},
} }
cmdParsersUpgrade.PersistentFlags().BoolVar(&all, "all", false, "Upgrade all the parsers") flags := cmdParsersUpgrade.Flags()
cmdParsersUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") flags.Bool("all", false, "Upgrade all the parsers")
flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files")
return cmdParsersUpgrade return cmdParsersUpgrade
} }
func runParsersInspect(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
var err error
// XXX: set global
prometheusURL, err = flags.GetString("url")
if err != nil {
return err
}
InspectItem(args[0], cwhub.PARSERS)
return nil
}
func NewParsersInspectCmd() *cobra.Command { func NewParsersInspectCmd() *cobra.Command {
var cmdParsersInspect = &cobra.Command{ cmdParsersInspect := &cobra.Command{
Use: "inspect [name]", Use: "inspect [name]",
Short: "Inspect given parser", Short: "Inspect given parser",
Long: `Inspect given parser`, Long: `Inspect given parser`,
Example: `cscli parsers inspect crowdsec/xxx`, Example: `cscli parsers inspect crowdsec/xxx`,
DisableAutoGenTag: true,
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS, args, toComplete) return compInstalledItems(cwhub.PARSERS, args, toComplete)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: runParsersInspect,
InspectItem(args[0], cwhub.PARSERS)
},
} }
cmdParsersInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url") flags := cmdParsersInspect.Flags()
flags.StringP("url", "u", "", "Prometheus url")
return cmdParsersInspect return cmdParsersInspect
} }
func runParsersList(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
all, err := flags.GetBool("all")
if err != nil {
return err
}
// XXX: will happily ignore missing parsers
ListItems(color.Output, []string{cwhub.PARSERS}, args, false, true, all)
return nil
}
func NewParsersListCmd() *cobra.Command { func NewParsersListCmd() *cobra.Command {
var cmdParsersList = &cobra.Command{ cmdParsersList := &cobra.Command{
Use: "list [name]", Use: "list [name]",
Short: "List all parsers or given one", Short: "List all parsers or given one",
Long: `List all parsers or given one`, Long: `List all parsers or given one`,
Example: `cscli parsers list Example: `cscli parsers list
cscli parser list crowdsecurity/xxx`, cscli parser list crowdsecurity/xxx`,
DisableAutoGenTag: true, DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) { RunE: runParsersList,
ListItems(color.Output, []string{cwhub.PARSERS}, args, false, true, all)
},
} }
cmdParsersList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") flags := cmdParsersList.Flags()
flags.BoolP("all", "a", false, "List disabled items as well")
return cmdParsersList return cmdParsersList
} }

View file

@ -19,7 +19,8 @@ func NewPostOverflowsCmd() *cobra.Command {
cscli postoverflows inspect crowdsecurity/cdn-whitelist cscli postoverflows inspect crowdsecurity/cdn-whitelist
cscli postoverflows upgrade crowdsecurity/cdn-whitelist cscli postoverflows upgrade crowdsecurity/cdn-whitelist
cscli postoverflows list cscli postoverflows list
cscli postoverflows remove crowdsecurity/cdn-whitelist`, cscli postoverflows remove crowdsecurity/cdn-whitelist
`,
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
Aliases: []string{"postoverflow"}, Aliases: []string{"postoverflow"},
DisableAutoGenTag: true, DisableAutoGenTag: true,
@ -47,9 +48,45 @@ func NewPostOverflowsCmd() *cobra.Command {
return cmdPostOverflows return cmdPostOverflows
} }
func NewPostOverflowsInstallCmd() *cobra.Command { func runPostOverflowsInstall(cmd *cobra.Command, args []string) error {
var ignoreError bool flags := cmd.Flags()
downloadOnly, err := flags.GetBool("download-only")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
ignoreError, err := flags.GetBool("ignore")
if err != nil {
return err
}
for _, name := range args {
t := cwhub.GetItem(cwhub.PARSERS_OVFLW, name)
if t == nil {
nearestItem, score := GetDistance(cwhub.PARSERS_OVFLW, name)
Suggest(cwhub.PARSERS_OVFLW, name, nearestItem.Name, score, ignoreError)
continue
}
if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS_OVFLW, force, downloadOnly); err != nil {
if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err)
}
log.Errorf("Error while installing '%s': %s", name, err)
}
}
return nil
}
func NewPostOverflowsInstallCmd() *cobra.Command {
cmdPostOverflowsInstall := &cobra.Command{ cmdPostOverflowsInstall := &cobra.Command{
Use: "install [config]", Use: "install [config]",
Short: "Install given postoverflow(s)", Short: "Install given postoverflow(s)",
@ -60,32 +97,58 @@ func NewPostOverflowsInstallCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compAllItems(cwhub.PARSERS_OVFLW, args, toComplete) return compAllItems(cwhub.PARSERS_OVFLW, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runPostOverflowsInstall,
for _, name := range args {
t := cwhub.GetItem(cwhub.PARSERS_OVFLW, name)
if t == nil {
nearestItem, score := GetDistance(cwhub.PARSERS_OVFLW, name)
Suggest(cwhub.PARSERS_OVFLW, name, nearestItem.Name, score, ignoreError)
continue
}
if err := cwhub.InstallItem(csConfig, name, cwhub.PARSERS_OVFLW, forceAction, downloadOnly); err != nil {
if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err)
}
log.Errorf("Error while installing '%s': %s", name, err)
}
}
return nil
},
} }
cmdPostOverflowsInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable") flags := cmdPostOverflowsInstall.Flags()
cmdPostOverflowsInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") flags.BoolP("download-only", "d", false, "Only download packages, don't enable")
cmdPostOverflowsInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple postoverflows") flags.Bool("force", false, "Force install : Overwrite tainted and outdated files")
flags.Bool("ignore", false, "Ignore errors when installing multiple postoverflows")
return cmdPostOverflowsInstall return cmdPostOverflowsInstall
} }
func runPostOverflowsRemove(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
purge, err := flags.GetBool("purge")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all {
err := cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, "", all, purge, force)
if err != nil {
return err
}
return nil
}
if len(args) == 0 {
return fmt.Errorf("specify at least one postoverflow to remove or '--all'")
}
for _, name := range args {
err := cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, name, all, purge, force)
if err != nil {
return err
}
}
return nil
}
func NewPostOverflowsRemoveCmd() *cobra.Command { func NewPostOverflowsRemoveCmd() *cobra.Command {
cmdPostOverflowsRemove := &cobra.Command{ cmdPostOverflowsRemove := &cobra.Command{
Use: "remove [config]", Use: "remove [config]",
@ -97,29 +160,44 @@ func NewPostOverflowsRemoveCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runPostOverflowsRemove,
}
flags := cmdPostOverflowsRemove.Flags()
flags.Bool("purge", false, "Delete source file too")
flags.Bool("force", false, "Force remove : Remove tainted and outdated files")
flags.Bool("all", false, "Delete all the postoverflows")
return cmdPostOverflowsRemove
}
func runPostOverflowUpgrade(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all { if all {
cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, "", all, purge, forceAction) cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", force)
return nil return nil
} }
if len(args) == 0 { if len(args) == 0 {
return fmt.Errorf("specify at least one postoverflow to remove or '--all'") return fmt.Errorf("specify at least one postoverflow to upgrade or '--all'")
} }
for _, name := range args { for _, name := range args {
cwhub.RemoveMany(csConfig, cwhub.PARSERS_OVFLW, name, all, purge, forceAction) cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, name, force)
} }
return nil return nil
},
}
cmdPostOverflowsRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too")
cmdPostOverflowsRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files")
cmdPostOverflowsRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the postoverflows")
return cmdPostOverflowsRemove
} }
func NewPostOverflowsUpgradeCmd() *cobra.Command { func NewPostOverflowsUpgradeCmd() *cobra.Command {
@ -132,46 +210,66 @@ func NewPostOverflowsUpgradeCmd() *cobra.Command {
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete)
}, },
RunE: func(cmd *cobra.Command, args []string) error { RunE: runPostOverflowUpgrade,
if all {
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, "", forceAction)
} else {
if len(args) == 0 {
return fmt.Errorf("specify at least one postoverflow to upgrade or '--all'")
}
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.PARSERS_OVFLW, name, forceAction)
}
}
return nil
},
} }
cmdPostOverflowsUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the postoverflows") flags := cmdPostOverflowsUpgrade.Flags()
cmdPostOverflowsUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files") flags.BoolP("all", "a", false, "Upgrade all the postoverflows")
flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files")
return cmdPostOverflowsUpgrade return cmdPostOverflowsUpgrade
} }
func runPostOverflowsInspect(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
var err error
// XXX: set global
prometheusURL, err = flags.GetString("url")
if err != nil {
return err
}
InspectItem(args[0], cwhub.PARSERS_OVFLW)
return nil
}
func NewPostOverflowsInspectCmd() *cobra.Command { func NewPostOverflowsInspectCmd() *cobra.Command {
cmdPostOverflowsInspect := &cobra.Command{ cmdPostOverflowsInspect := &cobra.Command{
Use: "inspect [config]", Use: "inspect [config]",
Short: "Inspect given postoverflow", Short: "Inspect given postoverflow",
Long: `Inspect given postoverflow`, Long: `Inspect given postoverflow`,
Example: `cscli postoverflows inspect crowdsec/xxx crowdsec/xyz`, Example: `cscli postoverflows inspect crowdsec/xxx crowdsec/xyz`,
DisableAutoGenTag: true,
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete) return compInstalledItems(cwhub.PARSERS_OVFLW, args, toComplete)
}, },
Run: func(cmd *cobra.Command, args []string) { RunE: runPostOverflowsInspect,
InspectItem(args[0], cwhub.PARSERS_OVFLW)
},
} }
flags := cmdPostOverflowsInspect.Flags()
// XXX: is this needed for postoverflows?
flags.StringP("url", "u", "", "Prometheus url")
return cmdPostOverflowsInspect return cmdPostOverflowsInspect
} }
func runPostOverflowsList(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
all, err := flags.GetBool("all")
if err != nil {
return err
}
// XXX: will happily ignore missing postoverflows
ListItems(color.Output, []string{cwhub.PARSERS_OVFLW}, args, false, true, all)
return nil
}
func NewPostOverflowsListCmd() *cobra.Command { func NewPostOverflowsListCmd() *cobra.Command {
cmdPostOverflowsList := &cobra.Command{ cmdPostOverflowsList := &cobra.Command{
Use: "list [config]", Use: "list [config]",
@ -180,12 +278,11 @@ func NewPostOverflowsListCmd() *cobra.Command {
Example: `cscli postoverflows list Example: `cscli postoverflows list
cscli postoverflows list crowdsecurity/xxx`, cscli postoverflows list crowdsecurity/xxx`,
DisableAutoGenTag: true, DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) { RunE: runPostOverflowsList,
ListItems(color.Output, []string{cwhub.PARSERS_OVFLW}, args, false, true, all)
},
} }
cmdPostOverflowsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well") flags := cmdPostOverflowsList.Flags()
flags.BoolP("all", "a", false, "List disabled items as well")
return cmdPostOverflowsList return cmdPostOverflowsList
} }

View file

@ -12,7 +12,7 @@ import (
) )
func NewScenariosCmd() *cobra.Command { func NewScenariosCmd() *cobra.Command {
var cmdScenarios = &cobra.Command{ cmdScenarios := &cobra.Command{
Use: "scenarios [action] [config]", Use: "scenarios [action] [config]",
Short: "Install/Remove/Upgrade/Inspect scenario(s) from hub", Short: "Install/Remove/Upgrade/Inspect scenario(s) from hub",
Example: `cscli scenarios list [-a] Example: `cscli scenarios list [-a]
@ -48,58 +48,90 @@ cscli scenarios remove crowdsecurity/ssh-bf
return cmdScenarios return cmdScenarios
} }
func NewCmdScenariosInstall() *cobra.Command { func runScenariosInstall(cmd *cobra.Command, args []string) error {
var ignoreError bool flags := cmd.Flags()
downloadOnly, err := flags.GetBool("download-only")
if err != nil {
return err
}
force, err := flags.GetBool("force")
if err != nil {
return err
}
ignoreError, err := flags.GetBool("ignore")
if err != nil {
return err
}
var cmdScenariosInstall = &cobra.Command{
Use: "install [config]",
Short: "Install given scenario(s)",
Long: `Fetch and install given scenario(s) from hub`,
Example: `cscli scenarios install crowdsec/xxx crowdsec/xyz`,
Args: cobra.MinimumNArgs(1),
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compAllItems(cwhub.SCENARIOS, args, toComplete)
},
DisableAutoGenTag: true,
RunE: func(cmd *cobra.Command, args []string) error {
for _, name := range args { for _, name := range args {
t := cwhub.GetItem(cwhub.SCENARIOS, name) t := cwhub.GetItem(cwhub.SCENARIOS, name)
if t == nil { if t == nil {
nearestItem, score := GetDistance(cwhub.SCENARIOS, name) nearestItem, score := GetDistance(cwhub.SCENARIOS, name)
Suggest(cwhub.SCENARIOS, name, nearestItem.Name, score, ignoreError) Suggest(cwhub.SCENARIOS, name, nearestItem.Name, score, ignoreError)
continue continue
} }
if err := cwhub.InstallItem(csConfig, name, cwhub.SCENARIOS, forceAction, downloadOnly); err != nil {
if err := cwhub.InstallItem(csConfig, name, cwhub.SCENARIOS, force, downloadOnly); err != nil {
if !ignoreError { if !ignoreError {
return fmt.Errorf("error while installing '%s': %w", name, err) return fmt.Errorf("error while installing '%s': %w", name, err)
} }
log.Errorf("Error while installing '%s': %s", name, err) log.Errorf("Error while installing '%s': %s", name, err)
} }
} }
return nil return nil
},
} }
cmdScenariosInstall.PersistentFlags().BoolVarP(&downloadOnly, "download-only", "d", false, "Only download packages, don't enable")
cmdScenariosInstall.PersistentFlags().BoolVar(&forceAction, "force", false, "Force install : Overwrite tainted and outdated files") func NewCmdScenariosInstall() *cobra.Command {
cmdScenariosInstall.PersistentFlags().BoolVar(&ignoreError, "ignore", false, "Ignore errors when installing multiple scenarios") cmdScenariosInstall := &cobra.Command{
Use: "install [config]",
Short: "Install given scenario(s)",
Long: `Fetch and install given scenario(s) from hub`,
Example: `cscli scenarios 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.SCENARIOS, args, toComplete)
},
RunE: runScenariosInstall,
}
flags := cmdScenariosInstall.Flags()
flags.BoolP("download-only", "d", false, "Only download packages, don't enable")
flags.Bool("force", false, "Force install : Overwrite tainted and outdated files")
flags.Bool("ignore", false, "Ignore errors when installing multiple scenarios")
return cmdScenariosInstall return cmdScenariosInstall
} }
func NewCmdScenariosRemove() *cobra.Command { func runScenariosRemove(cmd *cobra.Command, args []string) error {
var cmdScenariosRemove = &cobra.Command{ flags := cmd.Flags()
Use: "remove [config]",
Short: "Remove given scenario(s)", purge, err := flags.GetBool("purge")
Long: `remove given scenario(s)`, if err != nil {
Example: `cscli scenarios remove crowdsec/xxx crowdsec/xyz`, return err
Aliases: []string{"delete"}, }
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.SCENARIOS, args, toComplete) force, err := flags.GetBool("force")
}, if err != nil {
DisableAutoGenTag: true, return err
RunE: func(cmd *cobra.Command, args []string) error { }
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all { if all {
cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, forceAction) err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, "", all, purge, force)
if err != nil {
return err
}
return nil return nil
} }
@ -108,81 +140,148 @@ func NewCmdScenariosRemove() *cobra.Command {
} }
for _, name := range args { for _, name := range args {
cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, forceAction) err := cwhub.RemoveMany(csConfig, cwhub.SCENARIOS, name, all, purge, force)
if err != nil {
return err
} }
}
return nil return nil
},
} }
cmdScenariosRemove.PersistentFlags().BoolVar(&purge, "purge", false, "Delete source file too")
cmdScenariosRemove.PersistentFlags().BoolVar(&forceAction, "force", false, "Force remove : Remove tainted and outdated files") func NewCmdScenariosRemove() *cobra.Command {
cmdScenariosRemove.PersistentFlags().BoolVar(&all, "all", false, "Delete all the scenarios") cmdScenariosRemove := &cobra.Command{
Use: "remove [config]",
Short: "Remove given scenario(s)",
Long: `remove given scenario(s)`,
Example: `cscli scenarios remove crowdsec/xxx crowdsec/xyz`,
Aliases: []string{"delete"},
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.SCENARIOS, args, toComplete)
},
RunE: runScenariosRemove,
}
flags := cmdScenariosRemove.Flags()
flags.Bool("purge", false, "Delete source file too")
flags.Bool("force", false, "Force remove: Remove tainted and outdated files")
flags.Bool("all", false, "Delete all the scenarios")
return cmdScenariosRemove return cmdScenariosRemove
} }
func runScenariosUpgrade(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
force, err := flags.GetBool("force")
if err != nil {
return err
}
all, err := flags.GetBool("all")
if err != nil {
return err
}
if all {
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", force)
return nil
}
if len(args) == 0 {
return fmt.Errorf("specify at least one scenario to upgrade or '--all'")
}
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, name, force)
}
return nil
}
func NewCmdScenariosUpgrade() *cobra.Command { func NewCmdScenariosUpgrade() *cobra.Command {
var cmdScenariosUpgrade = &cobra.Command{ cmdScenariosUpgrade := &cobra.Command{
Use: "upgrade [config]", Use: "upgrade [config]",
Short: "Upgrade given scenario(s)", Short: "Upgrade given scenario(s)",
Long: `Fetch and Upgrade given scenario(s) from hub`, Long: `Fetch and Upgrade given scenario(s) from hub`,
Example: `cscli scenarios upgrade crowdsec/xxx crowdsec/xyz`, Example: `cscli scenarios upgrade crowdsec/xxx crowdsec/xyz`,
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.SCENARIOS, args, toComplete) return compInstalledItems(cwhub.SCENARIOS, args, toComplete)
}, },
DisableAutoGenTag: true, RunE: runScenariosUpgrade,
RunE: func(cmd *cobra.Command, args []string) error {
if all {
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, "", forceAction)
} else {
if len(args) == 0 {
return fmt.Errorf("specify at least one scenario to upgrade or '--all'")
} }
for _, name := range args {
cwhub.UpgradeConfig(csConfig, cwhub.SCENARIOS, name, forceAction) flags := cmdScenariosUpgrade.Flags()
} flags.BoolP("all", "a", false, "Upgrade all the scenarios")
} flags.Bool("force", false, "Force upgrade : Overwrite tainted and outdated files")
return nil
},
}
cmdScenariosUpgrade.PersistentFlags().BoolVarP(&all, "all", "a", false, "Upgrade all the scenarios")
cmdScenariosUpgrade.PersistentFlags().BoolVar(&forceAction, "force", false, "Force upgrade : Overwrite tainted and outdated files")
return cmdScenariosUpgrade return cmdScenariosUpgrade
} }
func runScenariosInspect(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
var err error
// XXX: set global
prometheusURL, err = flags.GetString("url")
if err != nil {
return err
}
InspectItem(args[0], cwhub.SCENARIOS)
return nil
}
func NewCmdScenariosInspect() *cobra.Command { func NewCmdScenariosInspect() *cobra.Command {
var cmdScenariosInspect = &cobra.Command{ cmdScenariosInspect := &cobra.Command{
Use: "inspect [config]", Use: "inspect [config]",
Short: "Inspect given scenario", Short: "Inspect given scenario",
Long: `Inspect given scenario`, Long: `Inspect given scenario`,
Example: `cscli scenarios inspect crowdsec/xxx`, Example: `cscli scenarios inspect crowdsec/xxx`,
Args: cobra.MinimumNArgs(1), Args: cobra.MinimumNArgs(1),
DisableAutoGenTag: true,
ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
return compInstalledItems(cwhub.SCENARIOS, args, toComplete) return compInstalledItems(cwhub.SCENARIOS, args, toComplete)
}, },
DisableAutoGenTag: true, RunE: runScenariosInspect,
Run: func(cmd *cobra.Command, args []string) {
InspectItem(args[0], cwhub.SCENARIOS)
},
} }
cmdScenariosInspect.PersistentFlags().StringVarP(&prometheusURL, "url", "u", "", "Prometheus url")
flags := cmdScenariosInspect.Flags()
flags.StringP("url", "u", "", "Prometheus url")
return cmdScenariosInspect return cmdScenariosInspect
} }
func runScenariosList(cmd *cobra.Command, args []string) error {
flags := cmd.Flags()
all, err := flags.GetBool("all")
if err != nil {
return err
}
// XXX: will happily ignore missing scenarios
ListItems(color.Output, []string{cwhub.SCENARIOS}, args, false, true, all)
return nil
}
func NewCmdScenariosList() *cobra.Command { func NewCmdScenariosList() *cobra.Command {
var cmdScenariosList = &cobra.Command{ cmdScenariosList := &cobra.Command{
Use: "list [config]", Use: "list [config]",
Short: "List all scenario(s) or given one", Short: "List all scenario(s) or given one",
Long: `List all scenario(s) or given one`, Long: `List all scenario(s) or given one`,
Example: `cscli scenarios list Example: `cscli scenarios list
cscli scenarios list crowdsecurity/xxx`, cscli scenarios list crowdsecurity/xxx`,
DisableAutoGenTag: true, DisableAutoGenTag: true,
Run: func(cmd *cobra.Command, args []string) { RunE: runScenariosList,
ListItems(color.Output, []string{cwhub.SCENARIOS}, args, false, true, all)
},
} }
cmdScenariosList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List disabled items as well")
flags := cmdScenariosList.Flags()
flags.BoolP("all", "a", false, "List disabled items as well")
return cmdScenariosList return cmdScenariosList
} }

View file

@ -135,7 +135,7 @@ func collectOSInfo() ([]byte, error) {
func collectHubItems(itemType string) []byte { func collectHubItems(itemType string) []byte {
out := bytes.NewBuffer(nil) out := bytes.NewBuffer(nil)
log.Infof("Collecting %s list", itemType) log.Infof("Collecting %s list", itemType)
ListItems(out, []string{itemType}, []string{}, false, true, all) ListItems(out, []string{itemType}, []string{}, false, true, false)
return out.Bytes() return out.Bytes()
} }

View file

@ -103,29 +103,28 @@ func InstallItem(csConfig *csconfig.Config, name string, obtype string, force bo
return nil 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) error {
func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all bool, purge bool, forceAction bool) {
if name != "" { if name != "" {
item := GetItem(itemType, name) item := GetItem(itemType, name)
if item == nil { if item == nil {
log.Fatalf("unable to retrieve: %s", name) return fmt.Errorf("unable to retrieve: %s", name)
} }
err := DisableItem(csConfig.Hub, item, purge, forceAction) err := DisableItem(csConfig.Hub, item, purge, forceAction)
if err != nil { if err != nil {
log.Fatalf("unable to disable %s : %v", item.Name, err) return fmt.Errorf("unable to disable %s: %w", item.Name, err)
} }
if err = AddItem(itemType, *item); err != nil { if err = AddItem(itemType, *item); err != nil {
log.Fatalf("unable to add %s: %v", item.Name, err) return fmt.Errorf("unable to add %s: %w", item.Name, err)
} }
return return nil
} }
if !all { if !all {
log.Fatal("removing item: no item specified") return fmt.Errorf("removing item: no item specified")
} }
disabled := 0 disabled := 0
@ -138,16 +137,18 @@ func RemoveMany(csConfig *csconfig.Config, itemType string, name string, all boo
err := DisableItem(csConfig.Hub, &v, purge, forceAction) err := DisableItem(csConfig.Hub, &v, purge, forceAction)
if err != nil { if err != nil {
log.Fatalf("unable to disable %s : %v", v.Name, err) return fmt.Errorf("unable to disable %s: %w", v.Name, err)
} }
if err := AddItem(itemType, v); err != nil { if err := AddItem(itemType, v); err != nil {
log.Fatalf("unable to add %s: %v", v.Name, err) return fmt.Errorf("unable to add %s: %w", v.Name, err)
} }
disabled++ disabled++
} }
log.Infof("Disabled %d items", disabled) log.Infof("Disabled %d items", disabled)
return nil
} }
func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, force bool) { func UpgradeConfig(csConfig *csconfig.Config, itemType string, name string, force bool) {

View file

@ -74,7 +74,9 @@ func TestUpgradeConfigInDisabledScenarioShouldNotBeInstalled(t *testing.T) {
require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed)
assertCollectionDepsInstalled(t, "crowdsecurity/test_collection") assertCollectionDepsInstalled(t, "crowdsecurity/test_collection")
RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) err := RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false)
require.NoError(t, err)
getHubIdxOrFail(t) getHubIdxOrFail(t)
// scenario referenced by collection was deleted hence, collection should be tainted // scenario referenced by collection was deleted hence, collection should be tainted
require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed)
@ -122,7 +124,9 @@ func TestUpgradeConfigNewScenarioIsInstalledWhenReferencedScenarioIsDisabled(t *
require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) require.True(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed)
assertCollectionDepsInstalled(t, "crowdsecurity/test_collection") assertCollectionDepsInstalled(t, "crowdsecurity/test_collection")
RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false) err := RemoveMany(cfg, SCENARIOS, "crowdsecurity/foobar_scenario", false, false, false)
require.NoError(t, err)
getHubIdxOrFail(t) getHubIdxOrFail(t)
// scenario referenced by collection was deleted hence, collection should be tainted // scenario referenced by collection was deleted hence, collection should be tainted
require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed) require.False(t, hubIdx[SCENARIOS]["crowdsecurity/foobar_scenario"].Installed)

View file

@ -98,7 +98,7 @@ func (w Walker) getItemInfo(path string) (itemFileInfo, bool, error) {
//.../hub/scenarios/crowdsec/ssh_bf.yaml //.../hub/scenarios/crowdsec/ssh_bf.yaml
//.../hub/profiles/crowdsec/linux.yaml //.../hub/profiles/crowdsec/linux.yaml
if len(subs) < 4 { if len(subs) < 4 {
log.Fatalf("path is too short : %s (%d)", path, len(subs)) return itemFileInfo{}, false, fmt.Errorf("path is too short : %s (%d)", path, len(subs))
} }
ret.fname = subs[len(subs)-1] ret.fname = subs[len(subs)-1]
@ -108,7 +108,7 @@ func (w Walker) getItemInfo(path string) (itemFileInfo, bool, error) {
} else if strings.HasPrefix(path, w.installdir) { // we're in install /etc/crowdsec/<type>/... } else if strings.HasPrefix(path, w.installdir) { // we're in install /etc/crowdsec/<type>/...
log.Tracef("in install dir") log.Tracef("in install dir")
if len(subs) < 3 { if len(subs) < 3 {
log.Fatalf("path is too short : %s (%d)", path, len(subs)) return itemFileInfo{}, false, fmt.Errorf("path is too short: %s (%d)", path, len(subs))
} }
///.../config/parser/stage/file.yaml ///.../config/parser/stage/file.yaml
///.../config/postoverflow/stage/file.yaml ///.../config/postoverflow/stage/file.yaml
@ -352,7 +352,7 @@ func CollecDepsCheck(v *Item) error {
for _, subName := range itemSlice { for _, subName := range itemSlice {
subItem, ok := hubIdx[sliceType][subName] subItem, ok := hubIdx[sliceType][subName]
if !ok { if !ok {
log.Fatalf("Referred %s %s in collection %s doesn't exist.", sliceType, subName, v.Name) return fmt.Errorf("referred %s %s in collection %s doesn't exist", sliceType, subName, v.Name)
} }
log.Tracef("check %s installed:%t", subItem.Name, subItem.Installed) log.Tracef("check %s installed:%t", subItem.Name, subItem.Installed)