|
|
|
|
@ -10,25 +10,22 @@ import ( |
|
|
|
|
"strings" |
|
|
|
|
|
|
|
|
|
"github.com/grafana/grafana/pkg/infra/log" |
|
|
|
|
"github.com/grafana/grafana/pkg/models" |
|
|
|
|
"github.com/grafana/grafana/pkg/services/contexthandler" |
|
|
|
|
"github.com/grafana/grafana/pkg/setting" |
|
|
|
|
macaron "gopkg.in/macaron.v1" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// AddCSPHeader adds the Content Security Policy header.
|
|
|
|
|
func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) macaron.Handler { |
|
|
|
|
return func(w http.ResponseWriter, req *http.Request, c *macaron.Context) { |
|
|
|
|
func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) func(http.Handler) http.Handler { |
|
|
|
|
return func(next http.Handler) http.Handler { |
|
|
|
|
return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { |
|
|
|
|
if !cfg.CSPEnabled { |
|
|
|
|
next.ServeHTTP(rw, req) |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
logger.Debug("Adding CSP header to response", "cfg", fmt.Sprintf("%p", cfg)) |
|
|
|
|
|
|
|
|
|
ctx, ok := c.Data["ctx"].(*models.ReqContext) |
|
|
|
|
if !ok { |
|
|
|
|
panic("Failed to convert context into models.ReqContext") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ctx := contexthandler.FromContext(req.Context()) |
|
|
|
|
if cfg.CSPTemplate == "" { |
|
|
|
|
logger.Debug("CSP template not configured, so returning 500") |
|
|
|
|
ctx.JsonApiErr(500, "CSP template has to be configured", nil) |
|
|
|
|
@ -47,8 +44,10 @@ func AddCSPHeader(cfg *setting.Cfg, logger log.Logger) macaron.Handler { |
|
|
|
|
re := regexp.MustCompile(`^\w+:(//)?`) |
|
|
|
|
rootPath := re.ReplaceAllString(cfg.AppURL, "") |
|
|
|
|
val = strings.ReplaceAll(val, "$ROOT_PATH", rootPath) |
|
|
|
|
w.Header().Set("Content-Security-Policy", val) |
|
|
|
|
rw.Header().Set("Content-Security-Policy", val) |
|
|
|
|
ctx.RequestNonce = nonce |
|
|
|
|
logger.Debug("Successfully generated CSP nonce", "nonce", nonce) |
|
|
|
|
next.ServeHTTP(rw, req) |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|