From 5d6b6dc6ac9139751a06a2496ad2e238afa19ed5 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Tue, 9 Feb 2021 23:45:47 -0500 Subject: [PATCH 01/13] Updated the version number --- main.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/main.go b/main.go index 7699ca7..a1d2793 100644 --- a/main.go +++ b/main.go @@ -27,11 +27,11 @@ func main() { // Handle the --version parameter if *versionParam { - fmt.Printf("%s\n", "2.2.3") + fmt.Printf("%s\n", "3.0.0") os.Exit(0) } - log.Println("Starting Adrian 2.2.3") + log.Println("Starting Adrian 3.0.0") log.Println("Loading adrian.yaml") var config adrianConfig.Config if *configParam != "" { From f49ed9929527362536e7e6aa4b5ab68948140da9 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Tue, 9 Feb 2021 23:57:41 -0500 Subject: [PATCH 02/13] HTTPS Support (#39) * Initial autotls commit * Big changes * HTTPS support with key file existence checking * Removed unnecessary files * Moved HTTPS settings to a new section of adrian.yaml * Example config file for HTTPS * Version number in the Server header * Only start HTTPS goroutine if an HTTPS port is defined --- adrian.https.yaml.example | 31 +++++++++++++ cache.go | 1 + config/main.go => config.go | 7 ++- fonts/css.go => css.go | 2 +- fonts/main.go => fonts.go | 11 ++--- go.mod | 18 ++++++++ go.sum | 66 ++++++++++++++++++++++++++ main.go | 72 +++++++++++++++++++++++------ middleware/main.go => middleware.go | 10 ++-- server.go | 9 ++-- fonts/watcher.go => watcher.go | 7 ++- fonts/weights.go => weights.go | 2 +- 12 files changed, 197 insertions(+), 39 deletions(-) create mode 100644 adrian.https.yaml.example rename config/main.go => config.go (92%) rename fonts/css.go => css.go (99%) rename fonts/main.go => fonts.go (95%) create mode 100644 go.mod create mode 100644 go.sum rename middleware/main.go => middleware.go (70%) rename fonts/watcher.go => watcher.go (87%) rename fonts/weights.go => weights.go (98%) diff --git a/adrian.https.yaml.example b/adrian.https.yaml.example new file mode 100644 index 0000000..9d7ce57 --- /dev/null +++ b/adrian.https.yaml.example @@ -0,0 +1,31 @@ +global: + + # Port number Adrian responds to + port: 80 + + # HTTPS support + https: + # HTTPS port number Adrian responds to + port: 4443 + # TLS Certificate file + cert: "cert.pem" + # TLS Key file + key: "key.pem" + + # Adrian will only allow fonts to be used on these URLs (CORS functionality) + domains: + - example.com + + # Directories where Adrian should look for fonts + directories: + - /usr/share/fonts + + # If true, replace font filenames with hashes so they can't be guessed as easily + obfuscate filenames: false + + # Used to set the cache-control header in responses + cache-control lifetime: 2628000 + + # Paths for writing logs to disk + logs: + access: "/var/log/adrian/access.log" diff --git a/cache.go b/cache.go index 7881f0d..eda1f88 100644 --- a/cache.go +++ b/cache.go @@ -3,6 +3,7 @@ package main import ( "fmt" "log" + "github.com/VictoriaMetrics/fastcache" "github.com/labstack/echo" ) diff --git a/config/main.go b/config.go similarity index 92% rename from config/main.go rename to config.go index 1ed3b7c..1325515 100644 --- a/config/main.go +++ b/config.go @@ -1,4 +1,4 @@ -package config +package main import ( "fmt" @@ -13,6 +13,11 @@ type Config struct { Global struct { Debug bool Port uint16 + HTTPS struct { + Port uint16 + Cert string + Key string + } Domains []string AllowedOrigins []string Directories []string diff --git a/fonts/css.go b/css.go similarity index 99% rename from fonts/css.go rename to css.go index 035f235..20f1877 100644 --- a/fonts/css.go +++ b/css.go @@ -1,4 +1,4 @@ -package fonts +package main import ( "fmt" diff --git a/fonts/main.go b/fonts.go similarity index 95% rename from fonts/main.go rename to fonts.go index 023a5de..b4f42fb 100644 --- a/fonts/main.go +++ b/fonts.go @@ -1,19 +1,18 @@ -package fonts +package main import ( - "crypto/sha256" "crypto/md5" + "crypto/sha256" "encoding/hex" "errors" + "io" "log" "os" - "io" "path" "regexp" "strings" "github.com/ConradIrwin/font/sfnt" - adrianConfig "github.com/dana-ross/adrian/config" ) // FontFileData describes a font (format) belonging to a font family @@ -55,7 +54,7 @@ var fonts = make(map[string]FontData) var uniqueIDXref = make(map[string]*FontVariant) // LoadFont loads a font into memory -func LoadFont(filePath string, config adrianConfig.Config) { +func LoadFont(filePath string, config Config) { fontFormat := GetCanonicalExtension(filePath) if _, ok := supportedFormats[fontFormat]; !ok { @@ -156,7 +155,7 @@ func GetFontVariantByUniqueID(uniqueID string) (fontVariant *FontVariant, err er } // calcUniqueID generates a unique ID for a font, optionally obfuscating it -func calcUniqueID(fontVariant FontVariant, config adrianConfig.Config) string { +func calcUniqueID(fontVariant FontVariant, config Config) string { if config.Global.ObfuscateFilenames { hash := sha256.New() hash.Write([]byte(fontVariant.Name)) diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..df5183e --- /dev/null +++ b/go.mod @@ -0,0 +1,18 @@ +module github.com/dana-ross/adrian + +go 1.15 + +require ( + dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab // indirect + github.com/ConradIrwin/font v0.0.0-20190603172541-e12dbea4cf12 + github.com/VictoriaMetrics/fastcache v1.5.7 + github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect + github.com/dsnet/compress v0.0.1 // indirect + github.com/fsnotify/fsnotify v1.4.9 + github.com/labstack/echo v3.3.10+incompatible + github.com/labstack/gommon v0.3.0 // indirect + github.com/valyala/fasttemplate v1.2.1 // indirect + golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect + golang.org/x/text v0.3.5 // indirect + gopkg.in/yaml.v2 v2.4.0 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..d5e1054 --- /dev/null +++ b/go.sum @@ -0,0 +1,66 @@ +dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab h1:Ew70NL+wL6v9looOiJJthlqA41VzoJS+q9AyjHJe6/g= +dmitri.shuralyov.com/font/woff2 v0.0.0-20180220214647-957792cbbdab/go.mod h1:FvHgTMJanm43G7B3MVSjS/jim5ytVqAJNAOpRhnuHJc= +github.com/ConradIrwin/font v0.0.0-20190603172541-e12dbea4cf12 h1:p6Fbemw7MLL8GECFdqBnGqrY6tfeNEECS1Gckyt6JJg= +github.com/ConradIrwin/font v0.0.0-20190603172541-e12dbea4cf12/go.mod h1:RfqDRypmK6cOLNPzccgIJ999A/yzpd0iGh6xazqpWrY= +github.com/VictoriaMetrics/fastcache v1.5.7 h1:4y6y0G8PRzszQUYIQHHssv/jgPHAb5qQuuDNdCbyAgw= +github.com/VictoriaMetrics/fastcache v1.5.7/go.mod h1:ptDBkNMQI4RtmVo8VS/XwRY6RoTu1dAWCbrk+6WsEM8= +github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/dana-ross/adrian v2.2.3+incompatible h1:YG+5tPqxv+wm5eKP/EUB3j/uAiQNN2MOj7pslJ0Vdew= +github.com/dana-ross/adrian v2.2.3+incompatible/go.mod h1:HTa8Oe+abOIs4hN23Ip/Z4teliifcBEca5D68Z5swEs= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgrijalva/jwt-go v1.0.2 h1:KPldsxuKGsS2FPWsNeg9ZO18aCrGKujPoWXn2yo+KQM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM= +github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dsnet/compress v0.0.1 h1:PlZu0n3Tuv04TzpfPbrnI0HW/YwodEXDS+oPKahKF0Q= +github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo= +github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= +github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= +github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= +github.com/labstack/echo v1.4.4 h1:1bEiBNeGSUKxcPDGfZ/7IgdhJJZx8wV/pICJh4W2NJI= +github.com/labstack/echo v3.3.10+incompatible h1:pGRcYk231ExFAyoAjAfD85kQzRJCRI8bbnE7CX5OEgg= +github.com/labstack/echo v3.3.10+incompatible/go.mod h1:0INS7j/VjnFxD4E2wkz67b8cVwCLbBmJyDaka6Cmk1s= +github.com/labstack/gommon v0.3.0 h1:JEeO0bvc78PKdyHxloTKiF8BD5iGrH8T6MSeGvSgob0= +github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k= +github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9 h1:d5US/mDsogSGW37IV293h//ZFaeajb69h+EHFsv2xGg= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= +github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= +github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= +github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad h1:DN0cp81fZ3njFcrLCytUHRSUkqBjfTo4Tx9RJTWs0EY= +golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9 h1:L2auWcuQIvxz9xSEqzESnV/QN/gNRXNApHi3fYwl2w0= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.5 h1:i6eZZ+zk0SOf0xgBpEpPD18qWcJda6q1sxt3S0kzyUQ= +golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/main.go b/main.go index a1d2793..71ffa7b 100644 --- a/main.go +++ b/main.go @@ -11,12 +11,11 @@ import ( "path/filepath" "strconv" "strings" - - adrianConfig "github.com/dana-ross/adrian/config" - adrianFonts "github.com/dana-ross/adrian/fonts" + "sync" "github.com/labstack/echo" "github.com/labstack/echo/middleware" + //"golang.org/x/crypto/acme/autocert" ) func main() { @@ -33,11 +32,11 @@ func main() { log.Println("Starting Adrian 3.0.0") log.Println("Loading adrian.yaml") - var config adrianConfig.Config + var config Config if *configParam != "" { - config = adrianConfig.LoadConfig(*configParam) + config = LoadConfig(*configParam) } else { - config = adrianConfig.LoadConfig("./adrian.yaml") + config = LoadConfig("./adrian.yaml") } log.Println("Initializing web server") e := Instantiate(config) @@ -48,11 +47,12 @@ func main() { CustomTimeFormat: "02/Jan/2006:03:04:05 -0700", Output: accessLog, })) + defer accessLog.Close() log.Println("Loading fonts and starting watchers") for _, folder := range config.Global.Directories { - adrianFonts.FindFonts(folder, config) - adrianFonts.InstantiateWatcher(folder, config) + FindFonts(folder, config) + InstantiateWatcher(folder, config) } @@ -62,8 +62,50 @@ func main() { registerCSSPath(e, accessLog) registerFontPath(e, accessLog) - log.Printf("Listening on port %d", config.Global.Port) - e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", config.Global.Port))) + var waitGroup sync.WaitGroup + waitGroup.Add(2) + go func(wg *sync.WaitGroup){ + defer wg.Done() + log.Printf("Listening for HTTP on port %d", config.Global.Port) + e.Logger.Fatal(e.Start(fmt.Sprintf(":%d", config.Global.Port))) + }(&waitGroup) + + if(config.Global.HTTPS.Port != 0) { + go func(wg *sync.WaitGroup){ + defer wg.Done() + if(config.Global.HTTPS.Cert == "") { + log.Printf("Missing HTTPS.Cert setting") + wg.Done() + return + } + _, HTTPSCertErr := os.Stat(config.Global.HTTPS.Cert) + if os.IsNotExist(HTTPSCertErr) { + log.Printf("HTTPSCert file %s not found", config.Global.HTTPS.Cert) + wg.Done() + return + } + if(config.Global.HTTPS.Key == "") { + log.Printf("Missing HTTPSKey setting") + wg.Done() + return + } + _, HTTPSKeyErr := os.Stat(config.Global.HTTPS.Key) + if os.IsNotExist(HTTPSKeyErr) { + log.Printf("HTTPSKey file %s not found", config.Global.HTTPS.Key) + wg.Done() + return + } + + log.Printf("Loading HTTPS Certificate %s", config.Global.HTTPS.Cert) + log.Printf("Loading HTTPS Key %s", config.Global.HTTPS.Key) + log.Printf("Listening for HTTPS on port %d", config.Global.HTTPS.Port) + + // e.Logger.Fatal(e.StartAutoTLS(fmt.Sprintf(":%d", config.Global.HTTPSPort))) + e.Logger.Fatal(e.StartTLS(fmt.Sprintf(":%d", config.Global.HTTPS.Port), config.Global.HTTPS.Cert, config.Global.HTTPS.Key)) + }(&waitGroup) + } + waitGroup.Wait() + } func registerCSSPath(e *echo.Echo, accessLog *os.File) { @@ -85,11 +127,11 @@ func registerCSSPath(e *echo.Echo, accessLog *os.File) { } fontWeights = uniqueInts(fontWeights) } - fontData, err := adrianFonts.GetFont(fontFamilyName) + fontData, err := GetFont(fontFamilyName) if err != nil { return return404(c) } - fontsCSS = fontsCSS + adrianFonts.FontFaceCSS(fontData, fontWeights, display) + fontsCSS = fontsCSS + FontFaceCSS(fontData, fontWeights, display) } writeToCache(c, fontsCSS) return c.String(http.StatusOK, fontsCSS) @@ -134,14 +176,14 @@ func outputFont(c echo.Context, mimeType string, accessLog *os.File) error { if error != nil { return return404(c) } - fontVariant, err := adrianFonts.GetFontVariantByUniqueID(basename(filename)) + fontVariant, err := GetFontVariantByUniqueID(basename(filename)) if err != nil { return return404(c) } - fontFileData, ok := fontVariant.Files[adrianFonts.GetCanonicalExtension(filename)] + fontFileData, ok := fontVariant.Files[GetCanonicalExtension(filename)] if !ok { - log.Fatal("Invalid font format" + adrianFonts.GetCanonicalExtension(filename)) + log.Fatal("Invalid font format" + GetCanonicalExtension(filename)) } for i := range c.Request().Header["If-None-Match"] { diff --git a/middleware/main.go b/middleware.go similarity index 70% rename from middleware/main.go rename to middleware.go index ae03fa5..a756d05 100644 --- a/middleware/main.go +++ b/middleware.go @@ -1,21 +1,21 @@ -package middleware +package main import ( - "github.com/labstack/echo" - adrianConfig "github.com/dana-ross/adrian/config" "strconv" + + "github.com/labstack/echo" ) // SetServerHeader sets a Server header func SetServerHeader(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { - c.Response().Header().Set(echo.HeaderServer, "Adrian 2.1.1") + c.Response().Header().Set(echo.HeaderServer, "Adrian 3.0.0") return next(c) } } // SetCacheControlHeaders sets headers for control over caching -func SetCacheControlHeaders(config adrianConfig.Config) func(echo.HandlerFunc) echo.HandlerFunc { +func SetCacheControlHeaders(config Config) func(echo.HandlerFunc) echo.HandlerFunc { return func (next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { c.Response().Header().Set("Cache-Control", "max-age=" + strconv.FormatUint(uint64(config.Global.CacheControlLifetime), 10) + ", public") diff --git a/server.go b/server.go index ecfb5c4..cd8f70c 100644 --- a/server.go +++ b/server.go @@ -3,15 +3,12 @@ package main import ( "net/http" - adrianMiddleware "github.com/dana-ross/adrian/middleware" - - adrianConfig "github.com/dana-ross/adrian/config" "github.com/labstack/echo" "github.com/labstack/echo/middleware" ) // Instantiate returns a pre-configured Echo instance -func Instantiate(config adrianConfig.Config) *echo.Echo { +func Instantiate(config Config) *echo.Echo { e := echo.New() e.HideBanner = true @@ -28,8 +25,8 @@ func Instantiate(config adrianConfig.Config) *echo.Echo { Level: 5, })) - e.Use(adrianMiddleware.SetServerHeader) - e.Use(adrianMiddleware.SetCacheControlHeaders(config)) + e.Use(SetServerHeader) + e.Use(SetCacheControlHeaders(config)) e.Use(readFromCache) diff --git a/fonts/watcher.go b/watcher.go similarity index 87% rename from fonts/watcher.go rename to watcher.go index 5804909..e4fe08c 100644 --- a/fonts/watcher.go +++ b/watcher.go @@ -1,4 +1,4 @@ -package fonts +package main import ( "fmt" @@ -7,12 +7,11 @@ import ( "path" "time" - adrianConfig "github.com/dana-ross/adrian/config" "github.com/fsnotify/fsnotify" ) // FindFonts loads all the fonts in a directory -func FindFonts(fontsPath string, config adrianConfig.Config) { +func FindFonts(fontsPath string, config Config) { filesInfo, err := ioutil.ReadDir(fontsPath) if err != nil { @@ -27,7 +26,7 @@ func FindFonts(fontsPath string, config adrianConfig.Config) { } // InstantiateWatcher is a thing -func InstantiateWatcher(path string, config adrianConfig.Config) { +func InstantiateWatcher(path string, config Config) { go func() { watcher, err := fsnotify.NewWatcher() if err != nil { diff --git a/fonts/weights.go b/weights.go similarity index 98% rename from fonts/weights.go rename to weights.go index 3cedef0..9e4ee74 100644 --- a/fonts/weights.go +++ b/weights.go @@ -1,4 +1,4 @@ -package fonts +package main import ( "regexp" From 77398498e0703467fd8c55cdba211fc635ac84cc Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Tue, 9 Feb 2021 23:58:54 -0500 Subject: [PATCH 03/13] Ignore HTTPS keyfiles --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4ece408..192886c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ .vscode *.exe adrian.yaml -adrian \ No newline at end of file +adrian +*.pem \ No newline at end of file From 5ff4cb334815acd468f0d6d4fe8d8ccd9485fb39 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:01:18 -0500 Subject: [PATCH 04/13] Example config file using port 443 --- adrian.https.yaml.example | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adrian.https.yaml.example b/adrian.https.yaml.example index 9d7ce57..7df1961 100644 --- a/adrian.https.yaml.example +++ b/adrian.https.yaml.example @@ -6,7 +6,7 @@ global: # HTTPS support https: # HTTPS port number Adrian responds to - port: 4443 + port: 443 # TLS Certificate file cert: "cert.pem" # TLS Key file From ffb0c53c6eec8ed7e11e391593cd9460464ee12e Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:01:34 -0500 Subject: [PATCH 05/13] Added HTTPS section to config in README --- README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 42ca3da..80fcec1 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,16 @@ global: # Port number Adrian responds to port: 80 - + + # HTTPS support + https: + # HTTPS port number Adrian responds to + port: 443 + # TLS Certificate file + cert: "cert.pem" + # TLS Key file + key: "key.pem" + # Adrian will only allow fonts to be used on these URLs (CORS functionality) domains: - example.com From 501d81f44c13befd9777eac097fd9b2c42b21bbd Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:04:36 -0500 Subject: [PATCH 06/13] HTTPS config docs --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 80fcec1..df01e0d 100644 --- a/README.md +++ b/README.md @@ -72,6 +72,22 @@ global: The TCP/IP port Adrian will listen to. Defaults to port 80. +##### https: + +IF HTTPS support is desired, configure it here. + +###### port: <integer> + +The TCP/IP port Adrian will listen to for HTTPS. Defaults to port 443. + +###### cert: <string> + +Path/Filename of a TLS certificate file to use. + +###### key: <string> + +Path/Filename of a TLS key file to use. + ##### domains A whitelist of domains allowed to use fonts hosted by this instance From f482fc7a788854666d82b911da8972dddf2fee83 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:13:13 -0500 Subject: [PATCH 07/13] LetEncrypt (autotls) support --- README.md | 12 ++++++-- adrian.https.yaml.example | 8 +++-- config.go | 1 + main.go | 63 ++++++++++++++++++++++----------------- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/README.md b/README.md index df01e0d..e1528bc 100644 --- a/README.md +++ b/README.md @@ -42,11 +42,13 @@ global: # HTTPS support https: + # Enable automatic TLS certificate generation using LetEncrypt + auto: false # HTTPS port number Adrian responds to - port: 443 - # TLS Certificate file + port: 4443 + # TLS Certificate file (if not using LetsEncrypt) cert: "cert.pem" - # TLS Key file + # TLS Key file (if not using LetsEncrypt) key: "key.pem" # Adrian will only allow fonts to be used on these URLs (CORS functionality) @@ -76,6 +78,10 @@ The TCP/IP port Adrian will listen to. Defaults to port 80. IF HTTPS support is desired, configure it here. +###### auto: <boolean> + +Enable automatic TLS certificate generation using LetEncrypt + ###### port: <integer> The TCP/IP port Adrian will listen to for HTTPS. Defaults to port 443. diff --git a/adrian.https.yaml.example b/adrian.https.yaml.example index 7df1961..d94c4e3 100644 --- a/adrian.https.yaml.example +++ b/adrian.https.yaml.example @@ -5,11 +5,13 @@ global: # HTTPS support https: + # Enable automatic TLS certificate generation using LetEncrypt + auto: false # HTTPS port number Adrian responds to - port: 443 - # TLS Certificate file + port: 4443 + # TLS Certificate file (if not using LetsEncrypt) cert: "cert.pem" - # TLS Key file + # TLS Key file (if not using LetsEncrypt) key: "key.pem" # Adrian will only allow fonts to be used on these URLs (CORS functionality) diff --git a/config.go b/config.go index 1325515..e35bd7d 100644 --- a/config.go +++ b/config.go @@ -14,6 +14,7 @@ type Config struct { Debug bool Port uint16 HTTPS struct { + Auto bool Port uint16 Cert string Key string diff --git a/main.go b/main.go index 71ffa7b..0517b5b 100644 --- a/main.go +++ b/main.go @@ -73,35 +73,42 @@ func main() { if(config.Global.HTTPS.Port != 0) { go func(wg *sync.WaitGroup){ defer wg.Done() - if(config.Global.HTTPS.Cert == "") { - log.Printf("Missing HTTPS.Cert setting") - wg.Done() - return - } - _, HTTPSCertErr := os.Stat(config.Global.HTTPS.Cert) - if os.IsNotExist(HTTPSCertErr) { - log.Printf("HTTPSCert file %s not found", config.Global.HTTPS.Cert) - wg.Done() - return - } - if(config.Global.HTTPS.Key == "") { - log.Printf("Missing HTTPSKey setting") - wg.Done() - return - } - _, HTTPSKeyErr := os.Stat(config.Global.HTTPS.Key) - if os.IsNotExist(HTTPSKeyErr) { - log.Printf("HTTPSKey file %s not found", config.Global.HTTPS.Key) - wg.Done() - return - } - log.Printf("Loading HTTPS Certificate %s", config.Global.HTTPS.Cert) - log.Printf("Loading HTTPS Key %s", config.Global.HTTPS.Key) - log.Printf("Listening for HTTPS on port %d", config.Global.HTTPS.Port) - - // e.Logger.Fatal(e.StartAutoTLS(fmt.Sprintf(":%d", config.Global.HTTPSPort))) - e.Logger.Fatal(e.StartTLS(fmt.Sprintf(":%d", config.Global.HTTPS.Port), config.Global.HTTPS.Cert, config.Global.HTTPS.Key)) + if(config.Global.HTTPS.Auto) { + log.Printf("LetsEncrypt support enabled.") + log.Printf("Listening for HTTPS on port %d", config.Global.HTTPS.Port) + e.Logger.Fatal(e.StartAutoTLS(fmt.Sprintf(":%d", config.Global.HTTPS.Port))) + } else { + if(config.Global.HTTPS.Cert == "") { + log.Printf("Missing HTTPS.Cert setting") + wg.Done() + return + } + _, HTTPSCertErr := os.Stat(config.Global.HTTPS.Cert) + if os.IsNotExist(HTTPSCertErr) { + log.Printf("HTTPSCert file %s not found", config.Global.HTTPS.Cert) + wg.Done() + return + } + if(config.Global.HTTPS.Key == "") { + log.Printf("Missing HTTPSKey setting") + wg.Done() + return + } + _, HTTPSKeyErr := os.Stat(config.Global.HTTPS.Key) + if os.IsNotExist(HTTPSKeyErr) { + log.Printf("HTTPSKey file %s not found", config.Global.HTTPS.Key) + wg.Done() + return + } + + log.Printf("Loading HTTPS Certificate %s", config.Global.HTTPS.Cert) + log.Printf("Loading HTTPS Key %s", config.Global.HTTPS.Key) + log.Printf("Listening for HTTPS on port %d", config.Global.HTTPS.Port) + + e.Logger.Fatal(e.StartTLS(fmt.Sprintf(":%d", config.Global.HTTPS.Port), config.Global.HTTPS.Cert, config.Global.HTTPS.Key)) + + } }(&waitGroup) } waitGroup.Wait() From 9d04fa4018b5e6db01955ad4b1ef276364cb8ec2 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:13:57 -0500 Subject: [PATCH 08/13] Added access.log to gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 192886c..15415b8 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ *.exe adrian.yaml adrian -*.pem \ No newline at end of file +*.pem +access.log \ No newline at end of file From 250fa76c69265508e7c969f2d68535355020861e Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:19:53 -0500 Subject: [PATCH 09/13] clean file paths --- fonts.go | 7 ++++--- main.go | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/fonts.go b/fonts.go index b4f42fb..3731dfc 100644 --- a/fonts.go +++ b/fonts.go @@ -9,6 +9,7 @@ import ( "log" "os" "path" + "path/filepath" "regexp" "strings" @@ -61,7 +62,7 @@ func LoadFont(filePath string, config Config) { return } - file, err := os.Open(filePath) + file, err := os.Open(filepath.Clean(filePath)) if err != nil { log.Fatal(err) } @@ -166,8 +167,8 @@ func calcUniqueID(fontVariant FontVariant, config Config) string { } // calcFileMD5 calculates the MD5 hash of a file -func calcFileMD5(filepath string) string { - file, err := os.Open(filepath) +func calcFileMD5(filePath string) string { + file, err := os.Open(filepath.Clean(filePath)) if err != nil { log.Fatal(err) } diff --git a/main.go b/main.go index 0517b5b..6ef8faa 100644 --- a/main.go +++ b/main.go @@ -232,7 +232,7 @@ func uniqueInts(input []int) []int { } func openAccessLog(path string) *os.File { - f, err := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) // #nosec + f, err := os.OpenFile(filepath.Clean(path), os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) // #nosec if err != nil { log.Fatal(fmt.Sprintf("Can't open access log file: %s", err)) } From 274ad9c16fa7d1051e4bb95ac5b23d3e8deb80d7 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:23:55 -0500 Subject: [PATCH 10/13] Error checking --- fonts.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/fonts.go b/fonts.go index 3731dfc..9de4c1e 100644 --- a/fonts.go +++ b/fonts.go @@ -159,7 +159,10 @@ func GetFontVariantByUniqueID(uniqueID string) (fontVariant *FontVariant, err er func calcUniqueID(fontVariant FontVariant, config Config) string { if config.Global.ObfuscateFilenames { hash := sha256.New() - hash.Write([]byte(fontVariant.Name)) + _, err := hash.Write([]byte(fontVariant.Name)) + if err != nil { + log.Fatal(err) + } return hex.EncodeToString(hash.Sum(nil)) } From 8ad76928fd5af0c5e9b25cd7be33b6b24a39a882 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:25:40 -0500 Subject: [PATCH 11/13] Ignore security warning for md5 in gosec --- fonts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.go b/fonts.go index 9de4c1e..f5cdd82 100644 --- a/fonts.go +++ b/fonts.go @@ -177,7 +177,7 @@ func calcFileMD5(filePath string) string { } defer file.Close() - hash := md5.New() + hash := md5.New() // #nosec if _, err := io.Copy(hash, file); err != nil { log.Fatal(err) } From 69e563518a9184d0f58f5f16ddc4af16d94b2ee1 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:26:33 -0500 Subject: [PATCH 12/13] Ignore security warning for md5 in gosec --- fonts.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fonts.go b/fonts.go index f5cdd82..4a180e3 100644 --- a/fonts.go +++ b/fonts.go @@ -1,7 +1,7 @@ package main import ( - "crypto/md5" + "crypto/md5" // #nosec "crypto/sha256" "encoding/hex" "errors" From 46cb3b2dff33adc2df66d68799a09091c0358d52 Mon Sep 17 00:00:00 2001 From: Dana Ross Date: Wed, 10 Feb 2021 00:30:35 -0500 Subject: [PATCH 13/13] Safer defer of *os.File.Close() --- fonts.go | 7 ++++++- main.go | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/fonts.go b/fonts.go index 4a180e3..c412f06 100644 --- a/fonts.go +++ b/fonts.go @@ -175,7 +175,12 @@ func calcFileMD5(filePath string) string { if err != nil { log.Fatal(err) } - defer file.Close() + defer func() { + err := file.Close() + if err != nil { + log.Printf("error closing the font file: %s", err) + } + }() hash := md5.New() // #nosec if _, err := io.Copy(hash, file); err != nil { diff --git a/main.go b/main.go index 6ef8faa..a83400e 100644 --- a/main.go +++ b/main.go @@ -47,7 +47,12 @@ func main() { CustomTimeFormat: "02/Jan/2006:03:04:05 -0700", Output: accessLog, })) - defer accessLog.Close() + defer func() { + err := accessLog.Close() + if err != nil { + log.Printf("error closing the access log: %s", err) + } + }() log.Println("Loading fonts and starting watchers") for _, folder := range config.Global.Directories {