From 7ef21662f9ad74b80d832b9f2aa9db2fb4192741 Mon Sep 17 00:00:00 2001 From: Michael Mandrus <41969079+mmandrus@users.noreply.github.com> Date: Wed, 29 Jun 2022 08:48:23 -0400 Subject: [PATCH] Plugins: Show that Secrets Manager Plugin is active in the UI (#50953) * add special handling on the plugin gathering side to check whether secrets manager plugins are enabled or not * show disabled badge in front end if the plugin is not enabled * Only show error in disabled badge hover if one is present (otherwise it shows "undefined") * refactor to make use of fields already available in the DTO * fix typo * if there is no error returned for the plugin, just show 'disabled' * fix typo * Update public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx Co-authored-by: Levente Balogh * Update frontendsettings.go add clarifying comment * fix unit test * rework task to use new frontend property combined with plugin type to determine if the plugin should be disabled * Update helpers.test.ts revert test change * fix unit test * bogus commit to trigger precommit * undo commit * run precommit manually Co-authored-by: Levente Balogh --- .betterer.results | 26 +++++++++---------- packages/grafana-data/src/types/config.ts | 1 + packages/grafana-data/src/types/plugin.ts | 1 + packages/grafana-runtime/src/config.ts | 1 + pkg/api/frontendsettings.go | 1 + pkg/api/frontendsettings_test.go | 2 ++ pkg/api/http_server.go | 5 +++- pkg/plugins/plugins.go | 4 +++ .../components/Badges/PluginDisabledBadge.tsx | 5 +++- .../components/PluginDetailsDisabledError.tsx | 2 +- public/app/features/plugins/admin/helpers.ts | 13 +++++++--- public/app/features/plugins/admin/types.ts | 1 + 12 files changed, 42 insertions(+), 20 deletions(-) diff --git a/.betterer.results b/.betterer.results index e5b875089e7..ee90f6fdde9 100644 --- a/.betterer.results +++ b/.betterer.results @@ -684,7 +684,7 @@ exports[`better eslint`] = { "packages/grafana-data/src/types/app.ts:2148970488": [ [75, 48, 3, "Unexpected any. Specify a different type.", "193409811"] ], - "packages/grafana-data/src/types/config.ts:2312759525": [ + "packages/grafana-data/src/types/config.ts:21897200": [ [185, 11, 3, "Unexpected any. Specify a different type.", "193409811"], [199, 16, 3, "Unexpected any. Specify a different type.", "193409811"] ], @@ -819,10 +819,10 @@ exports[`better eslint`] = { [192, 52, 3, "Unexpected any. Specify a different type.", "193409811"], [192, 72, 3, "Unexpected any. Specify a different type.", "193409811"] ], - "packages/grafana-data/src/types/plugin.ts:695757440": [ - [173, 22, 3, "Unexpected any. Specify a different type.", "193409811"], - [190, 29, 3, "Unexpected any. Specify a different type.", "193409811"], - [196, 16, 7, "Do not use any type assertions.", "3399135973"] + "packages/grafana-data/src/types/plugin.ts:2556367579": [ + [174, 22, 3, "Unexpected any. Specify a different type.", "193409811"], + [191, 29, 3, "Unexpected any. Specify a different type.", "193409811"], + [197, 16, 7, "Do not use any type assertions.", "3399135973"] ], "packages/grafana-data/src/types/query.ts:4277928644": [ [100, 14, 3, "Unexpected any. Specify a different type.", "193409811"], @@ -1211,12 +1211,12 @@ exports[`better eslint`] = { [31, 49, 3, "Unexpected any. Specify a different type.", "193409811"], [31, 73, 3, "Unexpected any. Specify a different type.", "193409811"] ], - "packages/grafana-runtime/src/config.ts:4181107692": [ + "packages/grafana-runtime/src/config.ts:2639113063": [ [66, 11, 3, "Unexpected any. Specify a different type.", "193409811"], [75, 29, 17, "Do not use any type assertions.", "4278379396"], - [106, 16, 3, "Unexpected any. Specify a different type.", "193409811"], - [191, 18, 13, "Do not use any type assertions.", "538937261"], - [191, 28, 3, "Unexpected any. Specify a different type.", "193409811"] + [107, 16, 3, "Unexpected any. Specify a different type.", "193409811"], + [192, 18, 13, "Do not use any type assertions.", "538937261"], + [192, 28, 3, "Unexpected any. Specify a different type.", "193409811"] ], "packages/grafana-runtime/src/services/AngularLoader.ts:3455177907": [ [45, 14, 3, "Unexpected any. Specify a different type.", "193409811"], @@ -6439,8 +6439,8 @@ exports[`better eslint`] = { [135, 28, 52, "Do not use any type assertions.", "963107955"], [177, 42, 56, "Do not use any type assertions.", "2128061450"] ], - "public/app/features/plugins/admin/helpers.ts:2721255382": [ - [215, 5, 45, "Do not use any type assertions.", "2083447632"] + "public/app/features/plugins/admin/helpers.ts:1783021315": [ + [216, 5, 45, "Do not use any type assertions.", "2083447632"] ], "public/app/features/plugins/admin/hooks/useHistory.tsx:3882862818": [ [4, 22, 3, "Unexpected any. Specify a different type.", "193409811"] @@ -6475,8 +6475,8 @@ exports[`better eslint`] = { "public/app/features/plugins/admin/state/selectors.ts:345773501": [ [62, 23, 27, "Do not use any type assertions.", "1285719276"] ], - "public/app/features/plugins/admin/types.ts:1638901340": [ - [238, 10, 3, "Unexpected any. Specify a different type.", "193409811"] + "public/app/features/plugins/admin/types.ts:804526334": [ + [239, 10, 3, "Unexpected any. Specify a different type.", "193409811"] ], "public/app/features/plugins/built_in_plugins.ts:2973583336": [ [93, 22, 3, "Unexpected any. Specify a different type.", "193409811"] diff --git a/packages/grafana-data/src/types/config.ts b/packages/grafana-data/src/types/config.ts index c505da1f4fc..2726b75c4b7 100644 --- a/packages/grafana-data/src/types/config.ts +++ b/packages/grafana-data/src/types/config.ts @@ -203,6 +203,7 @@ export interface GrafanaConfig { unifiedAlertingEnabled: boolean; angularSupportEnabled: boolean; feedbackLinksEnabled: boolean; + secretsManagerPluginEnabled: boolean; googleAnalyticsId: string | undefined; rudderstackWriteKey: string | undefined; rudderstackDataPlaneUrl: string | undefined; diff --git a/packages/grafana-data/src/types/plugin.ts b/packages/grafana-data/src/types/plugin.ts index a3c08442493..c14468083e0 100644 --- a/packages/grafana-data/src/types/plugin.ts +++ b/packages/grafana-data/src/types/plugin.ts @@ -16,6 +16,7 @@ export enum PluginType { datasource = 'datasource', app = 'app', renderer = 'renderer', + secretsmanager = 'secretsmanager', } /** Describes status of {@link https://grafana.com/docs/grafana/latest/plugins/plugin-signatures/ | plugin signature} */ diff --git a/packages/grafana-runtime/src/config.ts b/packages/grafana-runtime/src/config.ts index 45b48afe4d8..e7cd5730fc0 100644 --- a/packages/grafana-runtime/src/config.ts +++ b/packages/grafana-runtime/src/config.ts @@ -83,6 +83,7 @@ export class GrafanaBootConfig implements GrafanaConfig { thumbnailsExist: boolean; } = { systemRequirements: { met: false, requiredImageRendererPluginVersion: '' }, thumbnailsExist: false }; rendererVersion = ''; + secretsManagerPluginEnabled = false; http2Enabled = false; dateFormats?: SystemDateFormatSettings; sentry = { diff --git a/pkg/api/frontendsettings.go b/pkg/api/frontendsettings.go index 6152025ce6f..caa75f6b543 100644 --- a/pkg/api/frontendsettings.go +++ b/pkg/api/frontendsettings.go @@ -152,6 +152,7 @@ func (hs *HTTPServer) getFrontendSettingsMap(c *models.ReqContext) (map[string]i "featureToggles": hs.Features.GetEnabled(c.Req.Context()), "rendererAvailable": hs.RenderService.IsAvailable(), "rendererVersion": hs.RenderService.Version(), + "secretsManagerPluginEnabled": hs.remoteSecretsCheck.ShouldUseRemoteSecretsPlugin(), "http2Enabled": hs.Cfg.Protocol == setting.HTTP2Scheme, "sentry": hs.Cfg.Sentry, "grafanaJavascriptAgent": hs.Cfg.GrafanaJavascriptAgent, diff --git a/pkg/api/frontendsettings_test.go b/pkg/api/frontendsettings_test.go index 26c3a939090..3e21a994c10 100644 --- a/pkg/api/frontendsettings_test.go +++ b/pkg/api/frontendsettings_test.go @@ -13,6 +13,7 @@ import ( pluginSettings "github.com/grafana/grafana/pkg/services/pluginsettings/service" "github.com/grafana/grafana/pkg/services/rendering" "github.com/grafana/grafana/pkg/services/secrets/fakes" + "github.com/grafana/grafana/pkg/services/secrets/kvstore" secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager" "github.com/grafana/grafana/pkg/services/sqlstore" "github.com/grafana/grafana/pkg/services/updatechecker" @@ -55,6 +56,7 @@ func setupTestEnvironment(t *testing.T, cfg *setting.Cfg, features *featuremgmt. grafanaUpdateChecker: &updatechecker.GrafanaService{}, AccessControl: accesscontrolmock.New().WithDisabled(), PluginSettings: pluginSettings.ProvideService(sqlStore, secretsService), + remoteSecretsCheck: &kvstore.OSSRemoteSecretsPluginCheck{}, } m := web.New() diff --git a/pkg/api/http_server.go b/pkg/api/http_server.go index f86bb9c5be3..5b285599d2e 100644 --- a/pkg/api/http_server.go +++ b/pkg/api/http_server.go @@ -69,6 +69,7 @@ import ( "github.com/grafana/grafana/pkg/services/search" "github.com/grafana/grafana/pkg/services/searchusers" "github.com/grafana/grafana/pkg/services/secrets" + secretsKV "github.com/grafana/grafana/pkg/services/secrets/kvstore" "github.com/grafana/grafana/pkg/services/serviceaccounts" "github.com/grafana/grafana/pkg/services/shorturls" "github.com/grafana/grafana/pkg/services/sqlstore" @@ -132,6 +133,7 @@ type HTTPServer struct { Listener net.Listener EncryptionService encryption.Internal SecretsService secrets.Service + remoteSecretsCheck secretsKV.UseRemoteSecretsPluginCheck DataSourcesService datasources.DataSourceService cleanUpService *cleanup.CleanUpService tracer tracing.Tracer @@ -199,7 +201,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi teamsPermissionsService accesscontrol.TeamPermissionsService, folderPermissionsService accesscontrol.FolderPermissionsService, dashboardPermissionsService accesscontrol.DashboardPermissionsService, dashboardVersionService dashver.Service, starService star.Service, csrfService csrf.Service, coremodelRegistry *registry.Generic, coremodelStaticRegistry *registry.Static, - kvStore kvstore.KVStore, + kvStore kvstore.KVStore, remoteSecretsCheck secretsKV.UseRemoteSecretsPluginCheck, ) (*HTTPServer, error) { web.Env = cfg.Env m := web.New() @@ -254,6 +256,7 @@ func ProvideHTTPServer(opts ServerOptions, cfg *setting.Cfg, routeRegister routi SocialService: socialService, EncryptionService: encryptionService, SecretsService: secretsService, + remoteSecretsCheck: remoteSecretsCheck, DataSourcesService: dataSourcesService, searchUsersService: searchUsersService, ldapGroups: ldapGroups, diff --git a/pkg/plugins/plugins.go b/pkg/plugins/plugins.go index dd17aae8501..7ae0208d69b 100644 --- a/pkg/plugins/plugins.go +++ b/pkg/plugins/plugins.go @@ -81,6 +81,10 @@ func (p PluginDTO) IsCorePlugin() bool { return p.Class == Core } +func (p PluginDTO) IsSecretsManager() bool { + return p.JSONData.Type == SecretsManager +} + func (p PluginDTO) IncludedInSignature(file string) bool { // permit Core plugin files if p.IsCorePlugin() { diff --git a/public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx b/public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx index dbac4871b07..5c31a77fe86 100644 --- a/public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx +++ b/public/app/features/plugins/admin/components/Badges/PluginDisabledBadge.tsx @@ -18,7 +18,10 @@ function errorCodeToTooltip(error?: PluginErrorCode): string | undefined { return 'Plugin disabled due to invalid plugin signature'; case PluginErrorCode.missingSignature: return 'Plugin disabled due to missing plugin signature'; + case null: + case undefined: + return 'Plugin disabled'; default: - return `Plugin disabled due to unkown error: ${error}`; + return `Plugin disabled due to unknown error${error ? `: ${error}` : ''}`; } } diff --git a/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx b/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx index 9f34a4b0ced..1d2c73711cb 100644 --- a/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx +++ b/public/app/features/plugins/admin/components/PluginDetailsDisabledError.tsx @@ -69,7 +69,7 @@ function renderDescriptionFromError(error?: PluginErrorCode): ReactElement { default: return (

- We failed to run this plugin due to an unkown reason and have therefor disabled it. We recommend you to + We failed to run this plugin due to an unkown reason and have therefore disabled it. We recommend you to reinstall the plugin to make sure you are running a working version of this plugin.

); diff --git a/public/app/features/plugins/admin/helpers.ts b/public/app/features/plugins/admin/helpers.ts index 2a52055b3a4..85d07798f31 100644 --- a/public/app/features/plugins/admin/helpers.ts +++ b/public/app/features/plugins/admin/helpers.ts @@ -1,4 +1,4 @@ -import { PluginSignatureStatus, dateTimeParse, PluginError, PluginErrorCode } from '@grafana/data'; +import { PluginSignatureStatus, dateTimeParse, PluginError, PluginType, PluginErrorCode } from '@grafana/data'; import { config } from '@grafana/runtime'; import { Settings } from 'app/core/config'; import { getBackendSrv } from 'app/core/services/backend_srv'; @@ -61,7 +61,7 @@ export function mapRemoteToCatalog(plugin: RemotePlugin, error?: PluginError): C status, } = plugin; - const isDisabled = !!error; + const isDisabled = !!error || isDisabledSecretsPlugin(typeCode); return { description, downloads, @@ -103,6 +103,7 @@ export function mapLocalToCatalog(plugin: LocalPlugin, error?: PluginError): Cat hasUpdate, } = plugin; + const isDisabled = !!error || isDisabledSecretsPlugin(type); return { description, downloads: 0, @@ -119,7 +120,7 @@ export function mapLocalToCatalog(plugin: LocalPlugin, error?: PluginError): Cat installedVersion: version, hasUpdate, isInstalled: true, - isDisabled: !!error, + isDisabled: isDisabled, isCore: signature === 'internal', isPublished: false, isDev: Boolean(dev), @@ -134,7 +135,7 @@ export function mapToCatalogPlugin(local?: LocalPlugin, remote?: RemotePlugin, e const installedVersion = local?.info.version; const id = remote?.slug || local?.id || ''; const type = local?.type || remote?.typeCode; - const isDisabled = !!error; + const isDisabled = !!error || isDisabledSecretsPlugin(type); let logos = { small: `/public/img/icn-${type}.svg`, @@ -274,6 +275,10 @@ function isPluginVisible(id: string) { return !pluginCatalogHiddenPlugins.includes(id); } +function isDisabledSecretsPlugin(type?: PluginType): boolean { + return type === PluginType.secretsmanager && !config.secretsManagerPluginEnabled; +} + export function isLocalCorePlugin(local?: LocalPlugin): boolean { return Boolean(local?.signature === 'internal'); } diff --git a/public/app/features/plugins/admin/types.ts b/public/app/features/plugins/admin/types.ts index e1551490ef1..cfd5efb6527 100644 --- a/public/app/features/plugins/admin/types.ts +++ b/public/app/features/plugins/admin/types.ts @@ -31,6 +31,7 @@ export enum PluginIconName { datasource = 'database', panel = 'credit-card', renderer = 'capture', + secretsmanager = 'key-skeleton-alt', } export interface CatalogPlugin {