Skip to content

Commit

Permalink
Sanitize path inputs (#245)
Browse files Browse the repository at this point in the history
* Sanitize path inputs

* removed the utils pkg dependecy

* Accept root dir instead of the config file during the server start
  • Loading branch information
charithabandi authored and brennanjl committed Feb 26, 2024
1 parent d36980d commit baf7c9b
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 67 deletions.
12 changes: 9 additions & 3 deletions internal/app/kwild/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var rootCmd = &cobra.Command{
}

var kwildCfg = config.DefaultConfig()
var cfgFile string
var rootDir string

func Execute() error {
rootCmd.AddCommand(
Expand All @@ -32,7 +32,7 @@ func Execute() error {
}

func init() {
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "kwild config file")
rootCmd.PersistentFlags().StringVar(&rootDir, "root_dir", "~/.kwild", "kwild root directory for config and data")
rootCmd.PersistentPreRunE = extractKwildConfig
}

Expand All @@ -46,7 +46,13 @@ func extractKwildConfig(cmd *cobra.Command, args []string) error {
}
}

err := kwildCfg.LoadKwildConfig(cfgFile)
rootDir, err := config.ExpandPath(rootDir)
if err != nil {
fmt.Println("Error while getting absolute path for config file: ", err)
return err
}

err = kwildCfg.LoadKwildConfig(rootDir)
if err != nil {
fmt.Println("Failed to load config: ", err)
return err
Expand Down
6 changes: 0 additions & 6 deletions internal/app/kwild/cmd/server/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,6 @@ func NewStartCmd(cfg *config.KwildConfig) *cobra.Command {
return errors.New("private key is not set")
}

if cfg.RootDir == "" {
return errors.New("kwild home directory not set")
}

signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, os.Interrupt, syscall.SIGTERM)
ctx, cancel := context.WithCancel(cmd.Context())
Expand All @@ -52,8 +48,6 @@ func NewStartCmd(cfg *config.KwildConfig) *cobra.Command {

func AddKwildFlags(cmd *cobra.Command, cfg *config.KwildConfig) {
// General APP flags:
cmd.Flags().StringVar(&cfg.RootDir, "home_dir", cfg.RootDir, "Kwild home directory to store blockchain, kwildb and other data")

cmd.Flags().StringVar(&cfg.AppCfg.PrivateKey, "app.private_key", cfg.AppCfg.PrivateKey, "Kwild app's private key")

cmd.Flags().StringVar(&cfg.AppCfg.GrpcListenAddress, "app.grpc_listen_addr", cfg.AppCfg.GrpcListenAddress, "Kwild app gRPC listen address")
Expand Down
11 changes: 1 addition & 10 deletions internal/app/kwild/cmd/utils/init.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package utils

import (
"os"
"path/filepath"

"github.com/kwilteam/kwil-db/internal/pkg/nodecfg"
"github.com/spf13/cobra"
)
Expand All @@ -18,13 +15,7 @@ func InitFilesCmd() *cobra.Command {
RunE: initFiles,
}

homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}

initFilesCmd.Flags().StringVarP(&initFlags.OutputDir, "output-dir", "o",
filepath.Join(homeDir, ".kwild"),
initFilesCmd.Flags().StringVarP(&initFlags.OutputDir, "output-dir", "o", "~/.kwild",
"directory to store initialization data for the node")
initFilesCmd.Flags().Int64VarP(&initFlags.InitialHeight, "initial-height", "i", 0,
"initial height of the first block")
Expand Down
22 changes: 10 additions & 12 deletions internal/app/kwild/cmd/utils/reset.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package utils

import (
"fmt"

"github.com/spf13/cobra"
"github.com/spf13/viper"

Expand All @@ -24,14 +22,14 @@ func NewResetAllCmd() *cobra.Command {
Aliases: []string{"unsafe_reset_all"},
Short: "(unsafe) Remove all the blockchain's data and WAL, reset this node's validator to genesis state, for testing purposes only",
RunE: func(cmd *cobra.Command, args []string) (err error) {
cfgFile := viper.GetString("config")
if cfgFile == "" {
fmt.Println("No config file specified")
return fmt.Errorf("no config file specified")
rootDir := viper.GetString("root_dir")
rootDir, err = config.ExpandPath(rootDir)
if err != nil {
return err
}

cfg := config.DefaultConfig()
err = cfg.LoadKwildConfig(cfgFile)
err = cfg.LoadKwildConfig(rootDir)
if err != nil {
return err
}
Expand All @@ -51,14 +49,14 @@ func NewResetStateCmd() *cobra.Command {
Aliases: []string{"reset_state"},
Short: "(unsafe) Remove all the data and WAL, for testing purposes only",
RunE: func(cmd *cobra.Command, args []string) (err error) {
cfgFile := viper.GetString("config")
if cfgFile == "" {
fmt.Println("No config file specified")
return fmt.Errorf("no config file specified")
rootDir := viper.GetString("root_dir")
rootDir, err = config.ExpandPath(rootDir)
if err != nil {
return err
}

cfg := config.DefaultConfig()
err = cfg.LoadKwildConfig(cfgFile)
err = cfg.LoadKwildConfig(rootDir)
if err != nil {
return err
}
Expand Down
53 changes: 46 additions & 7 deletions internal/app/kwild/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import (
"fmt"
"os"
"path/filepath"
"strings"

cometCfg "github.com/cometbft/cometbft/config"
"github.com/kwilteam/kwil-db/pkg/log"
"github.com/spf13/viper"
)

type KwildConfig struct {
RootDir string `mapstructure:"home_dir"`
RootDir string

AppCfg *AppConfig `mapstructure:"app"`
ChainCfg *cometCfg.Config `mapstructure:"chain"`
Expand Down Expand Up @@ -46,19 +47,27 @@ type SnapshotConfig struct {
SnapshotDir string `mapstructure:"snapshot_dir"`
}

func (cfg *KwildConfig) LoadKwildConfig(cfgFile string) error {
err := cfg.ParseConfig(cfgFile)
func (cfg *KwildConfig) LoadKwildConfig(rootDir string) error {
// Expand root dir path
rootDir, err := ExpandPath(rootDir)
if err != nil {
return fmt.Errorf("failed to expand rootdir path: %v", err)
}
cfg.RootDir = rootDir

cfgFile := filepath.Join(rootDir, "config.toml")
err = cfg.ParseConfig(cfgFile)
if err != nil {
return fmt.Errorf("failed to parse config file: %v", err)
}

rootDir := cfg.RootDir
cfg.ChainCfg.SetRoot(filepath.Join(rootDir, "abci"))
err = cfg.sanitizeCfgPaths()
if err != nil {
return fmt.Errorf("failed to sanitize config paths: %v", err)
}

cfg.configureLogging()
cfg.configureCerts()
cfg.AppCfg.SqliteFilePath = rootify(cfg.AppCfg.SqliteFilePath, rootDir)
cfg.AppCfg.SnapshotConfig.SnapshotDir = rootify(cfg.AppCfg.SnapshotConfig.SnapshotDir, rootDir)

if err := cfg.ChainCfg.ValidateBasic(); err != nil {
return fmt.Errorf("invalid chain configuration data: %v", err)
Expand Down Expand Up @@ -147,3 +156,33 @@ func rootify(path, rootDir string) string {
}
return filepath.Join(rootDir, path)
}

func (cfg *KwildConfig) sanitizeCfgPaths() error {
rootDir := cfg.RootDir
cfg.AppCfg.SqliteFilePath = rootify(cfg.AppCfg.SqliteFilePath, rootDir)
cfg.AppCfg.SnapshotConfig.SnapshotDir = rootify(cfg.AppCfg.SnapshotConfig.SnapshotDir, rootDir)

cfg.ChainCfg.SetRoot(filepath.Join(rootDir, "abci"))
return nil
}

func ExpandPath(path string) (string, error) {
var expandedPath string

if tail, cut := strings.CutPrefix(path, "~/"); cut {
// Expands ~ in the path
homeDir, err := os.UserHomeDir()
if err != nil {
return "", err
}
expandedPath = filepath.Join(homeDir, tail)
} else {
// Expands relative paths
absPath, err := filepath.Abs(path)
if err != nil {
return "", fmt.Errorf("failed to get absolute path of file: %v due to error: %v", path, err)
}
expandedPath = absPath
}
return expandedPath, nil
}
31 changes: 17 additions & 14 deletions internal/pkg/nodecfg/generate.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,32 +48,35 @@ type TestnetGenerateConfig struct {

func GenerateNodeConfig(genCfg *NodeGenerateConfig) error {
cfg := config.DefaultConfig()
cfg.RootDir = genCfg.OutputDir

err := initFilesWithConfig(cfg, 0)
rootDir, err := config.ExpandPath(genCfg.OutputDir)
if err != nil {
fmt.Println("Error while getting absolute path for output directory: ", err)
return err
}

cfg.ChainCfg.RPC.ListenAddress = "tcp://0.0.0.0:26657"

outputPath := genCfg.OutputDir
// this only works on linux
if strings.HasPrefix(genCfg.OutputDir, "~/") {
dirname, err := os.UserHomeDir()
if err != nil {
return err
}
outputPath = filepath.Join(dirname, genCfg.OutputDir[2:])
cfg.RootDir = rootDir
err = initFilesWithConfig(cfg, 0)
if err != nil {
return err
}

writeConfigFile(filepath.Join(outputPath, "config.toml"), cfg)
cfg.ChainCfg.RPC.ListenAddress = "tcp://0.0.0.0:26657"

writeConfigFile(filepath.Join(rootDir, "config.toml"), cfg)

fmt.Println("Successfully initialized node directory: ", genCfg.OutputDir)
fmt.Println("Successfully initialized node directory: ", rootDir)
return nil
}

func GenerateTestnetConfig(genCfg *TestnetGenerateConfig) error {
rootDir, err := config.ExpandPath(genCfg.OutputDir)
if err != nil {
fmt.Println("Error while getting absolute path for output directory: ", err)
return err
}
genCfg.OutputDir = rootDir

if len(genCfg.Hostnames) > 0 && len(genCfg.Hostnames) != (genCfg.NValidators+genCfg.NNonValidators) {
return fmt.Errorf(
"testnet needs precisely %d hostnames (number of validators plus nonValidators) if --hostname parameter is used",
Expand Down
26 changes: 11 additions & 15 deletions internal/pkg/nodecfg/toml.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,18 @@ const defaultConfigTemplate = `
# Only the config.toml and genesis file are required to run the kwild node
# The rest of the files & directories are created by the kwild node on startup
#######################################################################
### Logging Config Options ###
#######################################################################
[log]
# Output level for logging, default is "info". Other options are "debug", "error", "warn", "trace"
log_level = "{{ .Logging.LogLevel }}"
# Directory to store the kwild node's data (described above)
home_dir = "{{ .RootDir }}"
# Output paths for the logger, can be stdout or a file path
output_paths = {{arrayFormatter .Logging.OutputPaths }}
# Output format: 'plain' or 'json'
log_format = "{{ .Logging.LogFormat }}"
#######################################################################
### App Config Options ###
Expand Down Expand Up @@ -139,19 +148,6 @@ max_snapshots = {{ .AppCfg.SnapshotConfig.MaxSnapshots}}
# The directory where the snapshots are stored. Can be absolute or relative to the kwild root directory
snapshot_dir = "{{ .AppCfg.SnapshotConfig.SnapshotDir }}"
#######################################################################
### Logging Config Options ###
#######################################################################
[log]
# Output level for logging, default is "info". Other options are "debug", "error", "warn", "trace"
log_level = "{{ .Logging.LogLevel }}"
# Output paths for the logger, can be stdout or a file path
output_paths = {{arrayFormatter .Logging.OutputPaths }}
# Output format: 'plain' or 'json'
log_format = "{{ .Logging.LogFormat }}"
#######################################################################
### Chain Main Base Config Options ###
#######################################################################
Expand Down

0 comments on commit baf7c9b

Please sign in to comment.