|
@@ -1,7 +1,6 @@
|
|
package main
|
|
package main
|
|
|
|
|
|
import (
|
|
import (
|
|
- "errors"
|
|
|
|
"fmt"
|
|
"fmt"
|
|
"math"
|
|
"math"
|
|
"os"
|
|
"os"
|
|
@@ -27,6 +26,7 @@ var (
|
|
metabaseConfigPath string
|
|
metabaseConfigPath string
|
|
metabaseConfigFolder = "metabase/"
|
|
metabaseConfigFolder = "metabase/"
|
|
metabaseConfigFile = "metabase.yaml"
|
|
metabaseConfigFile = "metabase.yaml"
|
|
|
|
+ metabaseImage = "metabase/metabase:v0.46.6.1"
|
|
/**/
|
|
/**/
|
|
metabaseListenAddress = "127.0.0.1"
|
|
metabaseListenAddress = "127.0.0.1"
|
|
metabaseListenPort = "3000"
|
|
metabaseListenPort = "3000"
|
|
@@ -96,7 +96,6 @@ cscli dashboard remove
|
|
return cmdDashboard
|
|
return cmdDashboard
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
func NewDashboardSetupCmd() *cobra.Command {
|
|
func NewDashboardSetupCmd() *cobra.Command {
|
|
var force bool
|
|
var force bool
|
|
|
|
|
|
@@ -111,7 +110,7 @@ cscli dashboard setup
|
|
cscli dashboard setup --listen 0.0.0.0
|
|
cscli dashboard setup --listen 0.0.0.0
|
|
cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
`,
|
|
`,
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
|
|
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
if metabaseDbPath == "" {
|
|
if metabaseDbPath == "" {
|
|
metabaseDbPath = csConfig.ConfigPaths.DataDir
|
|
metabaseDbPath = csConfig.ConfigPaths.DataDir
|
|
}
|
|
}
|
|
@@ -123,70 +122,23 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
isValid = passwordIsValid(metabasePassword)
|
|
isValid = passwordIsValid(metabasePassword)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- var answer bool
|
|
|
|
- if valid, err := checkSystemMemory(); err == nil && !valid {
|
|
|
|
- if !forceYes {
|
|
|
|
- prompt := &survey.Confirm{
|
|
|
|
- Message: "Metabase requires 1-2GB of RAM, your system is below this requirement continue ?",
|
|
|
|
- Default: true,
|
|
|
|
- }
|
|
|
|
- if err := survey.AskOne(prompt, &answer); err != nil {
|
|
|
|
- log.Warnf("unable to ask about RAM check: %s", err)
|
|
|
|
- }
|
|
|
|
- if !answer {
|
|
|
|
- log.Fatal("Unable to continue due to RAM requirement")
|
|
|
|
- }
|
|
|
|
- } else {
|
|
|
|
- log.Warnf("Metabase requires 1-2GB of RAM, your system is below this requirement")
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- groupExist := false
|
|
|
|
- dockerGroup, err := user.LookupGroup(crowdsecGroup)
|
|
|
|
- if err == nil {
|
|
|
|
- groupExist = true
|
|
|
|
- }
|
|
|
|
- if !forceYes && !groupExist {
|
|
|
|
- prompt := &survey.Confirm{
|
|
|
|
- Message: fmt.Sprintf("For metabase docker to be able to access SQLite file we need to add a new group called '%s' to the system, is it ok for you ?", crowdsecGroup),
|
|
|
|
- Default: true,
|
|
|
|
- }
|
|
|
|
- if err := survey.AskOne(prompt, &answer); err != nil {
|
|
|
|
- log.Fatalf("unable to ask to force: %s", err)
|
|
|
|
- }
|
|
|
|
|
|
+ if err := checkSystemMemory(&forceYes); err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
- if !answer && !forceYes && !groupExist {
|
|
|
|
- log.Fatalf("unable to continue without creating '%s' group", crowdsecGroup)
|
|
|
|
|
|
+ warnIfNotLoopback(metabaseListenAddress)
|
|
|
|
+ if err := disclaimer(&forceYes); err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
- if !groupExist {
|
|
|
|
- groupAddCmd, err := exec.LookPath("groupadd")
|
|
|
|
- if err != nil {
|
|
|
|
- log.Fatalf("unable to find 'groupadd' command, can't continue")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- groupAdd := &exec.Cmd{Path: groupAddCmd, Args: []string{groupAddCmd, crowdsecGroup}}
|
|
|
|
- if err := groupAdd.Run(); err != nil {
|
|
|
|
- log.Fatalf("unable to add group '%s': %s", dockerGroup, err)
|
|
|
|
- }
|
|
|
|
- dockerGroup, err = user.LookupGroup(crowdsecGroup)
|
|
|
|
- if err != nil {
|
|
|
|
- log.Fatalf("unable to lookup '%s' group: %+v", dockerGroup, err)
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- intID, err := strconv.Atoi(dockerGroup.Gid)
|
|
|
|
|
|
+ dockerGroup, err := checkGroups(&forceYes)
|
|
if err != nil {
|
|
if err != nil {
|
|
- log.Fatalf("unable to convert group ID to int: %s", err)
|
|
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
- if err := os.Chown(csConfig.DbConfig.DbPath, 0, intID); err != nil {
|
|
|
|
- log.Fatalf("unable to chown sqlite db file '%s': %s", csConfig.DbConfig.DbPath, err)
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- mb, err := metabase.SetupMetabase(csConfig.API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath, dockerGroup.Gid, metabaseContainerID)
|
|
|
|
|
|
+ mb, err := metabase.SetupMetabase(csConfig.API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath, dockerGroup.Gid, metabaseContainerID, metabaseImage)
|
|
if err != nil {
|
|
if err != nil {
|
|
- log.Fatal(err)
|
|
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
-
|
|
|
|
if err := mb.DumpConfig(metabaseConfigPath); err != nil {
|
|
if err := mb.DumpConfig(metabaseConfigPath); err != nil {
|
|
- log.Fatal(err)
|
|
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
|
|
|
|
log.Infof("Metabase is ready")
|
|
log.Infof("Metabase is ready")
|
|
@@ -194,11 +146,13 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
fmt.Printf("\tURL : '%s'\n", mb.Config.ListenURL)
|
|
fmt.Printf("\tURL : '%s'\n", mb.Config.ListenURL)
|
|
fmt.Printf("\tusername : '%s'\n", mb.Config.Username)
|
|
fmt.Printf("\tusername : '%s'\n", mb.Config.Username)
|
|
fmt.Printf("\tpassword : '%s'\n", mb.Config.Password)
|
|
fmt.Printf("\tpassword : '%s'\n", mb.Config.Password)
|
|
|
|
+ return nil
|
|
},
|
|
},
|
|
}
|
|
}
|
|
cmdDashSetup.Flags().BoolVarP(&force, "force", "f", false, "Force setup : override existing files")
|
|
cmdDashSetup.Flags().BoolVarP(&force, "force", "f", false, "Force setup : override existing files")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseDbPath, "dir", "d", "", "Shared directory with metabase container")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseDbPath, "dir", "d", "", "Shared directory with metabase container")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseListenAddress, "listen", "l", metabaseListenAddress, "Listen address of container")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseListenAddress, "listen", "l", metabaseListenAddress, "Listen address of container")
|
|
|
|
+ cmdDashSetup.Flags().StringVar(&metabaseImage, "metabase-image", metabaseImage, "Metabase image to use")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container")
|
|
cmdDashSetup.Flags().StringVarP(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container")
|
|
cmdDashSetup.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
|
|
cmdDashSetup.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
|
|
//cmdDashSetup.Flags().StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user")
|
|
//cmdDashSetup.Flags().StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user")
|
|
@@ -214,18 +168,24 @@ func NewDashboardStartCmd() *cobra.Command {
|
|
Long: `Stats the metabase container using docker.`,
|
|
Long: `Stats the metabase container using docker.`,
|
|
Args: cobra.ExactArgs(0),
|
|
Args: cobra.ExactArgs(0),
|
|
DisableAutoGenTag: true,
|
|
DisableAutoGenTag: true,
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
|
|
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
mb, err := metabase.NewMetabase(metabaseConfigPath, metabaseContainerID)
|
|
mb, err := metabase.NewMetabase(metabaseConfigPath, metabaseContainerID)
|
|
if err != nil {
|
|
if err != nil {
|
|
- log.Fatal(err)
|
|
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ warnIfNotLoopback(mb.Config.ListenAddr)
|
|
|
|
+ if err := disclaimer(&forceYes); err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
if err := mb.Container.Start(); err != nil {
|
|
if err := mb.Container.Start(); err != nil {
|
|
- log.Fatalf("Failed to start metabase container : %s", err)
|
|
|
|
|
|
+ return fmt.Errorf("failed to start metabase container : %s", err)
|
|
}
|
|
}
|
|
log.Infof("Started metabase")
|
|
log.Infof("Started metabase")
|
|
- log.Infof("url : http://%s:%s", metabaseListenAddress, metabaseListenPort)
|
|
|
|
|
|
+ log.Infof("url : http://%s:%s", mb.Config.ListenAddr, mb.Config.ListenPort)
|
|
|
|
+ return nil
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
+ cmdDashStart.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
|
|
return cmdDashStart
|
|
return cmdDashStart
|
|
}
|
|
}
|
|
|
|
|
|
@@ -236,33 +196,33 @@ func NewDashboardStopCmd() *cobra.Command {
|
|
Long: `Stops the metabase container using docker.`,
|
|
Long: `Stops the metabase container using docker.`,
|
|
Args: cobra.ExactArgs(0),
|
|
Args: cobra.ExactArgs(0),
|
|
DisableAutoGenTag: true,
|
|
DisableAutoGenTag: true,
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
|
|
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
if err := metabase.StopContainer(metabaseContainerID); err != nil {
|
|
if err := metabase.StopContainer(metabaseContainerID); err != nil {
|
|
- log.Fatalf("unable to stop container '%s': %s", metabaseContainerID, err)
|
|
|
|
|
|
+ return fmt.Errorf("unable to stop container '%s': %s", metabaseContainerID, err)
|
|
}
|
|
}
|
|
|
|
+ return nil
|
|
},
|
|
},
|
|
}
|
|
}
|
|
return cmdDashStop
|
|
return cmdDashStop
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
func NewDashboardShowPasswordCmd() *cobra.Command {
|
|
func NewDashboardShowPasswordCmd() *cobra.Command {
|
|
var cmdDashShowPassword = &cobra.Command{Use: "show-password",
|
|
var cmdDashShowPassword = &cobra.Command{Use: "show-password",
|
|
Short: "displays password of metabase.",
|
|
Short: "displays password of metabase.",
|
|
Args: cobra.ExactArgs(0),
|
|
Args: cobra.ExactArgs(0),
|
|
DisableAutoGenTag: true,
|
|
DisableAutoGenTag: true,
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
|
|
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
m := metabase.Metabase{}
|
|
m := metabase.Metabase{}
|
|
if err := m.LoadConfig(metabaseConfigPath); err != nil {
|
|
if err := m.LoadConfig(metabaseConfigPath); err != nil {
|
|
- log.Fatal(err)
|
|
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
log.Printf("'%s'", m.Config.Password)
|
|
log.Printf("'%s'", m.Config.Password)
|
|
|
|
+ return nil
|
|
},
|
|
},
|
|
}
|
|
}
|
|
return cmdDashShowPassword
|
|
return cmdDashShowPassword
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
func NewDashboardRemoveCmd() *cobra.Command {
|
|
func NewDashboardRemoveCmd() *cobra.Command {
|
|
var force bool
|
|
var force bool
|
|
|
|
|
|
@@ -276,53 +236,59 @@ func NewDashboardRemoveCmd() *cobra.Command {
|
|
cscli dashboard remove
|
|
cscli dashboard remove
|
|
cscli dashboard remove --force
|
|
cscli dashboard remove --force
|
|
`,
|
|
`,
|
|
- Run: func(cmd *cobra.Command, args []string) {
|
|
|
|
- answer := true
|
|
|
|
|
|
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
if !forceYes {
|
|
if !forceYes {
|
|
|
|
+ var answer bool
|
|
prompt := &survey.Confirm{
|
|
prompt := &survey.Confirm{
|
|
Message: "Do you really want to remove crowdsec dashboard? (all your changes will be lost)",
|
|
Message: "Do you really want to remove crowdsec dashboard? (all your changes will be lost)",
|
|
Default: true,
|
|
Default: true,
|
|
}
|
|
}
|
|
if err := survey.AskOne(prompt, &answer); err != nil {
|
|
if err := survey.AskOne(prompt, &answer); err != nil {
|
|
- log.Fatalf("unable to ask to force: %s", err)
|
|
|
|
|
|
+ return fmt.Errorf("unable to ask to force: %s", err)
|
|
|
|
+ }
|
|
|
|
+ if !answer {
|
|
|
|
+ return fmt.Errorf("user stated no to continue")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
- if answer {
|
|
|
|
- if metabase.IsContainerExist(metabaseContainerID) {
|
|
|
|
- log.Debugf("Stopping container %s", metabaseContainerID)
|
|
|
|
- if err := metabase.StopContainer(metabaseContainerID); err != nil {
|
|
|
|
- log.Warningf("unable to stop container '%s': %s", metabaseContainerID, err)
|
|
|
|
- }
|
|
|
|
- dockerGroup, err := user.LookupGroup(crowdsecGroup)
|
|
|
|
- if err == nil { // if group exist, remove it
|
|
|
|
- groupDelCmd, err := exec.LookPath("groupdel")
|
|
|
|
- if err != nil {
|
|
|
|
- log.Fatalf("unable to find 'groupdel' command, can't continue")
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- groupDel := &exec.Cmd{Path: groupDelCmd, Args: []string{groupDelCmd, crowdsecGroup}}
|
|
|
|
- if err := groupDel.Run(); err != nil {
|
|
|
|
- log.Errorf("unable to delete group '%s': %s", dockerGroup, err)
|
|
|
|
- }
|
|
|
|
|
|
+ if metabase.IsContainerExist(metabaseContainerID) {
|
|
|
|
+ log.Debugf("Stopping container %s", metabaseContainerID)
|
|
|
|
+ if err := metabase.StopContainer(metabaseContainerID); err != nil {
|
|
|
|
+ log.Warningf("unable to stop container '%s': %s", metabaseContainerID, err)
|
|
|
|
+ }
|
|
|
|
+ dockerGroup, err := user.LookupGroup(crowdsecGroup)
|
|
|
|
+ if err == nil { // if group exist, remove it
|
|
|
|
+ groupDelCmd, err := exec.LookPath("groupdel")
|
|
|
|
+ if err != nil {
|
|
|
|
+ return fmt.Errorf("unable to find 'groupdel' command, can't continue")
|
|
}
|
|
}
|
|
- log.Debugf("Removing container %s", metabaseContainerID)
|
|
|
|
- if err := metabase.RemoveContainer(metabaseContainerID); err != nil {
|
|
|
|
- log.Warningf("unable to remove container '%s': %s", metabaseContainerID, err)
|
|
|
|
|
|
+
|
|
|
|
+ groupDel := &exec.Cmd{Path: groupDelCmd, Args: []string{groupDelCmd, crowdsecGroup}}
|
|
|
|
+ if err := groupDel.Run(); err != nil {
|
|
|
|
+ log.Warnf("unable to delete group '%s': %s", dockerGroup, err)
|
|
}
|
|
}
|
|
- log.Infof("container %s stopped & removed", metabaseContainerID)
|
|
|
|
}
|
|
}
|
|
- log.Debugf("Removing metabase db %s", csConfig.ConfigPaths.DataDir)
|
|
|
|
- if err := metabase.RemoveDatabase(csConfig.ConfigPaths.DataDir); err != nil {
|
|
|
|
- log.Warningf("failed to remove metabase internal db : %s", err)
|
|
|
|
|
|
+ log.Debugf("Removing container %s", metabaseContainerID)
|
|
|
|
+ if err := metabase.RemoveContainer(metabaseContainerID); err != nil {
|
|
|
|
+ log.Warnf("unable to remove container '%s': %s", metabaseContainerID, err)
|
|
|
|
+ }
|
|
|
|
+ log.Infof("container %s stopped & removed", metabaseContainerID)
|
|
|
|
+ }
|
|
|
|
+ log.Debugf("Removing metabase db %s", csConfig.ConfigPaths.DataDir)
|
|
|
|
+ if err := metabase.RemoveDatabase(csConfig.ConfigPaths.DataDir); err != nil {
|
|
|
|
+ log.Warnf("failed to remove metabase internal db : %s", err)
|
|
|
|
+ }
|
|
|
|
+ if force {
|
|
|
|
+ m := metabase.Metabase{}
|
|
|
|
+ if err := m.LoadConfig(metabaseConfigPath); err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
- if force {
|
|
|
|
- if err := metabase.RemoveImageContainer(); err != nil {
|
|
|
|
- if !strings.Contains(err.Error(), "No such image") {
|
|
|
|
- log.Fatalf("removing docker image: %s", err)
|
|
|
|
- }
|
|
|
|
|
|
+ if err := metabase.RemoveImageContainer(m.Config.Image); err != nil {
|
|
|
|
+ if !strings.Contains(err.Error(), "No such image") {
|
|
|
|
+ return fmt.Errorf("removing docker image: %s", err)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
+ return nil
|
|
},
|
|
},
|
|
}
|
|
}
|
|
cmdDashRemove.Flags().BoolVarP(&force, "force", "f", false, "Remove also the metabase image")
|
|
cmdDashRemove.Flags().BoolVarP(&force, "force", "f", false, "Remove also the metabase image")
|
|
@@ -347,13 +313,95 @@ func passwordIsValid(password string) bool {
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-func checkSystemMemory() (bool, error) {
|
|
|
|
|
|
+func checkSystemMemory(forceYes *bool) error {
|
|
totMem := memory.TotalMemory()
|
|
totMem := memory.TotalMemory()
|
|
- if totMem == 0 {
|
|
|
|
- return true, errors.New("Unable to get system total memory")
|
|
|
|
|
|
+ if totMem >= uint64(math.Pow(2, 30)) {
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ if !*forceYes {
|
|
|
|
+ var answer bool
|
|
|
|
+ prompt := &survey.Confirm{
|
|
|
|
+ Message: "Metabase requires 1-2GB of RAM, your system is below this requirement continue ?",
|
|
|
|
+ Default: true,
|
|
|
|
+ }
|
|
|
|
+ if err := survey.AskOne(prompt, &answer); err != nil {
|
|
|
|
+ return fmt.Errorf("unable to ask about RAM check: %s", err)
|
|
|
|
+ }
|
|
|
|
+ if !answer {
|
|
|
|
+ return fmt.Errorf("user stated no to continue")
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ log.Warn("Metabase requires 1-2GB of RAM, your system is below this requirement")
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func warnIfNotLoopback(addr string) {
|
|
|
|
+ if addr == "127.0.0.1" || addr == "::1" {
|
|
|
|
+ return
|
|
|
|
+ }
|
|
|
|
+ log.Warnf("You are potentially exposing your metabase port to the internet (addr: %s), please consider using a reverse proxy", addr)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func disclaimer(forceYes *bool) error {
|
|
|
|
+ if !*forceYes {
|
|
|
|
+ var answer bool
|
|
|
|
+ prompt := &survey.Confirm{
|
|
|
|
+ Message: "CrowdSec takes no responsibility for the security of your metabase instance. Do you accept these responsibilities ?",
|
|
|
|
+ Default: true,
|
|
|
|
+ }
|
|
|
|
+ if err := survey.AskOne(prompt, &answer); err != nil {
|
|
|
|
+ return fmt.Errorf("unable to ask to question: %s", err)
|
|
|
|
+ }
|
|
|
|
+ if !answer {
|
|
|
|
+ return fmt.Errorf("user stated no to responsibilities")
|
|
|
|
+ }
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ log.Warn("CrowdSec takes no responsibility for the security of your metabase instance. You used force yes, so you accept this disclaimer")
|
|
|
|
+ return nil
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func checkGroups(forceYes *bool) (*user.Group, error) {
|
|
|
|
+ groupExist := false
|
|
|
|
+ dockerGroup, err := user.LookupGroup(crowdsecGroup)
|
|
|
|
+ if err == nil {
|
|
|
|
+ groupExist = true
|
|
|
|
+ }
|
|
|
|
+ if !groupExist {
|
|
|
|
+ if !*forceYes {
|
|
|
|
+ var answer bool
|
|
|
|
+ prompt := &survey.Confirm{
|
|
|
|
+ Message: fmt.Sprintf("For metabase docker to be able to access SQLite file we need to add a new group called '%s' to the system, is it ok for you ?", crowdsecGroup),
|
|
|
|
+ Default: true,
|
|
|
|
+ }
|
|
|
|
+ if err := survey.AskOne(prompt, &answer); err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to ask to question: %s", err)
|
|
|
|
+ }
|
|
|
|
+ if !answer {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to continue without creating '%s' group", crowdsecGroup)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ groupAddCmd, err := exec.LookPath("groupadd")
|
|
|
|
+ if err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to find 'groupadd' command, can't continue")
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ groupAdd := &exec.Cmd{Path: groupAddCmd, Args: []string{groupAddCmd, crowdsecGroup}}
|
|
|
|
+ if err := groupAdd.Run(); err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to add group '%s': %s", dockerGroup, err)
|
|
|
|
+ }
|
|
|
|
+ dockerGroup, err = user.LookupGroup(crowdsecGroup)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to lookup '%s' group: %+v", dockerGroup, err)
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ intID, err := strconv.Atoi(dockerGroup.Gid)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to convert group ID to int: %s", err)
|
|
}
|
|
}
|
|
- if uint64(math.Pow(2, 30)) >= totMem {
|
|
|
|
- return false, nil
|
|
|
|
|
|
+ if err := os.Chown(csConfig.DbConfig.DbPath, 0, intID); err != nil {
|
|
|
|
+ return dockerGroup, fmt.Errorf("unable to chown sqlite db file '%s': %s", csConfig.DbConfig.DbPath, err)
|
|
}
|
|
}
|
|
- return true, nil
|
|
|
|
|
|
+ return dockerGroup, nil
|
|
}
|
|
}
|