Enforce domain, host header validation against domain setting, Refactoring of PR #1866, Closes #1732

This commit is contained in:
Torkel Ödegaard
2015-05-05 11:21:06 +02:00
parent 1f2cba81eb
commit 34539c0c13
7 changed files with 39 additions and 11 deletions

View File

@ -29,6 +29,10 @@ http_port = 3000
# The public facing domain name used to access grafana from a browser # The public facing domain name used to access grafana from a browser
domain = localhost 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 # The full public facing url
root_url = %(protocol)s://%(domain)s:%(http_port)s/ root_url = %(protocol)s://%(domain)s:%(http_port)s/

View File

@ -29,6 +29,10 @@
# The public facing domain name used to access grafana from a browser # The public facing domain name used to access grafana from a browser
;domain = localhost ;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 # The full public facing url
;root_url = %(protocol)s://%(domain)s:%(http_port)s/ ;root_url = %(protocol)s://%(domain)s:%(http_port)s/

View File

@ -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 This setting is only used in as a part of the root_url setting (see below). Important if you
use github or google oauth. 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 ### root_url
This is the full url used to access grafana from a web browser. This is important if you use 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). google or github oauth authentication (for the callback url to be correct).

View File

@ -40,6 +40,10 @@ func newMacaron() *macaron.Macaron {
Delims: macaron.Delims{Left: "[[", Right: "]]"}, Delims: macaron.Delims{Left: "[[", Right: "]]"},
})) }))
if setting.EnforceDomain {
m.Use(middleware.ValidateHostHeader(setting.Domain))
}
m.Use(middleware.GetContextHandler()) m.Use(middleware.GetContextHandler())
m.Use(middleware.Sessioner(&setting.SessionOptions)) m.Use(middleware.Sessioner(&setting.SessionOptions))

View File

@ -34,16 +34,6 @@ func GetContextHandler() macaron.Handler {
AllowAnonymous: false, 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 // the order in which these are tested are important
// look for api key in Authorization header first // look for api key in Authorization header first
// then init session and look for userId in session // then init session and look for userId in session

View File

@ -0,0 +1,22 @@
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
}
}
}

View File

@ -65,6 +65,7 @@ var (
RouterLogging bool RouterLogging bool
StaticRootPath string StaticRootPath string
EnableGzip bool EnableGzip bool
EnforceDomain bool
// Security settings. // Security settings.
SecretKey string SecretKey string
@ -355,10 +356,10 @@ func NewConfigContext(args *CommandLineArgs) {
Domain = server.Key("domain").MustString("localhost") Domain = server.Key("domain").MustString("localhost")
HttpAddr = server.Key("http_addr").MustString("0.0.0.0") HttpAddr = server.Key("http_addr").MustString("0.0.0.0")
HttpPort = server.Key("http_port").MustString("3000") HttpPort = server.Key("http_port").MustString("3000")
StaticRootPath = makeAbsolute(server.Key("static_root_path").String(), HomePath) StaticRootPath = makeAbsolute(server.Key("static_root_path").String(), HomePath)
RouterLogging = server.Key("router_logging").MustBool(false) RouterLogging = server.Key("router_logging").MustBool(false)
EnableGzip = server.Key("enable_gzip").MustBool(false) EnableGzip = server.Key("enable_gzip").MustBool(false)
EnforceDomain = server.Key("enforce_domain").MustBool(false)
security := Cfg.Section("security") security := Cfg.Section("security")
SecretKey = security.Key("secret_key").String() SecretKey = security.Key("secret_key").String()