Compare commits

...

4 Commits

9 changed files with 137 additions and 21 deletions

View File

@ -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"

View 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
},
}
}

View File

@ -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(),
}, },
} }
} }

View File

@ -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
} }

View File

@ -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"

View File

@ -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

View File

@ -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()

View File

@ -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)
} }

View File

@ -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
}