/* Copyright © 2025 Jake jake.young.dev@gmail.com */ package cmd import ( "crypto/rand" "fmt" "io" "os" "code.jakeyoungdev.com/jake/mctl/cryptography" "github.com/spf13/cobra" "github.com/spf13/viper" "golang.org/x/term" ) var ( cfgserver string cfgport int ) // configCmd represents the config command var configCmd = &cobra.Command{ Use: "config", Example: "mctl config -s x.x.x.x -p 61695", Short: "Create and populate config file", Long: `Creates the .mctl file in the user home directory populating it with the server address, rcon password, and rcon port to be pulled when using Login command`, Run: func(cmd *cobra.Command, args []string) { //read in password using term to keep it secure/hidden from bash history fmt.Printf("Password: ") ps, err := term.ReadPassword(int(os.Stdin.Fd())) cobra.CheckErr(err) //generate and apply random nonce nonce := make([]byte, 12) _, err = io.ReadFull(rand.Reader, nonce) cobra.CheckErr(err) viper.Set("nonce", string(nonce)) //encrypt password ciphert, err := cryptography.EncryptPassword(ps) cobra.CheckErr(err) //update config file with new values viper.Set("server", cfgserver) viper.Set("password", string(ciphert)) viper.Set("port", cfgport) viper.WriteConfig() fmt.Println() fmt.Println("Config file updated!") }, } func init() { initConfig() configCmd.Flags().StringVarP(&cfgserver, "server", "s", "", "server address") configCmd.MarkFlagRequired("server") configCmd.Flags().IntVarP(&cfgport, "port", "p", 0, "server rcon port") configCmd.MarkFlagRequired("port") rootCmd.AddCommand(configCmd) } // init config sets viper config and checks for config file, creating it if it doesn't exist func initConfig() { home, err := os.UserHomeDir() cobra.CheckErr(err) viper.AddConfigPath(home) viper.SetConfigType("yaml") viper.SetConfigName(".mctl") viper.AutomaticEnv() viper.ReadInConfig() if err := viper.ReadInConfig(); err != nil { //file does not exist, create it viper.Set("server", cfgserver) viper.Set("password", "") viper.Set("port", cfgport) viper.Set("nonce", "") //generate psuedo-random key uu := make([]byte, 32) _, err := rand.Read(uu) cobra.CheckErr(err) //create custom command map cmdMap := make(map[string]any, 0) //write config viper.Set("customcmd", cmdMap) viper.Set("device", string(uu)) viper.SafeWriteConfig() } }