Just accept a public key to authenticate tokens signed by the token signing service

This commit is contained in:
Melon 2023-07-03 18:47:05 +01:00
parent ab36a39917
commit eb8954f794
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
5 changed files with 16 additions and 103 deletions

View File

@ -6,7 +6,6 @@ type startUpConfig struct {
Listen listenConfig `json:"listen"`
InkscapeCmd string `json:"inkscape"`
RateLimit uint64 `json:"rate_limit"`
SignerIssuer string `json:"signer_issuer"`
}
type listenConfig struct {

View File

@ -15,7 +15,6 @@ func main() {
subcommands.Register(subcommands.CommandsCommand(), "")
subcommands.Register(&serveCmd{}, "")
subcommands.Register(&setupCmd{}, "")
subcommands.Register(&tokenCmd{}, "")
flag.Parse()
ctx := context.Background()

View File

@ -18,7 +18,6 @@ import (
"github.com/google/subcommands"
"io/fs"
"log"
"math/rand"
"net/http"
"os"
"os/signal"
@ -96,14 +95,14 @@ func normalLoad(conf startUpConfig, wd string) {
}
}
// load the MJWT RSA private key from a pem encoded file
mjwtSigner, err := mjwt.NewMJwtSignerFromFileOrCreate(conf.SignerIssuer, filepath.Join(wd, "violet.private.pem"), rand.New(rand.NewSource(time.Now().UnixNano())), 4096)
// load the MJWT RSA public key from a pem encoded file
mJwtVerify, err := mjwt.NewMJwtVerifierFromFile(filepath.Join(wd, "signer.public.pem"))
if err != nil {
log.Fatal("[Violet] Failed to load MJWT verifier public key from file: ", err)
log.Fatalf("[Violet] Failed to load MJWT verifier public key from file '%s': %s", filepath.Join(wd, "signer.public.pem"), err)
}
// open sqlite database
db, err := sql.Open("sqlite3", "violet.db.sqlite")
db, err := sql.Open("sqlite3", filepath.Join(wd, "violet.db.sqlite"))
if err != nil {
log.Fatal("[Violet] Failed to open database")
}
@ -130,7 +129,7 @@ func normalLoad(conf startUpConfig, wd string) {
Acme: acmeChallenges,
Certs: allowedCerts,
Favicons: dynamicFavicons,
Signer: mjwtSigner,
Signer: mJwtVerify,
ErrorPages: dynamicErrorPages,
Router: dynamicRouter,
}

View File

@ -59,15 +59,14 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
// store answers from questions
var answers struct {
SelfSigned bool
ErrorPages bool
ApiListen string
HttpListen string
HttpsListen string
RateLimit uint64
FirstDomain string
ApiUrl string
SignerIssuer string
SelfSigned bool
ErrorPages bool
ApiListen string
HttpListen string
HttpsListen string
RateLimit uint64
FirstDomain string
ApiUrl string
}
// ask main questions
@ -104,10 +103,6 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
return nil
},
},
{
Name: "SignerIssuer",
Prompt: &survey.Input{Message: "Issuer name to sign API tokens with", Default: "Violet"},
},
{
Name: "FirstDomain",
Prompt: &survey.Input{Message: "First domain", Default: "example.com", Help: "Setup the first domain or it will be more difficult to setup later"},
@ -120,7 +115,7 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
}
// generate database path
databaseFile := filepath.Join(wdAbs, "violet.sqlite")
databaseFile := filepath.Join(wdAbs, "violet.db.sqlite")
errorPagePath := ""
if answers.ErrorPages {
errorPagePath = filepath.Join(wdAbs, "error-pages")
@ -142,9 +137,8 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
Http: answers.HttpListen,
Https: answers.HttpsListen,
},
InkscapeCmd: "inkscape",
RateLimit: answers.RateLimit,
SignerIssuer: answers.SignerIssuer,
InkscapeCmd: "inkscape",
RateLimit: answers.RateLimit,
})
if err != nil {
fmt.Println("[Violet] Failed to write config file: ", err)

View File

@ -1,78 +0,0 @@
package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"github.com/MrMelon54/mjwt"
"github.com/google/subcommands"
"github.com/google/uuid"
"os"
"path/filepath"
)
type tokenCmd struct {
configPath string
audience stringSliceFlag
duration string
permission stringSliceFlag
}
func (t *tokenCmd) Name() string { return "auth" }
func (t *tokenCmd) Synopsis() string {
return "Generate an auth token for using the API"
}
func (t *tokenCmd) SetFlags(f *flag.FlagSet) {
f.StringVar(&t.configPath, "conf", "", "/path/to/config.json : path to the config file")
f.Var(&t.audience, "a", "specify the audience attribute, this flag can be used multiple times")
f.StringVar(&t.duration, "d", "15m", "specify the duration attribute (default: 15m)")
f.Var(&t.permission, "p", "specify the permissions granted by this token, this flag can be used multiple times")
}
func (t *tokenCmd) Usage() string {
return `token [-conf <config file>] [-a <audience>] [-d <duration>] [-p <permission>]
Generate an access/refresh token pair for using the API.
`
}
func (t *tokenCmd) Execute(ctx context.Context, f *flag.FlagSet, args ...interface{}) subcommands.ExitStatus {
err := t.normal()
if err != nil {
fmt.Println("[Violet] Error: ", err)
return subcommands.ExitFailure
}
return subcommands.ExitSuccess
}
func (t *tokenCmd) normal() error {
wd := filepath.Dir(t.configPath)
openConfig, err := os.Open(t.configPath)
if err != nil {
return err
}
var a struct {
SignerIssuer string `json:"signer_issuer"`
}
err = json.NewDecoder(openConfig).Decode(&a)
if err != nil {
return err
}
signer, err := mjwt.NewMJwtSignerFromFile(a.SignerIssuer, filepath.Join(wd, "violet.private.pem"))
if err != nil {
return err
}
signer.GenerateJwt(uuid.NewString())
}
type stringSliceFlag []string
func (a *stringSliceFlag) String() string {
return fmt.Sprintf("%v", *a)
}
func (a *stringSliceFlag) Set(s string) error {
*a = append(*a, s)
return nil
}