Compare commits
4 Commits
4c6e979bb6
...
8a5a1cd482
Author | SHA1 | Date | |
---|---|---|---|
8a5a1cd482 | |||
3fd25988cf | |||
ebe3e77879 | |||
3078ea7d21 |
@ -113,10 +113,5 @@ nfpms:
|
|||||||
file_info:
|
file_info:
|
||||||
mode: 0700
|
mode: 0700
|
||||||
packager: apk
|
packager: apk
|
||||||
- dst: /var/log/storage-server
|
|
||||||
type: dir
|
|
||||||
file_info:
|
|
||||||
mode: 0750
|
|
||||||
packager: apk
|
|
||||||
scripts:
|
scripts:
|
||||||
postinstall: "misc/packaging/common/postinstall-storage-server.sh"
|
postinstall: "misc/packaging/common/postinstall-storage-server.sh"
|
75
cmd/storage-server/command/auth/check_token.go
Normal file
75
cmd/storage-server/command/auth/check_token.go
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
package auth
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"forge.cadoles.com/arcad/edge/cmd/storage-server/command/flag"
|
||||||
|
"forge.cadoles.com/arcad/edge/pkg/jwtutil"
|
||||||
|
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func CheckToken() *cli.Command {
|
||||||
|
return &cli.Command{
|
||||||
|
Name: "check-token",
|
||||||
|
Usage: "Validate and print the given token with the private key",
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "token",
|
||||||
|
Required: true,
|
||||||
|
},
|
||||||
|
flag.PrivateKey,
|
||||||
|
flag.PrivateKeySigningAlgorithm,
|
||||||
|
flag.PrivateKeyDefaultSize,
|
||||||
|
},
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
privateKeyFile := flag.GetPrivateKey(ctx)
|
||||||
|
signingAlgorithm := flag.GetSigningAlgorithm(ctx)
|
||||||
|
privateKeyDefaultSize := flag.GetPrivateKeyDefaultSize(ctx)
|
||||||
|
rawToken := ctx.String("token")
|
||||||
|
|
||||||
|
if rawToken == "" {
|
||||||
|
return errors.New("you must provide a value for --token flag")
|
||||||
|
}
|
||||||
|
|
||||||
|
privateKey, err := jwtutil.LoadOrGenerateKey(
|
||||||
|
privateKeyFile,
|
||||||
|
privateKeyDefaultSize,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
keySet, err := jwtutil.NewKeySet()
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = jwtutil.AddKeyWithSigningAlgo(keySet, privateKey, jwa.SignatureAlgorithm(signingAlgorithm))
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
token, err := jwtutil.Parse([]byte(rawToken), keySet)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
claims, err := token.AsMap(ctx.Context)
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
json, err := json.MarshalIndent(claims, "", " ")
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Println(string(json))
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ func Root() *cli.Command {
|
|||||||
Usage: "Auth related command",
|
Usage: "Auth related command",
|
||||||
Subcommands: []*cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
NewToken(),
|
NewToken(),
|
||||||
|
CheckToken(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,11 @@ func Run() *cli.Command {
|
|||||||
Aliases: []string{"addr"},
|
Aliases: []string{"addr"},
|
||||||
Value: ":3001",
|
Value: ":3001",
|
||||||
},
|
},
|
||||||
|
&cli.IntFlag{
|
||||||
|
Name: "log-level",
|
||||||
|
EnvVars: []string{"STORAGE_SERVER_LOG_LEVEL"},
|
||||||
|
Value: int(logger.LevelError),
|
||||||
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "blobstore-dsn-pattern",
|
Name: "blobstore-dsn-pattern",
|
||||||
EnvVars: []string{"STORAGE_SERVER_BLOBSTORE_DSN_PATTERN"},
|
EnvVars: []string{"STORAGE_SERVER_BLOBSTORE_DSN_PATTERN"},
|
||||||
@ -80,6 +85,9 @@ func Run() *cli.Command {
|
|||||||
privateKeyFile := flag.GetPrivateKey(ctx)
|
privateKeyFile := flag.GetPrivateKey(ctx)
|
||||||
signingAlgorithm := flag.GetSigningAlgorithm(ctx)
|
signingAlgorithm := flag.GetSigningAlgorithm(ctx)
|
||||||
privateKeyDefaultSize := flag.GetPrivateKeyDefaultSize(ctx)
|
privateKeyDefaultSize := flag.GetPrivateKeyDefaultSize(ctx)
|
||||||
|
logLevel := ctx.Int("log-level")
|
||||||
|
|
||||||
|
logger.SetLevel(logger.Level(logLevel))
|
||||||
|
|
||||||
router := chi.NewRouter()
|
router := chi.NewRouter()
|
||||||
|
|
||||||
@ -91,11 +99,6 @@ func Run() *cli.Command {
|
|||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
publicKey, err := privateKey.PublicKey()
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
getBlobStoreServer := createGetCachedStoreServer(
|
getBlobStoreServer := createGetCachedStoreServer(
|
||||||
func(dsn string) (storage.BlobStore, error) {
|
func(dsn string) (storage.BlobStore, error) {
|
||||||
return driver.NewBlobStore(dsn)
|
return driver.NewBlobStore(dsn)
|
||||||
@ -125,12 +128,17 @@ func Run() *cli.Command {
|
|||||||
|
|
||||||
router.Use(middleware.RealIP)
|
router.Use(middleware.RealIP)
|
||||||
router.Use(middleware.Logger)
|
router.Use(middleware.Logger)
|
||||||
router.Use(authenticate(publicKey, jwa.SignatureAlgorithm(signingAlgorithm)))
|
|
||||||
|
logger.Debug(ctx.Context, "using authentication", logger.F("privateKey", privateKeyFile), logger.F("signingAlgorithm", signingAlgorithm))
|
||||||
|
|
||||||
|
router.Use(authenticate(privateKey, jwa.SignatureAlgorithm(signingAlgorithm)))
|
||||||
|
|
||||||
router.Handle("/blobstore", createStoreHandler(getBlobStoreServer, blobStoreDSNPattern, true, cacheSize, cacheTTL))
|
router.Handle("/blobstore", createStoreHandler(getBlobStoreServer, blobStoreDSNPattern, true, cacheSize, cacheTTL))
|
||||||
router.Handle("/documentstore", createStoreHandler(getDocumentStoreServer, documentStoreDSNPattern, true, cacheSize, cacheTTL))
|
router.Handle("/documentstore", createStoreHandler(getDocumentStoreServer, documentStoreDSNPattern, true, cacheSize, cacheTTL))
|
||||||
router.Handle("/sharestore", createStoreHandler(getShareStoreServer, shareStoreDSNPattern, false, cacheSize, cacheTTL))
|
router.Handle("/sharestore", createStoreHandler(getShareStoreServer, shareStoreDSNPattern, false, cacheSize, cacheTTL))
|
||||||
|
|
||||||
|
logger.Info(ctx.Context, "listening", logger.F("addr", addr))
|
||||||
|
|
||||||
if err := http.ListenAndServe(addr, router); err != nil {
|
if err := http.ListenAndServe(addr, router); err != nil {
|
||||||
return errors.WithStack(err)
|
return errors.WithStack(err)
|
||||||
}
|
}
|
||||||
@ -218,15 +226,17 @@ func authenticate(privateKey jwk.Key, signingAlgorithm jwa.SignatureAlgorithm) f
|
|||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
|
|
||||||
createKeySet.Do(func() {
|
createKeySet.Do(func() {
|
||||||
err = privateKey.Set(jwk.AlgorithmKey, signingAlgorithm)
|
var keySet jwk.Set
|
||||||
|
|
||||||
|
keySet, err = jwtutil.NewKeySet()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err = errors.WithStack(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var keySet jwk.Set
|
err = jwtutil.AddKeyWithSigningAlgo(keySet, privateKey, signingAlgorithm)
|
||||||
|
|
||||||
keySet, err = jwtutil.NewKeySet(privateKey)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
err = errors.WithStack(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#!/sbin/openrc-run
|
#!/sbin/openrc-run
|
||||||
|
|
||||||
command="/usr/bin/storage-server"
|
command="/usr/bin/storage-server"
|
||||||
command_args=run""
|
command_args="run"
|
||||||
supervisor=supervise-daemon
|
supervisor=supervise-daemon
|
||||||
output_log="/var/log/storage-server.log"
|
output_log="/var/log/storage-server.log"
|
||||||
error_log="$output_log"
|
error_log="$output_log"
|
||||||
|
@ -4,6 +4,7 @@ pkg/sdk/client/src/**/*.js
|
|||||||
pkg/sdk/client/src/**/*.ts
|
pkg/sdk/client/src/**/*.ts
|
||||||
misc/client-sdk-testsuite/dist/server/*.js
|
misc/client-sdk-testsuite/dist/server/*.js
|
||||||
modd.conf
|
modd.conf
|
||||||
|
.env
|
||||||
{
|
{
|
||||||
prep: make build-sdk build-cli build-storage-server
|
prep: make build-sdk build-cli build-storage-server
|
||||||
daemon: make run-app
|
daemon: make run-app
|
||||||
|
@ -1,11 +1,36 @@
|
|||||||
package jwtutil
|
package jwtutil
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func AddKeyWithSigningAlgo(keySet jwk.Set, key jwk.Key, signingAlgorithm jwa.SignatureAlgorithm) error {
|
||||||
|
addedKey := key
|
||||||
|
|
||||||
|
if !strings.HasPrefix(string(signingAlgorithm), "HS") {
|
||||||
|
publicKey, err := key.PublicKey()
|
||||||
|
if err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
addedKey = publicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := addedKey.Set(jwk.AlgorithmKey, signingAlgorithm); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := keySet.AddKey(addedKey); err != nil {
|
||||||
|
return errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewKeySet(keys ...jwk.Key) (jwk.Set, error) {
|
func NewKeySet(keys ...jwk.Key) (jwk.Set, error) {
|
||||||
set := jwk.NewSet()
|
set := jwk.NewSet()
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||||
"github.com/lestrrat-go/jwx/v2/jws"
|
|
||||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
@ -111,10 +110,7 @@ func FindToken(r *http.Request, getKeySet GetKeySetFunc, funcs ...FindTokenOptio
|
|||||||
return nil, errors.WithStack(ErrNoKeySet)
|
return nil, errors.WithStack(ErrNoKeySet)
|
||||||
}
|
}
|
||||||
|
|
||||||
token, err := jwt.Parse([]byte(rawToken),
|
token, err := Parse([]byte(rawToken), keySet)
|
||||||
jwt.WithKeySet(keySet, jws.WithRequireKid(false)),
|
|
||||||
jwt.WithValidate(true),
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.WithStack(err)
|
return nil, errors.WithStack(err)
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import (
|
|||||||
|
|
||||||
"github.com/lestrrat-go/jwx/v2/jwa"
|
"github.com/lestrrat-go/jwx/v2/jwa"
|
||||||
"github.com/lestrrat-go/jwx/v2/jwk"
|
"github.com/lestrrat-go/jwx/v2/jwk"
|
||||||
|
"github.com/lestrrat-go/jwx/v2/jws"
|
||||||
"github.com/lestrrat-go/jwx/v2/jwt"
|
"github.com/lestrrat-go/jwx/v2/jwt"
|
||||||
"github.com/oklog/ulid/v2"
|
"github.com/oklog/ulid/v2"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
@ -38,3 +39,15 @@ func SignedToken(key jwk.Key, signingAlgorithm jwa.SignatureAlgorithm, claims ma
|
|||||||
|
|
||||||
return rawToken, nil
|
return rawToken, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Parse(rawToken []byte, keySet jwk.Set) (jwt.Token, error) {
|
||||||
|
token, err := jwt.Parse(rawToken,
|
||||||
|
jwt.WithKeySet(keySet, jws.WithRequireKid(false)),
|
||||||
|
jwt.WithValidate(true),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.WithStack(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return token, nil
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user