2020-11-30 09:37:17 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2021-12-29 13:08:47 +00:00
|
|
|
"encoding/csv"
|
2020-11-30 09:37:17 +00:00
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
middlewares "github.com/crowdsecurity/crowdsec/pkg/apiserver/middlewares/v1"
|
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/database"
|
|
|
|
"github.com/enescakir/emoji"
|
|
|
|
"github.com/olekukonko/tablewriter"
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/spf13/cobra"
|
|
|
|
)
|
|
|
|
|
|
|
|
var keyIP string
|
|
|
|
var keyLength int
|
2021-11-02 07:37:51 +00:00
|
|
|
var key string
|
2020-11-30 09:37:17 +00:00
|
|
|
|
|
|
|
func NewBouncersCmd() *cobra.Command {
|
|
|
|
/* ---- DECISIONS COMMAND */
|
|
|
|
var cmdBouncers = &cobra.Command{
|
|
|
|
Use: "bouncers [action]",
|
2021-04-16 08:50:08 +00:00
|
|
|
Short: "Manage bouncers [requires local API]",
|
|
|
|
Long: `To list/add/delete bouncers.
|
|
|
|
Note: This command requires database direct access, so is intended to be run on Local API/master.
|
2020-11-30 09:37:17 +00:00
|
|
|
`,
|
2021-08-31 13:03:47 +00:00
|
|
|
Args: cobra.MinimumNArgs(1),
|
|
|
|
DisableAutoGenTag: true,
|
2020-11-30 09:37:17 +00:00
|
|
|
PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
|
|
var err error
|
2021-04-16 08:50:08 +00:00
|
|
|
if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
|
|
|
|
log.Fatal("Local API is disabled, please run this command on the local API machine")
|
|
|
|
}
|
2021-03-24 17:16:17 +00:00
|
|
|
if err := csConfig.LoadDBConfig(); err != nil {
|
|
|
|
log.Fatalf(err.Error())
|
|
|
|
}
|
2020-11-30 09:37:17 +00:00
|
|
|
dbClient, err = database.NewClient(csConfig.DbConfig)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("unable to create new database client: %s", err)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var cmdBouncersList = &cobra.Command{
|
2021-08-31 13:03:47 +00:00
|
|
|
Use: "list",
|
|
|
|
Short: "List bouncers",
|
|
|
|
Long: `List bouncers`,
|
|
|
|
Example: `cscli bouncers list`,
|
|
|
|
Args: cobra.ExactArgs(0),
|
|
|
|
DisableAutoGenTag: true,
|
2020-11-30 09:37:17 +00:00
|
|
|
Run: func(cmd *cobra.Command, arg []string) {
|
|
|
|
blockers, err := dbClient.ListBouncers()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorf("unable to list blockers: %s", err)
|
|
|
|
}
|
|
|
|
if csConfig.Cscli.Output == "human" {
|
|
|
|
|
|
|
|
table := tablewriter.NewWriter(os.Stdout)
|
|
|
|
table.SetCenterSeparator("")
|
|
|
|
table.SetColumnSeparator("")
|
|
|
|
|
|
|
|
table.SetHeaderAlignment(tablewriter.ALIGN_LEFT)
|
|
|
|
table.SetAlignment(tablewriter.ALIGN_LEFT)
|
|
|
|
table.SetHeader([]string{"Name", "IP Address", "Valid", "Last API pull", "Type", "Version"})
|
|
|
|
for _, b := range blockers {
|
|
|
|
var revoked string
|
|
|
|
if !b.Revoked {
|
2022-03-09 15:15:18 +00:00
|
|
|
revoked = emoji.CheckMark.String()
|
2020-11-30 09:37:17 +00:00
|
|
|
} else {
|
2022-03-09 15:15:18 +00:00
|
|
|
revoked = emoji.Prohibited.String()
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
|
|
|
table.Append([]string{b.Name, b.IPAddress, revoked, b.LastPull.Format(time.RFC3339), b.Type, b.Version})
|
|
|
|
}
|
|
|
|
table.Render()
|
|
|
|
} else if csConfig.Cscli.Output == "json" {
|
|
|
|
x, err := json.MarshalIndent(blockers, "", " ")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("failed to unmarshal")
|
|
|
|
}
|
|
|
|
fmt.Printf("%s", string(x))
|
|
|
|
} else if csConfig.Cscli.Output == "raw" {
|
2021-12-29 13:08:47 +00:00
|
|
|
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)
|
|
|
|
}
|
2020-11-30 09:37:17 +00:00
|
|
|
for _, b := range blockers {
|
|
|
|
var revoked string
|
|
|
|
if !b.Revoked {
|
|
|
|
revoked = "validated"
|
|
|
|
} else {
|
|
|
|
revoked = "pending"
|
|
|
|
}
|
2021-12-29 13:08:47 +00:00
|
|
|
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)
|
|
|
|
}
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
2021-12-29 13:08:47 +00:00
|
|
|
csvwriter.Flush()
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cmdBouncers.AddCommand(cmdBouncersList)
|
|
|
|
|
|
|
|
var cmdBouncersAdd = &cobra.Command{
|
|
|
|
Use: "add MyBouncerName [--length 16]",
|
|
|
|
Short: "add bouncer",
|
|
|
|
Long: `add bouncer`,
|
2021-11-02 07:37:51 +00:00
|
|
|
Example: fmt.Sprintf(`cscli bouncers add MyBouncerName
|
|
|
|
cscli bouncers add MyBouncerName -l 24
|
|
|
|
cscli bouncers add MyBouncerName -k %s`, generatePassword(32)),
|
2021-08-31 13:03:47 +00:00
|
|
|
Args: cobra.ExactArgs(1),
|
|
|
|
DisableAutoGenTag: true,
|
2020-11-30 09:37:17 +00:00
|
|
|
Run: func(cmd *cobra.Command, arg []string) {
|
|
|
|
keyName := arg[0]
|
2021-11-02 07:37:51 +00:00
|
|
|
var apiKey string
|
|
|
|
var err error
|
2020-11-30 09:37:17 +00:00
|
|
|
if keyName == "" {
|
2021-12-14 10:09:57 +00:00
|
|
|
log.Fatalf("Please provide a name for the api key")
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
2021-11-02 07:37:51 +00:00
|
|
|
apiKey = key
|
|
|
|
if key == "" {
|
|
|
|
apiKey, err = middlewares.GenerateAPIKey(keyLength)
|
|
|
|
}
|
2020-11-30 09:37:17 +00:00
|
|
|
if err != nil {
|
2021-12-14 10:09:57 +00:00
|
|
|
log.Fatalf("unable to generate api key: %s", err)
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
|
|
|
err = dbClient.CreateBouncer(keyName, keyIP, middlewares.HashSHA512(apiKey))
|
|
|
|
if err != nil {
|
2021-12-13 09:30:55 +00:00
|
|
|
log.Fatalf("unable to create bouncer: %s", err)
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if csConfig.Cscli.Output == "human" {
|
|
|
|
fmt.Printf("Api key for '%s':\n\n", keyName)
|
|
|
|
fmt.Printf(" %s\n\n", apiKey)
|
2021-04-16 08:50:08 +00:00
|
|
|
fmt.Print("Please keep this key since you will not be able to retrieve it!\n")
|
2020-11-30 09:37:17 +00:00
|
|
|
} else if csConfig.Cscli.Output == "raw" {
|
|
|
|
fmt.Printf("%s", apiKey)
|
|
|
|
} else if csConfig.Cscli.Output == "json" {
|
|
|
|
j, err := json.Marshal(apiKey)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatalf("unable to marshal api key")
|
|
|
|
}
|
|
|
|
fmt.Printf("%s", string(j))
|
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cmdBouncersAdd.Flags().IntVarP(&keyLength, "length", "l", 16, "length of the api key")
|
2021-11-02 07:37:51 +00:00
|
|
|
cmdBouncersAdd.Flags().StringVarP(&key, "key", "k", "", "api key for the bouncer")
|
2020-11-30 09:37:17 +00:00
|
|
|
cmdBouncers.AddCommand(cmdBouncersAdd)
|
|
|
|
|
|
|
|
var cmdBouncersDelete = &cobra.Command{
|
2021-08-31 13:03:47 +00:00
|
|
|
Use: "delete MyBouncerName",
|
|
|
|
Short: "delete bouncer",
|
2021-09-02 10:23:06 +00:00
|
|
|
Args: cobra.MinimumNArgs(1),
|
2021-08-31 13:03:47 +00:00
|
|
|
DisableAutoGenTag: true,
|
2021-09-02 10:23:06 +00:00
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
for _, bouncerID := range args {
|
|
|
|
err := dbClient.DeleteBouncer(bouncerID)
|
|
|
|
if err != nil {
|
2021-12-14 10:09:57 +00:00
|
|
|
log.Fatalf("unable to delete bouncer: %s", err)
|
2021-09-02 10:23:06 +00:00
|
|
|
}
|
|
|
|
log.Infof("bouncer '%s' deleted successfully", bouncerID)
|
2020-11-30 09:37:17 +00:00
|
|
|
}
|
|
|
|
},
|
|
|
|
}
|
|
|
|
cmdBouncers.AddCommand(cmdBouncersDelete)
|
|
|
|
return cmdBouncers
|
|
|
|
}
|