Hardcode some file names

This commit is contained in:
Melon 2023-07-01 12:14:44 +01:00
parent 7e05271a79
commit 76e37f7af9
Signed by: melon
GPG Key ID: 6C9D970C50D26A25
10 changed files with 62 additions and 61 deletions

View File

@ -1,15 +1,12 @@
package main package main
type startUpConfig struct { type startUpConfig struct {
Database string `json:"db"`
MjwtPubKey string `json:"mjwt_pub_key"`
CertPath string `json:"cert_path"`
KeyPath string `json:"key_path"`
SelfSigned bool `json:"self_signed"` SelfSigned bool `json:"self_signed"`
ErrorPagePath string `json:"error_page_path"` ErrorPagePath string `json:"error_page_path"`
Listen listenConfig `json:"listen"` Listen listenConfig `json:"listen"`
InkscapeCmd string `json:"inkscape"` InkscapeCmd string `json:"inkscape"`
RateLimit uint64 `json:"rate_limit"` RateLimit uint64 `json:"rate_limit"`
SignerIssuer string `json:"signer_issuer"`
} }
type listenConfig struct { type listenConfig struct {

View File

@ -18,9 +18,11 @@ import (
"github.com/google/subcommands" "github.com/google/subcommands"
"io/fs" "io/fs"
"log" "log"
"math/rand"
"net/http" "net/http"
"os" "os"
"os/signal" "os/signal"
"path/filepath"
"syscall" "syscall"
"time" "time"
) )
@ -63,26 +65,24 @@ func (s *serveCmd) Execute(ctx context.Context, f *flag.FlagSet, _ ...interface{
return subcommands.ExitFailure return subcommands.ExitFailure
} }
normalLoad(conf) // working directory is the parent of the config file
wd := filepath.Dir(s.configPath)
normalLoad(conf, wd)
return subcommands.ExitSuccess return subcommands.ExitSuccess
} }
func normalLoad(conf startUpConfig) { func normalLoad(conf startUpConfig, wd string) {
// the cert and key paths are useless in self-signed mode // the cert and key paths are useless in self-signed mode
if !conf.SelfSigned { if !conf.SelfSigned {
if conf.CertPath != "" {
// create path to cert dir // create path to cert dir
err := os.MkdirAll(conf.CertPath, os.ModePerm) err := os.MkdirAll(filepath.Join(wd, "certs"), os.ModePerm)
if err != nil { if err != nil {
log.Fatalf("[Violet] Failed to create certificate path '%s'", conf.CertPath) log.Fatal("[Violet] Failed to create certificate path")
} }
}
if conf.KeyPath != "" {
// create path to key dir // create path to key dir
err := os.MkdirAll(conf.KeyPath, os.ModePerm) err = os.MkdirAll(filepath.Join(wd, "keys"), os.ModePerm)
if err != nil { if err != nil {
log.Fatalf("[Violet] Failed to create certificate key path '%s'", conf.KeyPath) log.Fatal("[Violet] Failed to create certificate key path")
}
} }
} }
@ -96,21 +96,24 @@ func normalLoad(conf startUpConfig) {
} }
} }
// load the MJWT RSA public key from a pem encoded file // load the MJWT RSA private key from a pem encoded file
mjwtVerify, err := mjwt.NewMJwtVerifierFromFile(conf.MjwtPubKey) mjwtSigner, err := mjwt.NewMJwtSignerFromFileOrCreate(conf.SignerIssuer, filepath.Join(wd, "violet.private.pem"), rand.New(rand.NewSource(time.Now().UnixNano())), 4096)
if err != nil { if err != nil {
log.Fatalf("[Violet] Failed to load MJWT verifier public key from file: '%s'", conf.MjwtPubKey) log.Fatal("[Violet] Failed to load MJWT verifier public key from file: ", err)
} }
// open sqlite database // open sqlite database
db, err := sql.Open("sqlite3", conf.Database) db, err := sql.Open("sqlite3", "violet.db.sqlite")
if err != nil { if err != nil {
log.Fatalf("[Violet] Failed to open database '%s'...", conf.Database) log.Fatal("[Violet] Failed to open database")
} }
certDir := os.DirFS(filepath.Join(wd, "certs"))
keyDir := os.DirFS(filepath.Join(wd, "keys"))
allowedDomains := domains.New(db) // load allowed domains allowedDomains := domains.New(db) // load allowed domains
acmeChallenges := utils.NewAcmeChallenge() // load acme challenge store acmeChallenges := utils.NewAcmeChallenge() // load acme challenge store
allowedCerts := certs.New(os.DirFS(conf.CertPath), os.DirFS(conf.KeyPath), conf.SelfSigned) // load certificate manager allowedCerts := certs.New(certDir, keyDir, conf.SelfSigned) // load certificate manager
hybridTransport := proxy.NewHybridTransport() // load reverse proxy hybridTransport := proxy.NewHybridTransport() // load reverse proxy
dynamicFavicons := favicons.New(db, conf.InkscapeCmd) // load dynamic favicon provider dynamicFavicons := favicons.New(db, conf.InkscapeCmd) // load dynamic favicon provider
dynamicErrorPages := errorPages.New(errorPageDir) // load dynamic error page provider dynamicErrorPages := errorPages.New(errorPageDir) // load dynamic error page provider
@ -127,7 +130,7 @@ func normalLoad(conf startUpConfig) {
Acme: acmeChallenges, Acme: acmeChallenges,
Certs: allowedCerts, Certs: allowedCerts,
Favicons: dynamicFavicons, Favicons: dynamicFavicons,
Verify: mjwtVerify, Signer: mjwtSigner,
ErrorPages: dynamicErrorPages, ErrorPages: dynamicErrorPages,
Router: dynamicRouter, Router: dynamicRouter,
} }

View File

@ -67,6 +67,7 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
RateLimit uint64 RateLimit uint64
FirstDomain string FirstDomain string
ApiUrl string ApiUrl string
SignerIssuer string
} }
// ask main questions // ask main questions
@ -103,6 +104,10 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
return nil return nil
}, },
}, },
{
Name: "SignerIssuer",
Prompt: &survey.Input{Message: "Issuer name to sign API tokens with", Default: "Violet"},
},
{ {
Name: "FirstDomain", 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"}, Prompt: &survey.Input{Message: "First domain", Default: "example.com", Help: "Setup the first domain or it will be more difficult to setup later"},
@ -130,10 +135,6 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
confEncode := json.NewEncoder(createConf) confEncode := json.NewEncoder(createConf)
confEncode.SetIndent("", " ") confEncode.SetIndent("", " ")
err = confEncode.Encode(startUpConfig{ err = confEncode.Encode(startUpConfig{
Database: filepath.Join(wdAbs, "violet.sqlite"),
MjwtPubKey: filepath.Join(wdAbs, "mjwt.public.key"),
CertPath: filepath.Join(wdAbs, "certs"),
KeyPath: filepath.Join(wdAbs, "keys"),
SelfSigned: answers.SelfSigned, SelfSigned: answers.SelfSigned,
ErrorPagePath: errorPagePath, ErrorPagePath: errorPagePath,
Listen: listenConfig{ Listen: listenConfig{
@ -143,6 +144,7 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
}, },
InkscapeCmd: "inkscape", InkscapeCmd: "inkscape",
RateLimit: answers.RateLimit, RateLimit: answers.RateLimit,
SignerIssuer: answers.SignerIssuer,
}) })
if err != nil { if err != nil {
fmt.Println("[Violet] Failed to write config file: ", err) fmt.Println("[Violet] Failed to write config file: ", err)

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.20
require ( require (
github.com/AlecAivazis/survey/v2 v2.3.7 github.com/AlecAivazis/survey/v2 v2.3.7
github.com/MrMelon54/certgen v0.0.1 github.com/MrMelon54/certgen v0.0.1
github.com/MrMelon54/mjwt v0.0.2 github.com/MrMelon54/mjwt v0.1.1
github.com/MrMelon54/png2ico v1.0.1 github.com/MrMelon54/png2ico v1.0.1
github.com/MrMelon54/rescheduler v0.0.1 github.com/MrMelon54/rescheduler v0.0.1
github.com/MrMelon54/trie v0.0.2 github.com/MrMelon54/trie v0.0.2

2
go.sum
View File

@ -4,6 +4,8 @@ github.com/MrMelon54/certgen v0.0.1 h1:ycWdZ2RlxQ5qSuejeBVv4aXjGo5hdqqL4j4EjrXnF
github.com/MrMelon54/certgen v0.0.1/go.mod h1:GHflVlSbtFLJZLpN1oWyUvDBRrR8qCWiwZLXCCnS2Gc= github.com/MrMelon54/certgen v0.0.1/go.mod h1:GHflVlSbtFLJZLpN1oWyUvDBRrR8qCWiwZLXCCnS2Gc=
github.com/MrMelon54/mjwt v0.0.2 h1:jDqyPnFloh80XdSmZ6jt9qhUj/ULcoQ4QSHXPdkAIE4= github.com/MrMelon54/mjwt v0.0.2 h1:jDqyPnFloh80XdSmZ6jt9qhUj/ULcoQ4QSHXPdkAIE4=
github.com/MrMelon54/mjwt v0.0.2/go.mod h1:HzY8P6Je+ovS/fwK5sILRMq5mnZT4+WuFRc98LBy7z4= github.com/MrMelon54/mjwt v0.0.2/go.mod h1:HzY8P6Je+ovS/fwK5sILRMq5mnZT4+WuFRc98LBy7z4=
github.com/MrMelon54/mjwt v0.1.1 h1:m+aTpxbhQCrOPKHN170DQMFR5r938LkviU38unob5Jw=
github.com/MrMelon54/mjwt v0.1.1/go.mod h1:oYrDBWK09Hju98xb+bRQ0wy+RuAzacxYvKYOZchR2Tk=
github.com/MrMelon54/png2ico v1.0.1 h1:zJoSSl4OkvSIMWGyGPvb8fWNa0KrUvMIjgNGLNLJhVQ= github.com/MrMelon54/png2ico v1.0.1 h1:zJoSSl4OkvSIMWGyGPvb8fWNa0KrUvMIjgNGLNLJhVQ=
github.com/MrMelon54/png2ico v1.0.1/go.mod h1:NOv3tO4497mInG+3tcFkIohmxCywUwMLU8WNxJZLVmU= github.com/MrMelon54/png2ico v1.0.1/go.mod h1:NOv3tO4497mInG+3tcFkIohmxCywUwMLU8WNxJZLVmU=
github.com/MrMelon54/rescheduler v0.0.1 h1:gzNvL8X81M00uYN0i9clFVrXCkG1UuLNYxDcvjKyBqo= github.com/MrMelon54/rescheduler v0.0.1 h1:gzNvL8X81M00uYN0i9clFVrXCkG1UuLNYxDcvjKyBqo=

View File

@ -18,7 +18,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
// Endpoint for compile action // Endpoint for compile action
r.POST("/compile", func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) { r.POST("/compile", func(rw http.ResponseWriter, req *http.Request, _ httprouter.Params) {
if !hasPerms(conf.Verify, req, "violet:compile") { if !hasPerms(conf.Signer, req, "violet:compile") {
utils.RespondHttpStatus(rw, http.StatusForbidden) utils.RespondHttpStatus(rw, http.StatusForbidden)
return return
} }
@ -30,7 +30,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
// Endpoint for domains // Endpoint for domains
r.PUT("/domain/:domain", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) { r.PUT("/domain/:domain", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
if !hasPerms(conf.Verify, req, "violet:domains") { if !hasPerms(conf.Signer, req, "violet:domains") {
utils.RespondHttpStatus(rw, http.StatusForbidden) utils.RespondHttpStatus(rw, http.StatusForbidden)
return return
} }
@ -41,7 +41,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
conf.Domains.Compile() conf.Domains.Compile()
}) })
r.DELETE("/domain/:domain", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) { r.DELETE("/domain/:domain", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
if !hasPerms(conf.Verify, req, "violet:domains") { if !hasPerms(conf.Signer, req, "violet:domains") {
utils.RespondHttpStatus(rw, http.StatusForbidden) utils.RespondHttpStatus(rw, http.StatusForbidden)
return return
} }
@ -59,7 +59,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
// Endpoint for acme-challenge // Endpoint for acme-challenge
r.PUT("/acme-challenge/:domain/:key/:value", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) { r.PUT("/acme-challenge/:domain/:key/:value", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
if !hasPerms(conf.Verify, req, "violet:acme-challenge") { if !hasPerms(conf.Signer, req, "violet:acme-challenge") {
utils.RespondHttpStatus(rw, http.StatusForbidden) utils.RespondHttpStatus(rw, http.StatusForbidden)
return return
} }
@ -72,7 +72,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
rw.WriteHeader(http.StatusAccepted) rw.WriteHeader(http.StatusAccepted)
}) })
r.DELETE("/acme-challenge/:domain/:key", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) { r.DELETE("/acme-challenge/:domain/:key", func(rw http.ResponseWriter, req *http.Request, params httprouter.Params) {
if !hasPerms(conf.Verify, req, "violet:acme-challenge") { if !hasPerms(conf.Signer, req, "violet:acme-challenge") {
utils.RespondHttpStatus(rw, http.StatusForbidden) utils.RespondHttpStatus(rw, http.StatusForbidden)
return return
} }

View File

@ -34,10 +34,7 @@ func genSnakeOilProv() mjwt.Signer {
func genSnakeOilKey(perm string) string { func genSnakeOilKey(perm string) string {
p := claims.NewPermStorage() p := claims.NewPermStorage()
p.Set(perm) p.Set(perm)
val, err := snakeOilProv.GenerateJwt("abc", "abc", 5*time.Minute, auth.AccessTokenClaims{ val, err := snakeOilProv.GenerateJwt("abc", "abc", nil, 5*time.Minute, auth.AccessTokenClaims{Perms: p})
UserId: 1,
Perms: p,
})
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -54,7 +51,7 @@ func TestNewApiServer_Compile(t *testing.T) {
apiConf := &Conf{ apiConf := &Conf{
Domains: &fakeDomains{}, Domains: &fakeDomains{},
Acme: utils.NewAcmeChallenge(), Acme: utils.NewAcmeChallenge(),
Verify: snakeOilProv, Signer: snakeOilProv,
} }
f := &fakeCompilable{} f := &fakeCompilable{}
srv := NewApiServer(apiConf, utils.MultiCompilable{f}) srv := NewApiServer(apiConf, utils.MultiCompilable{f})
@ -81,7 +78,7 @@ func TestNewApiServer_AcmeChallenge_Put(t *testing.T) {
apiConf := &Conf{ apiConf := &Conf{
Domains: &fakeDomains{}, Domains: &fakeDomains{},
Acme: utils.NewAcmeChallenge(), Acme: utils.NewAcmeChallenge(),
Verify: snakeOilProv, Signer: snakeOilProv,
} }
srv := NewApiServer(apiConf, utils.MultiCompilable{}) srv := NewApiServer(apiConf, utils.MultiCompilable{})
acmeKey := genSnakeOilKey("violet:acme-challenge") acmeKey := genSnakeOilKey("violet:acme-challenge")
@ -125,7 +122,7 @@ func TestNewApiServer_AcmeChallenge_Delete(t *testing.T) {
apiConf := &Conf{ apiConf := &Conf{
Domains: &fakeDomains{}, Domains: &fakeDomains{},
Acme: utils.NewAcmeChallenge(), Acme: utils.NewAcmeChallenge(),
Verify: snakeOilProv, Signer: snakeOilProv,
} }
srv := NewApiServer(apiConf, utils.MultiCompilable{}) srv := NewApiServer(apiConf, utils.MultiCompilable{})
acmeKey := genSnakeOilKey("violet:acme-challenge") acmeKey := genSnakeOilKey("violet:acme-challenge")

View File

@ -20,7 +20,7 @@ type Conf struct {
Acme AcmeChallengeProvider Acme AcmeChallengeProvider
Certs CertProvider Certs CertProvider
Favicons *favicons.Favicons Favicons *favicons.Favicons
Verify mjwt.Verifier Signer mjwt.Verifier
ErrorPages *errorPages.ErrorPages ErrorPages *errorPages.ErrorPages
Router *router.Manager Router *router.Manager
} }

View File

@ -14,7 +14,7 @@ func TestNewHttpServer_AcmeChallenge(t *testing.T) {
httpConf := &Conf{ httpConf := &Conf{
Domains: &fakeDomains{}, Domains: &fakeDomains{},
Acme: utils.NewAcmeChallenge(), Acme: utils.NewAcmeChallenge(),
Verify: snakeOilProv, Signer: snakeOilProv,
} }
srv := NewHttpServer(httpConf) srv := NewHttpServer(httpConf)
httpConf.Acme.Put("example.com", "456", "456def") httpConf.Acme.Put("example.com", "456", "456def")

View File

@ -30,7 +30,7 @@ func TestNewHttpsServer_RateLimit(t *testing.T) {
RateLimit: 5, RateLimit: 5,
Domains: &fakeDomains{}, Domains: &fakeDomains{},
Certs: certs.New(nil, nil, true), Certs: certs.New(nil, nil, true),
Verify: snakeOilProv, Signer: snakeOilProv,
Router: router.NewManager(db, proxy.NewHybridTransportWithCalls(ft, ft)), Router: router.NewManager(db, proxy.NewHybridTransportWithCalls(ft, ft)),
} }
srv := NewHttpsServer(httpsConf) srv := NewHttpsServer(httpsConf)