grafana/pkg/api/swagger.go
Josh Hunt a0b99e0039
CSP: Add configurable form-action directive via $FORM_ACTION_ADDITIONAL_HOSTS (#121473)
* CSP: Add configurable form-action directive via $FORM_ACTION_ADDITIONAL_HOSTS

Add support for customising the CSP form-action directive through a new
`[security] form_action_additional_hosts` config setting. The setting
specifies additional hosts beyond 'self' (which should be included
directly in the CSP template).

The new $FORM_ACTION_ADDITIONAL_HOSTS template variable is replaced with
the configured hosts, or empty string when unset.

Supported in both the standard Grafana codepath and the frontend service
codepath, where it can be overridden per-tenant via the settings service.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* split config on space instead of comma, aligned with allow_embedded_hosts

* fix integration test

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 15:42:40 +00:00

44 lines
1.3 KiB
Go

package api
import (
"net/http"
"github.com/grafana/grafana/pkg/api/routing"
"github.com/grafana/grafana/pkg/api/webassets"
"github.com/grafana/grafana/pkg/middleware"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/util/errhttp"
)
func (hs *HTTPServer) registerSwaggerUI(r routing.RouteRegister) {
// Deprecated
r.Get("/swagger-ui", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "swagger", http.StatusMovedPermanently)
})
// Deprecated
r.Get("/openapi3", func(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, "swagger", http.StatusMovedPermanently)
})
// The swagger based api navigator
r.Get("/swagger", func(c *contextmodel.ReqContext) {
ctx := c.Req.Context()
assets, err := webassets.GetWebAssets(ctx, hs.Cfg, hs.License)
if err != nil {
errhttp.Write(ctx, err, c.Resp)
return
}
data := map[string]any{
"Nonce": c.RequestNonce,
"Assets": assets,
}
if hs.Cfg.CSPEnabled {
data["CSPEnabled"] = true
hosts := middleware.CSPHostLists{FormActionAdditionalHosts: hs.Cfg.FormActionAdditionalHosts}
data["CSPContent"] = middleware.ReplacePolicyVariables(hs.Cfg.CSPTemplate, hs.Cfg.AppURL, hosts, c.RequestNonce)
}
c.HTML(http.StatusOK, "swagger", data)
})
}