mirror of
https://github.com/grafana/grafana.git
synced 2026-09-05 04:40:13 -05:00
Security: Add new setting allow_embedding (#16853)
When allow_embedding is false (default) the Grafana backend will set the http header `X-Frame-Options: deny` in all responses to non-static content which will instruct browser to not allow Grafana to be embedded in `<frame>`, `<iframe>`, `<embed>` or `<object>`. Closes #14189
This commit is contained in:
@@ -176,6 +176,9 @@ cookie_secure = false
|
||||
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none"
|
||||
cookie_samesite = lax
|
||||
|
||||
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
|
||||
allow_embedding = false
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
|
||||
@@ -172,6 +172,9 @@ log_queries =
|
||||
# set cookie SameSite attribute. defaults to `lax`. can be set to "lax", "strict" and "none"
|
||||
;cookie_samesite = lax
|
||||
|
||||
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
|
||||
;allow_embedding = false
|
||||
|
||||
#################################### Snapshots ###########################
|
||||
[snapshots]
|
||||
# snapshot sharing options
|
||||
|
||||
@@ -314,6 +314,12 @@ Set to `true` if you host Grafana behind HTTPS. Default is `false`.
|
||||
|
||||
Sets the `SameSite` cookie attribute and prevents the browser from sending this cookie along with cross-site requests. The main goal is mitigate the risk of cross-origin information leakage. It also provides some protection against cross-site request forgery attacks (CSRF), [read more here](https://www.owasp.org/index.php/SameSite). Valid values are `lax`, `strict` and `none`. Default is `lax`.
|
||||
|
||||
### allow_embedding
|
||||
|
||||
When `false`, the HTTP header `X-Frame-Options: deny` will be set in Grafana HTTP responses which will instruct
|
||||
browsers to not allow rendering Grafana in a `<frame>`, `<iframe>`, `<embed>` or `<object>`. The main goal is to
|
||||
mitigate the risk of [Clickjacking](https://www.owasp.org/index.php/Clickjacking). Default is `false`.
|
||||
|
||||
<hr />
|
||||
|
||||
## [users]
|
||||
|
||||
@@ -152,6 +152,8 @@ The default cookie name for storing the auth token is `grafana_session`. you can
|
||||
|
||||
## Upgrading to v6.2
|
||||
|
||||
### Ensure encryption of datasource secrets
|
||||
|
||||
Datasources store passwords and basic auth passwords in secureJsonData encrypted by default. Existing datasource
|
||||
will keep working with unencrypted passwords. If you want to migrate to encrypted storage for your existing datasources
|
||||
you can do that by:
|
||||
@@ -160,3 +162,9 @@ password and save the datasource.
|
||||
- For datasources created by provisioning, you need to update your config file and use secureJsonData.password or
|
||||
secureJsonData.basicAuthPassword field. See [provisioning docs](/administration/provisioning) for example of current
|
||||
configuration.
|
||||
|
||||
### Embedding Grafana
|
||||
|
||||
If you're embedding Grafana in a `<frame>`, `<iframe>`, `<embed>` or `<object>` on a different website it will no longer work due to a new setting
|
||||
that per default instructs the browser to not allow Grafana to be embedded. Read more [here](/installation/configuration/#allow-embedding) about
|
||||
this new setting.
|
||||
|
||||
@@ -237,6 +237,10 @@ func AddDefaultResponseHeaders() macaron.Handler {
|
||||
if !strings.HasPrefix(ctx.Req.URL.Path, "/api/datasources/proxy/") {
|
||||
AddNoCacheHeaders(ctx.Resp)
|
||||
}
|
||||
|
||||
if !setting.AllowEmbedding {
|
||||
AddXFrameOptionsDenyHeader(w)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -246,3 +250,7 @@ func AddNoCacheHeaders(w macaron.ResponseWriter) {
|
||||
w.Header().Add("Pragma", "no-cache")
|
||||
w.Header().Add("Expires", "-1")
|
||||
}
|
||||
|
||||
func AddXFrameOptionsDenyHeader(w macaron.ResponseWriter) {
|
||||
w.Header().Add("X-Frame-Options", "deny")
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
So(sc.resp.Header().Get("Expires"), ShouldBeEmpty)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should add Cache-Control header for GET requests with html response", func(sc *scenarioContext) {
|
||||
middlewareScenario(t, "middleware should add Cache-Control header for requests with html response", func(sc *scenarioContext) {
|
||||
sc.handler(func(c *m.ReqContext) {
|
||||
data := &dtos.IndexViewData{
|
||||
User: &dtos.CurrentUser{},
|
||||
@@ -65,6 +65,17 @@ func TestMiddlewareContext(t *testing.T) {
|
||||
So(sc.resp.Header().Get("Expires"), ShouldEqual, "-1")
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should add X-Frame-Options header with deny for request when not allowing embedding", func(sc *scenarioContext) {
|
||||
sc.fakeReq("GET", "/api/search").exec()
|
||||
So(sc.resp.Header().Get("X-Frame-Options"), ShouldEqual, "deny")
|
||||
})
|
||||
|
||||
middlewareScenario(t, "middleware should not add X-Frame-Options header for request when allowing embedding", func(sc *scenarioContext) {
|
||||
setting.AllowEmbedding = true
|
||||
sc.fakeReq("GET", "/api/search").exec()
|
||||
So(sc.resp.Header().Get("X-Frame-Options"), ShouldBeEmpty)
|
||||
})
|
||||
|
||||
middlewareScenario(t, "Invalid api key", func(sc *scenarioContext) {
|
||||
sc.apiKey = "invalid_key_test"
|
||||
sc.fakeReq("GET", "/").exec()
|
||||
|
||||
@@ -93,6 +93,7 @@ var (
|
||||
DisableBruteForceLoginProtection bool
|
||||
CookieSecure bool
|
||||
CookieSameSite http.SameSite
|
||||
AllowEmbedding bool
|
||||
|
||||
// Snapshots
|
||||
ExternalSnapshotUrl string
|
||||
@@ -690,6 +691,8 @@ func (cfg *Cfg) Load(args *CommandLineArgs) error {
|
||||
cfg.CookieSameSite = CookieSameSite
|
||||
}
|
||||
|
||||
AllowEmbedding = security.Key("allow_embedding").MustBool(false)
|
||||
|
||||
// read snapshots settings
|
||||
snapshots := iniFile.Section("snapshots")
|
||||
ExternalSnapshotUrl, err = valueAsString(snapshots, "external_snapshot_url", "")
|
||||
|
||||
Reference in New Issue
Block a user