|
@@ -3,7 +3,10 @@ package main
|
|
|
import (
|
|
|
"fmt"
|
|
|
"os"
|
|
|
+ "os/exec"
|
|
|
+ "os/user"
|
|
|
"path/filepath"
|
|
|
+ "strconv"
|
|
|
|
|
|
"github.com/AlecAivazis/survey/v2"
|
|
|
"github.com/crowdsecurity/crowdsec/pkg/metabase"
|
|
@@ -24,6 +27,7 @@ var (
|
|
|
metabaseListenAddress = "127.0.0.1"
|
|
|
metabaseListenPort = "3000"
|
|
|
metabaseContainerID = "/crowdsec-metabase"
|
|
|
+ crowdsecGroup = "crowdsec"
|
|
|
|
|
|
forceYes bool
|
|
|
|
|
@@ -72,7 +76,48 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
|
if metabasePassword == "" {
|
|
|
metabasePassword = generatePassword(16)
|
|
|
}
|
|
|
- mb, err := metabase.SetupMetabase(csConfig.API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath)
|
|
|
+ var answer bool
|
|
|
+ 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 !answer && !forceYes && !groupExist {
|
|
|
+ log.Fatalf("unable to continue without creating '%s' group", crowdsecGroup)
|
|
|
+ }
|
|
|
+ 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)
|
|
|
+ if err != nil {
|
|
|
+ log.Fatalf("unable to convert group ID to int: %s", 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)
|
|
|
if err != nil {
|
|
|
log.Fatalf(err.Error())
|
|
|
}
|
|
@@ -92,6 +137,7 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password <password>
|
|
|
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(&metabaseListenPort, "port", "p", metabaseListenPort, "Listen port of container")
|
|
|
+ cmdDashSetup.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
|
|
|
//cmdDashSetup.Flags().StringVarP(&metabaseUser, "user", "u", "crowdsec@crowdsec.net", "metabase user")
|
|
|
cmdDashSetup.Flags().StringVar(&metabasePassword, "password", "", "metabase password")
|
|
|
|
|
@@ -149,34 +195,44 @@ cscli dashboard remove --force
|
|
|
log.Fatalf("unable to ask to force: %s", err)
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
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)
|
|
|
+ }
|
|
|
+ }
|
|
|
log.Debugf("Removing container %s", metabaseContainerID)
|
|
|
if err := metabase.RemoveContainer(metabaseContainerID); err != nil {
|
|
|
log.Warningf("unable to remove container '%s': %s", metabaseContainerID, err)
|
|
|
}
|
|
|
log.Infof("container %s stopped & removed", metabaseContainerID)
|
|
|
}
|
|
|
- log.Debugf("Removing database %s", csConfig.ConfigPaths.DataDir)
|
|
|
+ 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)
|
|
|
}
|
|
|
if force {
|
|
|
- log.Debugf("Removing image %s", metabaseImage)
|
|
|
- if err := metabase.RemoveImageContainer(metabaseImage); err != nil {
|
|
|
- log.Warningf("Failed to remove metabase container %s : %s", metabaseImage, err)
|
|
|
+ if err := metabase.RemoveImageContainer(); err != nil {
|
|
|
+ log.Fatalf("removing docker image: %s", err)
|
|
|
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
},
|
|
|
}
|
|
|
- cmdDashRemove.Flags().BoolVarP(&force, "force", "f", false, "Force remove : stop the container if running and remove.")
|
|
|
+ cmdDashRemove.Flags().BoolVarP(&force, "force", "f", false, "Remove also the metabase image")
|
|
|
cmdDashRemove.Flags().BoolVarP(&forceYes, "yes", "y", false, "force yes")
|
|
|
cmdDashboard.AddCommand(cmdDashRemove)
|
|
|
|