1package middleware
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/grafana/grafana/pkg/models"
8	"github.com/grafana/grafana/pkg/setting"
9	"github.com/grafana/grafana/pkg/web"
10)
11
12var (
13	ReqGrafanaAdmin = Auth(&AuthOptions{
14		ReqSignedIn:     true,
15		ReqGrafanaAdmin: true,
16	})
17	ReqSignedIn            = Auth(&AuthOptions{ReqSignedIn: true})
18	ReqSignedInNoAnonymous = Auth(&AuthOptions{ReqSignedIn: true, ReqNoAnonynmous: true})
19	ReqEditorRole          = RoleAuth(models.ROLE_EDITOR, models.ROLE_ADMIN)
20	ReqOrgAdmin            = RoleAuth(models.ROLE_ADMIN)
21)
22
23func HandleNoCacheHeader(ctx *models.ReqContext) {
24	ctx.SkipCache = ctx.Req.Header.Get("X-Grafana-NoCache") == "true"
25}
26
27func AddDefaultResponseHeaders(cfg *setting.Cfg) web.Handler {
28	return func(c *web.Context) {
29		c.Resp.Before(func(w web.ResponseWriter) {
30			// if response has already been written, skip.
31			if w.Written() {
32				return
33			}
34
35			if !strings.HasPrefix(c.Req.URL.Path, "/api/datasources/proxy/") {
36				addNoCacheHeaders(c.Resp)
37			}
38
39			if !cfg.AllowEmbedding {
40				addXFrameOptionsDenyHeader(w)
41			}
42
43			addSecurityHeaders(w, cfg)
44		})
45	}
46}
47
48// addSecurityHeaders adds HTTP(S) response headers that enable various security protections in the client's browser.
49func addSecurityHeaders(w web.ResponseWriter, cfg *setting.Cfg) {
50	if (cfg.Protocol == setting.HTTPSScheme || cfg.Protocol == setting.HTTP2Scheme) && cfg.StrictTransportSecurity {
51		strictHeaderValues := []string{fmt.Sprintf("max-age=%v", cfg.StrictTransportSecurityMaxAge)}
52		if cfg.StrictTransportSecurityPreload {
53			strictHeaderValues = append(strictHeaderValues, "preload")
54		}
55		if cfg.StrictTransportSecuritySubDomains {
56			strictHeaderValues = append(strictHeaderValues, "includeSubDomains")
57		}
58		w.Header().Set("Strict-Transport-Security", strings.Join(strictHeaderValues, "; "))
59	}
60
61	if cfg.ContentTypeProtectionHeader {
62		w.Header().Set("X-Content-Type-Options", "nosniff")
63	}
64
65	if cfg.XSSProtectionHeader {
66		w.Header().Set("X-XSS-Protection", "1; mode=block")
67	}
68}
69
70func addNoCacheHeaders(w web.ResponseWriter) {
71	w.Header().Set("Cache-Control", "no-cache")
72	w.Header().Set("Pragma", "no-cache")
73	w.Header().Set("Expires", "-1")
74}
75
76func addXFrameOptionsDenyHeader(w web.ResponseWriter) {
77	w.Header().Set("X-Frame-Options", "deny")
78}
79