Skip to content

Commit

Permalink
Fix token loading for remote nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
LordRalex committed Apr 11, 2020
1 parent 4426c12 commit ab8339a
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 80 deletions.
55 changes: 0 additions & 55 deletions authorization.go
Expand Up @@ -14,64 +14,9 @@
package pufferpanel

import (
"bytes"
"crypto/ecdsa"
"crypto/x509"
"encoding/pem"
"github.com/spf13/viper"
"golang.org/x/crypto/ssh"
"io"
"os"
"sync"
)

type SFTPAuthorization interface {
Validate(username, password string) (perms *ssh.Permissions, err error)
}

var publicKey *ecdsa.PublicKey

var atLocker = &sync.RWMutex{}

func SetPublicKey(key *ecdsa.PublicKey) {
atLocker.Lock()
defer atLocker.Unlock()
publicKey = key
}

func GetPublicKey() *ecdsa.PublicKey {
atLocker.RLock()
defer atLocker.RUnlock()
return publicKey
}

func LoadPublicKey() (*ecdsa.PublicKey, error) {
publicKey := GetPublicKey()
if publicKey != nil {
return publicKey, nil
}

f, err := os.OpenFile(viper.GetString("daemon.auth.publicKey"), os.O_RDONLY, 660)
defer Close(f)

var buf bytes.Buffer

_, _ = io.Copy(&buf, f)

block, _ := pem.Decode(buf.Bytes())
if block == nil {
return nil, ErrKeyNotPEM
}
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
return nil, err
}

publicKey, ok := pub.(*ecdsa.PublicKey)
if !ok {
return nil, ErrKeyNotECDSA
}

SetPublicKey(publicKey)
return publicKey, nil
}
2 changes: 0 additions & 2 deletions cmd/run.go
Expand Up @@ -109,8 +109,6 @@ func internalRun(cmd *cobra.Command, args []string) error {

func panel(ch chan error) {
services.ValidateTokenLoaded()
pufferpanel.SetPublicKey(services.GetPublicKey())

services.LoadEmailService()

go func() {
Expand Down
5 changes: 2 additions & 3 deletions config.go
Expand Up @@ -37,8 +37,8 @@ func init() {
viper.SetDefault("panel.database.dialect", "sqlite3")
//viper.SetDefault("panel.database.url", "file:pufferpanel.db?cache=shared")
viper.SetDefault("panel.database.log", false)
viper.SetDefault("panel.token.private", "private.pem")
viper.SetDefault("panel.token.public", "public.pem")
viper.SetDefault("token.private", "private.pem")
viper.SetDefault("token.public", "public.pem")

viper.SetDefault("panel.web.files", "www")
viper.SetDefault("panel.email.templates", "email/emails.json")
Expand All @@ -55,7 +55,6 @@ func init() {
viper.SetDefault("daemon.console.forward", false)
viper.SetDefault("daemon.sftp.host", "0.0.0.0:5657")
viper.SetDefault("daemon.sftp.key", "sftp.key")
viper.SetDefault("daemon.auth.publicKey", "panel.pem")
viper.SetDefault("daemon.auth.url", "http://localhost:8080")
viper.SetDefault("daemon.auth.clientId", "")
viper.SetDefault("daemon.auth.clientSecret", "")
Expand Down
12 changes: 2 additions & 10 deletions middleware/oauth2.go
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/pufferpanel/pufferpanel/v2"
"github.com/pufferpanel/pufferpanel/v2/programs"
"github.com/pufferpanel/pufferpanel/v2/response"
"github.com/pufferpanel/pufferpanel/v2/services"
"net/http"
"strings"
)
Expand Down Expand Up @@ -51,16 +52,7 @@ func OAuth2Handler(requiredScope pufferpanel.Scope, requireServer bool) gin.Hand
authToken = authArr[1]
}

var err error
key := pufferpanel.GetPublicKey()
if key == nil {
key, err = pufferpanel.LoadPublicKey()
if response.HandleError(c, err, http.StatusInternalServerError) {
return
}
}

token, err := pufferpanel.ParseToken(key, authToken)
token, err := services.ParseToken(authToken)
if response.HandleError(c, err, http.StatusForbidden) {
return
}
Expand Down
2 changes: 1 addition & 1 deletion services/node.go
Expand Up @@ -167,7 +167,7 @@ func doesDaemonUseSSL(node *models.Node) (bool, error) {
return false, nil
}

path := fmt.Sprintf("://%s:%d", node.PrivateHost, node.PrivatePort)
path := fmt.Sprintf("://%s:%d/daemon", node.PrivateHost, node.PrivatePort)

_, err := http.Get("https" + path)

Expand Down
58 changes: 49 additions & 9 deletions services/token.go
Expand Up @@ -20,13 +20,15 @@ import (
"crypto/rand"
"crypto/x509"
"encoding/pem"
"errors"
"github.com/dgrijalva/jwt-go"
"github.com/jinzhu/gorm"
"github.com/pufferpanel/pufferpanel/v2"
"github.com/pufferpanel/pufferpanel/v2/logging"
"github.com/pufferpanel/pufferpanel/v2/models"
"github.com/spf13/viper"
"io"
"io/ioutil"
"os"
"strconv"
"sync"
Expand All @@ -35,13 +37,16 @@ import (

var signingMethod = jwt.SigningMethodES256
var privateKey *ecdsa.PrivateKey
var publicKey *ecdsa.PublicKey
var locker sync.Mutex

func GetPublicKey() *ecdsa.PublicKey {
ValidateTokenLoaded()
if privateKey != nil {
return &privateKey.PublicKey
} else {
return publicKey
}
return nil
}

func Generate(claims jwt.Claims) (string, error) {
Expand Down Expand Up @@ -160,20 +165,25 @@ func (ps *Permission) GenerateOAuthForUser(userId uint, serverId *string) (strin

func ParseToken(token string) (*pufferpanel.Token, error) {
ValidateTokenLoaded()
return pufferpanel.ParseToken(&privateKey.PublicKey, token)
return pufferpanel.ParseToken(publicKey, token)
}

func ValidateTokenLoaded() {
locker.Lock()
defer locker.Unlock()
if privateKey == nil {
load()
//only load public if panel is disabled
if !viper.GetBool("panel.enable") {
if publicKey == nil {
loadPublic()
}
} else if privateKey == nil {
loadPrivate()
}
}

func load() {
func loadPrivate() {
var privKey *ecdsa.PrivateKey
privKeyFile, err := os.OpenFile(viper.GetString("panel.token.private"), os.O_RDONLY, 0600)
privKeyFile, err := os.OpenFile(viper.GetString("token.private"), os.O_RDONLY, 0600)
defer pufferpanel.Close(privKeyFile)
if os.IsNotExist(err) {
privKey, err = generatePrivateKey()
Expand All @@ -192,19 +202,20 @@ func load() {

privateKey = privKey

pubKey := &privateKey.PublicKey
pubKeyEncoded, err := x509.MarshalPKIXPublicKey(pubKey)
publicKey = &privateKey.PublicKey
pubKeyEncoded, err := x509.MarshalPKIXPublicKey(publicKey)
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
return
}

pubKeyFile, err := os.OpenFile(viper.GetString("panel.token.public"), os.O_CREATE|os.O_RDWR, 0644)
pubKeyFile, err := os.OpenFile(viper.GetString("token.public"), os.O_CREATE|os.O_RDWR, 0644)
defer pufferpanel.Close(pubKeyFile)
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
return
}

err = pem.Encode(pubKeyFile, &pem.Block{Type: "PUBLIC KEY", Bytes: pubKeyEncoded})
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
Expand Down Expand Up @@ -238,3 +249,32 @@ func generatePrivateKey() (privKey *ecdsa.PrivateKey, err error) {

return
}

func loadPublic() {
pubKeyFile, err := os.OpenFile(viper.GetString("token.public"), os.O_RDONLY, 0644)
defer pufferpanel.Close(pubKeyFile)
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
return
}

data, err := ioutil.ReadAll(pubKeyFile)
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
return
}

block, _ := pem.Decode(data)
key, err := x509.ParsePKIXPublicKey(block.Bytes)
if err != nil {
logging.Error().Printf("Internal error on token service: %s", err)
return
}

var ok bool
publicKey, ok = key.(*ecdsa.PublicKey)
if !ok {
logging.Error().Printf("Internal error on token service: %s", errors.New("public key is not ECDSA"))
return
}
}

0 comments on commit ab8339a

Please sign in to comment.