grafana/pkg/api/plugin_proxy.go
Karl Persson 684d68365e
IDforwarding: forward signed id to plugins (#75651)
* Plugins: Add client middlware that forwards the signed grafana id token if present

* DsProxy: Set grafana id header if id token exists

* Add util function to apply id token to header

* Only add id forwarding middleware if feature toggle is enabled

* Add feature toggles to ds proxy and check if id forwarding is enabled

* Clean up test setup

* Change to use backend.ForwardHTTPHeaders interface

* PluginProxy: Forward signed identity when feature toggle is enabled

* PluginProxy: forrward signed id header
2023-10-02 09:14:10 +02:00

72 lines
2.0 KiB
Go

package api
import (
"crypto/tls"
"net"
"net/http"
"regexp"
"sync"
"time"
"github.com/grafana/grafana/pkg/api/pluginproxy"
contextmodel "github.com/grafana/grafana/pkg/services/contexthandler/model"
"github.com/grafana/grafana/pkg/services/pluginsintegration/pluginsettings"
"github.com/grafana/grafana/pkg/web"
)
var (
once sync.Once
pluginProxyTransport *http.Transport
)
func (hs *HTTPServer) ProxyPluginRequest(c *contextmodel.ReqContext) {
once.Do(func() {
pluginProxyTransport = &http.Transport{
TLSClientConfig: &tls.Config{
InsecureSkipVerify: hs.Cfg.PluginsAppsSkipVerifyTLS,
Renegotiation: tls.RenegotiateFreelyAsClient,
},
Proxy: http.ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).DialContext,
TLSHandshakeTimeout: 10 * time.Second,
}
})
pluginID := web.Params(c.Req)[":pluginId"]
plugin, exists := hs.pluginStore.Plugin(c.Req.Context(), pluginID)
if !exists {
c.JsonApiErr(http.StatusNotFound, "Plugin not found, no installed plugin with that id", nil)
return
}
query := pluginsettings.GetByPluginIDArgs{OrgID: c.OrgID, PluginID: plugin.ID}
ps, err := hs.PluginSettings.GetPluginSettingByPluginID(c.Req.Context(), &query)
if err != nil {
c.JsonApiErr(http.StatusInternalServerError, "Failed to fetch plugin settings", err)
return
}
proxyPath := getProxyPath(c)
p, err := pluginproxy.NewPluginProxy(ps, plugin.Routes, c, proxyPath, hs.Cfg, hs.SecretsService, hs.tracer, pluginProxyTransport, hs.Features)
if err != nil {
c.JsonApiErr(http.StatusInternalServerError, "Failed to create plugin proxy", err)
return
}
p.HandleRequest()
}
var pluginProxyPathRegexp = regexp.MustCompile(`^\/api\/plugin-proxy\/([\w\-]+)\/?`)
func extractProxyPath(originalRawPath string) string {
return pluginProxyPathRegexp.ReplaceAllString(originalRawPath, "")
}
func getProxyPath(c *contextmodel.ReqContext) string {
return extractProxyPath(c.Req.URL.EscapedPath())
}