Commit 34539c0c by Torkel Ödegaard

Enforce domain, host header validation against domain setting, Refactoring of PR…

Enforce domain, host header validation against domain setting, Refactoring of PR #1866, Closes #1732
parent 1f2cba81
......@@ -29,6 +29,10 @@ http_port = 3000
# The public facing domain name used to access grafana from a browser
domain = localhost
# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
enforce_domain = false
# The full public facing url
root_url = %(protocol)s://%(domain)s:%(http_port)s/
......
......@@ -29,6 +29,10 @@
# The public facing domain name used to access grafana from a browser
;domain = localhost
# Redirect to correct domain if host header does not match domain
# Prevents DNS rebinding attacks
;enforce_domain = false
# The full public facing url
;root_url = %(protocol)s://%(domain)s:%(http_port)s/
......
......@@ -72,6 +72,9 @@ Another way is put nginx or apache infront of Grafana and have them proxy reques
This setting is only used in as a part of the root_url setting (see below). Important if you
use github or google oauth.
### enforce_domain
Redirect to correct domain if host header does not match domain. Prevents DNS rebinding attacks. Default is false.
### root_url
This is the full url used to access grafana from a web browser. This is important if you use
google or github oauth authentication (for the callback url to be correct).
......
......@@ -40,6 +40,10 @@ func newMacaron() *macaron.Macaron {
Delims: macaron.Delims{Left: "[[", Right: "]]"},
}))
if setting.EnforceDomain {
m.Use(middleware.ValidateHostHeader(setting.Domain))
}
m.Use(middleware.GetContextHandler())
m.Use(middleware.Sessioner(&setting.SessionOptions))
......
......@@ -34,16 +34,6 @@ func GetContextHandler() macaron.Handler {
AllowAnonymous: false,
}
h := ctx.Req.Host
if i := strings.Index(h, ":"); i >= 0 {
h = h[:i]
}
if !strings.EqualFold(h, setting.Domain) {
ctx.Redirect(strings.TrimSuffix(setting.AppUrl, "/")+ctx.Req.RequestURI, 301)
return
}
// the order in which these are tested are important
// look for api key in Authorization header first
// then init session and look for userId in session
......
package middleware
import (
"strings"
"github.com/Unknwon/macaron"
"github.com/grafana/grafana/pkg/setting"
)
func ValidateHostHeader(domain string) macaron.Handler {
return func(c *macaron.Context) {
h := c.Req.Host
if i := strings.Index(h, ":"); i >= 0 {
h = h[:i]
}
if !strings.EqualFold(h, domain) {
c.Redirect(strings.TrimSuffix(setting.AppUrl, "/")+c.Req.RequestURI, 301)
return
}
}
}
......@@ -65,6 +65,7 @@ var (
RouterLogging bool
StaticRootPath string
EnableGzip bool
EnforceDomain bool
// Security settings.
SecretKey string
......@@ -355,10 +356,10 @@ func NewConfigContext(args *CommandLineArgs) {
Domain = server.Key("domain").MustString("localhost")
HttpAddr = server.Key("http_addr").MustString("0.0.0.0")
HttpPort = server.Key("http_port").MustString("3000")
StaticRootPath = makeAbsolute(server.Key("static_root_path").String(), HomePath)
RouterLogging = server.Key("router_logging").MustBool(false)
EnableGzip = server.Key("enable_gzip").MustBool(false)
EnforceDomain = server.Key("enforce_domain").MustBool(false)
security := Cfg.Section("security")
SecretKey = security.Key("secret_key").String()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment