mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Plugins: Periodically update public signing key (#70080)
This commit is contained in:
committed by
GitHub
parent
62ee1fa05a
commit
7c1c196031
@@ -1399,8 +1399,11 @@ plugin_catalog_url = https://grafana.com/grafana/plugins/
|
|||||||
plugin_catalog_hidden_plugins =
|
plugin_catalog_hidden_plugins =
|
||||||
# Log all backend requests for core and external plugins.
|
# Log all backend requests for core and external plugins.
|
||||||
log_backend_requests = false
|
log_backend_requests = false
|
||||||
# Force download of public key for verifying plugin signature on startup.
|
# Disable download of the public key for verifying plugin signature.
|
||||||
enforce_public_key_download = false
|
public_key_retrieval_disabled = false
|
||||||
|
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
||||||
|
# Requires public_key_retrieval_disabled to be false to have any effect.
|
||||||
|
public_key_retrieval_on_startup = false
|
||||||
|
|
||||||
#################################### Grafana Live ##########################################
|
#################################### Grafana Live ##########################################
|
||||||
[live]
|
[live]
|
||||||
|
|||||||
@@ -1326,8 +1326,11 @@
|
|||||||
;plugin_catalog_hidden_plugins =
|
;plugin_catalog_hidden_plugins =
|
||||||
# Log all backend requests for core and external plugins.
|
# Log all backend requests for core and external plugins.
|
||||||
;log_backend_requests = false
|
;log_backend_requests = false
|
||||||
# Force download of public key for verifying plugin signature on startup.
|
# Disable download of the public key for verifying plugin signature.
|
||||||
;enforce_public_key_download = false
|
; public_key_retrieval_disabled = false
|
||||||
|
# Force download of the public key for verifying plugin signature on startup. If disabled, the public key will be retrieved every 10 days.
|
||||||
|
# Requires public_key_retrieval_disabled to be false to have any effect.
|
||||||
|
; public_key_retrieval_on_startup = false
|
||||||
|
|
||||||
#################################### Grafana Live ##########################################
|
#################################### Grafana Live ##########################################
|
||||||
[live]
|
[live]
|
||||||
|
|||||||
@@ -2033,6 +2033,14 @@ Custom install/learn more URL for enterprise plugins. Defaults to https://grafan
|
|||||||
|
|
||||||
Enter a comma-separated list of plugin identifiers to hide in the plugin catalog.
|
Enter a comma-separated list of plugin identifiers to hide in the plugin catalog.
|
||||||
|
|
||||||
|
### public_key_retrieval_disabled
|
||||||
|
|
||||||
|
Disable download of the public key for verifying plugin signature. The default is `false`. If disabled, it will use the hardcoded public key.
|
||||||
|
|
||||||
|
### public_key_retrieval_on_startup
|
||||||
|
|
||||||
|
Force download of the public key for verifying plugin signature on startup. The default is `false`. If disabled, the public key will be retrieved every 10 days. Requires `public_key_retrieval_disabled` to be false to have any effect.
|
||||||
|
|
||||||
<hr>
|
<hr>
|
||||||
|
|
||||||
## [live]
|
## [live]
|
||||||
|
|||||||
@@ -108,7 +108,6 @@ Experimental features might be changed or removed without prior notice.
|
|||||||
| `alertStateHistoryLokiOnly` | Disable Grafana alerts from emitting annotations when a remote Loki instance is available. |
|
| `alertStateHistoryLokiOnly` | Disable Grafana alerts from emitting annotations when a remote Loki instance is available. |
|
||||||
| `unifiedRequestLog` | Writes error logs to the request logger |
|
| `unifiedRequestLog` | Writes error logs to the request logger |
|
||||||
| `pyroscopeFlameGraph` | Changes flame graph to pyroscope one |
|
| `pyroscopeFlameGraph` | Changes flame graph to pyroscope one |
|
||||||
| `pluginsAPIManifestKey` | Use grafana.com API to retrieve the public manifest key |
|
|
||||||
| `extraThemes` | Enables extra themes |
|
| `extraThemes` | Enables extra themes |
|
||||||
| `lokiPredefinedOperations` | Adds predefined query operations to Loki query editor |
|
| `lokiPredefinedOperations` | Adds predefined query operations to Loki query editor |
|
||||||
| `pluginsFrontendSandbox` | Enables the plugins frontend sandbox |
|
| `pluginsFrontendSandbox` | Enables the plugins frontend sandbox |
|
||||||
|
|||||||
@@ -90,7 +90,6 @@ export interface FeatureToggles {
|
|||||||
refactorVariablesTimeRange?: boolean;
|
refactorVariablesTimeRange?: boolean;
|
||||||
useCachingService?: boolean;
|
useCachingService?: boolean;
|
||||||
enableElasticsearchBackendQuerying?: boolean;
|
enableElasticsearchBackendQuerying?: boolean;
|
||||||
pluginsAPIManifestKey?: boolean;
|
|
||||||
advancedDataSourcePicker?: boolean;
|
advancedDataSourcePicker?: boolean;
|
||||||
faroDatasourceSelector?: boolean;
|
faroDatasourceSelector?: boolean;
|
||||||
enableDatagridEditing?: boolean;
|
enableDatagridEditing?: boolean;
|
||||||
|
|||||||
@@ -487,12 +487,6 @@ var (
|
|||||||
Stage: FeatureStagePublicPreview,
|
Stage: FeatureStagePublicPreview,
|
||||||
Owner: grafanaObservabilityLogsSquad,
|
Owner: grafanaObservabilityLogsSquad,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
Name: "pluginsAPIManifestKey",
|
|
||||||
Description: "Use grafana.com API to retrieve the public manifest key",
|
|
||||||
Stage: FeatureStageExperimental,
|
|
||||||
Owner: grafanaPluginsPlatformSquad,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
Name: "advancedDataSourcePicker",
|
Name: "advancedDataSourcePicker",
|
||||||
Description: "Enable a new data source picker with contextual information, recently used order and advanced mode",
|
Description: "Enable a new data source picker with contextual information, recently used order and advanced mode",
|
||||||
|
|||||||
@@ -71,7 +71,6 @@ externalServiceAuth,experimental,@grafana/grafana-authnz-team,true,false,false,f
|
|||||||
refactorVariablesTimeRange,preview,@grafana/dashboards-squad,false,false,false,false
|
refactorVariablesTimeRange,preview,@grafana/dashboards-squad,false,false,false,false
|
||||||
useCachingService,GA,@grafana/grafana-operator-experience-squad,false,false,true,false
|
useCachingService,GA,@grafana/grafana-operator-experience-squad,false,false,true,false
|
||||||
enableElasticsearchBackendQuerying,preview,@grafana/observability-logs,false,false,false,false
|
enableElasticsearchBackendQuerying,preview,@grafana/observability-logs,false,false,false,false
|
||||||
pluginsAPIManifestKey,experimental,@grafana/plugins-platform-backend,false,false,false,false
|
|
||||||
advancedDataSourcePicker,GA,@grafana/dashboards-squad,false,false,false,true
|
advancedDataSourcePicker,GA,@grafana/dashboards-squad,false,false,false,true
|
||||||
faroDatasourceSelector,preview,@grafana/app-o11y,false,false,false,true
|
faroDatasourceSelector,preview,@grafana/app-o11y,false,false,false,true
|
||||||
enableDatagridEditing,preview,@grafana/grafana-bi-squad,false,false,false,true
|
enableDatagridEditing,preview,@grafana/grafana-bi-squad,false,false,false,true
|
||||||
|
|||||||
|
@@ -295,10 +295,6 @@ const (
|
|||||||
// Enable the processing of queries and responses in the Elasticsearch data source through backend
|
// Enable the processing of queries and responses in the Elasticsearch data source through backend
|
||||||
FlagEnableElasticsearchBackendQuerying = "enableElasticsearchBackendQuerying"
|
FlagEnableElasticsearchBackendQuerying = "enableElasticsearchBackendQuerying"
|
||||||
|
|
||||||
// FlagPluginsAPIManifestKey
|
|
||||||
// Use grafana.com API to retrieve the public manifest key
|
|
||||||
FlagPluginsAPIManifestKey = "pluginsAPIManifestKey"
|
|
||||||
|
|
||||||
// FlagAdvancedDataSourcePicker
|
// FlagAdvancedDataSourcePicker
|
||||||
// Enable a new data source picker with contextual information, recently used order and advanced mode
|
// Enable a new data source picker with contextual information, recently used order and advanced mode
|
||||||
FlagAdvancedDataSourcePicker = "advancedDataSourcePicker"
|
FlagAdvancedDataSourcePicker = "advancedDataSourcePicker"
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import (
|
|||||||
"github.com/grafana/grafana/pkg/plugins"
|
"github.com/grafana/grafana/pkg/plugins"
|
||||||
"github.com/grafana/grafana/pkg/plugins/log"
|
"github.com/grafana/grafana/pkg/plugins/log"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
|
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -29,9 +28,8 @@ type ManifestKeys struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type KeyRetriever struct {
|
type KeyRetriever struct {
|
||||||
cfg *setting.Cfg
|
cfg *setting.Cfg
|
||||||
log log.Logger
|
log log.Logger
|
||||||
flags featuremgmt.FeatureToggles
|
|
||||||
|
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
cli http.Client
|
cli http.Client
|
||||||
@@ -41,20 +39,19 @@ type KeyRetriever struct {
|
|||||||
|
|
||||||
var _ plugins.KeyRetriever = (*KeyRetriever)(nil)
|
var _ plugins.KeyRetriever = (*KeyRetriever)(nil)
|
||||||
|
|
||||||
func ProvideService(cfg *setting.Cfg, kv plugins.KeyStore, flags featuremgmt.FeatureToggles) *KeyRetriever {
|
func ProvideService(cfg *setting.Cfg, kv plugins.KeyStore) *KeyRetriever {
|
||||||
kr := &KeyRetriever{
|
kr := &KeyRetriever{
|
||||||
cfg: cfg,
|
cfg: cfg,
|
||||||
flags: flags,
|
log: log.New("plugin.signature.key_retriever"),
|
||||||
log: log.New("plugin.signature.key_retriever"),
|
cli: makeHttpClient(),
|
||||||
cli: makeHttpClient(),
|
kv: kv,
|
||||||
kv: kv,
|
|
||||||
}
|
}
|
||||||
return kr
|
return kr
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDisabled disables dynamic retrieval of public keys from the API server.
|
// IsDisabled disables dynamic retrieval of public keys from the API server.
|
||||||
func (kr *KeyRetriever) IsDisabled() bool {
|
func (kr *KeyRetriever) IsDisabled() bool {
|
||||||
return !kr.flags.IsEnabled(featuremgmt.FlagPluginsAPIManifestKey)
|
return kr.cfg.PluginSkipPublicKeyDownload
|
||||||
}
|
}
|
||||||
|
|
||||||
func (kr *KeyRetriever) Run(ctx context.Context) error {
|
func (kr *KeyRetriever) Run(ctx context.Context) error {
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -47,7 +46,7 @@ func Test_PublicKeyUpdate(t *testing.T) {
|
|||||||
expectedKey := "fake"
|
expectedKey := "fake"
|
||||||
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
||||||
cfg.GrafanaComURL = s.URL
|
cfg.GrafanaComURL = s.URL
|
||||||
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()), featuremgmt.WithFeatures(featuremgmt.FlagPluginsAPIManifestKey))
|
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()))
|
||||||
go func() {
|
go func() {
|
||||||
err := v.Run(context.Background())
|
err := v.Run(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -68,7 +67,7 @@ func Test_PublicKeyUpdate(t *testing.T) {
|
|||||||
expectedKey := "fake"
|
expectedKey := "fake"
|
||||||
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
||||||
cfg.GrafanaComURL = s.URL
|
cfg.GrafanaComURL = s.URL
|
||||||
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()), featuremgmt.WithFeatures(featuremgmt.FlagPluginsAPIManifestKey))
|
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()))
|
||||||
go func() {
|
go func() {
|
||||||
err := v.Run(context.Background())
|
err := v.Run(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -88,7 +87,7 @@ func Test_PublicKeyUpdate(t *testing.T) {
|
|||||||
expectedKey := "fake"
|
expectedKey := "fake"
|
||||||
s, done := setFakeAPIServer(t, expectedKey, "other")
|
s, done := setFakeAPIServer(t, expectedKey, "other")
|
||||||
cfg.GrafanaComURL = s.URL
|
cfg.GrafanaComURL = s.URL
|
||||||
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()), featuremgmt.WithFeatures(featuremgmt.FlagPluginsAPIManifestKey))
|
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()))
|
||||||
go func() {
|
go func() {
|
||||||
err := v.Run(context.Background())
|
err := v.Run(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -115,7 +114,7 @@ func Test_PublicKeyUpdate(t *testing.T) {
|
|||||||
expectedKey := "fake"
|
expectedKey := "fake"
|
||||||
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
s, done := setFakeAPIServer(t, expectedKey, "7e4d0c6a708866e7")
|
||||||
cfg.GrafanaComURL = s.URL
|
cfg.GrafanaComURL = s.URL
|
||||||
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()), featuremgmt.WithFeatures(featuremgmt.FlagPluginsAPIManifestKey))
|
v := ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()))
|
||||||
// Simulate an updated key
|
// Simulate an updated key
|
||||||
err := v.kv.SetLastUpdated(context.Background())
|
err := v.kv.SetLastUpdated(context.Background())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import (
|
|||||||
|
|
||||||
"github.com/grafana/grafana/pkg/infra/kvstore"
|
"github.com/grafana/grafana/pkg/infra/kvstore"
|
||||||
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
|
"github.com/grafana/grafana/pkg/plugins/manager/signature/statickey"
|
||||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/keyretriever/dynamic"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/keyretriever/dynamic"
|
||||||
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
"github.com/grafana/grafana/pkg/services/pluginsintegration/keystore"
|
||||||
"github.com/grafana/grafana/pkg/setting"
|
"github.com/grafana/grafana/pkg/setting"
|
||||||
@@ -16,7 +15,7 @@ import (
|
|||||||
func Test_GetPublicKey(t *testing.T) {
|
func Test_GetPublicKey(t *testing.T) {
|
||||||
t.Run("it should return a static key", func(t *testing.T) {
|
t.Run("it should return a static key", func(t *testing.T) {
|
||||||
cfg := &setting.Cfg{}
|
cfg := &setting.Cfg{}
|
||||||
kr := ProvideService(dynamic.ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore()), featuremgmt.WithFeatures()))
|
kr := ProvideService(dynamic.ProvideService(cfg, keystore.ProvideService(kvstore.NewFakeKVStore())))
|
||||||
key, err := kr.GetPublicKey(context.Background(), statickey.GetDefaultKeyID())
|
key, err := kr.GetPublicKey(context.Background(), statickey.GetDefaultKeyID())
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, statickey.GetDefaultKey(), key)
|
require.Equal(t, statickey.GetDefaultKey(), key)
|
||||||
|
|||||||
@@ -241,6 +241,7 @@ type Cfg struct {
|
|||||||
PluginAdminEnabled bool
|
PluginAdminEnabled bool
|
||||||
PluginAdminExternalManageEnabled bool
|
PluginAdminExternalManageEnabled bool
|
||||||
PluginForcePublicKeyDownload bool
|
PluginForcePublicKeyDownload bool
|
||||||
|
PluginSkipPublicKeyDownload bool
|
||||||
|
|
||||||
PluginsCDNURLTemplate string
|
PluginsCDNURLTemplate string
|
||||||
PluginLogBackendRequests bool
|
PluginLogBackendRequests bool
|
||||||
|
|||||||
@@ -30,7 +30,8 @@ func (cfg *Cfg) readPluginSettings(iniFile *ini.File) error {
|
|||||||
cfg.PluginsEnableAlpha = pluginsSection.Key("enable_alpha").MustBool(false)
|
cfg.PluginsEnableAlpha = pluginsSection.Key("enable_alpha").MustBool(false)
|
||||||
cfg.PluginsAppsSkipVerifyTLS = pluginsSection.Key("app_tls_skip_verify_insecure").MustBool(false)
|
cfg.PluginsAppsSkipVerifyTLS = pluginsSection.Key("app_tls_skip_verify_insecure").MustBool(false)
|
||||||
cfg.PluginSettings = extractPluginSettings(iniFile.Sections())
|
cfg.PluginSettings = extractPluginSettings(iniFile.Sections())
|
||||||
cfg.PluginForcePublicKeyDownload = pluginsSection.Key("enforce_public_key_download").MustBool(false)
|
cfg.PluginSkipPublicKeyDownload = pluginsSection.Key("public_key_retrieval_disabled").MustBool(false)
|
||||||
|
cfg.PluginForcePublicKeyDownload = pluginsSection.Key("public_key_retrieval_on_startup").MustBool(false)
|
||||||
|
|
||||||
pluginsAllowUnsigned := pluginsSection.Key("allow_loading_unsigned_plugins").MustString("")
|
pluginsAllowUnsigned := pluginsSection.Key("allow_loading_unsigned_plugins").MustString("")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user