Use API key to get node deployment information

This commit is contained in:
Dane Everitt 2020-04-12 17:04:32 -07:00
parent 137b6cddae
commit 89bda64e47
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53

View File

@ -1,52 +1,65 @@
package cmd package cmd
import ( import (
"crypto/tls"
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/AlecAivazis/survey/v2"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/creasty/defaults"
"github.com/pterodactyl/wings/config"
"github.com/spf13/cobra"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/url" "net/url"
"os" "os"
"path" "path"
"regexp"
"github.com/AlecAivazis/survey/v2" "time"
"github.com/AlecAivazis/survey/v2/terminal"
"github.com/pterodactyl/wings/config"
"github.com/spf13/cobra"
) )
var ( var (
configureArgs struct { configureArgs struct {
PanelURL string PanelURL string
Token string Token string
Override bool Node string
Override bool
AllowInsecure bool
} }
) )
var nodeIdRegex = regexp.MustCompile(`^(\d+)$`)
var configureCmd = &cobra.Command{ var configureCmd = &cobra.Command{
Use: "configure", Use: "configure",
Short: "Use a token to configure wings automatically", Short: "Use a token to configure wings automatically",
Run: configureCmdRun,
Run: configureCmdRun,
} }
func init() { func init() {
configureCmd.PersistentFlags().StringVarP(&configureArgs.PanelURL, "panel-url", "p", "", "the baseurl of the pterodactyl panel to fetch the configuration from") configureCmd.PersistentFlags().StringVarP(&configureArgs.PanelURL, "panel-url", "p", "", "The base URL for this daemon's panel")
configureCmd.PersistentFlags().StringVarP(&configureArgs.Token, "token", "t", "", "the auto-deploy token to use") configureCmd.PersistentFlags().StringVarP(&configureArgs.Token, "token", "t", "", "The API key to use for fetching node information")
configureCmd.PersistentFlags().BoolVar(&configureArgs.Override, "override", false, "override an existing configuration") configureCmd.PersistentFlags().StringVarP(&configureArgs.Node, "node", "n", "", "The ID of the node which will be connected to this daemon")
configureCmd.PersistentFlags().BoolVar(&configureArgs.Override, "override", false, "Set to true to override an existing configuration for this node")
configureCmd.PersistentFlags().BoolVar(&configureArgs.AllowInsecure, "allow-insecure", false, "Set to true to disable certificate checking")
} }
func configureCmdRun(cmd *cobra.Command, args []string) { func configureCmdRun(cmd *cobra.Command, args []string) {
_, err := os.Stat("config.yml") http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{
if err != os.ErrNotExist && !configureArgs.Override { InsecureSkipVerify: true,
survey.AskOne(&survey.Confirm{Message: "Override existing configuration file"}, &configureArgs.Override)
if !configureArgs.Override {
fmt.Println("Aborted.")
os.Exit(1)
}
} }
questions := []*survey.Question{} if _, err := os.Stat("config.yml"); err == nil && !configureArgs.Override {
survey.AskOne(&survey.Confirm{Message: "Override existing configuration file"}, &configureArgs.Override)
if !configureArgs.Override {
fmt.Println("Aborting process; a configuration file already exists for this node.")
os.Exit(1)
}
} else if err != nil && !os.IsNotExist(err) {
panic(err)
}
var questions []*survey.Question
if configureArgs.PanelURL == "" { if configureArgs.PanelURL == "" {
questions = append(questions, &survey.Question{ questions = append(questions, &survey.Question{
Name: "PanelURL", Name: "PanelURL",
@ -60,14 +73,15 @@ func configureCmdRun(cmd *cobra.Command, args []string) {
}, },
}) })
} }
if configureArgs.Token == "" { if configureArgs.Token == "" {
questions = append(questions, &survey.Question{ questions = append(questions, &survey.Question{
Name: "Token", Name: "Token",
Prompt: &survey.Input{Message: "Token: "}, Prompt: &survey.Input{Message: "API Token: "},
Validate: func(ans interface{}) error { Validate: func(ans interface{}) error {
if str, ok := ans.(string); ok { if str, ok := ans.(string); ok {
if len(str) != 32 { if len(str) == 0 {
return fmt.Errorf("the token needs to have 32 characters") return fmt.Errorf("please provide a valid authentication token")
} }
} }
return nil return nil
@ -75,39 +89,85 @@ func configureCmdRun(cmd *cobra.Command, args []string) {
}) })
} }
err = survey.Ask(questions, &configureArgs) if configureArgs.Node == "" {
if err == terminal.InterruptErr { questions = append(questions, &survey.Question{
return Name: "Node",
Prompt: &survey.Input{Message: "Node ID: "},
Validate: func(ans interface{}) error {
if str, ok := ans.(string); ok {
if !nodeIdRegex.Match([]byte(str)) {
return fmt.Errorf("please provide a valid authentication token")
}
}
return nil
},
})
} }
if err := survey.Ask(questions, &configureArgs); err != nil {
if err == terminal.InterruptErr {
return
}
panic(err)
}
c := &http.Client{
Timeout: time.Second * 30,
}
req, err := getRequest()
if err != nil { if err != nil {
panic(err) panic(err)
} }
url, err := url.Parse(configureArgs.PanelURL) res, err := c.Do(req)
url.Path = path.Join(url.Path, "daemon/configure", configureArgs.Token)
req, err := http.NewRequest("GET", url.String(), nil)
if err != nil { if err != nil {
panic(err) fmt.Println("Failed to fetch configuration from the panel.\n", err.Error())
}
req.Header.Add("Accept", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil {
fmt.Println("Couldn't fetch configuration from panel.\n", err.Error())
os.Exit(1) os.Exit(1)
} }
defer res.Body.Close() defer res.Body.Close()
if res.StatusCode == http.StatusForbidden { if res.StatusCode == http.StatusForbidden {
fmt.Println("The provided token is invalid.") fmt.Println("The authentication credentials provided were not valid.")
os.Exit(1) os.Exit(1)
} }
configJSON, err := ioutil.ReadAll(res.Body)
cfg := config.Configuration{} b, err := ioutil.ReadAll(res.Body)
json.Unmarshal(configJSON, &cfg)
err = cfg.WriteToDisk() cfg := new(config.Configuration)
if err != nil { if err := defaults.Set(cfg); err != nil {
panic(err)
}
if err := json.Unmarshal(b, &cfg); err != nil {
panic(err)
}
if err = cfg.WriteToDisk(); err != nil {
panic(err) panic(err)
} }
fmt.Println("Successfully configured wings.") fmt.Println("Successfully configured wings.")
} }
func getRequest() (*http.Request, error) {
u, err := url.Parse(configureArgs.PanelURL)
if err != nil {
panic(err)
}
u.Path = path.Join(u.Path, fmt.Sprintf("api/application/nodes/%s/configuration", configureArgs.Node))
r, err := http.NewRequest(http.MethodGet, u.String(), nil)
if err != nil {
return nil, err
}
r.Header.Set("Accept", "application/vnd.pterodactyl.v1+json")
r.Header.Set("Content-Type", "application/json")
r.Header.Set("Authorization", fmt.Sprintf("Bearer %s", configureArgs.Token))
return r, nil
}