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
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"`
ErrorPagePath string `json:"error_page_path"`
Listen listenConfig `json:"listen"`
InkscapeCmd string `json:"inkscape"`
RateLimit uint64 `json:"rate_limit"`
SignerIssuer string `json:"signer_issuer"`
}
type listenConfig struct {

View File

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

View File

@ -59,14 +59,15 @@ 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
SelfSigned bool
ErrorPages bool
ApiListen string
HttpListen string
HttpsListen string
RateLimit uint64
FirstDomain string
ApiUrl string
SignerIssuer string
}
// ask main questions
@ -103,6 +104,10 @@ 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"},
@ -130,10 +135,6 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
confEncode := json.NewEncoder(createConf)
confEncode.SetIndent("", " ")
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,
ErrorPagePath: errorPagePath,
Listen: listenConfig{
@ -141,8 +142,9 @@ func (s *setupCmd) Execute(_ context.Context, _ *flag.FlagSet, _ ...interface{})
Http: answers.HttpListen,
Https: answers.HttpsListen,
},
InkscapeCmd: "inkscape",
RateLimit: answers.RateLimit,
InkscapeCmd: "inkscape",
RateLimit: answers.RateLimit,
SignerIssuer: answers.SignerIssuer,
})
if err != nil {
fmt.Println("[Violet] Failed to write config file: ", err)

2
go.mod
View File

@ -5,7 +5,7 @@ go 1.20
require (
github.com/AlecAivazis/survey/v2 v2.3.7
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/rescheduler v0.0.1
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/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.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/go.mod h1:NOv3tO4497mInG+3tcFkIohmxCywUwMLU8WNxJZLVmU=
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
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)
return
}
@ -30,7 +30,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
// Endpoint for domains
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)
return
}
@ -41,7 +41,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
conf.Domains.Compile()
})
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)
return
}
@ -59,7 +59,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
// Endpoint for acme-challenge
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)
return
}
@ -72,7 +72,7 @@ func NewApiServer(conf *Conf, compileTarget utils.MultiCompilable) *http.Server
rw.WriteHeader(http.StatusAccepted)
})
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)
return
}

View File

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

View File

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

View File

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

View File

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