Pārlūkot izejas kodu

Alert inspect improvement / Use correct CSV output when listing in raw format (#1127)

AlteredCoder 3 gadi atpakaļ
vecāks
revīzija
9c8ca5c73a

+ 29 - 24
cmd/crowdsec-cli/alerts.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"context"
+	"encoding/csv"
 	"encoding/json"
 	"fmt"
 	"net/url"
@@ -48,36 +49,38 @@ func DecisionsFromAlert(alert *models.Alert) string {
 func AlertsToTable(alerts *models.GetAlertsResponse, printMachine bool) error {
 
 	if csConfig.Cscli.Output == "raw" {
+		csvwriter := csv.NewWriter(os.Stdout)
 		if printMachine {
-			fmt.Printf("id,scope,value,reason,country,as,decisions,created_at,machine\n")
+			err := csvwriter.Write([]string{"id", "scope", "value", "reason", "country", "as", "decisions", "created_at", "machine"})
+			if err != nil {
+				return err
+			}
 		} else {
-			fmt.Printf("id,scope,value,reason,country,as,decisions,created_at\n")
+			err := csvwriter.Write([]string{"id", "scope", "value", "reason", "country", "as", "decisions", "created_at"})
+			if err != nil {
+				return err
+			}
 		}
 		for _, alertItem := range *alerts {
+			row := []string{
+				fmt.Sprintf("%d", alertItem.ID),
+				*alertItem.Source.Scope,
+				*alertItem.Source.Value,
+				*alertItem.Scenario,
+				alertItem.Source.Cn,
+				alertItem.Source.AsNumber + " " + alertItem.Source.AsName,
+				DecisionsFromAlert(alertItem),
+				*alertItem.StartAt,
+			}
 			if printMachine {
-				fmt.Printf("%v,%v,%v,%v,%v,%v,%v,%v,%v\n",
-					alertItem.ID,
-					*alertItem.Source.Scope,
-					*alertItem.Source.Value,
-					*alertItem.Scenario,
-					alertItem.Source.Cn,
-					alertItem.Source.AsNumber+" "+alertItem.Source.AsName,
-					DecisionsFromAlert(alertItem),
-					*alertItem.StartAt,
-					alertItem.MachineID)
-			} else {
-				fmt.Printf("%v,%v,%v,%v,%v,%v,%v,%v\n",
-					alertItem.ID,
-					*alertItem.Source.Scope,
-					*alertItem.Source.Value,
-					*alertItem.Scenario,
-					alertItem.Source.Cn,
-					alertItem.Source.AsNumber+" "+alertItem.Source.AsName,
-					DecisionsFromAlert(alertItem),
-					*alertItem.StartAt)
+				row = append(row, alertItem.MachineID)
+			}
+			err := csvwriter.Write(row)
+			if err != nil {
+				return err
 			}
-
 		}
+		csvwriter.Flush()
 	} else if csConfig.Cscli.Output == "json" {
 		x, _ := json.MarshalIndent(alerts, "", " ")
 		fmt.Printf("%s", string(x))
@@ -143,7 +146,9 @@ func DisplayOneAlert(alert *models.Alert, withDetail bool) error {
 		fmt.Printf(" - Events Count : %d\n", *alert.EventsCount)
 		fmt.Printf(" - Scope:Value: %s\n", scopeAndValue)
 		fmt.Printf(" - Country    : %s\n", alert.Source.Cn)
-		fmt.Printf(" - AS         : %s\n\n", alert.Source.AsName)
+		fmt.Printf(" - AS         : %s\n", alert.Source.AsName)
+		fmt.Printf(" - Begin      : %s\n", *alert.StartAt)
+		fmt.Printf(" - End        : %s\n\n", *alert.StopAt)
 		foundActive := false
 		table := tablewriter.NewWriter(os.Stdout)
 		table.SetHeader([]string{"ID", "scope:value", "action", "expiration", "created_at"})

+ 11 - 1
cmd/crowdsec-cli/bouncers.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"encoding/csv"
 	"encoding/json"
 	"fmt"
 	"os"
@@ -82,6 +83,11 @@ Note: This command requires database direct access, so is intended to be run on
 				}
 				fmt.Printf("%s", string(x))
 			} else if csConfig.Cscli.Output == "raw" {
+				csvwriter := csv.NewWriter(os.Stdout)
+				err := csvwriter.Write([]string{"name", "ip", "revoked", "last_pull", "type", "version"})
+				if err != nil {
+					log.Fatalf("failed to write raw header: %s", err)
+				}
 				for _, b := range blockers {
 					var revoked string
 					if !b.Revoked {
@@ -89,8 +95,12 @@ Note: This command requires database direct access, so is intended to be run on
 					} else {
 						revoked = "pending"
 					}
-					fmt.Printf("%s,%s,%s,%s,%s\n", b.Name, b.IPAddress, revoked, b.LastPull.Format(time.RFC3339), b.Version)
+					err := csvwriter.Write([]string{b.Name, b.IPAddress, revoked, b.LastPull.Format(time.RFC3339), b.Type, b.Version})
+					if err != nil {
+						log.Fatalf("failed to write raw: %s", err)
+					}
 				}
+				csvwriter.Flush()
 			}
 		},
 	}

+ 1 - 1
cmd/crowdsec-cli/collections.go

@@ -139,7 +139,7 @@ func NewCollectionsCmd() *cobra.Command {
 		Args:              cobra.ExactArgs(0),
 		DisableAutoGenTag: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			ListItem(cwhub.COLLECTIONS, args)
+			ListItem(cwhub.COLLECTIONS, args, false, true)
 		},
 	}
 	cmdCollectionsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well disabled items")

+ 18 - 8
cmd/crowdsec-cli/decisions.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	"context"
+	"encoding/csv"
 	"encoding/json"
 	"fmt"
 	"net/url"
@@ -52,23 +53,32 @@ func DecisionsToTable(alerts *models.GetAlertsResponse) error {
 		alertItem.Decisions = newDecisions
 	}
 	if csConfig.Cscli.Output == "raw" {
-		fmt.Printf("id,source,ip,reason,action,country,as,events_count,expiration,simulated,alert_id\n")
+		csvwriter := csv.NewWriter(os.Stdout)
+		err := csvwriter.Write([]string{"id", "source", "ip", "reason", "action", "country", "as", "events_count", "expiration", "simulated", "alert_id"})
+		if err != nil {
+			return err
+		}
 		for _, alertItem := range *alerts {
 			for _, decisionItem := range alertItem.Decisions {
-				fmt.Printf("%v,%v,%v,%v,%v,%v,%v,%v,%v,%v,%v\n",
-					decisionItem.ID,
+				err := csvwriter.Write([]string{
+					fmt.Sprintf("%d", decisionItem.ID),
 					*decisionItem.Origin,
-					*decisionItem.Scope+":"+*decisionItem.Value,
+					*decisionItem.Scope + ":" + *decisionItem.Value,
 					*decisionItem.Scenario,
 					*decisionItem.Type,
 					alertItem.Source.Cn,
-					alertItem.Source.AsNumber+" "+alertItem.Source.AsName,
-					*alertItem.EventsCount,
+					alertItem.Source.AsNumber + " " + alertItem.Source.AsName,
+					fmt.Sprintf("%d", *alertItem.EventsCount),
 					*decisionItem.Duration,
-					*decisionItem.Simulated,
-					alertItem.ID)
+					fmt.Sprintf("%t", *decisionItem.Simulated),
+					fmt.Sprintf("%d", alertItem.ID),
+				})
+				if err != nil {
+					return err
+				}
 			}
 		}
+		csvwriter.Flush()
 	} else if csConfig.Cscli.Output == "json" {
 		x, _ := json.MarshalIndent(alerts, "", " ")
 		fmt.Printf("%s", string(x))

+ 4 - 4
cmd/crowdsec-cli/hub.go

@@ -57,13 +57,13 @@ cscli hub update # Download list of available configurations from the hub
 			}
 			cwhub.DisplaySummary()
 			log.Printf("PARSERS:")
-			ListItem(cwhub.PARSERS, args)
+			ListItem(cwhub.PARSERS, args, true, true)
 			log.Printf("SCENARIOS:")
-			ListItem(cwhub.SCENARIOS, args)
+			ListItem(cwhub.SCENARIOS, args, true, false)
 			log.Printf("COLLECTIONS:")
-			ListItem(cwhub.COLLECTIONS, args)
+			ListItem(cwhub.COLLECTIONS, args, true, false)
 			log.Printf("POSTOVERFLOWS:")
-			ListItem(cwhub.PARSERS_OVFLW, args)
+			ListItem(cwhub.PARSERS_OVFLW, args, true, false)
 		},
 	}
 	cmdHubList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well disabled items")

+ 11 - 2
cmd/crowdsec-cli/machines.go

@@ -2,6 +2,7 @@ package main
 
 import (
 	saferand "crypto/rand"
+	"encoding/csv"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
@@ -144,7 +145,11 @@ Note: This command requires database direct access, so is intended to be run on
 				}
 				fmt.Printf("%s", string(x))
 			} else if csConfig.Cscli.Output == "raw" {
-				fmt.Printf("machine_id,ip_address,updated_at,validated,version\n")
+				csvwriter := csv.NewWriter(os.Stdout)
+				err := csvwriter.Write([]string{"machine_id", "ip_address", "updated_at", "validated", "version"})
+				if err != nil {
+					log.Fatalf("failed to write header: %s", err)
+				}
 				for _, w := range machines {
 					var validated string
 					if w.IsValidated {
@@ -152,8 +157,12 @@ Note: This command requires database direct access, so is intended to be run on
 					} else {
 						validated = "false"
 					}
-					fmt.Printf("%s,%s,%s,%s,%s\n", w.MachineId, w.IpAddress, w.UpdatedAt.Format(time.RFC3339), validated, w.Version)
+					err := csvwriter.Write([]string{w.MachineId, w.IpAddress, w.UpdatedAt.Format(time.RFC3339), validated, w.Version})
+					if err != nil {
+						log.Fatalf("failed to write raw output : %s", err)
+					}
 				}
+				csvwriter.Flush()
 			} else {
 				log.Errorf("unknown output '%s'", csConfig.Cscli.Output)
 			}

+ 1 - 1
cmd/crowdsec-cli/parsers.go

@@ -132,7 +132,7 @@ cscli parsers remove crowdsecurity/sshd-logs
 cscli parser list crowdsecurity/xxx`,
 		DisableAutoGenTag: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			ListItem(cwhub.PARSERS, args)
+			ListItem(cwhub.PARSERS, args, false, true)
 		},
 	}
 	cmdParsersList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well disabled items")

+ 1 - 1
cmd/crowdsec-cli/postoverflows.go

@@ -130,7 +130,7 @@ func NewPostOverflowsCmd() *cobra.Command {
 cscli postoverflows list crowdsecurity/xxx`,
 		DisableAutoGenTag: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			ListItem(cwhub.PARSERS_OVFLW, args)
+			ListItem(cwhub.PARSERS_OVFLW, args, false, true)
 		},
 	}
 	cmdPostOverflowsList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well disabled items")

+ 1 - 1
cmd/crowdsec-cli/scenarios.go

@@ -132,7 +132,7 @@ cscli scenarios remove crowdsecurity/ssh-bf
 cscli scenarios list crowdsecurity/xxx`,
 		DisableAutoGenTag: true,
 		Run: func(cmd *cobra.Command, args []string) {
-			ListItem(cwhub.SCENARIOS, args)
+			ListItem(cwhub.SCENARIOS, args, false, true)
 		},
 	}
 	cmdScenariosList.PersistentFlags().BoolVarP(&all, "all", "a", false, "List as well disabled items")

+ 31 - 3
cmd/crowdsec-cli/utils.go

@@ -1,6 +1,7 @@
 package main
 
 import (
+	"encoding/csv"
 	"encoding/json"
 	"fmt"
 	"io/ioutil"
@@ -101,7 +102,7 @@ func setHubBranch() error {
 	return nil
 }
 
-func ListItem(itemType string, args []string) {
+func ListItem(itemType string, args []string, showType bool, showHeader bool) {
 
 	var hubStatus []map[string]string
 
@@ -131,13 +132,40 @@ func ListItem(itemType string, args []string) {
 		}
 		fmt.Printf("%s", string(x))
 	} else if csConfig.Cscli.Output == "raw" {
-		fmt.Printf("name,status,version,description\n")
+		csvwriter := csv.NewWriter(os.Stdout)
+		if showHeader {
+			if showType {
+				err := csvwriter.Write([]string{"name", "status", "version", "description", "type"})
+				if err != nil {
+					log.Fatalf("failed to write header: %s", err)
+				}
+			} else {
+				err := csvwriter.Write([]string{"name", "status", "version", "description"})
+				if err != nil {
+					log.Fatalf("failed to write header: %s", err)
+				}
+			}
+
+		}
 		for _, v := range hubStatus {
 			if v["local_version"] == "" {
 				v["local_version"] = "n/a"
 			}
-			fmt.Printf("%s,%s,%s,%s\n", v["name"], v["status"], v["local_version"], v["description"])
+			row := []string{
+				v["name"],
+				v["status"],
+				v["local_version"],
+				v["description"],
+			}
+			if showType {
+				row = append(row, itemType)
+			}
+			err := csvwriter.Write(row)
+			if err != nil {
+				log.Fatalf("failed to write raw output : %s", err)
+			}
 		}
+		csvwriter.Flush()
 	}
 }