lib/httpserver: add flags to specify HSTS / Frame-Options / CSP headers for httpserver (#5111)

support `Strict-Transport-Security`, `Content-Security-Policy` and `X-Frame-Options`
HTTP headers in all VictoriaMetrics components. 
The values for headers can be specified by users via the following flags: 
`-http.header.hsts`, `-http.header.csp` and `-http.header.frameOptions`.

Co-authored-by: hagen1778 <roman@victoriametrics.com>
This commit is contained in:
Dima Lazerka
2023-10-30 03:33:38 -07:00
committed by GitHub
parent 29cebd82fb
commit ad839aa492
22 changed files with 175 additions and 1 deletions

View File

@@ -51,6 +51,10 @@ var (
shutdownDelay = flag.Duration("http.shutdownDelay", 0, `Optional delay before http server shutdown. During this delay, the server returns non-OK responses from /health page, so load balancers can route new requests to other servers`)
idleConnTimeout = flag.Duration("http.idleConnTimeout", time.Minute, "Timeout for incoming idle http connections")
connTimeout = flag.Duration("http.connTimeout", 2*time.Minute, `Incoming http connections are closed after the configured timeout. This may help to spread the incoming load among a cluster of services behind a load balancer. Please note that the real timeout may be bigger by up to 10% as a protection against the thundering herd problem`)
headerHSTS = flag.String("http.header.hsts", "", "Value for 'Strict-Transport-Security' header")
headerFrameOptions = flag.String("http.header.frameOptions", "", "Value for 'X-Frame-Options' header")
headerCSP = flag.String("http.header.csp", "", "Value for 'Content-Security-Policy' header")
)
var (
@@ -238,6 +242,15 @@ func handlerWrapper(s *server, w http.ResponseWriter, r *http.Request, rh Reques
}
}()
if *headerHSTS != "" {
w.Header().Add("Strict-Transport-Security", *headerHSTS)
}
if *headerFrameOptions != "" {
w.Header().Add("X-Frame-Options", *headerFrameOptions)
}
if *headerCSP != "" {
w.Header().Add("Content-Security-Policy", *headerCSP)
}
w.Header().Add("X-Server-Hostname", hostname)
requestsTotal.Inc()
if whetherToCloseConn(r) {

View File

@@ -3,6 +3,7 @@ package httpserver
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
)
@@ -34,3 +35,32 @@ func TestGetQuotedRemoteAddr(t *testing.T) {
f("1.2.3.4", "foo.bar", `"1.2.3.4, X-Forwarded-For: foo.bar"`)
f("1.2\n\"3.4", "foo\nb\"ar", `"1.2\n\"3.4, X-Forwarded-For: foo\nb\"ar"`)
}
func TestHandlerWrapper(t *testing.T) {
*headerHSTS = "foo"
*headerFrameOptions = "bar"
*headerCSP = "baz"
defer func() {
*headerHSTS = ""
*headerFrameOptions = ""
*headerCSP = ""
}()
req, _ := http.NewRequest("GET", "/health", nil)
srv := &server{s: &http.Server{}}
w := &httptest.ResponseRecorder{}
handlerWrapper(srv, w, req, func(_ http.ResponseWriter, _ *http.Request) bool {
return true
})
if w.Header().Get("Strict-Transport-Security") != "foo" {
t.Errorf("HSTS header not set")
}
if w.Header().Get("X-Frame-Options") != "bar" {
t.Errorf("X-Frame-Options header not set")
}
if w.Header().Get("Content-Security-Policy") != "baz" {
t.Errorf("CSP header not set")
}
}