33e5c5b44349b1a2a65f1d666236ed3cd5086f75 — Martin Angers 7 months ago b3ef6ad
add secure headers config
4 files changed, 38 insertions(+), 21 deletions(-)

M builder/builder.go
M go.mod
M go.sum
M kick.go
M builder/builder.go => builder/builder.go +5 -0
@@ 14,6 14,7 @@
 	"github.com/gorilla/csrf"
 	"github.com/gorilla/handlers"
 	"github.com/julienschmidt/httprouter"
+	"github.com/unrolled/secure"
 	"golang.org/x/crypto/acme/autocert"
 )
 


@@ 173,6 174,10 @@
 	if s.Root.RequestIDHeader != "" {
 		mw = append(mw, requestID(s.Root.RequestIDHeader, s.Root.RequestIDForceNew))
 	}
+	if s.Root.SecurityHeaders != nil {
+		sec := secure.New(*s.Root.SecurityHeaders)
+		mw = append(mw, sec.Handler)
+	}
 	if fn := s.Root.LoggingFunc; fn != nil {
 		mw = append(mw, logging(fn))
 	}

M go.mod => go.mod +1 -0
@@ 10,6 10,7 @@
 	github.com/julienschmidt/httprouter v1.2.0
 	github.com/kr/pretty v0.1.0 // indirect
 	github.com/sirupsen/logrus v1.4.0
+	github.com/unrolled/secure v1.0.0
 	golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c
 	gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
 )

M go.sum => go.sum +2 -0
@@ 34,6 34,8 @@
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
 github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/unrolled/secure v1.0.0 h1:2p4MlT30bNNjaFxA+gtDuLT/73fnXblTC+W/lCzOaZc=
+github.com/unrolled/secure v1.0.0/go.mod h1:mnPT77IAdsi/kV7+Es7y+pXALeV3h7G6dQF6mNYjcLA=
 golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
 golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=

M kick.go => kick.go +30 -21
@@ 12,6 12,8 @@
 	"os/signal"
 	"sync/atomic"
 	"time"
+
+	"github.com/unrolled/secure"
 )
 
 // ErrTooManyBytes is the error returned by writes to


@@ 361,10 363,25 @@
 // server as a whole, before multiplexing the request based on
 // method and path as defined by the Routes field of the server.
 type Root struct {
-	PanicRecoveryFunc       func(w http.ResponseWriter, r *http.Request, panicVal interface{})
-	LoggingFunc             func(w http.ResponseWriter, r *http.Request, info map[string]interface{})
+	// PanicRecoveryFunc is the function called to recover from
+	// a panic. It should write the response, but the panic is
+	// already recovered when this is called, and the recovered
+	// value is passed as panicVal. If nil, there is no panic
+	// recovery.
+	PanicRecoveryFunc func(w http.ResponseWriter, r *http.Request, panicVal interface{})
+
+	// LoggingFunc is the function called to log a request.
+	// Relevant information is stored in the info map.
+	LoggingFunc func(w http.ResponseWriter, r *http.Request, info map[string]interface{})
+
+	// MethodNotAllowedHandler is the handler called if a request
+	// is made to a path that has a configured handler, but no
+	// handler for that specific method.
 	MethodNotAllowedHandler http.Handler
-	NotFoundHandler         http.Handler
+
+	// NotFoundHandler is the handler called if no match is found
+	// for the requested method and path.
+	NotFoundHandler http.Handler
 
 	TrustProxyHeaders   bool
 	AllowMethodOverride bool


@@ 375,6 392,16 @@
 	RequestIDHeader   string
 	RequestIDForceNew bool
 
+	// SecurityHeaders configures subtle but important HTTP headers
+	// for better secufiry. This is currently a direct usage of the
+	// unrolled/secure package's Options struct, should probably be
+	// abstracted to a package-local struct and that 3rd-party package
+	// used only in the builder.
+	//
+	// See https://www.owasp.org/index.php/OWASP_Secure_Headers_Project#tab=Headers
+	// for an overview of the headers and their role.
+	SecurityHeaders *secure.Options
+
 	Gzip *GzipConfig
 }
 


@@ 407,7 434,6 @@
 	RequestContentTypes  []string
 	ResponseContentTypes []string
 
-	Websocket    *WebsocketConfig
 	CORS         *CORSConfig
 	CSRF         *CSRFConfig
 	RequestLimit *RequestLimitConfig


@@ 415,23 441,6 @@
 	_ struct{} // prevent unkeyed creation of this struct
 }
 
-// WebsocketConfig configures the websocket support for a
-// handler.
-type WebsocketConfig struct {
-	ReadBufferSize  int
-	WriteBufferSize int
-	MaxMessageBytes int
-
-	HandshakeTimeout time.Duration
-	ReadTimeout      time.Duration
-	WriteTimeout     time.Duration
-
-	Subprotocols   []string
-	AllowedOrigins []string
-
-	_ struct{} // prevent unkeyed creation of this struct
-}
-
 // CORSConfig configures the cross-origin resource sharing.
 type CORSConfig struct {
 	AllowCredentials bool