Allow Iframes on Grafana with Traefik (Docker)
Overview
This document aims to show how to allow embedding iframes of panels from Grafana. However there’s a couple warnings.
- For the embed to work, Grafana must be open to the world and configured with SSL
- SameSite must be set to ‘none’ therefore, some CSRF attacks are feasible
- Even after embedding, loggin to grafana is mandatory so all users which access this iframe, must have a grafana user
- SSL configuration is mandatory since cookie_secure is set to True
- On how to get the iframe to display on the webpage, refer to this link
Configuring traefik
So, with the default configuration you will get an error similar to this one: Refused to display '[<https://my-domain.com/>](<https://my-domain.com>)' in a frame because it set 'X-Frame-Options' to 'deny'.
Do not waste time configuring traefik to not Deny X-Frame-Options
since it’s deprecated, instead what we are going to configure is Content-Security-Policy and in this case, we are going to configure it with the frame-ancestors options, so in traefik it will look like this:
- "traefik.http.middlewares.frame.headers.contentSecurityPolicy=frame-ancestors https://my-domain.com https://*.my-other-domain.com"
This will allow the domains listed to load contents from grafana
ℹ️ When using CSP instead, the usage of X-Frame-Options gets overridden
We also need to configure via labels, that grafana HTTP router on traefik, uses this middleware, so at the end it will look like this:
- "traefik.http.middlewares.frame.headers.contentSecurityPolicy=frame-ancestors https://my-domain.com https://*.my-other-domain.com"
- "traefik.http.routers.grafana.middlewares=frame"
⚠️ Note: you need to configure these labels on grafana container in docker-compose.yml
⚠️ Note: on traefik.http.routers.grafana.middlewares
grafana is the name of the router you are assigning the middleware, this might change depending on the set-up
Confirm that you are using the middleware
Refer to your Traefik dashboard, and search for the grafana router, you should see a middleware attached to it like this:
Configuring Grafana
For grafana, it depends, in this case we are going to add the configuration as env variables, here you have what you need:
- GF_SECURITY_ALLOW_EMBEDDING=true
- GF_SECURITY_COOKIE_SAMESITE=none
- GF_SECURITY_COOKIE_SECURE=true
GF_SECURITY_ALLOW_EMBEDDING
: allows usage of iframesGF_SECURITY_COOKIE_SAMESITE
: this cookies controls how content can be displayed, default is “lax” which only allows embedding content when is displayed inside the same domain. Setting it to “none” allows us to show from everywhere embedded content (this, by default is a security hole, but we control with traefik which domains can display content from grafana)GF_SECURITY_COOKIE_SECURE
: this setting only allows set-cookie if the site works through SSL, without this option, embedding will work on firefox, but not on chrome.
Results
I’ve tested the configuration, using a docker container with nginx serving a static page with the iframe I want so show, remember is important that SSL is configured, and if possible, with a valid certificate.
Results:
Sources
- CSP Docs: CSP: frame-ancestors — HTTP | MDN
- Grafana config: How to authenticate and embedded Grafana charts into iframe?
- CSP vs X-Frame: does not work in iframe · Issue #6 · rmountjoy92/DashMachine