From ed3d501081e9b8ff8bb217a7426f23d0ecc4c9e1 Mon Sep 17 00:00:00 2001 From: Laurence Jones Date: Mon, 4 Dec 2023 10:06:41 +0000 Subject: [PATCH] [Metabase] QOL Changes and chown wal files (#2627) * Add detection sqlie wal for dashboard chown * Lean it down a little * Change to for loop with extensions * Keep existing uid on files incase user is running as a unpriviledge user * I have no idea :shrug: * Exclude dash.go and update windows * Update * Renam * Remove the os check since we no longer get to this stage for those os's --------- Co-authored-by: Manuel Sabban --- cmd/crowdsec-cli/dashboard.go | 79 ++++++++++++++--------- cmd/crowdsec-cli/dashboard_unsupported.go | 22 +++++++ pkg/metabase/container.go | 9 --- 3 files changed, 70 insertions(+), 40 deletions(-) create mode 100644 cmd/crowdsec-cli/dashboard_unsupported.go diff --git a/cmd/crowdsec-cli/dashboard.go b/cmd/crowdsec-cli/dashboard.go index 8eab614e9..a2d6c229a 100644 --- a/cmd/crowdsec-cli/dashboard.go +++ b/cmd/crowdsec-cli/dashboard.go @@ -1,3 +1,5 @@ +//go:build linux + package main import ( @@ -9,6 +11,7 @@ import ( "path/filepath" "strconv" "strings" + "syscall" "unicode" "github.com/AlecAivazis/survey/v2" @@ -136,6 +139,9 @@ cscli dashboard setup -l 0.0.0.0 -p 443 --password if err != nil { return err } + if err = chownDatabase(dockerGroup.Gid); err != nil { + return err + } mb, err := metabase.SetupMetabase(csConfig.API.Server.DbConfig, metabaseListenAddress, metabaseListenPort, metabaseUser, metabasePassword, metabaseDbPath, dockerGroup.Gid, metabaseContainerID, metabaseImage) if err != nil { return err @@ -366,45 +372,56 @@ func disclaimer(forceYes *bool) error { } func checkGroups(forceYes *bool) (*user.Group, error) { - groupExist := false dockerGroup, err := user.LookupGroup(crowdsecGroup) if err == nil { - groupExist = true + return dockerGroup, nil } - 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) - } + 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, } - groupAddCmd, err := exec.LookPath("groupadd") - if err != nil { - return dockerGroup, fmt.Errorf("unable to find 'groupadd' command, can't continue") + if err := survey.AskOne(prompt, &answer); err != nil { + return dockerGroup, fmt.Errorf("unable to ask to question: %s", err) } - - 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) + if !answer { + return dockerGroup, fmt.Errorf("unable to continue without creating '%s' group", crowdsecGroup) } } - intID, err := strconv.Atoi(dockerGroup.Gid) + groupAddCmd, err := exec.LookPath("groupadd") if err != nil { - return dockerGroup, fmt.Errorf("unable to convert group ID to int: %s", err) + return dockerGroup, fmt.Errorf("unable to find 'groupadd' command, can't continue") } - 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) + + 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) } - return dockerGroup, nil + return user.LookupGroup(crowdsecGroup) +} + +func chownDatabase(gid string) error { + intID, err := strconv.Atoi(gid) + if err != nil { + return fmt.Errorf("unable to convert group ID to int: %s", err) + } + if stat, err := os.Stat(csConfig.DbConfig.DbPath); !os.IsNotExist(err) { + info := stat.Sys() + if err := os.Chown(csConfig.DbConfig.DbPath, int(info.(*syscall.Stat_t).Uid), intID); err != nil { + return fmt.Errorf("unable to chown sqlite db file '%s': %s", csConfig.DbConfig.DbPath, err) + } + } + if csConfig.DbConfig.Type == "sqlite" && csConfig.DbConfig.UseWal != nil && *csConfig.DbConfig.UseWal { + for _, ext := range []string{"-wal", "-shm"} { + file := csConfig.DbConfig.DbPath + ext + if stat, err := os.Stat(file); !os.IsNotExist(err) { + info := stat.Sys() + if err := os.Chown(file, int(info.(*syscall.Stat_t).Uid), intID); err != nil { + return fmt.Errorf("unable to chown sqlite db file '%s': %s", file, err) + } + } + } + } + return nil } diff --git a/cmd/crowdsec-cli/dashboard_unsupported.go b/cmd/crowdsec-cli/dashboard_unsupported.go new file mode 100644 index 000000000..f2325ea07 --- /dev/null +++ b/cmd/crowdsec-cli/dashboard_unsupported.go @@ -0,0 +1,22 @@ +//go:build !linux + +package main + +import ( + "runtime" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func NewDashboardCmd() *cobra.Command { + var cmdDashboard = &cobra.Command{ + Use: "dashboard", + DisableAutoGenTag: true, + Run: func(cmd *cobra.Command, args []string) { + log.Infof("Dashboard command is disabled on %s", runtime.GOOS) + }, + } + + return cmdDashboard +} diff --git a/pkg/metabase/container.go b/pkg/metabase/container.go index b3df7aca7..8b3dd4084 100644 --- a/pkg/metabase/container.go +++ b/pkg/metabase/container.go @@ -4,7 +4,6 @@ import ( "bufio" "context" "fmt" - "runtime" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/container" @@ -93,14 +92,6 @@ func (c *Container) Create() error { Tty: true, Env: env, } - os := runtime.GOOS - switch os { - case "linux": - case "windows", "darwin": - return fmt.Errorf("mac and windows are not supported yet") - default: - return fmt.Errorf("OS '%s' is not supported", os) - } log.Infof("creating container '%s'", c.Name) resp, err := c.CLI.ContainerCreate(ctx, dockerConfig, hostConfig, nil, nil, c.Name)