Plugins: Add token to gcom requests (#96261)

pull/96992/head^2
Hugo Kiyodi Oshiro 7 months ago committed by GitHub
parent 3b8499eaee
commit a8174f9285
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      pkg/api/grafana_com_proxy.go
  2. 4
      pkg/plugins/config/config.go
  3. 16
      pkg/plugins/repo/client.go
  4. 18
      pkg/plugins/repo/client_test.go
  5. 4
      pkg/plugins/repo/service.go
  6. 1
      pkg/services/pluginsintegration/pluginconfig/config.go

@ -23,7 +23,7 @@ var grafanaComProxyTransport = &http.Transport{
TLSHandshakeTimeout: 10 * time.Second, TLSHandshakeTimeout: 10 * time.Second,
} }
func ReverseProxyGnetReq(logger log.Logger, proxyPath string, version string, grafanaComAPIUrl string) *httputil.ReverseProxy { func ReverseProxyGnetReq(logger log.Logger, proxyPath, version, grafanaComAPIUrl, grafanaComAPIToken string) *httputil.ReverseProxy {
url, _ := url.Parse(grafanaComAPIUrl) url, _ := url.Parse(grafanaComAPIUrl)
director := func(req *http.Request) { director := func(req *http.Request) {
@ -40,6 +40,10 @@ func ReverseProxyGnetReq(logger log.Logger, proxyPath string, version string, gr
// send the current Grafana version for each request proxied to GCOM // send the current Grafana version for each request proxied to GCOM
req.Header.Add("grafana-version", version) req.Header.Add("grafana-version", version)
if grafanaComAPIToken != "" {
req.Header.Set("Authorization", "Bearer "+grafanaComAPIToken)
}
} }
return proxyutil.NewReverseProxy(logger, director) return proxyutil.NewReverseProxy(logger, director)
@ -47,7 +51,7 @@ func ReverseProxyGnetReq(logger log.Logger, proxyPath string, version string, gr
func (hs *HTTPServer) ProxyGnetRequest(c *contextmodel.ReqContext) { func (hs *HTTPServer) ProxyGnetRequest(c *contextmodel.ReqContext) {
proxyPath := web.Params(c.Req)["*"] proxyPath := web.Params(c.Req)["*"]
proxy := ReverseProxyGnetReq(c.Logger, proxyPath, hs.Cfg.BuildVersion, hs.Cfg.GrafanaComAPIURL) proxy := ReverseProxyGnetReq(c.Logger, proxyPath, hs.Cfg.BuildVersion, hs.Cfg.GrafanaComAPIURL, hs.Cfg.PluginInstallToken)
proxy.Transport = grafanaComProxyTransport proxy.Transport = grafanaComProxyTransport
proxy.ServeHTTP(c.Resp, c.Req) proxy.ServeHTTP(c.Resp, c.Req)
} }

@ -19,6 +19,7 @@ type PluginManagementCfg struct {
PluginsCDNURLTemplate string PluginsCDNURLTemplate string
GrafanaComAPIURL string GrafanaComAPIURL string
GrafanaComAPIToken string
GrafanaAppURL string GrafanaAppURL string
@ -38,7 +39,7 @@ type Features struct {
// NewPluginManagementCfg returns a new PluginManagementCfg. // NewPluginManagementCfg returns a new PluginManagementCfg.
func NewPluginManagementCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string, func NewPluginManagementCfg(devMode bool, pluginsPath string, pluginSettings setting.PluginSettings, pluginsAllowUnsigned []string,
pluginsCDNURLTemplate string, appURL string, features Features, angularSupportEnabled bool, pluginsCDNURLTemplate string, appURL string, features Features, angularSupportEnabled bool,
grafanaComAPIURL string, disablePlugins []string, hideAngularDeprecation []string, forwardHostEnvVars []string, grafanaComAPIURL string, disablePlugins []string, hideAngularDeprecation []string, forwardHostEnvVars []string, grafanaComAPIToken string,
) *PluginManagementCfg { ) *PluginManagementCfg {
return &PluginManagementCfg{ return &PluginManagementCfg{
PluginsPath: pluginsPath, PluginsPath: pluginsPath,
@ -53,5 +54,6 @@ func NewPluginManagementCfg(devMode bool, pluginsPath string, pluginSettings set
AngularSupportEnabled: angularSupportEnabled, AngularSupportEnabled: angularSupportEnabled,
HideAngularDeprecation: hideAngularDeprecation, HideAngularDeprecation: hideAngularDeprecation,
ForwardHostEnvVars: forwardHostEnvVars, ForwardHostEnvVars: forwardHostEnvVars,
GrafanaComAPIToken: grafanaComAPIToken,
} }
} }

@ -23,15 +23,17 @@ type Client struct {
httpClient http.Client httpClient http.Client
httpClientNoTimeout http.Client httpClientNoTimeout http.Client
retryCount int retryCount int
grafanaComAPIToken string
log log.PrettyLogger log log.PrettyLogger
} }
func NewClient(skipTLSVerify bool, logger log.PrettyLogger) *Client { func NewClient(skipTLSVerify bool, grafanaComAPIToken string, logger log.PrettyLogger) *Client {
return &Client{ return &Client{
httpClient: MakeHttpClient(skipTLSVerify, 10*time.Second), httpClient: MakeHttpClient(skipTLSVerify, 10*time.Second),
httpClientNoTimeout: MakeHttpClient(skipTLSVerify, 0), httpClientNoTimeout: MakeHttpClient(skipTLSVerify, 0),
log: logger, log: logger,
grafanaComAPIToken: grafanaComAPIToken,
} }
} }
@ -153,6 +155,14 @@ func (c *Client) downloadFile(ctx context.Context, tmpFile *os.File, pluginURL,
// Note: This is also used as part of the grafana plugin install CLI operation // Note: This is also used as part of the grafana plugin install CLI operation
bodyReader, err := c.sendReqNoTimeout(ctx, u, compatOpts) bodyReader, err := c.sendReqNoTimeout(ctx, u, compatOpts)
if err != nil { if err != nil {
var errResp ErrResponse4xx
if errors.As(err, &errResp) {
if errResp.StatusCode() == 401 {
c.log.Error("Unauthorized download plugin", "error", err)
return err
}
}
if c.retryCount < 3 { if c.retryCount < 3 {
c.retryCount++ c.retryCount++
c.log.Debug("Failed downloading. Will retry.") c.log.Debug("Failed downloading. Will retry.")
@ -223,6 +233,10 @@ func (c *Client) createReq(ctx context.Context, url *url.URL, compatOpts CompatO
req.Header.Set("grafana-origin", orig.(string)) req.Header.Set("grafana-origin", orig.(string))
} }
if c.grafanaComAPIToken != "" {
req.Header.Set("Authorization", "Bearer "+c.grafanaComAPIToken)
}
return req, err return req, err
} }

@ -69,4 +69,22 @@ func Test_Download(t *testing.T) {
require.NoError(t, err) require.NoError(t, err)
require.Equal(t, 2, count, "should retry on error") require.Equal(t, 2, count, "should retry on error")
}) })
t.Run("it should use gcom token when it's available", func(t *testing.T) {
expectedToken := "token-test"
var gcomCalled bool
fakeServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
require.Equal(t, "Bearer "+expectedToken, token, "gcom token should be set")
err := writeFakeZip(w)
require.NoError(t, err)
gcomCalled = true
}))
defer fakeServer.Close()
cli := fakeServer.Client()
repo := Client{httpClient: *cli, httpClientNoTimeout: *cli, log: log.NewPrettyLogger("test"), grafanaComAPIToken: expectedToken}
_, err := repo.Download(context.Background(), fakeServer.URL, "", CompatOpts{})
require.NoError(t, err)
require.True(t, gcomCalled)
})
} }

@ -30,19 +30,21 @@ func ProvideService(cfg *config.PluginManagementCfg) (*Manager, error) {
SkipTLSVerify: false, SkipTLSVerify: false,
BaseURL: baseURL, BaseURL: baseURL,
Logger: log.NewPrettyLogger("plugin.repository"), Logger: log.NewPrettyLogger("plugin.repository"),
GrafanaComAPIToken: cfg.GrafanaComAPIToken,
}), nil }), nil
} }
type ManagerCfg struct { type ManagerCfg struct {
SkipTLSVerify bool SkipTLSVerify bool
BaseURL string BaseURL string
GrafanaComAPIToken string
Logger log.PrettyLogger Logger log.PrettyLogger
} }
func NewManager(cfg ManagerCfg) *Manager { func NewManager(cfg ManagerCfg) *Manager {
return &Manager{ return &Manager{
baseURL: cfg.BaseURL, baseURL: cfg.BaseURL,
client: NewClient(cfg.SkipTLSVerify, cfg.Logger), client: NewClient(cfg.SkipTLSVerify, cfg.GrafanaComAPIToken, cfg.Logger),
log: cfg.Logger, log: cfg.Logger,
} }
} }

@ -39,6 +39,7 @@ func ProvidePluginManagementConfig(cfg *setting.Cfg, settingProvider setting.Pro
cfg.DisablePlugins, cfg.DisablePlugins,
cfg.HideAngularDeprecation, cfg.HideAngularDeprecation,
cfg.ForwardHostEnvVars, cfg.ForwardHostEnvVars,
cfg.PluginInstallToken,
), nil ), nil
} }

Loading…
Cancel
Save