2022-05-18 14:13:33 +00:00
package main
import (
2022-08-30 13:45:52 +00:00
"context"
2022-05-18 14:13:33 +00:00
"encoding/csv"
"encoding/json"
"fmt"
"io/fs"
2022-08-30 13:45:52 +00:00
"net/url"
2022-05-18 14:13:33 +00:00
"os"
"path/filepath"
2022-08-30 13:45:52 +00:00
"strconv"
2022-05-18 14:13:33 +00:00
"strings"
2022-08-30 13:45:52 +00:00
"time"
2022-05-18 14:13:33 +00:00
2022-10-13 10:28:24 +00:00
"github.com/fatih/color"
2022-08-30 13:45:52 +00:00
"github.com/go-openapi/strfmt"
2022-05-18 14:13:33 +00:00
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
2022-08-30 13:45:52 +00:00
"gopkg.in/tomb.v2"
2023-11-28 13:17:54 +00:00
"gopkg.in/yaml.v3"
2022-10-07 09:05:35 +00:00
2023-11-28 13:17:54 +00:00
"github.com/crowdsecurity/go-cs-lib/ptr"
2023-07-28 14:35:08 +00:00
"github.com/crowdsecurity/go-cs-lib/version"
2023-05-23 08:52:47 +00:00
2024-02-12 10:40:59 +00:00
"github.com/crowdsecurity/crowdsec/cmd/crowdsec-cli/require"
2022-10-07 09:05:35 +00:00
"github.com/crowdsecurity/crowdsec/pkg/apiclient"
"github.com/crowdsecurity/crowdsec/pkg/csconfig"
"github.com/crowdsecurity/crowdsec/pkg/csplugin"
"github.com/crowdsecurity/crowdsec/pkg/csprofiles"
2023-11-28 13:17:54 +00:00
"github.com/crowdsecurity/crowdsec/pkg/models"
2024-02-12 10:40:59 +00:00
"github.com/crowdsecurity/crowdsec/pkg/types"
2022-05-18 14:13:33 +00:00
)
type NotificationsCfg struct {
Config csplugin . PluginConfig ` json:"plugin_config" `
Profiles [ ] * csconfig . ProfileCfg ` json:"associated_profiles" `
2022-08-30 13:45:52 +00:00
ids [ ] uint
2022-05-18 14:13:33 +00:00
}
2024-02-12 10:40:59 +00:00
type cliNotifications struct {
cfg configGetter
}
2023-12-07 13:36:35 +00:00
2024-02-12 10:40:59 +00:00
func NewCLINotifications ( cfg configGetter ) * cliNotifications {
return & cliNotifications {
cfg : cfg ,
}
2023-12-07 13:36:35 +00:00
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) NewCommand ( ) * cobra . Command {
2023-12-07 13:36:35 +00:00
cmd := & cobra . Command {
2022-05-18 14:13:33 +00:00
Use : "notifications [action]" ,
Short : "Helper for notification plugin configuration" ,
Long : "To list/inspect/test notification template" ,
Args : cobra . MinimumNArgs ( 1 ) ,
Aliases : [ ] string { "notifications" , "notification" } ,
DisableAutoGenTag : true ,
2024-02-12 10:40:59 +00:00
PersistentPreRunE : func ( _ * cobra . Command , _ [ ] string ) error {
cfg := cli . cfg ( )
if err := require . LAPI ( cfg ) ; err != nil {
2023-07-27 15:02:20 +00:00
return err
}
2024-02-12 10:40:59 +00:00
if err := cfg . LoadAPIClient ( ) ; err != nil {
2023-12-21 12:27:34 +00:00
return fmt . Errorf ( "loading api client: %w" , err )
}
2024-02-12 10:40:59 +00:00
if err := require . Notifications ( cfg ) ; err != nil {
2023-07-27 15:02:20 +00:00
return err
2022-08-02 18:44:19 +00:00
}
2023-07-27 15:02:20 +00:00
return nil
2022-05-18 14:13:33 +00:00
} ,
}
2023-12-07 13:36:35 +00:00
cmd . AddCommand ( cli . NewListCmd ( ) )
cmd . AddCommand ( cli . NewInspectCmd ( ) )
cmd . AddCommand ( cli . NewReinjectCmd ( ) )
cmd . AddCommand ( cli . NewTestCmd ( ) )
2023-01-19 12:29:36 +00:00
2023-12-07 13:36:35 +00:00
return cmd
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) getPluginConfigs ( ) ( map [ string ] csplugin . PluginConfig , error ) {
cfg := cli . cfg ( )
2023-01-19 12:29:36 +00:00
pcfgs := map [ string ] csplugin . PluginConfig { }
wf := func ( path string , info fs . FileInfo , err error ) error {
if info == nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "error while traversing directory %s: %w" , path , err )
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
name := filepath . Join ( cfg . ConfigPaths . NotificationDir , info . Name ( ) ) //Avoid calling info.Name() twice
2023-01-19 12:29:36 +00:00
if ( strings . HasSuffix ( name , "yaml" ) || strings . HasSuffix ( name , "yml" ) ) && ! ( info . IsDir ( ) ) {
ts , err := csplugin . ParsePluginConfigFile ( name )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "loading notifification plugin configuration with %s: %w" , name , err )
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
2023-01-19 12:29:36 +00:00
for _ , t := range ts {
2023-11-28 13:17:54 +00:00
csplugin . SetRequiredFields ( & t )
2023-01-19 12:29:36 +00:00
pcfgs [ t . Name ] = t
}
}
2024-02-12 10:40:59 +00:00
2023-01-19 12:29:36 +00:00
return nil
}
2024-02-12 10:40:59 +00:00
if err := filepath . Walk ( cfg . ConfigPaths . NotificationDir , wf ) ; err != nil {
2023-06-22 13:01:34 +00:00
return nil , fmt . Errorf ( "while loading notifification plugin configuration: %w" , err )
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
return pcfgs , nil
}
2023-01-19 12:29:36 +00:00
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) getProfilesConfigs ( ) ( map [ string ] NotificationsCfg , error ) {
cfg := cli . cfg ( )
2023-01-19 12:29:36 +00:00
// A bit of a tricky stuf now: reconcile profiles and notification plugins
2024-02-12 10:40:59 +00:00
pcfgs , err := cli . getPluginConfigs ( )
2023-11-28 13:17:54 +00:00
if err != nil {
return nil , err
}
2024-02-12 10:40:59 +00:00
2023-01-19 12:29:36 +00:00
ncfgs := map [ string ] NotificationsCfg { }
2023-12-21 11:16:54 +00:00
for _ , pc := range pcfgs {
ncfgs [ pc . Name ] = NotificationsCfg {
Config : pc ,
}
}
2024-02-12 10:40:59 +00:00
profiles , err := csprofiles . NewProfile ( cfg . API . Server . Profiles )
2023-01-19 12:29:36 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return nil , fmt . Errorf ( "while extracting profiles from configuration: %w" , err )
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
2023-01-19 12:29:36 +00:00
for profileID , profile := range profiles {
for _ , notif := range profile . Cfg . Notifications {
2023-12-21 11:16:54 +00:00
pc , ok := pcfgs [ notif ]
if ! ok {
return nil , fmt . Errorf ( "notification plugin '%s' does not exist" , notif )
}
2024-02-12 10:40:59 +00:00
2023-12-21 11:16:54 +00:00
tmp , ok := ncfgs [ pc . Name ]
if ! ok {
return nil , fmt . Errorf ( "notification plugin '%s' does not exist" , pc . Name )
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
2023-12-21 11:16:54 +00:00
tmp . Profiles = append ( tmp . Profiles , profile . Cfg )
tmp . ids = append ( tmp . ids , uint ( profileID ) )
ncfgs [ pc . Name ] = tmp
2023-01-19 12:29:36 +00:00
}
}
2024-02-12 10:40:59 +00:00
2023-01-19 12:29:36 +00:00
return ncfgs , nil
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) NewListCmd ( ) * cobra . Command {
2023-12-07 13:36:35 +00:00
cmd := & cobra . Command {
2022-05-18 14:13:33 +00:00
Use : "list" ,
2023-11-28 13:17:54 +00:00
Short : "list active notifications plugins" ,
Long : ` list active notifications plugins ` ,
2022-05-18 14:13:33 +00:00
Example : ` cscli notifications list ` ,
Args : cobra . ExactArgs ( 0 ) ,
DisableAutoGenTag : true ,
2024-02-12 10:40:59 +00:00
RunE : func ( _ * cobra . Command , _ [ ] string ) error {
cfg := cli . cfg ( )
ncfgs , err := cli . getProfilesConfigs ( )
2022-08-30 13:45:52 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "can't build profiles configuration: %w" , err )
2022-08-30 13:45:52 +00:00
}
2024-02-12 10:40:59 +00:00
if cfg . Cscli . Output == "human" {
2022-10-13 10:28:24 +00:00
notificationListTable ( color . Output , ncfgs )
2024-02-12 10:40:59 +00:00
} else if cfg . Cscli . Output == "json" {
2022-05-18 14:13:33 +00:00
x , err := json . MarshalIndent ( ncfgs , "" , " " )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "failed to marshal notification configuration: %w" , err )
2022-05-18 14:13:33 +00:00
}
fmt . Printf ( "%s" , string ( x ) )
2024-02-12 10:40:59 +00:00
} else if cfg . Cscli . Output == "raw" {
2022-05-18 14:13:33 +00:00
csvwriter := csv . NewWriter ( os . Stdout )
err := csvwriter . Write ( [ ] string { "Name" , "Type" , "Profile name" } )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "failed to write raw header: %w" , err )
2022-05-18 14:13:33 +00:00
}
for _ , b := range ncfgs {
profilesList := [ ] string { }
for _ , p := range b . Profiles {
profilesList = append ( profilesList , p . Name )
}
err := csvwriter . Write ( [ ] string { b . Config . Name , b . Config . Type , strings . Join ( profilesList , ", " ) } )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "failed to write raw content: %w" , err )
2022-05-18 14:13:33 +00:00
}
}
csvwriter . Flush ( )
}
2024-02-12 10:40:59 +00:00
2022-08-30 13:45:52 +00:00
return nil
2022-05-18 14:13:33 +00:00
} ,
}
2023-12-07 13:36:35 +00:00
return cmd
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) NewInspectCmd ( ) * cobra . Command {
2023-12-07 13:36:35 +00:00
cmd := & cobra . Command {
2022-05-18 14:13:33 +00:00
Use : "inspect" ,
Short : "Inspect active notifications plugin configuration" ,
Long : ` Inspect active notifications plugin and show configuration ` ,
Example : ` cscli notifications inspect <plugin_name> ` ,
Args : cobra . ExactArgs ( 1 ) ,
DisableAutoGenTag : true ,
2024-02-12 10:40:59 +00:00
RunE : func ( _ * cobra . Command , args [ ] string ) error {
cfg := cli . cfg ( )
ncfgs , err := cli . getProfilesConfigs ( )
2022-08-30 13:45:52 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "can't build profiles configuration: %w" , err )
2022-05-18 14:13:33 +00:00
}
2024-02-12 10:40:59 +00:00
ncfg , ok := ncfgs [ args [ 0 ] ]
2023-11-28 13:17:54 +00:00
if ! ok {
return fmt . Errorf ( "plugin '%s' does not exist or is not active" , args [ 0 ] )
2022-05-18 14:13:33 +00:00
}
2024-02-12 10:40:59 +00:00
if cfg . Cscli . Output == "human" || cfg . Cscli . Output == "raw" {
fmt . Printf ( " - %15s: %15s\n" , "Type" , ncfg . Config . Type )
fmt . Printf ( " - %15s: %15s\n" , "Name" , ncfg . Config . Name )
fmt . Printf ( " - %15s: %15s\n" , "Timeout" , ncfg . Config . TimeOut )
fmt . Printf ( " - %15s: %15s\n" , "Format" , ncfg . Config . Format )
for k , v := range ncfg . Config . Config {
2022-05-18 14:13:33 +00:00
fmt . Printf ( " - %15s: %15v\n" , k , v )
}
2024-02-12 10:40:59 +00:00
} else if cfg . Cscli . Output == "json" {
2022-05-18 14:13:33 +00:00
x , err := json . MarshalIndent ( cfg , "" , " " )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "failed to marshal notification configuration: %w" , err )
2022-05-18 14:13:33 +00:00
}
fmt . Printf ( "%s" , string ( x ) )
}
2024-02-12 10:40:59 +00:00
2022-08-30 13:45:52 +00:00
return nil
2022-05-18 14:13:33 +00:00
} ,
}
2023-01-19 12:29:36 +00:00
2023-12-07 13:36:35 +00:00
return cmd
2023-01-19 12:29:36 +00:00
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) NewTestCmd ( ) * cobra . Command {
2023-11-28 13:17:54 +00:00
var (
pluginBroker csplugin . PluginBroker
pluginTomb tomb . Tomb
alertOverride string
)
2024-02-12 10:40:59 +00:00
2023-12-07 13:36:35 +00:00
cmd := & cobra . Command {
2023-11-28 13:17:54 +00:00
Use : "test [plugin name]" ,
Short : "send a generic test alert to notification plugin" ,
Long : ` send a generic test alert to a notification plugin to test configuration even if is not active ` ,
Example : ` cscli notifications test [plugin_name] ` ,
Args : cobra . ExactArgs ( 1 ) ,
DisableAutoGenTag : true ,
2024-02-12 10:40:59 +00:00
PreRunE : func ( _ * cobra . Command , args [ ] string ) error {
cfg := cli . cfg ( )
pconfigs , err := cli . getPluginConfigs ( )
2023-11-28 13:17:54 +00:00
if err != nil {
return fmt . Errorf ( "can't build profiles configuration: %w" , err )
}
2024-02-12 10:40:59 +00:00
pcfg , ok := pconfigs [ args [ 0 ] ]
2023-11-28 13:17:54 +00:00
if ! ok {
return fmt . Errorf ( "plugin name: '%s' does not exist" , args [ 0 ] )
}
//Create a single profile with plugin name as notification name
2024-02-12 10:40:59 +00:00
return pluginBroker . Init ( cfg . PluginConfig , [ ] * csconfig . ProfileCfg {
2023-11-28 13:17:54 +00:00
{
Notifications : [ ] string {
2024-02-12 10:40:59 +00:00
pcfg . Name ,
2023-11-28 13:17:54 +00:00
} ,
} ,
2024-02-12 10:40:59 +00:00
} , cfg . ConfigPaths )
2023-11-28 13:17:54 +00:00
} ,
2024-02-12 10:40:59 +00:00
RunE : func ( _ * cobra . Command , _ [ ] string ) error {
2023-11-28 13:17:54 +00:00
pluginTomb . Go ( func ( ) error {
pluginBroker . Run ( & pluginTomb )
return nil
} )
alert := & models . Alert {
Capacity : ptr . Of ( int32 ( 0 ) ) ,
Decisions : [ ] * models . Decision { {
Duration : ptr . Of ( "4h" ) ,
Scope : ptr . Of ( "Ip" ) ,
Value : ptr . Of ( "10.10.10.10" ) ,
Type : ptr . Of ( "ban" ) ,
Scenario : ptr . Of ( "test alert" ) ,
Origin : ptr . Of ( types . CscliOrigin ) ,
} } ,
Events : [ ] * models . Event { } ,
EventsCount : ptr . Of ( int32 ( 1 ) ) ,
Leakspeed : ptr . Of ( "0" ) ,
Message : ptr . Of ( "test alert" ) ,
ScenarioHash : ptr . Of ( "" ) ,
Scenario : ptr . Of ( "test alert" ) ,
ScenarioVersion : ptr . Of ( "" ) ,
Simulated : ptr . Of ( false ) ,
Source : & models . Source {
AsName : "" ,
AsNumber : "" ,
Cn : "" ,
IP : "10.10.10.10" ,
Range : "" ,
Scope : ptr . Of ( "Ip" ) ,
Value : ptr . Of ( "10.10.10.10" ) ,
} ,
StartAt : ptr . Of ( time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ) ,
StopAt : ptr . Of ( time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ) ,
CreatedAt : time . Now ( ) . UTC ( ) . Format ( time . RFC3339 ) ,
}
if err := yaml . Unmarshal ( [ ] byte ( alertOverride ) , alert ) ; err != nil {
return fmt . Errorf ( "failed to unmarshal alert override: %w" , err )
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
pluginBroker . PluginChannel <- csplugin . ProfileAlert {
ProfileID : uint ( 0 ) ,
Alert : alert ,
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
pluginTomb . Kill ( fmt . Errorf ( "terminating" ) )
pluginTomb . Wait ( )
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
return nil
} ,
}
2023-12-07 13:36:35 +00:00
cmd . Flags ( ) . StringVarP ( & alertOverride , "alert" , "a" , "" , "JSON string used to override alert fields in the generic alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)" )
2023-11-28 13:17:54 +00:00
2023-12-07 13:36:35 +00:00
return cmd
2023-11-28 13:17:54 +00:00
}
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) NewReinjectCmd ( ) * cobra . Command {
var (
alertOverride string
alert * models . Alert
)
2023-01-19 12:29:36 +00:00
2023-12-07 13:36:35 +00:00
cmd := & cobra . Command {
2022-08-30 13:45:52 +00:00
Use : "reinject" ,
2023-11-28 13:17:54 +00:00
Short : "reinject an alert into profiles to trigger notifications" ,
Long : ` reinject an alert into profiles to be evaluated by the filter and sent to matched notifications plugins ` ,
2022-08-30 13:45:52 +00:00
Example : `
cscli notifications reinject < alert_id >
2023-11-28 13:17:54 +00:00
cscli notifications reinject < alert_id > - a ' { "remediation" : false , "scenario" : "notification/test" } '
2022-08-30 13:45:52 +00:00
cscli notifications reinject < alert_id > - a ' { "remediation" : true , "scenario" : "notification/test" } '
` ,
Args : cobra . ExactArgs ( 1 ) ,
DisableAutoGenTag : true ,
2024-02-12 10:40:59 +00:00
PreRunE : func ( _ * cobra . Command , args [ ] string ) error {
2023-11-28 13:17:54 +00:00
var err error
2024-02-12 10:40:59 +00:00
alert , err = cli . fetchAlertFromArgString ( args [ 0 ] )
2023-11-28 13:17:54 +00:00
if err != nil {
return err
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
return nil
} ,
2024-02-12 10:40:59 +00:00
RunE : func ( _ * cobra . Command , _ [ ] string ) error {
2022-08-30 13:45:52 +00:00
var (
pluginBroker csplugin . PluginBroker
pluginTomb tomb . Tomb
)
2024-02-12 10:40:59 +00:00
cfg := cli . cfg ( )
2022-08-30 13:45:52 +00:00
if alertOverride != "" {
2023-11-28 13:17:54 +00:00
if err := json . Unmarshal ( [ ] byte ( alertOverride ) , alert ) ; err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "can't unmarshal data in the alert flag: %w" , err )
2022-08-30 13:45:52 +00:00
}
}
2024-02-12 10:40:59 +00:00
err := pluginBroker . Init ( cfg . PluginConfig , cfg . API . Server . Profiles , cfg . ConfigPaths )
2022-08-30 13:45:52 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "can't initialize plugins: %w" , err )
2022-08-30 13:45:52 +00:00
}
pluginTomb . Go ( func ( ) error {
pluginBroker . Run ( & pluginTomb )
return nil
} )
2024-02-12 10:40:59 +00:00
profiles , err := csprofiles . NewProfile ( cfg . API . Server . Profiles )
2022-08-30 13:45:52 +00:00
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "cannot extract profiles from configuration: %w" , err )
2022-08-30 13:45:52 +00:00
}
for id , profile := range profiles {
_ , matched , err := profile . EvaluateProfile ( alert )
if err != nil {
2023-06-22 13:01:34 +00:00
return fmt . Errorf ( "can't evaluate profile %s: %w" , profile . Cfg . Name , err )
2022-08-30 13:45:52 +00:00
}
if ! matched {
log . Infof ( "The profile %s didn't match" , profile . Cfg . Name )
continue
}
log . Infof ( "The profile %s matched, sending to its configured notification plugins" , profile . Cfg . Name )
loop :
for {
select {
case pluginBroker . PluginChannel <- csplugin . ProfileAlert {
ProfileID : uint ( id ) ,
Alert : alert ,
} :
break loop
default :
time . Sleep ( 50 * time . Millisecond )
log . Info ( "sleeping\n" )
}
}
2024-02-12 10:40:59 +00:00
2022-08-30 13:45:52 +00:00
if profile . Cfg . OnSuccess == "break" {
log . Infof ( "The profile %s contains a 'on_success: break' so bailing out" , profile . Cfg . Name )
break
}
}
2023-11-28 13:17:54 +00:00
//time.Sleep(2 * time.Second) // There's no mechanism to ensure notification has been sent
2023-06-22 13:01:34 +00:00
pluginTomb . Kill ( fmt . Errorf ( "terminating" ) )
2022-08-30 13:45:52 +00:00
pluginTomb . Wait ( )
2024-02-12 10:40:59 +00:00
2022-08-30 13:45:52 +00:00
return nil
} ,
}
2023-12-07 13:36:35 +00:00
cmd . Flags ( ) . StringVarP ( & alertOverride , "alert" , "a" , "" , "JSON string used to override alert fields in the reinjected alert (see crowdsec/pkg/models/alert.go in the source tree for the full definition of the object)" )
2022-08-02 18:44:19 +00:00
2023-12-07 13:36:35 +00:00
return cmd
2022-05-18 14:13:33 +00:00
}
2023-11-28 13:17:54 +00:00
2024-02-12 10:40:59 +00:00
func ( cli * cliNotifications ) fetchAlertFromArgString ( toParse string ) ( * models . Alert , error ) {
cfg := cli . cfg ( )
2023-11-28 13:17:54 +00:00
id , err := strconv . Atoi ( toParse )
if err != nil {
return nil , fmt . Errorf ( "bad alert id %s" , toParse )
}
2024-02-12 10:40:59 +00:00
apiURL , err := url . Parse ( cfg . API . Client . Credentials . URL )
2023-11-28 13:17:54 +00:00
if err != nil {
return nil , fmt . Errorf ( "error parsing the URL of the API: %w" , err )
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
client , err := apiclient . NewClient ( & apiclient . Config {
2024-02-12 10:40:59 +00:00
MachineID : cfg . API . Client . Credentials . Login ,
Password : strfmt . Password ( cfg . API . Client . Credentials . Password ) ,
2023-11-28 13:17:54 +00:00
UserAgent : fmt . Sprintf ( "crowdsec/%s" , version . String ( ) ) ,
URL : apiURL ,
VersionPrefix : "v1" ,
} )
if err != nil {
return nil , fmt . Errorf ( "error creating the client for the API: %w" , err )
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
alert , _ , err := client . Alerts . GetByID ( context . Background ( ) , id )
if err != nil {
return nil , fmt . Errorf ( "can't find alert with id %d: %w" , id , err )
}
2024-02-12 10:40:59 +00:00
2023-11-28 13:17:54 +00:00
return alert , nil
}