123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287 |
- package main
- import (
- "encoding/json"
- "fmt"
- "io/ioutil"
- "math/rand"
- "path"
- "strings"
- "time"
- "github.com/crowdsecurity/crowdsec/pkg/cwhub"
- "github.com/crowdsecurity/crowdsec/pkg/outputs"
- "github.com/crowdsecurity/crowdsec/pkg/types"
- "github.com/denisbrodbeck/machineid"
- log "github.com/sirupsen/logrus"
- "github.com/spf13/cobra"
- "gopkg.in/yaml.v2"
- )
- var (
- passwordLength = 64
- upper = "ABCDEFGHIJKLMNOPQRSTUVWXY"
- lower = "abcdefghijklmnopqrstuvwxyz"
- digits = "0123456789"
- )
- var (
- userID string // for flag parsing
- outputCTX *outputs.Output
- )
- const (
- uuid = "/proc/sys/kernel/random/uuid"
- apiConfigFile = "api.yaml"
- )
- func dumpCredentials() error {
- if config.output == "json" {
- credsYaml, err := json.Marshal(&outputCTX.API.Creds)
- if err != nil {
- log.Fatalf("Can't marshal credentials : %v", err)
- }
- fmt.Printf("%s\n", string(credsYaml))
- } else {
- credsYaml, err := yaml.Marshal(&outputCTX.API.Creds)
- if err != nil {
- log.Fatalf("Can't marshal credentials : %v", err)
- }
- fmt.Printf("%s\n", string(credsYaml))
- }
- return nil
- }
- func generatePassword() string {
- rand.Seed(time.Now().UnixNano())
- charset := upper + lower + digits
- buf := make([]byte, passwordLength)
- buf[0] = digits[rand.Intn(len(digits))]
- buf[1] = upper[rand.Intn(len(upper))]
- buf[2] = lower[rand.Intn(len(lower))]
- for i := 3; i < passwordLength; i++ {
- buf[i] = charset[rand.Intn(len(charset))]
- }
- rand.Shuffle(len(buf), func(i, j int) {
- buf[i], buf[j] = buf[j], buf[i]
- })
- return string(buf)
- }
- func pullTOP() error {
- /*profile from cwhub*/
- var profiles []string
- if _, ok := cwhub.HubIdx[cwhub.SCENARIOS]; !ok || len(cwhub.HubIdx[cwhub.SCENARIOS]) == 0 {
- log.Errorf("no loaded scenarios, can't fill profiles")
- return fmt.Errorf("no profiles")
- }
- for _, item := range cwhub.HubIdx[cwhub.SCENARIOS] {
- if item.Tainted || !item.Installed {
- continue
- }
- profiles = append(profiles, item.Name)
- }
- outputCTX.API.Creds.Profile = strings.Join(profiles[:], ",")
- if err := outputCTX.API.Signin(); err != nil {
- log.Fatalf(err.Error())
- }
- ret, err := outputCTX.API.PullTop()
- if err != nil {
- log.Fatalf(err.Error())
- }
- log.Warningf("api pull returned %d entries", len(ret))
- for _, item := range ret {
- if _, ok := item["range_ip"]; !ok {
- continue
- }
- if _, ok := item["scenario"]; !ok {
- continue
- }
- item["scenario"] = fmt.Sprintf("api: %s", item["scenario"])
- if _, ok := item["action"]; !ok {
- continue
- }
- if _, ok := item["expiration"]; !ok {
- continue
- }
- if _, ok := item["country"]; !ok {
- item["country"] = ""
- }
- if _, ok := item["as_org"]; !ok {
- item["as_org"] = ""
- }
- if _, ok := item["as_num"]; !ok {
- item["as_num"] = ""
- }
- var signalOcc types.SignalOccurence
- signalOcc, err = simpleBanToSignal(item["range_ip"], item["scenario"], item["expiration"], item["action"], item["as_name"], item["as_num"], item["country"], "api")
- if err != nil {
- return fmt.Errorf("failed to convert ban to signal : %s", err)
- }
- if err := outputCTX.Insert(signalOcc); err != nil {
- log.Fatalf("Unable to write pull to sqliteDB : %+s", err.Error())
- }
- }
- outputCTX.Flush()
- log.Infof("Wrote %d bans from api to database.", len(ret))
- return nil
- }
- func NewAPICmd() *cobra.Command {
- var cmdAPI = &cobra.Command{
- Use: "api [action]",
- Short: "Crowdsec API interaction",
- Long: `
- Allow to register your machine into crowdsec API to send and receive signal.
- `,
- Example: `
- cscli api register # Register to Crowdsec API
- cscli api pull # Pull malevolant IPs from Crowdsec API
- cscli api reset # Reset your machines credentials
- cscli api enroll # Enroll your machine to the user account you created on Crowdsec backend
- cscli api credentials # Display your API credentials
- `,
- Args: cobra.MinimumNArgs(1),
- PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
- var err error
- if !config.configured {
- return fmt.Errorf("you must configure cli before interacting with hub")
- }
- outputConfig := outputs.OutputFactory{
- BackendFolder: config.BackendPluginFolder,
- }
- outputCTX, err = outputs.NewOutput(&outputConfig, false)
- if err != nil {
- return err
- }
- err = outputCTX.LoadAPIConfig(path.Join(config.InstallFolder, apiConfigFile))
- if err != nil {
- return err
- }
- return nil
- },
- }
- var cmdAPIRegister = &cobra.Command{
- Use: "register",
- Short: "Register on Crowdsec API",
- Long: `This command will register your machine to crowdsec API to allow you to receive list of malveolent IPs.
- The printed machine_id and password should be added to your api.yaml file.`,
- Example: `cscli api register`,
- Args: cobra.MinimumNArgs(0),
- Run: func(cmd *cobra.Command, args []string) {
- id, err := machineid.ID()
- if err != nil {
- log.Fatalf("failed to get machine id: %s", err)
- }
- if id == "" {
- bID, err := ioutil.ReadFile(uuid)
- if err != nil {
- log.Fatalf("can'get a valid machine_id")
- }
- id = string(bID)
- }
- password := generatePassword()
- if err := outputCTX.API.RegisterMachine(id, password); err != nil {
- log.Fatalf(err.Error())
- }
- fmt.Printf("machine_id: %s\n", outputCTX.API.Creds.User)
- fmt.Printf("password: %s\n", outputCTX.API.Creds.Password)
- },
- }
- var cmdAPIEnroll = &cobra.Command{
- Use: "enroll",
- Short: "Associate your machine to an existing crowdsec user",
- Long: `Enrolling your machine into your user account will allow for more accurate lists and threat detection. See website to create user account.`,
- Example: `cscli api enroll -u 1234567890ffff`,
- Args: cobra.MinimumNArgs(0),
- Run: func(cmd *cobra.Command, args []string) {
- if err := outputCTX.API.Signin(); err != nil {
- log.Fatalf("unable to signin : %s", err)
- }
- if err := outputCTX.API.Enroll(userID); err != nil {
- log.Fatalf(err.Error())
- }
- },
- }
- var cmdAPIResetPassword = &cobra.Command{
- Use: "reset",
- Short: "Reset password on CrowdSec API",
- Long: `Attempts to reset your credentials to the API.`,
- Example: `cscli api reset`,
- Args: cobra.MinimumNArgs(0),
- Run: func(cmd *cobra.Command, args []string) {
- id, err := machineid.ID()
- if err != nil {
- log.Fatalf("failed to get machine id: %s", err)
- }
- if id == "" {
- bID, err := ioutil.ReadFile(uuid)
- if err != nil {
- log.Fatalf("can'get a valid machine_id")
- }
- id = string(bID)
- }
- password := generatePassword()
- if err := outputCTX.API.ResetPassword(id, password); err != nil {
- log.Fatalf(err.Error())
- }
- fmt.Printf("machine_id: %s\n", outputCTX.API.Creds.User)
- fmt.Printf("password: %s\n", outputCTX.API.Creds.Password)
- },
- }
- var cmdAPIPull = &cobra.Command{
- Use: "pull",
- Short: "Pull crowdsec API TopX",
- Long: `Pulls a list of malveolent IPs relevant to your situation and add them into the local ban database.`,
- Example: `cscli api pull`,
- Args: cobra.MinimumNArgs(0),
- Run: func(cmd *cobra.Command, args []string) {
- if err := cwhub.GetHubIdx(); err != nil {
- log.Fatalf(err.Error())
- }
- err := pullTOP()
- if err != nil {
- log.Fatalf(err.Error())
- }
- },
- }
- var cmdAPICreds = &cobra.Command{
- Use: "credentials",
- Short: "Display api credentials",
- Long: ``,
- Example: `cscli api credentials`,
- Args: cobra.MinimumNArgs(0),
- Run: func(cmd *cobra.Command, args []string) {
- if err := dumpCredentials(); err != nil {
- log.Fatalf(err.Error())
- }
- },
- }
- cmdAPI.AddCommand(cmdAPICreds)
- cmdAPIEnroll.Flags().StringVarP(&userID, "user", "u", "", "User ID (required)")
- if err := cmdAPIEnroll.MarkFlagRequired("user"); err != nil {
- log.Errorf("'user' flag : %s", err)
- }
- cmdAPI.AddCommand(cmdAPIEnroll)
- cmdAPI.AddCommand(cmdAPIResetPassword)
- cmdAPI.AddCommand(cmdAPIRegister)
- cmdAPI.AddCommand(cmdAPIPull)
- return cmdAPI
- }
|