refact "cscli notifications" (#2833)
This commit is contained in:
parent
bdecf38616
commit
eada3739e6
|
@ -246,7 +246,7 @@ It is meant to allow you to manage bans, parsers/scenarios/etc, api and generall
|
||||||
cmd.AddCommand(NewConsoleCmd())
|
cmd.AddCommand(NewConsoleCmd())
|
||||||
cmd.AddCommand(NewCLIExplain(cli.cfg).NewCommand())
|
cmd.AddCommand(NewCLIExplain(cli.cfg).NewCommand())
|
||||||
cmd.AddCommand(NewCLIHubTest().NewCommand())
|
cmd.AddCommand(NewCLIHubTest().NewCommand())
|
||||||
cmd.AddCommand(NewCLINotifications().NewCommand())
|
cmd.AddCommand(NewCLINotifications(cli.cfg).NewCommand())
|
||||||
cmd.AddCommand(NewCLISupport().NewCommand())
|
cmd.AddCommand(NewCLISupport().NewCommand())
|
||||||
cmd.AddCommand(NewCLIPapi(cli.cfg).NewCommand())
|
cmd.AddCommand(NewCLIPapi(cli.cfg).NewCommand())
|
||||||
cmd.AddCommand(NewCLICollection().NewCommand())
|
cmd.AddCommand(NewCLICollection().NewCommand())
|
||||||
|
|
|
@ -23,14 +23,13 @@ import (
|
||||||
"github.com/crowdsecurity/go-cs-lib/ptr"
|
"github.com/crowdsecurity/go-cs-lib/ptr"
|
||||||
"github.com/crowdsecurity/go-cs-lib/version"
|
"github.com/crowdsecurity/go-cs-lib/version"
|
||||||
|
|
||||||
|
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/csprofiles"
|
"github.com/crowdsecurity/crowdsec/pkg/csprofiles"
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/types"
|
|
||||||
|
|
||||||
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
|
|
||||||
"github.com/crowdsecurity/crowdsec/pkg/models"
|
"github.com/crowdsecurity/crowdsec/pkg/models"
|
||||||
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type NotificationsCfg struct {
|
type NotificationsCfg struct {
|
||||||
|
@ -39,13 +38,17 @@ type NotificationsCfg struct {
|
||||||
ids []uint
|
ids []uint
|
||||||
}
|
}
|
||||||
|
|
||||||
type cliNotifications struct{}
|
type cliNotifications struct {
|
||||||
|
cfg configGetter
|
||||||
func NewCLINotifications() *cliNotifications {
|
|
||||||
return &cliNotifications{}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli cliNotifications) NewCommand() *cobra.Command {
|
func NewCLINotifications(cfg configGetter) *cliNotifications {
|
||||||
|
return &cliNotifications{
|
||||||
|
cfg: cfg,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cli *cliNotifications) NewCommand() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "notifications [action]",
|
Use: "notifications [action]",
|
||||||
Short: "Helper for notification plugin configuration",
|
Short: "Helper for notification plugin configuration",
|
||||||
|
@ -53,14 +56,15 @@ func (cli cliNotifications) NewCommand() *cobra.Command {
|
||||||
Args: cobra.MinimumNArgs(1),
|
Args: cobra.MinimumNArgs(1),
|
||||||
Aliases: []string{"notifications", "notification"},
|
Aliases: []string{"notifications", "notification"},
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
|
PersistentPreRunE: func(_ *cobra.Command, _ []string) error {
|
||||||
if err := require.LAPI(csConfig); err != nil {
|
cfg := cli.cfg()
|
||||||
|
if err := require.LAPI(cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := csConfig.LoadAPIClient(); err != nil {
|
if err := cfg.LoadAPIClient(); err != nil {
|
||||||
return fmt.Errorf("loading api client: %w", err)
|
return fmt.Errorf("loading api client: %w", err)
|
||||||
}
|
}
|
||||||
if err := require.Notifications(csConfig); err != nil {
|
if err := require.Notifications(cfg); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -76,67 +80,79 @@ func (cli cliNotifications) NewCommand() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPluginConfigs() (map[string]csplugin.PluginConfig, error) {
|
func (cli *cliNotifications) getPluginConfigs() (map[string]csplugin.PluginConfig, error) {
|
||||||
|
cfg := cli.cfg()
|
||||||
pcfgs := map[string]csplugin.PluginConfig{}
|
pcfgs := map[string]csplugin.PluginConfig{}
|
||||||
wf := func(path string, info fs.FileInfo, err error) error {
|
wf := func(path string, info fs.FileInfo, err error) error {
|
||||||
if info == nil {
|
if info == nil {
|
||||||
return fmt.Errorf("error while traversing directory %s: %w", path, err)
|
return fmt.Errorf("error while traversing directory %s: %w", path, err)
|
||||||
}
|
}
|
||||||
name := filepath.Join(csConfig.ConfigPaths.NotificationDir, info.Name()) //Avoid calling info.Name() twice
|
|
||||||
|
name := filepath.Join(cfg.ConfigPaths.NotificationDir, info.Name()) //Avoid calling info.Name() twice
|
||||||
if (strings.HasSuffix(name, "yaml") || strings.HasSuffix(name, "yml")) && !(info.IsDir()) {
|
if (strings.HasSuffix(name, "yaml") || strings.HasSuffix(name, "yml")) && !(info.IsDir()) {
|
||||||
ts, err := csplugin.ParsePluginConfigFile(name)
|
ts, err := csplugin.ParsePluginConfigFile(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("loading notifification plugin configuration with %s: %w", name, err)
|
return fmt.Errorf("loading notifification plugin configuration with %s: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, t := range ts {
|
for _, t := range ts {
|
||||||
csplugin.SetRequiredFields(&t)
|
csplugin.SetRequiredFields(&t)
|
||||||
pcfgs[t.Name] = t
|
pcfgs[t.Name] = t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := filepath.Walk(csConfig.ConfigPaths.NotificationDir, wf); err != nil {
|
if err := filepath.Walk(cfg.ConfigPaths.NotificationDir, wf); err != nil {
|
||||||
return nil, fmt.Errorf("while loading notifification plugin configuration: %w", err)
|
return nil, fmt.Errorf("while loading notifification plugin configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return pcfgs, nil
|
return pcfgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getProfilesConfigs() (map[string]NotificationsCfg, error) {
|
func (cli *cliNotifications) getProfilesConfigs() (map[string]NotificationsCfg, error) {
|
||||||
|
cfg := cli.cfg()
|
||||||
// A bit of a tricky stuf now: reconcile profiles and notification plugins
|
// A bit of a tricky stuf now: reconcile profiles and notification plugins
|
||||||
pcfgs, err := getPluginConfigs()
|
pcfgs, err := cli.getPluginConfigs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
ncfgs := map[string]NotificationsCfg{}
|
ncfgs := map[string]NotificationsCfg{}
|
||||||
for _, pc := range pcfgs {
|
for _, pc := range pcfgs {
|
||||||
ncfgs[pc.Name] = NotificationsCfg{
|
ncfgs[pc.Name] = NotificationsCfg{
|
||||||
Config: pc,
|
Config: pc,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
profiles, err := csprofiles.NewProfile(csConfig.API.Server.Profiles)
|
|
||||||
|
profiles, err := csprofiles.NewProfile(cfg.API.Server.Profiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("while extracting profiles from configuration: %w", err)
|
return nil, fmt.Errorf("while extracting profiles from configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for profileID, profile := range profiles {
|
for profileID, profile := range profiles {
|
||||||
for _, notif := range profile.Cfg.Notifications {
|
for _, notif := range profile.Cfg.Notifications {
|
||||||
pc, ok := pcfgs[notif]
|
pc, ok := pcfgs[notif]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("notification plugin '%s' does not exist", notif)
|
return nil, fmt.Errorf("notification plugin '%s' does not exist", notif)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp, ok := ncfgs[pc.Name]
|
tmp, ok := ncfgs[pc.Name]
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("notification plugin '%s' does not exist", pc.Name)
|
return nil, fmt.Errorf("notification plugin '%s' does not exist", pc.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
tmp.Profiles = append(tmp.Profiles, profile.Cfg)
|
tmp.Profiles = append(tmp.Profiles, profile.Cfg)
|
||||||
tmp.ids = append(tmp.ids, uint(profileID))
|
tmp.ids = append(tmp.ids, uint(profileID))
|
||||||
ncfgs[pc.Name] = tmp
|
ncfgs[pc.Name] = tmp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return ncfgs, nil
|
return ncfgs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli cliNotifications) NewListCmd() *cobra.Command {
|
func (cli *cliNotifications) NewListCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Short: "list active notifications plugins",
|
Short: "list active notifications plugins",
|
||||||
|
@ -144,21 +160,22 @@ func (cli cliNotifications) NewListCmd() *cobra.Command {
|
||||||
Example: `cscli notifications list`,
|
Example: `cscli notifications list`,
|
||||||
Args: cobra.ExactArgs(0),
|
Args: cobra.ExactArgs(0),
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
RunE: func(cmd *cobra.Command, arg []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
ncfgs, err := getProfilesConfigs()
|
cfg := cli.cfg()
|
||||||
|
ncfgs, err := cli.getProfilesConfigs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't build profiles configuration: %w", err)
|
return fmt.Errorf("can't build profiles configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if csConfig.Cscli.Output == "human" {
|
if cfg.Cscli.Output == "human" {
|
||||||
notificationListTable(color.Output, ncfgs)
|
notificationListTable(color.Output, ncfgs)
|
||||||
} else if csConfig.Cscli.Output == "json" {
|
} else if cfg.Cscli.Output == "json" {
|
||||||
x, err := json.MarshalIndent(ncfgs, "", " ")
|
x, err := json.MarshalIndent(ncfgs, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal notification configuration: %w", err)
|
return fmt.Errorf("failed to marshal notification configuration: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s", string(x))
|
fmt.Printf("%s", string(x))
|
||||||
} else if csConfig.Cscli.Output == "raw" {
|
} else if cfg.Cscli.Output == "raw" {
|
||||||
csvwriter := csv.NewWriter(os.Stdout)
|
csvwriter := csv.NewWriter(os.Stdout)
|
||||||
err := csvwriter.Write([]string{"Name", "Type", "Profile name"})
|
err := csvwriter.Write([]string{"Name", "Type", "Profile name"})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -176,6 +193,7 @@ func (cli cliNotifications) NewListCmd() *cobra.Command {
|
||||||
}
|
}
|
||||||
csvwriter.Flush()
|
csvwriter.Flush()
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -183,7 +201,7 @@ func (cli cliNotifications) NewListCmd() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli cliNotifications) NewInspectCmd() *cobra.Command {
|
func (cli *cliNotifications) NewInspectCmd() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "inspect",
|
Use: "inspect",
|
||||||
Short: "Inspect active notifications plugin configuration",
|
Short: "Inspect active notifications plugin configuration",
|
||||||
|
@ -191,36 +209,32 @@ func (cli cliNotifications) NewInspectCmd() *cobra.Command {
|
||||||
Example: `cscli notifications inspect <plugin_name>`,
|
Example: `cscli notifications inspect <plugin_name>`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, args []string) error {
|
||||||
if args[0] == "" {
|
cfg := cli.cfg()
|
||||||
return fmt.Errorf("please provide a plugin name to inspect")
|
ncfgs, err := cli.getProfilesConfigs()
|
||||||
}
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
|
||||||
ncfgs, err := getProfilesConfigs()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't build profiles configuration: %w", err)
|
return fmt.Errorf("can't build profiles configuration: %w", err)
|
||||||
}
|
}
|
||||||
cfg, ok := ncfgs[args[0]]
|
ncfg, ok := ncfgs[args[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("plugin '%s' does not exist or is not active", args[0])
|
return fmt.Errorf("plugin '%s' does not exist or is not active", args[0])
|
||||||
}
|
}
|
||||||
if csConfig.Cscli.Output == "human" || csConfig.Cscli.Output == "raw" {
|
if cfg.Cscli.Output == "human" || cfg.Cscli.Output == "raw" {
|
||||||
fmt.Printf(" - %15s: %15s\n", "Type", cfg.Config.Type)
|
fmt.Printf(" - %15s: %15s\n", "Type", ncfg.Config.Type)
|
||||||
fmt.Printf(" - %15s: %15s\n", "Name", cfg.Config.Name)
|
fmt.Printf(" - %15s: %15s\n", "Name", ncfg.Config.Name)
|
||||||
fmt.Printf(" - %15s: %15s\n", "Timeout", cfg.Config.TimeOut)
|
fmt.Printf(" - %15s: %15s\n", "Timeout", ncfg.Config.TimeOut)
|
||||||
fmt.Printf(" - %15s: %15s\n", "Format", cfg.Config.Format)
|
fmt.Printf(" - %15s: %15s\n", "Format", ncfg.Config.Format)
|
||||||
for k, v := range cfg.Config.Config {
|
for k, v := range ncfg.Config.Config {
|
||||||
fmt.Printf(" - %15s: %15v\n", k, v)
|
fmt.Printf(" - %15s: %15v\n", k, v)
|
||||||
}
|
}
|
||||||
} else if csConfig.Cscli.Output == "json" {
|
} else if cfg.Cscli.Output == "json" {
|
||||||
x, err := json.MarshalIndent(cfg, "", " ")
|
x, err := json.MarshalIndent(cfg, "", " ")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to marshal notification configuration: %w", err)
|
return fmt.Errorf("failed to marshal notification configuration: %w", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("%s", string(x))
|
fmt.Printf("%s", string(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -228,12 +242,13 @@ func (cli cliNotifications) NewInspectCmd() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli cliNotifications) NewTestCmd() *cobra.Command {
|
func (cli *cliNotifications) NewTestCmd() *cobra.Command {
|
||||||
var (
|
var (
|
||||||
pluginBroker csplugin.PluginBroker
|
pluginBroker csplugin.PluginBroker
|
||||||
pluginTomb tomb.Tomb
|
pluginTomb tomb.Tomb
|
||||||
alertOverride string
|
alertOverride string
|
||||||
)
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "test [plugin name]",
|
Use: "test [plugin name]",
|
||||||
Short: "send a generic test alert to notification plugin",
|
Short: "send a generic test alert to notification plugin",
|
||||||
|
@ -241,25 +256,26 @@ func (cli cliNotifications) NewTestCmd() *cobra.Command {
|
||||||
Example: `cscli notifications test [plugin_name]`,
|
Example: `cscli notifications test [plugin_name]`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(_ *cobra.Command, args []string) error {
|
||||||
pconfigs, err := getPluginConfigs()
|
cfg := cli.cfg()
|
||||||
|
pconfigs, err := cli.getPluginConfigs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't build profiles configuration: %w", err)
|
return fmt.Errorf("can't build profiles configuration: %w", err)
|
||||||
}
|
}
|
||||||
cfg, ok := pconfigs[args[0]]
|
pcfg, ok := pconfigs[args[0]]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("plugin name: '%s' does not exist", args[0])
|
return fmt.Errorf("plugin name: '%s' does not exist", args[0])
|
||||||
}
|
}
|
||||||
//Create a single profile with plugin name as notification name
|
//Create a single profile with plugin name as notification name
|
||||||
return pluginBroker.Init(csConfig.PluginConfig, []*csconfig.ProfileCfg{
|
return pluginBroker.Init(cfg.PluginConfig, []*csconfig.ProfileCfg{
|
||||||
{
|
{
|
||||||
Notifications: []string{
|
Notifications: []string{
|
||||||
cfg.Name,
|
pcfg.Name,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}, csConfig.ConfigPaths)
|
}, cfg.ConfigPaths)
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
pluginTomb.Go(func() error {
|
pluginTomb.Go(func() error {
|
||||||
pluginBroker.Run(&pluginTomb)
|
pluginBroker.Run(&pluginTomb)
|
||||||
return nil
|
return nil
|
||||||
|
@ -298,13 +314,16 @@ func (cli cliNotifications) NewTestCmd() *cobra.Command {
|
||||||
if err := yaml.Unmarshal([]byte(alertOverride), alert); err != nil {
|
if err := yaml.Unmarshal([]byte(alertOverride), alert); err != nil {
|
||||||
return fmt.Errorf("failed to unmarshal alert override: %w", err)
|
return fmt.Errorf("failed to unmarshal alert override: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginBroker.PluginChannel <- csplugin.ProfileAlert{
|
pluginBroker.PluginChannel <- csplugin.ProfileAlert{
|
||||||
ProfileID: uint(0),
|
ProfileID: uint(0),
|
||||||
Alert: alert,
|
Alert: alert,
|
||||||
}
|
}
|
||||||
|
|
||||||
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
|
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
|
||||||
pluginTomb.Kill(fmt.Errorf("terminating"))
|
pluginTomb.Kill(fmt.Errorf("terminating"))
|
||||||
pluginTomb.Wait()
|
pluginTomb.Wait()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -313,9 +332,11 @@ func (cli cliNotifications) NewTestCmd() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cli cliNotifications) NewReinjectCmd() *cobra.Command {
|
func (cli *cliNotifications) NewReinjectCmd() *cobra.Command {
|
||||||
var alertOverride string
|
var (
|
||||||
var alert *models.Alert
|
alertOverride string
|
||||||
|
alert *models.Alert
|
||||||
|
)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "reinject",
|
Use: "reinject",
|
||||||
|
@ -328,25 +349,30 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
|
||||||
`,
|
`,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
DisableAutoGenTag: true,
|
DisableAutoGenTag: true,
|
||||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
PreRunE: func(_ *cobra.Command, args []string) error {
|
||||||
var err error
|
var err error
|
||||||
alert, err = FetchAlertFromArgString(args[0])
|
alert, err = cli.fetchAlertFromArgString(args[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(_ *cobra.Command, _ []string) error {
|
||||||
var (
|
var (
|
||||||
pluginBroker csplugin.PluginBroker
|
pluginBroker csplugin.PluginBroker
|
||||||
pluginTomb tomb.Tomb
|
pluginTomb tomb.Tomb
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cfg := cli.cfg()
|
||||||
|
|
||||||
if alertOverride != "" {
|
if alertOverride != "" {
|
||||||
if err := json.Unmarshal([]byte(alertOverride), alert); err != nil {
|
if err := json.Unmarshal([]byte(alertOverride), alert); err != nil {
|
||||||
return fmt.Errorf("can't unmarshal data in the alert flag: %w", err)
|
return fmt.Errorf("can't unmarshal data in the alert flag: %w", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := pluginBroker.Init(csConfig.PluginConfig, csConfig.API.Server.Profiles, csConfig.ConfigPaths)
|
|
||||||
|
err := pluginBroker.Init(cfg.PluginConfig, cfg.API.Server.Profiles, cfg.ConfigPaths)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("can't initialize plugins: %w", err)
|
return fmt.Errorf("can't initialize plugins: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -356,7 +382,7 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
profiles, err := csprofiles.NewProfile(csConfig.API.Server.Profiles)
|
profiles, err := csprofiles.NewProfile(cfg.API.Server.Profiles)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot extract profiles from configuration: %w", err)
|
return fmt.Errorf("cannot extract profiles from configuration: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -382,9 +408,9 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
|
||||||
default:
|
default:
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
log.Info("sleeping\n")
|
log.Info("sleeping\n")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if profile.Cfg.OnSuccess == "break" {
|
if profile.Cfg.OnSuccess == "break" {
|
||||||
log.Infof("The profile %s contains a 'on_success: break' so bailing out", profile.Cfg.Name)
|
log.Infof("The profile %s contains a 'on_success: break' so bailing out", profile.Cfg.Name)
|
||||||
break
|
break
|
||||||
|
@ -393,6 +419,7 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
|
||||||
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
|
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
|
||||||
pluginTomb.Kill(fmt.Errorf("terminating"))
|
pluginTomb.Kill(fmt.Errorf("terminating"))
|
||||||
pluginTomb.Wait()
|
pluginTomb.Wait()
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -401,18 +428,22 @@ cscli notifications reinject <alert_id> -a '{"remediation": true,"scenario":"not
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func FetchAlertFromArgString(toParse string) (*models.Alert, error) {
|
func (cli *cliNotifications) fetchAlertFromArgString(toParse string) (*models.Alert, error) {
|
||||||
|
cfg := cli.cfg()
|
||||||
|
|
||||||
id, err := strconv.Atoi(toParse)
|
id, err := strconv.Atoi(toParse)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("bad alert id %s", toParse)
|
return nil, fmt.Errorf("bad alert id %s", toParse)
|
||||||
}
|
}
|
||||||
apiURL, err := url.Parse(csConfig.API.Client.Credentials.URL)
|
|
||||||
|
apiURL, err := url.Parse(cfg.API.Client.Credentials.URL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error parsing the URL of the API: %w", err)
|
return nil, fmt.Errorf("error parsing the URL of the API: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := apiclient.NewClient(&apiclient.Config{
|
client, err := apiclient.NewClient(&apiclient.Config{
|
||||||
MachineID: csConfig.API.Client.Credentials.Login,
|
MachineID: cfg.API.Client.Credentials.Login,
|
||||||
Password: strfmt.Password(csConfig.API.Client.Credentials.Password),
|
Password: strfmt.Password(cfg.API.Client.Credentials.Password),
|
||||||
UserAgent: fmt.Sprintf("crowdsec/%s", version.String()),
|
UserAgent: fmt.Sprintf("crowdsec/%s", version.String()),
|
||||||
URL: apiURL,
|
URL: apiURL,
|
||||||
VersionPrefix: "v1",
|
VersionPrefix: "v1",
|
||||||
|
@ -420,9 +451,11 @@ func FetchAlertFromArgString(toParse string) (*models.Alert, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error creating the client for the API: %w", err)
|
return nil, fmt.Errorf("error creating the client for the API: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
alert, _, err := client.Alerts.GetByID(context.Background(), id)
|
alert, _, err := client.Alerts.GetByID(context.Background(), id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("can't find alert with id %d: %w", id, err)
|
return nil, fmt.Errorf("can't find alert with id %d: %w", id, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return alert, nil
|
return alert, nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue