Merge pull request #18 from matthewpi/gin-fixes

Even more Gin fixes
This commit is contained in:
Dane Everitt 2020-04-06 16:42:16 -07:00 committed by GitHub
commit cc54b99b55
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 35 additions and 98 deletions

View File

@ -1,34 +0,0 @@
package main
import (
"github.com/gbrlsnchs/jwt/v3"
"github.com/pterodactyl/wings/config"
"time"
)
var alg *jwt.HMACSHA
// ArchiveTokenPayload represents an Archive Token Payload.
type ArchiveTokenPayload struct {
jwt.Payload
}
func ParseArchiveJWT(token []byte) (*ArchiveTokenPayload, error) {
var payload ArchiveTokenPayload
if alg == nil {
alg = jwt.NewHS256([]byte(config.Get().AuthenticationToken))
}
now := time.Now()
verifyOptions := jwt.ValidatePayload(
&payload.Payload,
jwt.ExpirationTimeValidator(now),
)
_, err := jwt.Verify(token, alg, &payload, verifyOptions)
if err != nil {
return nil, err
}
return &payload, nil
}

View File

@ -1,47 +0,0 @@
package main
import (
"github.com/gbrlsnchs/jwt/v3"
cache2 "github.com/patrickmn/go-cache"
"sync"
"time"
)
type JWTokens struct {
cache *cache2.Cache
mutex *sync.Mutex
}
var _tokens *JWTokens
type DownloadBackupPayload struct {
jwt.Payload
ServerUuid string `json:"server_uuid"`
BackupUuid string `json:"backup_uuid"`
UniqueId string `json:"unique_id"`
}
func getTokenStore() *JWTokens {
if _tokens == nil {
_tokens = &JWTokens{
cache: cache2.New(time.Minute*60, time.Minute*5),
mutex: &sync.Mutex{},
}
}
return _tokens
}
// Determines if a given JWT unique token is valid.
func (tokens *JWTokens) IsValidToken(token string) bool {
tokens.mutex.Lock()
defer tokens.mutex.Unlock()
_, exists := tokens.cache.Get(token)
if !exists {
_tokens.cache.Add(token, "", time.Minute*60)
}
return !exists
}

View File

@ -1,20 +1,31 @@
package router package router
import "github.com/gin-gonic/gin" import (
"github.com/gin-gonic/gin"
)
// Configures the routing infrastructure for this daemon instance. // Configures the routing infrastructure for this daemon instance.
func Configure() *gin.Engine { func Configure() *gin.Engine {
router := gin.Default() router := gin.Default()
router.Use(SetAccessControlHeaders) router.Use(SetAccessControlHeaders)
router.OPTIONS("/api/system", func(c *gin.Context) {
c.Status(200)
})
// These routes use signed URLs to validate access to the resource being requested. // These routes use signed URLs to validate access to the resource being requested.
router.GET("/download/backup", getDownloadBackup) router.GET("/download/backup", getDownloadBackup)
// This route is special is sits above all of the other requests because we are // This route is special it sits above all of the other requests because we are
// using a JWT to authorize access to it, therefore it needs to be publically // using a JWT to authorize access to it, therefore it needs to be publicly
// accessible. // accessible.
router.GET("/api/servers/:server/ws", getServerWebsocket) router.GET("/api/servers/:server/ws", getServerWebsocket)
// This request is called by another daemon when a server is going to be transferred out.
// This request does not need the AuthorizationMiddleware as the panel should never call it
// and requests are authenticated through a JWT the panel issues to the other daemon.
router.GET("/api/servers/:server/archive", getServerArchive)
// All of the routes beyond this mount will use an authorization middleware // All of the routes beyond this mount will use an authorization middleware
// and will not be accessible without the correct Authorization header provided. // and will not be accessible without the correct Authorization header provided.
protected := router.Use(AuthorizationMiddleware) protected := router.Use(AuthorizationMiddleware)
@ -39,7 +50,8 @@ func Configure() *gin.Engine {
server.POST("/reinstall", postServerReinstall) server.POST("/reinstall", postServerReinstall)
server.POST("/backup", postServerBackup) server.POST("/backup", postServerBackup)
server.GET("/archive", getServerArchive) // This archive request causes the archive to start being created
// this should only be triggered by the panel.
server.POST("/archive", postServerArchive) server.POST("/archive", postServerArchive)
files := server.Group("/files") files := server.Group("/files")

View File

@ -1,6 +1,7 @@
package router package router
import ( import (
"bytes"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"github.com/pterodactyl/wings/installer" "github.com/pterodactyl/wings/installer"
"github.com/pterodactyl/wings/server" "github.com/pterodactyl/wings/server"
@ -30,10 +31,10 @@ func getAllServers(c *gin.Context) {
// Creates a new server on the wings daemon and begins the installation process // Creates a new server on the wings daemon and begins the installation process
// for it. // for it.
func postCreateServer(c *gin.Context) { func postCreateServer(c *gin.Context) {
var data []byte buf := bytes.Buffer{}
c.Bind(&data) buf.ReadFrom(c.Request.Body)
install, err := installer.New(data) install, err := installer.New(buf.Bytes())
if err != nil { if err != nil {
TrackedError(err). TrackedError(err).
SetMessage("Failed to validate the data provided in the request."). SetMessage("Failed to validate the data provided in the request.").

View File

@ -37,14 +37,14 @@ func getServerArchive(c *gin.Context) {
} }
token := tokens.TransferPayload{} token := tokens.TransferPayload{}
if err := tokens.ParseToken([]byte(c.Query("token")), &token); err != nil { if err := tokens.ParseToken([]byte(auth[1]), &token); err != nil {
TrackedError(err).AbortWithServerError(c) TrackedError(err).AbortWithServerError(c)
return return
} }
if token.Subject != c.Param("server") { if token.Subject != c.Param("server") {
c.AbortWithStatusJSON(http.StatusForbidden, gin.H{ c.AbortWithStatusJSON(http.StatusForbidden, gin.H{
"error": "You are not authorized to access this endpoint.", "error": "( .. •˘___˘• .. )",
}) })
return return
} }
@ -54,7 +54,6 @@ func getServerArchive(c *gin.Context) {
st, err := s.Archiver.Stat() st, err := s.Archiver.Stat()
if err != nil { if err != nil {
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
// zap.S().Errorw("failed to stat archive for reading", zap.String("server", s.Uuid), zap.Error(err))
TrackedServerError(err, s).SetMessage("failed to stat archive").AbortWithServerError(c) TrackedServerError(err, s).SetMessage("failed to stat archive").AbortWithServerError(c)
return return
} }
@ -65,7 +64,6 @@ func getServerArchive(c *gin.Context) {
checksum, err := s.Archiver.Checksum() checksum, err := s.Archiver.Checksum()
if err != nil { if err != nil {
// zap.S().Errorw("failed to calculate checksum", zap.String("server", s.Uuid), zap.Error(err))
TrackedServerError(err, s).SetMessage("failed to calculate checksum").AbortWithServerError(c) TrackedServerError(err, s).SetMessage("failed to calculate checksum").AbortWithServerError(c)
return return
} }
@ -75,7 +73,6 @@ func getServerArchive(c *gin.Context) {
tserr := TrackedServerError(err, s) tserr := TrackedServerError(err, s)
if !os.IsNotExist(err) { if !os.IsNotExist(err) {
tserr.SetMessage("failed to open archive for reading") tserr.SetMessage("failed to open archive for reading")
// zap.S().Errorw("failed to open archive for reading", zap.String("server", s.Uuid), zap.Error(err))
} else { } else {
tserr.SetMessage("failed to open archive") tserr.SetMessage("failed to open archive")
} }
@ -271,8 +268,6 @@ func postTransfer(c *gin.Context) {
return return
} }
zap.S().Debug(string(serverData))
// Create a new server installer (note this does not execute the install script) // Create a new server installer (note this does not execute the install script)
i, err := installer.New(serverData) i, err := installer.New(serverData)
if err != nil { if err != nil {
@ -287,8 +282,19 @@ func postTransfer(c *gin.Context) {
i.Execute() i.Execute()
// Un-archive the archive. That sounds weird.. // Un-archive the archive. That sounds weird..
archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem.Path()) if err := archiver.NewTarGz().Unarchive(archivePath, i.Server().Filesystem.Path()); err != nil {
zap.S().Errorw("failed to extract archive", zap.String("server", serverID), zap.Error(err))
return
}
// We mark the process as being successful here as if we fail to send a transfer success,
// then a transfer failure won't probably be successful either.
//
// It may be useful to retry sending the transfer success every so often just in case of a small
// hiccup or the fix of whatever error causing the success request to fail.
hasError = false
// Notify the panel that the transfer succeeded.
rerr, err := api.NewRequester().SendTransferSuccess(serverID) rerr, err := api.NewRequester().SendTransferSuccess(serverID)
if rerr != nil || err != nil { if rerr != nil || err != nil {
if err != nil { if err != nil {
@ -301,7 +307,6 @@ func postTransfer(c *gin.Context) {
} }
zap.S().Debugw("successfully notified panel about transfer success", zap.String("server", serverID)) zap.S().Debugw("successfully notified panel about transfer success", zap.String("server", serverID))
hasError = false
}(buf.Bytes()) }(buf.Bytes())
c.Status(http.StatusAccepted) c.Status(http.StatusAccepted)