|
@@ -29,22 +29,15 @@ import (
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/types"
|
|
|
)
|
|
|
|
|
|
-var machineID string
|
|
|
-var machinePassword string
|
|
|
-var interactive bool
|
|
|
-var apiURL string
|
|
|
-var outputFile string
|
|
|
-var forceAdd bool
|
|
|
-var autoAdd bool
|
|
|
-
|
|
|
var (
|
|
|
passwordLength = 64
|
|
|
- upper = "ABCDEFGHIJKLMNOPQRSTUVWXY"
|
|
|
- lower = "abcdefghijklmnopqrstuvwxyz"
|
|
|
- digits = "0123456789"
|
|
|
)
|
|
|
|
|
|
func generatePassword(length int) string {
|
|
|
+ upper := "ABCDEFGHIJKLMNOPQRSTUVWXY"
|
|
|
+ lower := "abcdefghijklmnopqrstuvwxyz"
|
|
|
+ digits := "0123456789"
|
|
|
+
|
|
|
charset := upper + lower + digits
|
|
|
charsetLength := len(charset)
|
|
|
|
|
@@ -149,32 +142,8 @@ func getAgents(out io.Writer, dbClient *database.Client) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-func NewMachinesCmd() *cobra.Command {
|
|
|
- /* ---- DECISIONS COMMAND */
|
|
|
- var cmdMachines = &cobra.Command{
|
|
|
- Use: "machines [action]",
|
|
|
- Short: "Manage local API machines [requires local API]",
|
|
|
- Long: `To list/add/delete/validate machines.
|
|
|
-Note: This command requires database direct access, so is intended to be run on the local API machine.
|
|
|
-`,
|
|
|
- Example: `cscli machines [action]`,
|
|
|
- DisableAutoGenTag: true,
|
|
|
- Aliases: []string{"machine"},
|
|
|
- PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
|
- if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
|
|
|
- if err != nil {
|
|
|
- log.Errorf("local api : %s", err)
|
|
|
- }
|
|
|
- log.Fatal("Local API is disabled, please run this command on the local API machine")
|
|
|
- }
|
|
|
- if err := csConfig.LoadDBConfig(); err != nil {
|
|
|
- log.Errorf("This command requires direct database access (must be run on the local API machine)")
|
|
|
- log.Fatal(err)
|
|
|
- }
|
|
|
- },
|
|
|
- }
|
|
|
-
|
|
|
- var cmdMachinesList = &cobra.Command{
|
|
|
+func NewMachinesListCmd() *cobra.Command {
|
|
|
+ cmdMachinesList := &cobra.Command{
|
|
|
Use: "list",
|
|
|
Short: "List machines",
|
|
|
Long: `List `,
|
|
@@ -195,9 +164,12 @@ Note: This command requires database direct access, so is intended to be run on
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
- cmdMachines.AddCommand(cmdMachinesList)
|
|
|
|
|
|
- var cmdMachinesAdd = &cobra.Command{
|
|
|
+ return cmdMachinesList
|
|
|
+}
|
|
|
+
|
|
|
+func NewMachinesAddCmd() *cobra.Command {
|
|
|
+ cmdMachinesAdd := &cobra.Command{
|
|
|
Use: "add",
|
|
|
Short: "add machine to the database.",
|
|
|
DisableAutoGenTag: true,
|
|
@@ -214,90 +186,132 @@ cscli machines add MyTestMachine --password MyPassword
|
|
|
log.Fatalf("unable to create new database client: %s", err)
|
|
|
}
|
|
|
},
|
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
- var dumpFile string
|
|
|
- var err error
|
|
|
+ RunE: runMachinesAdd,
|
|
|
+ }
|
|
|
|
|
|
- // create machineID if not specified by user
|
|
|
- if len(args) == 0 {
|
|
|
- if !autoAdd {
|
|
|
- printHelp(cmd)
|
|
|
- return
|
|
|
- }
|
|
|
- machineID, err = generateID("")
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("unable to generate machine id : %s", err)
|
|
|
- }
|
|
|
- } else {
|
|
|
- machineID = args[0]
|
|
|
- }
|
|
|
+ flags := cmdMachinesAdd.Flags()
|
|
|
+ flags.StringP("password", "p", "", "machine password to login to the API")
|
|
|
+ flags.StringP("file", "f", "", "output file destination (defaults to "+csconfig.DefaultConfigPath("local_api_credentials.yaml"))
|
|
|
+ flags.StringP("url", "u", "", "URL of the local API")
|
|
|
+ flags.BoolP("interactive", "i", false, "interfactive mode to enter the password")
|
|
|
+ flags.BoolP("auto", "a", false, "automatically generate password (and username if not provided)")
|
|
|
+ flags.Bool("force", false, "will force add the machine if it already exist")
|
|
|
|
|
|
- /*check if file already exists*/
|
|
|
- if outputFile != "" {
|
|
|
- dumpFile = outputFile
|
|
|
- } else if csConfig.API.Client != nil && csConfig.API.Client.CredentialsFilePath != "" {
|
|
|
- dumpFile = csConfig.API.Client.CredentialsFilePath
|
|
|
- }
|
|
|
+ return cmdMachinesAdd
|
|
|
+}
|
|
|
|
|
|
- // create a password if it's not specified by user
|
|
|
- if machinePassword == "" && !interactive {
|
|
|
- if !autoAdd {
|
|
|
- printHelp(cmd)
|
|
|
- return
|
|
|
- }
|
|
|
- machinePassword = generatePassword(passwordLength)
|
|
|
- } else if machinePassword == "" && interactive {
|
|
|
- qs := &survey.Password{
|
|
|
- Message: "Please provide a password for the machine",
|
|
|
- }
|
|
|
- survey.AskOne(qs, &machinePassword)
|
|
|
- }
|
|
|
- password := strfmt.Password(machinePassword)
|
|
|
- _, err = dbClient.CreateMachine(&machineID, &password, "", true, forceAdd, types.PasswordAuthType)
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("unable to create machine: %s", err)
|
|
|
- }
|
|
|
- log.Infof("Machine '%s' successfully added to the local API", machineID)
|
|
|
-
|
|
|
- if apiURL == "" {
|
|
|
- if csConfig.API.Client != nil && csConfig.API.Client.Credentials != nil && csConfig.API.Client.Credentials.URL != "" {
|
|
|
- apiURL = csConfig.API.Client.Credentials.URL
|
|
|
- } else if csConfig.API.Server != nil && csConfig.API.Server.ListenURI != "" {
|
|
|
- apiURL = "http://" + csConfig.API.Server.ListenURI
|
|
|
- } else {
|
|
|
- log.Fatalf("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
|
|
|
- }
|
|
|
- }
|
|
|
- apiCfg := csconfig.ApiCredentialsCfg{
|
|
|
- Login: machineID,
|
|
|
- Password: password.String(),
|
|
|
- URL: apiURL,
|
|
|
- }
|
|
|
- apiConfigDump, err := yaml.Marshal(apiCfg)
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("unable to marshal api credentials: %s", err)
|
|
|
- }
|
|
|
- if dumpFile != "" && dumpFile != "-" {
|
|
|
- err = os.WriteFile(dumpFile, apiConfigDump, 0644)
|
|
|
- if err != nil {
|
|
|
- log.Fatalf("write api credentials in '%s' failed: %s", dumpFile, err)
|
|
|
- }
|
|
|
- log.Printf("API credentials dumped to '%s'", dumpFile)
|
|
|
- } else {
|
|
|
- fmt.Printf("%s\n", string(apiConfigDump))
|
|
|
- }
|
|
|
- },
|
|
|
+func runMachinesAdd(cmd *cobra.Command, args []string) error {
|
|
|
+ var dumpFile string
|
|
|
+ var err error
|
|
|
+
|
|
|
+ flags := cmd.Flags()
|
|
|
+
|
|
|
+ machinePassword, err := flags.GetString("password")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ outputFile, err := flags.GetString("file")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ apiURL, err := flags.GetString("url")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ interactive, err := flags.GetBool("interactive")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ autoAdd, err := flags.GetBool("auto")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ forceAdd, err := flags.GetBool("force")
|
|
|
+ if err != nil {
|
|
|
+ return err
|
|
|
+ }
|
|
|
+
|
|
|
+ var machineID string
|
|
|
+
|
|
|
+ // create machineID if not specified by user
|
|
|
+ if len(args) == 0 {
|
|
|
+ if !autoAdd {
|
|
|
+ printHelp(cmd)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ machineID, err = generateID("")
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("unable to generate machine id : %s", err)
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ machineID = args[0]
|
|
|
+ }
|
|
|
+
|
|
|
+ /*check if file already exists*/
|
|
|
+ if outputFile != "" {
|
|
|
+ dumpFile = outputFile
|
|
|
+ } else if csConfig.API.Client != nil && csConfig.API.Client.CredentialsFilePath != "" {
|
|
|
+ dumpFile = csConfig.API.Client.CredentialsFilePath
|
|
|
+ }
|
|
|
+
|
|
|
+ // create a password if it's not specified by user
|
|
|
+ if machinePassword == "" && !interactive {
|
|
|
+ if !autoAdd {
|
|
|
+ printHelp(cmd)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ machinePassword = generatePassword(passwordLength)
|
|
|
+ } else if machinePassword == "" && interactive {
|
|
|
+ qs := &survey.Password{
|
|
|
+ Message: "Please provide a password for the machine",
|
|
|
+ }
|
|
|
+ survey.AskOne(qs, &machinePassword)
|
|
|
+ }
|
|
|
+ password := strfmt.Password(machinePassword)
|
|
|
+ _, err = dbClient.CreateMachine(&machineID, &password, "", true, forceAdd, types.PasswordAuthType)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("unable to create machine: %s", err)
|
|
|
+ }
|
|
|
+ log.Infof("Machine '%s' successfully added to the local API", machineID)
|
|
|
+
|
|
|
+ if apiURL == "" {
|
|
|
+ if csConfig.API.Client != nil && csConfig.API.Client.Credentials != nil && csConfig.API.Client.Credentials.URL != "" {
|
|
|
+ apiURL = csConfig.API.Client.Credentials.URL
|
|
|
+ } else if csConfig.API.Server != nil && csConfig.API.Server.ListenURI != "" {
|
|
|
+ apiURL = "http://" + csConfig.API.Server.ListenURI
|
|
|
+ } else {
|
|
|
+ log.Fatalf("unable to dump an api URL. Please provide it in your configuration or with the -u parameter")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ apiCfg := csconfig.ApiCredentialsCfg{
|
|
|
+ Login: machineID,
|
|
|
+ Password: password.String(),
|
|
|
+ URL: apiURL,
|
|
|
}
|
|
|
- cmdMachinesAdd.Flags().StringVarP(&machinePassword, "password", "p", "", "machine password to login to the API")
|
|
|
- cmdMachinesAdd.Flags().StringVarP(&outputFile, "file", "f", "",
|
|
|
- "output file destination (defaults to "+csconfig.DefaultConfigPath("local_api_credentials.yaml"))
|
|
|
- cmdMachinesAdd.Flags().StringVarP(&apiURL, "url", "u", "", "URL of the local API")
|
|
|
- cmdMachinesAdd.Flags().BoolVarP(&interactive, "interactive", "i", false, "interfactive mode to enter the password")
|
|
|
- cmdMachinesAdd.Flags().BoolVarP(&autoAdd, "auto", "a", false, "automatically generate password (and username if not provided)")
|
|
|
- cmdMachinesAdd.Flags().BoolVar(&forceAdd, "force", false, "will force add the machine if it already exist")
|
|
|
- cmdMachines.AddCommand(cmdMachinesAdd)
|
|
|
-
|
|
|
- var cmdMachinesDelete = &cobra.Command{
|
|
|
+ apiConfigDump, err := yaml.Marshal(apiCfg)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("unable to marshal api credentials: %s", err)
|
|
|
+ }
|
|
|
+ if dumpFile != "" && dumpFile != "-" {
|
|
|
+ err = os.WriteFile(dumpFile, apiConfigDump, 0644)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("write api credentials in '%s' failed: %s", dumpFile, err)
|
|
|
+ }
|
|
|
+ log.Printf("API credentials dumped to '%s'", dumpFile)
|
|
|
+ } else {
|
|
|
+ fmt.Printf("%s\n", string(apiConfigDump))
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewMachinesDeleteCmd() *cobra.Command {
|
|
|
+ cmdMachinesDelete := &cobra.Command{
|
|
|
Use: "delete [machine_name]...",
|
|
|
Short: "delete machines",
|
|
|
Example: `cscli machines delete "machine1" "machine2"`,
|
|
@@ -330,20 +344,27 @@ cscli machines add MyTestMachine --password MyPassword
|
|
|
}
|
|
|
return ret, cobra.ShellCompDirectiveNoFileComp
|
|
|
},
|
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
- for _, machineID := range args {
|
|
|
- err := dbClient.DeleteWatcher(machineID)
|
|
|
- if err != nil {
|
|
|
- log.Errorf("unable to delete machine '%s': %s", machineID, err)
|
|
|
- return
|
|
|
- }
|
|
|
- log.Infof("machine '%s' deleted successfully", machineID)
|
|
|
- }
|
|
|
- },
|
|
|
+ RunE: runMachinesDelete,
|
|
|
}
|
|
|
- cmdMachines.AddCommand(cmdMachinesDelete)
|
|
|
|
|
|
- var cmdMachinesValidate = &cobra.Command{
|
|
|
+ return cmdMachinesDelete
|
|
|
+}
|
|
|
+
|
|
|
+func runMachinesDelete(cmd *cobra.Command, args []string) error {
|
|
|
+ for _, machineID := range args {
|
|
|
+ err := dbClient.DeleteWatcher(machineID)
|
|
|
+ if err != nil {
|
|
|
+ log.Errorf("unable to delete machine '%s': %s", machineID, err)
|
|
|
+ return nil
|
|
|
+ }
|
|
|
+ log.Infof("machine '%s' deleted successfully", machineID)
|
|
|
+ }
|
|
|
+
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+func NewMachinesValidateCmd() *cobra.Command {
|
|
|
+ cmdMachinesValidate := &cobra.Command{
|
|
|
Use: "validate",
|
|
|
Short: "validate a machine to access the local API",
|
|
|
Long: `validate a machine to access the local API.`,
|
|
@@ -358,14 +379,45 @@ cscli machines add MyTestMachine --password MyPassword
|
|
|
}
|
|
|
},
|
|
|
Run: func(cmd *cobra.Command, args []string) {
|
|
|
- machineID = args[0]
|
|
|
+ machineID := args[0]
|
|
|
if err := dbClient.ValidateMachine(machineID); err != nil {
|
|
|
log.Fatalf("unable to validate machine '%s': %s", machineID, err)
|
|
|
}
|
|
|
log.Infof("machine '%s' validated successfully", machineID)
|
|
|
},
|
|
|
}
|
|
|
- cmdMachines.AddCommand(cmdMachinesValidate)
|
|
|
+
|
|
|
+ return cmdMachinesValidate
|
|
|
+}
|
|
|
+
|
|
|
+func NewMachinesCmd() *cobra.Command {
|
|
|
+ var cmdMachines = &cobra.Command{
|
|
|
+ Use: "machines [action]",
|
|
|
+ Short: "Manage local API machines [requires local API]",
|
|
|
+ Long: `To list/add/delete/validate machines.
|
|
|
+Note: This command requires database direct access, so is intended to be run on the local API machine.
|
|
|
+`,
|
|
|
+ Example: `cscli machines [action]`,
|
|
|
+ DisableAutoGenTag: true,
|
|
|
+ Aliases: []string{"machine"},
|
|
|
+ PersistentPreRun: func(cmd *cobra.Command, args []string) {
|
|
|
+ if err := csConfig.LoadAPIServer(); err != nil || csConfig.DisableAPI {
|
|
|
+ if err != nil {
|
|
|
+ log.Errorf("local api : %s", err)
|
|
|
+ }
|
|
|
+ log.Fatal("Local API is disabled, please run this command on the local API machine")
|
|
|
+ }
|
|
|
+ if err := csConfig.LoadDBConfig(); err != nil {
|
|
|
+ log.Errorf("This command requires direct database access (must be run on the local API machine)")
|
|
|
+ log.Fatal(err)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ cmdMachines.AddCommand(NewMachinesListCmd())
|
|
|
+ cmdMachines.AddCommand(NewMachinesAddCmd())
|
|
|
+ cmdMachines.AddCommand(NewMachinesDeleteCmd())
|
|
|
+ cmdMachines.AddCommand(NewMachinesValidateCmd())
|
|
|
|
|
|
return cmdMachines
|
|
|
}
|