72d9de3a0f
* 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 <balogh.levente.hu@gmail.com> * 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 * show custom uninstall message if the plugin is a secrets manager * bogus commit to trigger precommit * undo commit * run precommit manually * add some consts * refactor a bit to pull plugin error management up a level * re-add code squashed in merge * fix compile issues * add code to set plugin error fatal flag after secret migration * refactor to move plugin startup out of Should Check func * re-add important check * make plugin startup errors fatal the first time we set a secret on the plugin * rename func to make intent clearler * remove unnecessary duplicate code from plugin mig * fix compile error * fix more compile errors * add some extra logging to secrets migration * have remote_plugin secret service managed plugin error fatal flag directly * add blank file for eventual unit tests * fix linting issues * changes from PR review * quick bit of cleanup * add comment explaining design decision * move more common test helpers to file * slightly update to first time Get secret call * add unit tests * remove override func from provider * fix linting issues * add test cleanup step * add some comments about refactoring to hacky test function Co-authored-by: Levente Balogh <balogh.levente.hu@gmail.com>
106 lines
3.5 KiB
Go
106 lines
3.5 KiB
Go
package kvstore
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/grafana/grafana/pkg/infra/kvstore"
|
|
"github.com/grafana/grafana/pkg/infra/log"
|
|
"github.com/grafana/grafana/pkg/services/secrets/fakes"
|
|
secretsManager "github.com/grafana/grafana/pkg/services/secrets/manager"
|
|
"github.com/grafana/grafana/pkg/services/sqlstore"
|
|
|
|
"github.com/grafana/grafana/pkg/setting"
|
|
"github.com/stretchr/testify/require"
|
|
"gopkg.in/ini.v1"
|
|
)
|
|
|
|
// This tests will create a mock sql database and an inmemory
|
|
// implementation of the secret manager to simulate the plugin.
|
|
func TestPluginSecretMigrationService_Migrate(t *testing.T) {
|
|
ctx := context.Background()
|
|
|
|
t.Run("migration run ok - 2 secrets migrated", func(t *testing.T) {
|
|
// --- SETUP
|
|
migratorService, secretsStore, sqlSecretStore := setupTestMigratorService(t)
|
|
var orgId int64 = 1
|
|
namespace1, namespace2 := "namespace-test", "namespace-test2"
|
|
typ := "type-test"
|
|
value := "SUPER_SECRET"
|
|
|
|
addSecretToSqlStore(t, sqlSecretStore, ctx, orgId, namespace1, typ, value)
|
|
addSecretToSqlStore(t, sqlSecretStore, ctx, orgId, namespace2, typ, value)
|
|
|
|
// --- EXECUTION
|
|
err := migratorService.Migrate(ctx)
|
|
require.NoError(t, err)
|
|
|
|
// --- VALIDATIONS
|
|
validateSecretWasDeleted(t, sqlSecretStore, ctx, orgId, namespace1, typ)
|
|
validateSecretWasDeleted(t, sqlSecretStore, ctx, orgId, namespace2, typ)
|
|
|
|
validateSecretWasStoreInPlugin(t, secretsStore, ctx, orgId, namespace1, typ)
|
|
validateSecretWasStoreInPlugin(t, secretsStore, ctx, orgId, namespace1, typ)
|
|
})
|
|
}
|
|
|
|
func addSecretToSqlStore(t *testing.T, sqlSecretStore *secretsKVStoreSQL, ctx context.Context, orgId int64, namespace1 string, typ string, value string) {
|
|
err := sqlSecretStore.Set(ctx, orgId, namespace1, typ, value)
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
// validates that secrets on the sql store were deleted.
|
|
func validateSecretWasDeleted(t *testing.T, sqlSecretStore *secretsKVStoreSQL, ctx context.Context, orgId int64, namespace1 string, typ string) {
|
|
res, err := sqlSecretStore.Keys(ctx, orgId, namespace1, typ)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 0, len(res))
|
|
}
|
|
|
|
// validates that secrets should be on the plugin
|
|
func validateSecretWasStoreInPlugin(t *testing.T, secretsStore SecretsKVStore, ctx context.Context, orgId int64, namespace1 string, typ string) {
|
|
resPlugin, err := secretsStore.Keys(ctx, orgId, namespace1, typ)
|
|
require.NoError(t, err)
|
|
require.Equal(t, 1, len(resPlugin))
|
|
}
|
|
|
|
//
|
|
func setupTestMigratorService(t *testing.T) (*PluginSecretMigrationService, SecretsKVStore, *secretsKVStoreSQL) {
|
|
t.Helper()
|
|
|
|
rawCfg := `
|
|
[secrets]
|
|
use_plugin = true
|
|
migrate_to_plugin = true
|
|
`
|
|
raw, err := ini.Load([]byte(rawCfg))
|
|
require.NoError(t, err)
|
|
cfg := &setting.Cfg{Raw: raw}
|
|
// this would be the plugin - mocked at the moment
|
|
secretsStoreForPlugin := NewFakeSecretsKVStore()
|
|
// Mocked remote plugin check, always return true
|
|
remoteCheck := provideMockRemotePluginCheck()
|
|
|
|
// this is to init the sql secret store inside the migration
|
|
sqlStore := sqlstore.InitTestDB(t)
|
|
secretsService := secretsManager.SetupTestService(t, fakes.NewFakeSecretsStore())
|
|
migratorService := ProvidePluginSecretMigrationService(
|
|
secretsStoreForPlugin,
|
|
cfg,
|
|
sqlStore,
|
|
secretsService,
|
|
remoteCheck,
|
|
kvstore.ProvideService(sqlStore),
|
|
)
|
|
|
|
secretsSql := &secretsKVStoreSQL{
|
|
sqlStore: sqlStore,
|
|
secretsService: secretsService,
|
|
log: log.New("test.logger"),
|
|
decryptionCache: decryptionCache{
|
|
cache: make(map[int64]cachedDecrypted),
|
|
},
|
|
}
|
|
|
|
return migratorService, secretsStoreForPlugin, secretsSql
|
|
}
|