From 068f3c04a0ee4a9918006bd61e9fe710116bdc83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ken-H=C3=A5vard=20Lieng?= Date: Mon, 25 Jan 2016 22:41:54 +0100 Subject: [PATCH] Add configurable HSTS and some other headers --- config.default.toml | 7 +++ server/index_template.go | 2 +- server/serve_files.go | 93 +++++++++++++++++++++++++--------------- 3 files changed, 66 insertions(+), 36 deletions(-) diff --git a/config.default.toml b/config.default.toml index 349d9dda..bb1eea40 100644 --- a/config.default.toml +++ b/config.default.toml @@ -58,3 +58,10 @@ secret = "" [auth.twitter] key = "" secret = "" + +# Strict-Transport-Security +[https.hsts] +enabled = false +max_age = 31536000 +include_subdomains = false +preload = false diff --git a/server/index_template.go b/server/index_template.go index 4479b8ed..928bfe70 100644 --- a/server/index_template.go +++ b/server/index_template.go @@ -10,7 +10,7 @@ import ( var ( index_0 = []byte(`Dispatch
`) ) diff --git a/server/serve_files.go b/server/serve_files.go index 2a7b2279..f70a7eb7 100644 --- a/server/serve_files.go +++ b/server/serve_files.go @@ -17,40 +17,44 @@ import ( "github.com/khlieng/dispatch/assets" ) -var files = []File{ - File{ - Path: "bundle.js", - Asset: "bundle.js.gz", - ContentType: "text/javascript", - CacheControl: "max-age=31536000", - }, - File{ - Path: "bundle.css", - Asset: "bundle.css.gz", - ContentType: "text/css", - CacheControl: "max-age=31536000", - }, - File{ - Path: "font/fontello.woff", - Asset: "font/fontello.woff.gz", - ContentType: "application/font-woff", - }, - File{ - Path: "font/fontello.ttf", - Asset: "font/fontello.ttf.gz", - ContentType: "application/x-font-ttf", - }, - File{ - Path: "font/fontello.eot", - Asset: "font/fontello.eot.gz", - ContentType: "application/vnd.ms-fontobject", - }, - File{ - Path: "font/fontello.svg", - Asset: "font/fontello.svg.gz", - ContentType: "image/svg+xml", - }, -} +var ( + files = []File{ + File{ + Path: "bundle.js", + Asset: "bundle.js.gz", + ContentType: "text/javascript", + CacheControl: "max-age=31536000", + }, + File{ + Path: "bundle.css", + Asset: "bundle.css.gz", + ContentType: "text/css", + CacheControl: "max-age=31536000", + }, + File{ + Path: "font/fontello.woff", + Asset: "font/fontello.woff.gz", + ContentType: "application/font-woff", + }, + File{ + Path: "font/fontello.ttf", + Asset: "font/fontello.ttf.gz", + ContentType: "application/x-font-ttf", + }, + File{ + Path: "font/fontello.eot", + Asset: "font/fontello.eot.gz", + ContentType: "application/vnd.ms-fontobject", + }, + File{ + Path: "font/fontello.svg", + Asset: "font/fontello.svg.gz", + ContentType: "image/svg+xml", + }, + } + + hstsHeader string +) type File struct { Path string @@ -76,6 +80,17 @@ func initFileServer() { hash = md5.Sum(data) files[1].Path = "bundle." + base64.RawURLEncoding.EncodeToString(hash[:]) + ".css" + + if viper.GetBool("https.hsts.enabled") { + hstsHeader = "max-age=" + viper.GetString("https.hsts.max_age") + + if viper.GetBool("https.hsts.include_subdomains") { + hstsHeader += "; includeSubDomains" + } + if viper.GetBool("https.hsts.preload") { + hstsHeader += "; preload" + } + } } } @@ -112,11 +127,19 @@ func serveIndex(w http.ResponseWriter, r *http.Request) { return } - w.Header().Set("Cache-Control", "no-store") w.Header().Set("Content-Type", "text/html") + w.Header().Set("Cache-Control", "no-store") + w.Header().Set("X-Content-Type-Options", "nosniff") + w.Header().Set("X-Frame-Options", "deny") + w.Header().Set("X-XSS-Protection", "1; mode=block") + + if hstsHeader != "" { + w.Header().Set("Strict-Transport-Security", hstsHeader) + } if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") { w.Header().Set("Content-Encoding", "gzip") + gzw := gzip.NewWriter(w) renderIndex(gzw, session) gzw.Close()