mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Encryption: De-duplicate encryption code with extensible service (#52472)
* Encryption: De-duplicate encryption code with extensible service * Fix Wire injections * Fix tests * Register reload handler
This commit is contained in:
committed by
GitHub
parent
9c6aab3bc9
commit
28e27e1365
@@ -12,6 +12,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/localcache"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/hooks"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
@@ -34,6 +36,8 @@ var wireSet = wire.NewSet(
|
||||
sqlstore.ProvideService,
|
||||
wire.InterfaceValue(new(usagestats.Service), noOpUsageStats{}),
|
||||
wire.InterfaceValue(new(routing.RouteRegister), noOpRouteRegister{}),
|
||||
encryptionservice.ProvideEncryptionService,
|
||||
wire.Bind(new(encryption.Internal), new(*encryptionservice.Service)),
|
||||
secretsDatabase.ProvideSecretsStore,
|
||||
wire.Bind(new(secrets.Store), new(*secretsDatabase.SecretsStoreImpl)),
|
||||
secretsManager.ProvideSecretsService,
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/registry"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders/osskmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/licensing"
|
||||
@@ -26,6 +26,6 @@ var wireExtsSet = wire.NewSet(
|
||||
wire.Bind(new(setting.Provider), new(*setting.OSSImpl)),
|
||||
osskmsproviders.ProvideService,
|
||||
wire.Bind(new(kmsproviders.Service), new(osskmsproviders.Service)),
|
||||
ossencryption.ProvideService,
|
||||
wire.Bind(new(encryption.Internal), new(*ossencryption.Service)),
|
||||
encryptionprovider.ProvideEncryptionProvider,
|
||||
wire.Bind(new(encryption.Provider), new(encryptionprovider.Provider)),
|
||||
)
|
||||
|
||||
@@ -59,6 +59,8 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/datasourceproxy"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/export"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/guardian"
|
||||
@@ -231,6 +233,8 @@ var wireBasicSet = wire.NewSet(
|
||||
graphite.ProvideService,
|
||||
prometheus.ProvideService,
|
||||
elasticsearch.ProvideService,
|
||||
encryptionservice.ProvideEncryptionService,
|
||||
wire.Bind(new(encryption.Internal), new(*encryptionservice.Service)),
|
||||
secretsManager.ProvideSecretsService,
|
||||
wire.Bind(new(secrets.Service), new(*secretsManager.SecretsService)),
|
||||
secretsDatabase.ProvideSecretsStore,
|
||||
|
||||
@@ -21,7 +21,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/services/datasources/permissions"
|
||||
datasourceservice "github.com/grafana/grafana/pkg/services/datasources/service"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders/osskmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/ldap"
|
||||
@@ -63,8 +63,8 @@ var wireExtsBasicSet = wire.NewSet(
|
||||
wire.Bind(new(registry.DatabaseMigrator), new(*migrations.OSSMigrations)),
|
||||
authinfoservice.ProvideOSSUserProtectionService,
|
||||
wire.Bind(new(login.UserProtectionService), new(*authinfoservice.OSSUserProtectionImpl)),
|
||||
ossencryption.ProvideService,
|
||||
wire.Bind(new(encryption.Internal), new(*ossencryption.Service)),
|
||||
encryptionprovider.ProvideEncryptionProvider,
|
||||
wire.Bind(new(encryption.Provider), new(encryptionprovider.Provider)),
|
||||
filters.ProvideOSSSearchUserFilter,
|
||||
wire.Bind(new(models.SearchUserFilter), new(*filters.OSSSearchUserFilter)),
|
||||
searchusers.ProvideUsersService,
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@@ -21,9 +21,18 @@ func TestIntegrationEngineTimeouts(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("skipping integration test")
|
||||
}
|
||||
|
||||
usMock := &usagestats.UsageStatsMock{T: t}
|
||||
|
||||
encProvider := encryptionprovider.ProvideEncryptionProvider()
|
||||
cfg := setting.NewCfg()
|
||||
settings := &setting.OSSImpl{Cfg: cfg}
|
||||
|
||||
encService, err := encryptionservice.ProvideEncryptionService(encProvider, usMock, settings)
|
||||
require.NoError(t, err)
|
||||
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, nil, setting.NewCfg(), nil, nil)
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, nil, cfg, nil, nil)
|
||||
setting.AlertingNotificationTimeout = 30 * time.Second
|
||||
setting.AlertingMaxAttempts = 3
|
||||
engine.resultHandler = &FakeResultHandler{}
|
||||
|
||||
@@ -7,15 +7,15 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/tracing"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/datasources"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type FakeEvalHandler struct {
|
||||
@@ -101,10 +101,17 @@ func (a *AlertStoreMock) SetAlertState(_ context.Context, _ *models.SetAlertStat
|
||||
|
||||
func TestEngineProcessJob(t *testing.T) {
|
||||
usMock := &usagestats.UsageStatsMock{T: t}
|
||||
|
||||
encProvider := encryptionprovider.ProvideEncryptionProvider()
|
||||
cfg := setting.NewCfg()
|
||||
settings := &setting.OSSImpl{Cfg: cfg}
|
||||
|
||||
encService, err := encryptionservice.ProvideEncryptionService(encProvider, usMock, settings)
|
||||
require.NoError(t, err)
|
||||
tracer := tracing.InitializeTracerForTest()
|
||||
|
||||
store := &AlertStoreMock{}
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, ossencryption.ProvideService(), nil, tracer, store, setting.NewCfg(), nil, nil)
|
||||
engine := ProvideAlertEngine(nil, nil, nil, usMock, encService, nil, tracer, store, cfg, nil, nil)
|
||||
setting.AlertingEvaluationTimeout = 30 * time.Second
|
||||
setting.AlertingNotificationTimeout = 30 * time.Second
|
||||
setting.AlertingMaxAttempts = 3
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -81,6 +81,8 @@ func TestWhenAlertManagerShouldNotify(t *testing.T) {
|
||||
|
||||
//nolint:goconst
|
||||
func TestAlertmanagerNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -92,7 +94,7 @@ func TestAlertmanagerNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewAlertmanagerNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewAlertmanagerNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -106,7 +108,7 @@ func TestAlertmanagerNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewAlertmanagerNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewAlertmanagerNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
alertmanagerNotifier := not.(*AlertmanagerNotifier)
|
||||
|
||||
require.NoError(t, err)
|
||||
@@ -125,7 +127,7 @@ func TestAlertmanagerNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewAlertmanagerNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewAlertmanagerNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
alertmanagerNotifier := not.(*AlertmanagerNotifier)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -7,13 +7,15 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDingDingNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
|
||||
@@ -24,7 +26,7 @@ func TestDingDingNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := newDingDingNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := newDingDingNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("settings should trigger incident", func(t *testing.T) {
|
||||
@@ -37,7 +39,7 @@ func TestDingDingNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := newDingDingNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := newDingDingNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
notifier := not.(*DingDingNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestDiscordNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestDiscordNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := newDiscordNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := newDiscordNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -41,7 +43,7 @@ func TestDiscordNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := newDiscordNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := newDiscordNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
discordNotifier := not.(*DiscordNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEmailNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewEmailNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewEmailNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -39,7 +41,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewEmailNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewEmailNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
emailNotifier := not.(*EmailNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -63,7 +65,7 @@ func TestEmailNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewEmailNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewEmailNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
emailNotifier := not.(*EmailNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGoogleChatNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := newGoogleChatNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := newGoogleChatNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -39,7 +41,7 @@ func TestGoogleChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := newGoogleChatNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := newGoogleChatNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
webhookNotifier := not.(*GoogleChatNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,13 +5,15 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
//nolint:goconst
|
||||
func TestHipChatNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -23,7 +25,7 @@ func TestHipChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewHipChatNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewHipChatNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -39,7 +41,7 @@ func TestHipChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewHipChatNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewHipChatNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
hipchatNotifier := not.(*HipChatNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -65,7 +67,7 @@ func TestHipChatNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewHipChatNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewHipChatNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
hipchatNotifier := not.(*HipChatNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestKafkaNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestKafkaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewKafkaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewKafkaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -40,7 +42,7 @@ func TestKafkaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewKafkaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewKafkaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
kafkaNotifier := not.(*KafkaNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestLineNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
|
||||
@@ -21,7 +23,7 @@ func TestLineNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewLINENotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewLINENotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
t.Run("settings should trigger incident", func(t *testing.T) {
|
||||
@@ -36,7 +38,7 @@ func TestLineNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewLINENotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewLINENotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
lineNotifier := not.(*LineNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
)
|
||||
|
||||
func TestOpsGenieNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -28,7 +30,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -45,7 +47,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
opsgenieNotifier := not.(*OpsGenieNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -69,7 +71,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
require.Equal(t, reflect.TypeOf(err), reflect.TypeOf(alerting.ValidationError{}))
|
||||
require.True(t, strings.HasSuffix(err.Error(), "Invalid value for sendTagsAs: \"not_a_valid_value\""))
|
||||
@@ -93,7 +95,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
}
|
||||
|
||||
notificationService := notifications.MockNotificationService()
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, notificationService) // unhandled error
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, notificationService) // unhandled error
|
||||
|
||||
opsgenieNotifier := notifier.(*OpsGenieNotifier)
|
||||
|
||||
@@ -142,7 +144,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
}
|
||||
|
||||
notificationService := notifications.MockNotificationService()
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, notificationService) // unhandled error
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, notificationService) // unhandled error
|
||||
|
||||
opsgenieNotifier := notifier.(*OpsGenieNotifier)
|
||||
|
||||
@@ -191,7 +193,7 @@ func TestOpsGenieNotifier(t *testing.T) {
|
||||
}
|
||||
|
||||
notificationService := notifications.MockNotificationService()
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, ossencryption.ProvideService().GetDecryptedValue, notificationService) // unhandled error
|
||||
notifier, notifierErr := NewOpsGenieNotifier(model, encryptionService.GetDecryptedValue, notificationService) // unhandled error
|
||||
|
||||
opsgenieNotifier := notifier.(*OpsGenieNotifier)
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -28,6 +28,8 @@ func presenceComparer(a, b string) bool {
|
||||
}
|
||||
|
||||
func TestPagerdutyNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
|
||||
@@ -40,7 +42,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err = NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -56,7 +58,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -79,7 +81,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -106,7 +108,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -131,7 +133,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
@@ -188,7 +190,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
@@ -245,7 +247,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
@@ -315,7 +317,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
@@ -395,7 +397,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
@@ -474,7 +476,7 @@ func TestPagerdutyNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPagerdutyNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPagerdutyNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
pagerdutyNotifier := not.(*PagerdutyNotifier)
|
||||
|
||||
@@ -8,13 +8,15 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestPushoverNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -26,7 +28,7 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewPushoverNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewPushoverNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -48,7 +50,7 @@ func TestPushoverNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewPushoverNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewPushoverNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
pushoverNotifier := not.(*PushoverNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSensuNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestSensuNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewSensuNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewSensuNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -41,7 +43,7 @@ func TestSensuNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSensuNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSensuNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
sensuNotifier := not.(*SensuNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -5,7 +5,8 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -21,7 +22,9 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewSensuGoNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
_, err = NewSensuGoNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
|
||||
json = `
|
||||
@@ -42,7 +45,7 @@ func TestSensuGoNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSensuGoNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSensuGoNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
sensuGoNotifier := not.(*SensuGoNotifier)
|
||||
|
||||
|
||||
@@ -9,13 +9,15 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSlackNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
|
||||
@@ -27,7 +29,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err = NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
assert.EqualError(t, err, "alert validation error: recipient must be specified when using the Slack chat API")
|
||||
})
|
||||
|
||||
@@ -45,7 +47,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
assert.Equal(t, "ops", slackNotifier.Name)
|
||||
@@ -83,7 +85,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
assert.Equal(t, "ops", slackNotifier.Name)
|
||||
@@ -116,7 +118,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
settingsJSON, err := simplejson.NewJson([]byte(json))
|
||||
require.NoError(t, err)
|
||||
|
||||
encryptionService := ossencryption.ProvideService()
|
||||
encryptionService := encryptionService
|
||||
securedSettingsJSON, err := encryptionService.EncryptJsonData(
|
||||
context.Background(),
|
||||
map[string]string{
|
||||
@@ -131,7 +133,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
SecureSettings: securedSettingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
assert.Equal(t, "ops", slackNotifier.Name)
|
||||
@@ -162,7 +164,7 @@ func TestSlackNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
assert.Equal(t, "1ABCDE", slackNotifier.recipient)
|
||||
@@ -253,7 +255,9 @@ func TestSendSlackRequest(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewSlackNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
not, err := NewSlackNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
slackNotifier := not.(*SlackNotifier)
|
||||
|
||||
|
||||
@@ -5,12 +5,14 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTeamsNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -22,7 +24,7 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewTeamsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewTeamsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -39,7 +41,7 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewTeamsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewTeamsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
teamsNotifier := not.(*TeamsNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -61,7 +63,7 @@ func TestTeamsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewTeamsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewTeamsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
teamsNotifier := not.(*TeamsNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -7,13 +7,15 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestTelegramNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -25,7 +27,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewTelegramNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewTelegramNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -43,7 +45,7 @@ func TestTelegramNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewTelegramNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewTelegramNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
telegramNotifier := not.(*TelegramNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
|
||||
@@ -7,12 +7,14 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestThreemaNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -24,7 +26,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewThreemaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewThreemaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -43,7 +45,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewThreemaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewThreemaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
threemaNotifier := not.(*ThreemaNotifier)
|
||||
|
||||
@@ -70,7 +72,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewThreemaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewThreemaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, not)
|
||||
var valErr alerting.ValidationError
|
||||
require.True(t, errors.As(err, &valErr))
|
||||
@@ -92,7 +94,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewThreemaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewThreemaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, not)
|
||||
var valErr alerting.ValidationError
|
||||
require.True(t, errors.As(err, &valErr))
|
||||
@@ -114,7 +116,7 @@ func TestThreemaNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewThreemaNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewThreemaNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, not)
|
||||
var valErr alerting.ValidationError
|
||||
require.True(t, errors.As(err, &valErr))
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/validations"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -25,6 +25,8 @@ func presenceComparerInt(a, b int64) bool {
|
||||
return a == b
|
||||
}
|
||||
func TestVictoropsNotifier(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Parsing alert notification from settings", func(t *testing.T) {
|
||||
t.Run("empty settings should return error", func(t *testing.T) {
|
||||
json := `{ }`
|
||||
@@ -36,7 +38,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err := NewVictoropsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err := NewVictoropsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -53,7 +55,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewVictoropsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewVictoropsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
victoropsNotifier := not.(*VictoropsNotifier)
|
||||
|
||||
require.Nil(t, err)
|
||||
@@ -77,7 +79,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewVictoropsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewVictoropsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
victoropsNotifier := not.(*VictoropsNotifier)
|
||||
@@ -125,7 +127,7 @@ func TestVictoropsNotifier(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewVictoropsNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewVictoropsNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Nil(t, err)
|
||||
|
||||
victoropsNotifier := not.(*VictoropsNotifier)
|
||||
|
||||
@@ -5,12 +5,15 @@ import (
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWebhookNotifier_parsingFromSettings(t *testing.T) {
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Empty settings should cause error", func(t *testing.T) {
|
||||
const json = `{}`
|
||||
|
||||
@@ -22,7 +25,7 @@ func TestWebhookNotifier_parsingFromSettings(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
_, err = NewWebHookNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
_, err = NewWebHookNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
@@ -37,7 +40,7 @@ func TestWebhookNotifier_parsingFromSettings(t *testing.T) {
|
||||
Settings: settingsJSON,
|
||||
}
|
||||
|
||||
not, err := NewWebHookNotifier(model, ossencryption.ProvideService().GetDecryptedValue, nil)
|
||||
not, err := NewWebHookNotifier(model, encryptionService.GetDecryptedValue, nil)
|
||||
require.NoError(t, err)
|
||||
webhookNotifier := not.(*WebhookNotifier)
|
||||
|
||||
|
||||
@@ -6,8 +6,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/components/simplejson"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/notifications"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
@@ -20,7 +22,15 @@ func TestService(t *testing.T) {
|
||||
nType := "test"
|
||||
registerTestNotifier(nType)
|
||||
|
||||
s := ProvideService(sqlStore, ossencryption.ProvideService(), nil)
|
||||
usMock := &usagestats.UsageStatsMock{T: t}
|
||||
|
||||
encProvider := encryptionprovider.ProvideEncryptionProvider()
|
||||
settings := &setting.OSSImpl{Cfg: setting.NewCfg()}
|
||||
|
||||
encService, err := encryptionservice.ProvideEncryptionService(encProvider, usMock, settings)
|
||||
require.NoError(t, err)
|
||||
|
||||
s := ProvideService(sqlStore, encService, nil)
|
||||
|
||||
origSecret := setting.SecretKey
|
||||
setting.SecretKey = "alert_notification_service_test"
|
||||
|
||||
@@ -1,6 +1,18 @@
|
||||
package encryption
|
||||
|
||||
import "context"
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
const (
|
||||
SaltLength = 8
|
||||
|
||||
AesCfb = "aes-cfb"
|
||||
AesGcm = "aes-gcm"
|
||||
)
|
||||
|
||||
// Internal must not be used for general purpose encryption.
|
||||
// This service is used as an internal component for envelope encryption
|
||||
@@ -8,11 +20,29 @@ import "context"
|
||||
//
|
||||
// Unless there is any specific reason, you must use secrets.Service instead.
|
||||
type Internal interface {
|
||||
Encrypt(ctx context.Context, payload []byte, secret string) ([]byte, error)
|
||||
Decrypt(ctx context.Context, payload []byte, secret string) ([]byte, error)
|
||||
Cipher
|
||||
Decipher
|
||||
|
||||
EncryptJsonData(ctx context.Context, kv map[string]string, secret string) (map[string][]byte, error)
|
||||
DecryptJsonData(ctx context.Context, sjd map[string][]byte, secret string) (map[string]string, error)
|
||||
|
||||
GetDecryptedValue(ctx context.Context, sjd map[string][]byte, key string, fallback string, secret string) string
|
||||
}
|
||||
|
||||
type Cipher interface {
|
||||
Encrypt(ctx context.Context, payload []byte, secret string) ([]byte, error)
|
||||
}
|
||||
|
||||
type Decipher interface {
|
||||
Decrypt(ctx context.Context, payload []byte, secret string) ([]byte, error)
|
||||
}
|
||||
|
||||
type Provider interface {
|
||||
ProvideCiphers() map[string]Cipher
|
||||
ProvideDeciphers() map[string]Decipher
|
||||
}
|
||||
|
||||
// KeyToBytes key length needs to be 32 bytes
|
||||
func KeyToBytes(secret, salt string) ([]byte, error) {
|
||||
return pbkdf2.Key([]byte(secret), []byte(salt), 10000, 32, sha256.New), nil
|
||||
}
|
||||
|
||||
22
pkg/services/encryption/encryption_test.go
Normal file
22
pkg/services/encryption/encryption_test.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package encryption
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_KeyToBytes(t *testing.T) {
|
||||
t.Run("with regular secret", func(t *testing.T) {
|
||||
key, err := KeyToBytes("secret", "salt")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, key, 32)
|
||||
})
|
||||
|
||||
t.Run("with very long secret", func(t *testing.T) {
|
||||
key, err := KeyToBytes("a very long secret key that is larger then 32bytes", "salt")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, key, 32)
|
||||
})
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package ossencryption
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"crypto/sha256"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
"golang.org/x/crypto/pbkdf2"
|
||||
)
|
||||
|
||||
// Service must not be used for encryption,
|
||||
// use secrets.Service implementing envelope encryption instead.
|
||||
type Service struct{}
|
||||
|
||||
func ProvideService() *Service {
|
||||
return &Service{}
|
||||
}
|
||||
|
||||
const (
|
||||
saltLength = 8
|
||||
aesCfb = "aes-cfb"
|
||||
encryptionAlgorithmDelimiter = '*'
|
||||
)
|
||||
|
||||
func (s *Service) Decrypt(_ context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
alg, payload, err := deriveEncryptionAlgorithm(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(payload) < saltLength {
|
||||
return nil, errors.New("unable to compute salt")
|
||||
}
|
||||
salt := payload[:saltLength]
|
||||
key, err := encryptionKeyToBytes(secret, string(salt))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch alg {
|
||||
case aesCfb:
|
||||
return decryptCFB(block, payload)
|
||||
default:
|
||||
return nil, errors.New("unsupported encryption algorithm")
|
||||
}
|
||||
}
|
||||
|
||||
func deriveEncryptionAlgorithm(payload []byte) (string, []byte, error) {
|
||||
if len(payload) == 0 {
|
||||
return "", nil, fmt.Errorf("unable to derive encryption algorithm")
|
||||
}
|
||||
|
||||
if payload[0] != encryptionAlgorithmDelimiter {
|
||||
return aesCfb, payload, nil // backwards compatibility
|
||||
}
|
||||
|
||||
payload = payload[1:]
|
||||
algDelim := bytes.Index(payload, []byte{encryptionAlgorithmDelimiter})
|
||||
if algDelim == -1 {
|
||||
return aesCfb, payload, nil // backwards compatibility
|
||||
}
|
||||
|
||||
algB64 := payload[:algDelim]
|
||||
payload = payload[algDelim+1:]
|
||||
|
||||
alg := make([]byte, base64.RawStdEncoding.DecodedLen(len(algB64)))
|
||||
|
||||
_, err := base64.RawStdEncoding.Decode(alg, algB64)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return string(alg), payload, nil
|
||||
}
|
||||
|
||||
func decryptCFB(block cipher.Block, payload []byte) ([]byte, error) {
|
||||
// The IV needs to be unique, but not secure. Therefore, it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
if len(payload) < aes.BlockSize {
|
||||
return nil, errors.New("payload too short")
|
||||
}
|
||||
|
||||
iv := payload[saltLength : saltLength+aes.BlockSize]
|
||||
payload = payload[saltLength+aes.BlockSize:]
|
||||
payloadDst := make([]byte, len(payload))
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
|
||||
// XORKeyStream can work in-place if the two arguments are the same.
|
||||
stream.XORKeyStream(payloadDst, payload)
|
||||
return payloadDst, nil
|
||||
}
|
||||
|
||||
func (s *Service) Encrypt(_ context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
salt, err := util.GetRandomString(saltLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := encryptionKeyToBytes(secret, salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
ciphertext := make([]byte, saltLength+aes.BlockSize+len(payload))
|
||||
copy(ciphertext[:saltLength], salt)
|
||||
iv := ciphertext[saltLength : saltLength+aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(ciphertext[saltLength+aes.BlockSize:], payload)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func (s *Service) EncryptJsonData(ctx context.Context, kv map[string]string, secret string) (map[string][]byte, error) {
|
||||
encrypted := make(map[string][]byte)
|
||||
for key, value := range kv {
|
||||
encryptedData, err := s.Encrypt(ctx, []byte(value), secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encrypted[key] = encryptedData
|
||||
}
|
||||
return encrypted, nil
|
||||
}
|
||||
|
||||
func (s *Service) DecryptJsonData(ctx context.Context, sjd map[string][]byte, secret string) (map[string]string, error) {
|
||||
decrypted := make(map[string]string)
|
||||
for key, data := range sjd {
|
||||
decryptedData, err := s.Decrypt(ctx, data, secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decrypted[key] = string(decryptedData)
|
||||
}
|
||||
return decrypted, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetDecryptedValue(ctx context.Context, sjd map[string][]byte, key, fallback, secret string) string {
|
||||
if value, ok := sjd[key]; ok {
|
||||
decryptedData, err := s.Decrypt(ctx, value, secret)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return string(decryptedData)
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
|
||||
// Key needs to be 32bytes
|
||||
func encryptionKeyToBytes(secret, salt string) ([]byte, error) {
|
||||
return pbkdf2.Key([]byte(secret), []byte(salt), 10000, 32, sha256.New), nil
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
package ossencryption
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestEncryption(t *testing.T) {
|
||||
svc := Service{}
|
||||
|
||||
t.Run("getting encryption key", func(t *testing.T) {
|
||||
key, err := encryptionKeyToBytes("secret", "salt")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, key, 32)
|
||||
|
||||
key, err = encryptionKeyToBytes("a very long secret key that is larger then 32bytes", "salt")
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, key, 32)
|
||||
})
|
||||
|
||||
t.Run("decrypting basic payload", func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
encrypted, err := svc.Encrypt(ctx, []byte("grafana"), "1234")
|
||||
require.NoError(t, err)
|
||||
|
||||
decrypted, err := svc.Decrypt(ctx, encrypted, "1234")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
|
||||
t.Run("decrypting empty payload should return error", func(t *testing.T) {
|
||||
_, err := svc.Decrypt(context.Background(), []byte(""), "1234")
|
||||
require.Error(t, err)
|
||||
|
||||
assert.Equal(t, "unable to derive encryption algorithm", err.Error())
|
||||
})
|
||||
|
||||
t.Run("decrypting ciphertext with aes-gcm as encryption algorithm should return error", func(t *testing.T) {
|
||||
// Raw slice of bytes that corresponds to the following ciphertext:
|
||||
// - 'grafana' as payload
|
||||
// - '1234' as secret
|
||||
// - 'aes-gcm' as encryption algorithm
|
||||
// With no encryption algorithm metadata.
|
||||
ciphertext := []byte{42, 89, 87, 86, 122, 76, 87, 100, 106, 98, 81, 42, 48, 99, 55, 50, 51, 48, 83, 66, 20, 99, 47, 238, 61, 44, 129, 125, 14, 37, 162, 230, 47, 31, 104, 70, 144, 223, 26, 51, 180, 17, 76, 52, 36, 93, 17, 203, 99, 158, 219, 102, 74, 173, 74}
|
||||
_, err := svc.Decrypt(context.Background(), ciphertext, "1234")
|
||||
require.Error(t, err)
|
||||
|
||||
assert.Equal(t, "unsupported encryption algorithm", err.Error())
|
||||
})
|
||||
|
||||
t.Run("decrypting ciphertext with aes-cfb as encryption algorithm do not fail", func(t *testing.T) {
|
||||
// Raw slice of bytes that corresponds to the following ciphertext:
|
||||
// - 'grafana' as payload
|
||||
// - '1234' as secret
|
||||
// - 'aes-cfb' as encryption algorithm
|
||||
// With no encryption algorithm metadata.
|
||||
ciphertext := []byte{42, 89, 87, 86, 122, 76, 87, 78, 109, 89, 103, 42, 73, 71, 50, 57, 121, 110, 90, 109, 115, 23, 237, 13, 130, 188, 151, 118, 98, 103, 80, 209, 79, 143, 22, 122, 44, 40, 102, 41, 136, 16, 27}
|
||||
decrypted, err := svc.Decrypt(context.Background(), ciphertext, "1234")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
}
|
||||
45
pkg/services/encryption/provider/cipher_aescfb.go
Normal file
45
pkg/services/encryption/provider/cipher_aescfb.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"io"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/util"
|
||||
)
|
||||
|
||||
type aesCfbCipher struct{}
|
||||
|
||||
func (c aesCfbCipher) Encrypt(_ context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
salt, err := util.GetRandomString(encryption.SaltLength)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key, err := encryption.KeyToBytes(secret, salt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// The IV needs to be unique, but not secure. Therefore, it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
ciphertext := make([]byte, encryption.SaltLength+aes.BlockSize+len(payload))
|
||||
copy(ciphertext[:encryption.SaltLength], salt)
|
||||
iv := ciphertext[encryption.SaltLength : encryption.SaltLength+aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
stream := cipher.NewCFBEncrypter(block, iv)
|
||||
stream.XORKeyStream(ciphertext[encryption.SaltLength+aes.BlockSize:], payload)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
20
pkg/services/encryption/provider/cipher_aescfb_test.go
Normal file
20
pkg/services/encryption/provider/cipher_aescfb_test.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_aesCfbCipher(t *testing.T) {
|
||||
cipher := aesCfbCipher{}
|
||||
ctx := context.Background()
|
||||
|
||||
encrypted, err := cipher.Encrypt(ctx, []byte("grafana"), "1234")
|
||||
require.NoError(t, err)
|
||||
assert.NotNil(t, encrypted)
|
||||
assert.NotEmpty(t, encrypted)
|
||||
}
|
||||
67
pkg/services/encryption/provider/decipher_aes.go
Normal file
67
pkg/services/encryption/provider/decipher_aes.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
)
|
||||
|
||||
type aesDecipher struct {
|
||||
algorithm string
|
||||
}
|
||||
|
||||
func (d aesDecipher) Decrypt(_ context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
if len(payload) < encryption.SaltLength {
|
||||
return nil, errors.New("unable to compute salt")
|
||||
}
|
||||
|
||||
salt := payload[:encryption.SaltLength]
|
||||
key, err := encryption.KeyToBytes(secret, string(salt))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch d.algorithm {
|
||||
case encryption.AesGcm:
|
||||
return decryptGCM(block, payload)
|
||||
default:
|
||||
return decryptCFB(block, payload)
|
||||
}
|
||||
}
|
||||
|
||||
func decryptGCM(block cipher.Block, payload []byte) ([]byte, error) {
|
||||
gcm, err := cipher.NewGCM(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
nonce := payload[encryption.SaltLength : encryption.SaltLength+gcm.NonceSize()]
|
||||
ciphertext := payload[encryption.SaltLength+gcm.NonceSize():]
|
||||
return gcm.Open(nil, nonce, ciphertext, nil)
|
||||
}
|
||||
|
||||
func decryptCFB(block cipher.Block, payload []byte) ([]byte, error) {
|
||||
// The IV needs to be unique, but not secure. Therefore, it's common to
|
||||
// include it at the beginning of the ciphertext.
|
||||
if len(payload) < aes.BlockSize {
|
||||
return nil, errors.New("payload too short")
|
||||
}
|
||||
|
||||
iv := payload[encryption.SaltLength : encryption.SaltLength+aes.BlockSize]
|
||||
payload = payload[encryption.SaltLength+aes.BlockSize:]
|
||||
payloadDst := make([]byte, len(payload))
|
||||
|
||||
stream := cipher.NewCFBDecrypter(block, iv)
|
||||
|
||||
// XORKeyStream can work in-place if the two arguments are the same.
|
||||
stream.XORKeyStream(payloadDst, payload)
|
||||
return payloadDst, nil
|
||||
}
|
||||
32
pkg/services/encryption/provider/decipher_aes_test.go
Normal file
32
pkg/services/encryption/provider/decipher_aes_test.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_aesDecipher(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
t.Run("aes-cfb", func(t *testing.T) {
|
||||
cipher := aesDecipher{algorithm: encryption.AesCfb}
|
||||
cfbEncryptedCiphertext := []byte{69, 84, 85, 120, 65, 82, 107, 88, 144, 188, 109, 229, 91, 88, 85, 113, 220, 35, 178, 190, 208, 182, 209, 91, 252, 119, 138, 133, 198, 8, 1}
|
||||
|
||||
decrypted, err := cipher.Decrypt(ctx, cfbEncryptedCiphertext, "1234")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
|
||||
t.Run("aes-gcm", func(t *testing.T) {
|
||||
cipher := aesDecipher{algorithm: encryption.AesGcm}
|
||||
gcmEncryptedCiphertext := []byte{48, 99, 55, 50, 51, 48, 83, 66, 20, 99, 47, 238, 61, 44, 129, 125, 14, 37, 162, 230, 47, 31, 104, 70, 144, 223, 26, 51, 180, 17, 76, 52, 36, 93, 17, 203, 99, 158, 219, 102, 74, 173, 74}
|
||||
|
||||
decrypted, err := cipher.Decrypt(ctx, gcmEncryptedCiphertext, "1234")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
}
|
||||
24
pkg/services/encryption/provider/provider.go
Normal file
24
pkg/services/encryption/provider/provider.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package provider
|
||||
|
||||
import (
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
)
|
||||
|
||||
type Provider struct{}
|
||||
|
||||
func ProvideEncryptionProvider() Provider {
|
||||
return Provider{}
|
||||
}
|
||||
|
||||
func (p Provider) ProvideCiphers() map[string]encryption.Cipher {
|
||||
return map[string]encryption.Cipher{
|
||||
encryption.AesCfb: aesCfbCipher{},
|
||||
}
|
||||
}
|
||||
|
||||
func (p Provider) ProvideDeciphers() map[string]encryption.Decipher {
|
||||
return map[string]encryption.Decipher{
|
||||
encryption.AesCfb: aesDecipher{algorithm: encryption.AesCfb},
|
||||
encryption.AesGcm: aesDecipher{algorithm: encryption.AesGcm},
|
||||
}
|
||||
}
|
||||
23
pkg/services/encryption/service/helpers.go
Normal file
23
pkg/services/encryption/service/helpers.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func SetupTestService(tb testing.TB) *Service {
|
||||
tb.Helper()
|
||||
|
||||
usMock := &usagestats.UsageStatsMock{T: tb}
|
||||
provider := encryptionprovider.ProvideEncryptionProvider()
|
||||
settings := &setting.OSSImpl{Cfg: setting.NewCfg()}
|
||||
|
||||
service, err := ProvideEncryptionService(provider, usMock, settings)
|
||||
require.NoError(tb, err)
|
||||
|
||||
return service
|
||||
}
|
||||
243
pkg/services/encryption/service/service.go
Normal file
243
pkg/services/encryption/service/service.go
Normal file
@@ -0,0 +1,243 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/log"
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
)
|
||||
|
||||
const (
|
||||
encryptionAlgorithmDelimiter = '*'
|
||||
|
||||
securitySection = "security.encryption"
|
||||
encryptionAlgorithmKey = "algorithm"
|
||||
defaultEncryptionAlgorithm = encryption.AesCfb
|
||||
)
|
||||
|
||||
// Service must not be used for encryption.
|
||||
// Use secrets.Service implementing envelope encryption instead.
|
||||
type Service struct {
|
||||
log log.Logger
|
||||
|
||||
settingsProvider setting.Provider
|
||||
usageMetrics usagestats.Service
|
||||
|
||||
ciphers map[string]encryption.Cipher
|
||||
deciphers map[string]encryption.Decipher
|
||||
}
|
||||
|
||||
func ProvideEncryptionService(
|
||||
provider encryption.Provider,
|
||||
usageMetrics usagestats.Service,
|
||||
settingsProvider setting.Provider,
|
||||
) (*Service, error) {
|
||||
s := &Service{
|
||||
log: log.New("encryption"),
|
||||
|
||||
ciphers: provider.ProvideCiphers(),
|
||||
deciphers: provider.ProvideDeciphers(),
|
||||
|
||||
usageMetrics: usageMetrics,
|
||||
settingsProvider: settingsProvider,
|
||||
}
|
||||
|
||||
algorithm := s.settingsProvider.
|
||||
KeyValue(securitySection, encryptionAlgorithmKey).
|
||||
MustString(defaultEncryptionAlgorithm)
|
||||
|
||||
if err := s.checkEncryptionAlgorithm(algorithm); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
settingsProvider.RegisterReloadHandler(securitySection, s)
|
||||
|
||||
s.registerUsageMetrics()
|
||||
|
||||
return s, nil
|
||||
}
|
||||
|
||||
func (s *Service) checkEncryptionAlgorithm(algorithm string) error {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
s.log.Error("Wrong security encryption configuration", "algorithm", algorithm, "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
if _, ok := s.ciphers[algorithm]; !ok {
|
||||
err = errors.New("no cipher registered for encryption algorithm configured")
|
||||
return err
|
||||
}
|
||||
|
||||
if _, ok := s.deciphers[algorithm]; !ok {
|
||||
err = errors.New("no cipher registered for encryption algorithm configured")
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) registerUsageMetrics() {
|
||||
s.usageMetrics.RegisterMetricsFunc(func(context.Context) (map[string]interface{}, error) {
|
||||
algorithm := s.settingsProvider.
|
||||
KeyValue(securitySection, encryptionAlgorithmKey).
|
||||
MustString(defaultEncryptionAlgorithm)
|
||||
|
||||
return map[string]interface{}{
|
||||
fmt.Sprintf("stats.encryption.%s.count", algorithm): 1,
|
||||
}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s *Service) Decrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
s.log.Error("Decryption failed", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
var (
|
||||
algorithm string
|
||||
toDecrypt []byte
|
||||
)
|
||||
algorithm, toDecrypt, err = deriveEncryptionAlgorithm(payload)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decipher, ok := s.deciphers[algorithm]
|
||||
if !ok {
|
||||
err = fmt.Errorf("no decipher available for algorithm '%s'", algorithm)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var decrypted []byte
|
||||
decrypted, err = decipher.Decrypt(ctx, toDecrypt, secret)
|
||||
|
||||
return decrypted, err
|
||||
}
|
||||
|
||||
func deriveEncryptionAlgorithm(payload []byte) (string, []byte, error) {
|
||||
if len(payload) == 0 {
|
||||
return "", nil, fmt.Errorf("unable to derive encryption algorithm")
|
||||
}
|
||||
|
||||
if payload[0] != encryptionAlgorithmDelimiter {
|
||||
return encryption.AesCfb, payload, nil // backwards compatibility
|
||||
}
|
||||
|
||||
payload = payload[1:]
|
||||
algorithmDelimiterIdx := bytes.Index(payload, []byte{encryptionAlgorithmDelimiter})
|
||||
if algorithmDelimiterIdx == -1 {
|
||||
return encryption.AesCfb, payload, nil // backwards compatibility
|
||||
}
|
||||
|
||||
algorithmB64 := payload[:algorithmDelimiterIdx]
|
||||
payload = payload[algorithmDelimiterIdx+1:]
|
||||
|
||||
algorithm := make([]byte, base64.RawStdEncoding.DecodedLen(len(algorithmB64)))
|
||||
|
||||
_, err := base64.RawStdEncoding.Decode(algorithm, algorithmB64)
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return string(algorithm), payload, nil
|
||||
}
|
||||
|
||||
func (s *Service) Encrypt(ctx context.Context, payload []byte, secret string) ([]byte, error) {
|
||||
var err error
|
||||
defer func() {
|
||||
if err != nil {
|
||||
s.log.Error("Encryption failed", "error", err)
|
||||
}
|
||||
}()
|
||||
|
||||
algorithm := s.settingsProvider.
|
||||
KeyValue(securitySection, encryptionAlgorithmKey).
|
||||
MustString(defaultEncryptionAlgorithm)
|
||||
|
||||
cipher, ok := s.ciphers[algorithm]
|
||||
if !ok {
|
||||
err = fmt.Errorf("no cipher available for algorithm '%s'", algorithm)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var encrypted []byte
|
||||
encrypted, err = cipher.Encrypt(ctx, payload, secret)
|
||||
|
||||
prefix := make([]byte, base64.RawStdEncoding.EncodedLen(len([]byte(algorithm)))+2)
|
||||
base64.RawStdEncoding.Encode(prefix[1:], []byte(algorithm))
|
||||
prefix[0] = encryptionAlgorithmDelimiter
|
||||
prefix[len(prefix)-1] = encryptionAlgorithmDelimiter
|
||||
|
||||
ciphertext := make([]byte, len(prefix)+len(encrypted))
|
||||
copy(ciphertext, prefix)
|
||||
copy(ciphertext[len(prefix):], encrypted)
|
||||
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
func (s *Service) EncryptJsonData(ctx context.Context, kv map[string]string, secret string) (map[string][]byte, error) {
|
||||
encrypted := make(map[string][]byte)
|
||||
for key, value := range kv {
|
||||
encryptedData, err := s.Encrypt(ctx, []byte(value), secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
encrypted[key] = encryptedData
|
||||
}
|
||||
return encrypted, nil
|
||||
}
|
||||
|
||||
func (s *Service) DecryptJsonData(ctx context.Context, sjd map[string][]byte, secret string) (map[string]string, error) {
|
||||
decrypted := make(map[string]string)
|
||||
for key, data := range sjd {
|
||||
decryptedData, err := s.Decrypt(ctx, data, secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
decrypted[key] = string(decryptedData)
|
||||
}
|
||||
return decrypted, nil
|
||||
}
|
||||
|
||||
func (s *Service) GetDecryptedValue(ctx context.Context, sjd map[string][]byte, key, fallback, secret string) string {
|
||||
if value, ok := sjd[key]; ok {
|
||||
decryptedData, err := s.Decrypt(ctx, value, secret)
|
||||
if err != nil {
|
||||
return fallback
|
||||
}
|
||||
|
||||
return string(decryptedData)
|
||||
}
|
||||
|
||||
return fallback
|
||||
}
|
||||
|
||||
func (s *Service) Validate(section setting.Section) error {
|
||||
s.log.Debug("Validating encryption config")
|
||||
|
||||
algorithm := section.KeyValue(encryptionAlgorithmKey).
|
||||
MustString(defaultEncryptionAlgorithm)
|
||||
|
||||
if err := s.checkEncryptionAlgorithm(algorithm); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Service) Reload(_ setting.Section) error {
|
||||
return nil
|
||||
}
|
||||
94
pkg/services/encryption/service/service_test.go
Normal file
94
pkg/services/encryption/service/service_test.go
Normal file
@@ -0,0 +1,94 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
"github.com/grafana/grafana/pkg/setting"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func Test_Service(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
encProvider := provider.Provider{}
|
||||
usageStats := &usagestats.UsageStatsMock{}
|
||||
settings := &setting.OSSImpl{Cfg: setting.NewCfg()}
|
||||
|
||||
svc, err := ProvideEncryptionService(encProvider, usageStats, settings)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("decrypt empty payload should return error", func(t *testing.T) {
|
||||
_, err := svc.Decrypt(context.Background(), []byte(""), "1234")
|
||||
require.Error(t, err)
|
||||
|
||||
assert.Equal(t, "unable to derive encryption algorithm", err.Error())
|
||||
})
|
||||
|
||||
t.Run("encrypt and decrypt with aes-cfb should work", func(t *testing.T) {
|
||||
settings.Cfg.Raw.Section(securitySection).Key(encryptionAlgorithmKey).SetValue(encryption.AesCfb)
|
||||
|
||||
encrypted, err := svc.Encrypt(ctx, []byte("grafana"), "1234")
|
||||
require.NoError(t, err)
|
||||
|
||||
decrypted, err := svc.Decrypt(ctx, encrypted, "1234")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
|
||||
t.Run("decrypt with aes-gcm should work", func(t *testing.T) {
|
||||
// Raw slice of bytes that corresponds to the following ciphertext:
|
||||
// - 'grafana' as payload
|
||||
// - '1234' as secret
|
||||
// - 'aes-gcm' as encryption algorithm
|
||||
ciphertext := []byte{42, 89, 87, 86, 122, 76, 87, 100, 106, 98, 81, 42, 48, 99, 55, 50, 51, 48, 83, 66, 20, 99, 47, 238, 61, 44, 129, 125, 14, 37, 162, 230, 47, 31, 104, 70, 144, 223, 26, 51, 180, 17, 76, 52, 36, 93, 17, 203, 99, 158, 219, 102, 74, 173, 74}
|
||||
|
||||
decrypted, err := svc.Decrypt(context.Background(), ciphertext, "1234")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
|
||||
t.Run("encrypt with aes-gcm should fail", func(t *testing.T) {
|
||||
settings.Cfg.Raw.Section(securitySection).Key(encryptionAlgorithmKey).SetValue(encryption.AesGcm)
|
||||
|
||||
_, err := svc.Encrypt(ctx, []byte("grafana"), "1234")
|
||||
require.Error(t, err)
|
||||
})
|
||||
|
||||
t.Run("decrypting legacy ciphertext should work", func(t *testing.T) {
|
||||
// Raw slice of bytes that corresponds to the following ciphertext:
|
||||
// - 'grafana' as payload
|
||||
// - '1234' as secret
|
||||
// - no encryption algorithm metadata
|
||||
ciphertext := []byte{73, 71, 50, 57, 121, 110, 90, 109, 115, 23, 237, 13, 130, 188, 151, 118, 98, 103, 80, 209, 79, 143, 22, 122, 44, 40, 102, 41, 136, 16, 27}
|
||||
|
||||
decrypted, err := svc.Decrypt(context.Background(), ciphertext, "1234")
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []byte("grafana"), decrypted)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_Service_MissingProvider(t *testing.T) {
|
||||
encProvider := fakeProvider{}
|
||||
usageStats := &usagestats.UsageStatsMock{}
|
||||
settings := &setting.OSSImpl{Cfg: setting.NewCfg()}
|
||||
|
||||
service, err := ProvideEncryptionService(encProvider, usageStats, settings)
|
||||
assert.Nil(t, service)
|
||||
assert.Error(t, err)
|
||||
}
|
||||
|
||||
type fakeProvider struct{}
|
||||
|
||||
func (p fakeProvider) ProvideCiphers() map[string]encryption.Cipher {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p fakeProvider) ProvideDeciphers() map[string]encryption.Decipher {
|
||||
return nil
|
||||
}
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/grafana/grafana/pkg/models"
|
||||
"github.com/grafana/grafana/pkg/services/alerting"
|
||||
"github.com/grafana/grafana/pkg/services/alerting/notifiers"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/sqlstore"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -33,6 +33,8 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
var sqlStore *sqlstore.SQLStore
|
||||
logger := log.New("fake.log")
|
||||
|
||||
encryptionService := encryptionservice.SetupTestService(t)
|
||||
|
||||
t.Run("Testing notification as configuration", func(t *testing.T) {
|
||||
setup := func() {
|
||||
sqlStore = sqlstore.InitTestDB(t)
|
||||
@@ -61,7 +63,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
_ = os.Setenv("TEST_VAR", "default")
|
||||
cfgProvider := &configReader{
|
||||
orgStore: sqlStore,
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
encryptionService: encryptionService,
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
|
||||
@@ -140,7 +142,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
setup()
|
||||
fakeAlertNotification := &fakeAlertNotification{}
|
||||
fakeAlertNotification.ExpectedAlertNotification = &models.AlertNotification{OrgId: 1}
|
||||
dc := newNotificationProvisioner(sqlStore, fakeAlertNotification, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, fakeAlertNotification, encryptionService, nil, logger)
|
||||
|
||||
err := dc.applyChanges(context.Background(), twoNotificationsConfig)
|
||||
if err != nil {
|
||||
@@ -166,7 +168,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
require.Equal(t, len(notificationsQuery.Result), 1)
|
||||
|
||||
t.Run("should update one notification", func(t *testing.T) {
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err = dc.applyChanges(context.Background(), twoNotificationsConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
@@ -175,7 +177,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
})
|
||||
t.Run("Two notifications with is_default", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err := dc.applyChanges(context.Background(), doubleNotificationsConfig)
|
||||
t.Run("should both be inserted", func(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
@@ -210,7 +212,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
require.Equal(t, len(notificationsQuery.Result), 2)
|
||||
|
||||
t.Run("should have two new notifications", func(t *testing.T) {
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err := dc.applyChanges(context.Background(), twoNotificationsConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
@@ -239,7 +241,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
err = sqlStore.CreateAlertNotificationCommand(context.Background(), &existingNotificationCmd)
|
||||
require.NoError(t, err)
|
||||
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err = dc.applyChanges(context.Background(), correctPropertiesWithOrgName)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
@@ -248,7 +250,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
|
||||
t.Run("Config doesn't contain required field", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err := dc.applyChanges(context.Background(), noRequiredFields)
|
||||
require.NotNil(t, err)
|
||||
|
||||
@@ -262,7 +264,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Empty yaml file", func(t *testing.T) {
|
||||
t.Run("should have not changed repo", func(t *testing.T) {
|
||||
setup()
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, ossencryption.ProvideService(), nil, logger)
|
||||
dc := newNotificationProvisioner(sqlStore, &fakeAlertNotification{}, encryptionService, nil, logger)
|
||||
err := dc.applyChanges(context.Background(), emptyFile)
|
||||
if err != nil {
|
||||
t.Fatalf("applyChanges return an error %v", err)
|
||||
@@ -277,7 +279,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Broken yaml should return error", func(t *testing.T) {
|
||||
reader := &configReader{
|
||||
orgStore: sqlStore,
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
encryptionService: encryptionService,
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
|
||||
@@ -288,7 +290,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Skip invalid directory", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
orgStore: sqlStore,
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
encryptionService: encryptionService,
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
|
||||
@@ -302,7 +304,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Unknown notifier should return error", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
orgStore: sqlStore,
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
encryptionService: encryptionService,
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
_, err := cfgProvider.readConfig(context.Background(), unknownNotifier)
|
||||
@@ -313,7 +315,7 @@ func TestNotificationAsConfig(t *testing.T) {
|
||||
t.Run("Read incorrect properties", func(t *testing.T) {
|
||||
cfgProvider := &configReader{
|
||||
orgStore: sqlStore,
|
||||
encryptionService: ossencryption.ProvideService(),
|
||||
encryptionService: encryptionService,
|
||||
log: log.New("test logger"),
|
||||
}
|
||||
_, err := cfgProvider.readConfig(context.Background(), incorrectSettings)
|
||||
|
||||
@@ -4,7 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders/osskmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
@@ -37,10 +38,14 @@ func setupTestService(tb testing.TB, store secrets.Store, features *featuremgmt.
|
||||
require.NoError(tb, err)
|
||||
|
||||
cfg := &setting.Cfg{Raw: raw}
|
||||
|
||||
settings := &setting.OSSImpl{Cfg: cfg}
|
||||
|
||||
encryption := ossencryption.ProvideService()
|
||||
encProvider := encryptionprovider.Provider{}
|
||||
usageStats := &usagestats.UsageStatsMock{}
|
||||
|
||||
encryption, err := encryptionservice.ProvideEncryptionService(encProvider, usageStats, settings)
|
||||
require.NoError(tb, err)
|
||||
|
||||
secretsService, err := ProvideSecretsService(
|
||||
store,
|
||||
osskmsproviders.ProvideService(encryption, settings, features),
|
||||
|
||||
@@ -6,7 +6,8 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/grafana/grafana/pkg/infra/usagestats"
|
||||
"github.com/grafana/grafana/pkg/services/encryption/ossencryption"
|
||||
encryptionprovider "github.com/grafana/grafana/pkg/services/encryption/provider"
|
||||
encryptionservice "github.com/grafana/grafana/pkg/services/encryption/service"
|
||||
"github.com/grafana/grafana/pkg/services/featuremgmt"
|
||||
"github.com/grafana/grafana/pkg/services/kmsproviders/osskmsproviders"
|
||||
"github.com/grafana/grafana/pkg/services/secrets"
|
||||
@@ -175,8 +176,14 @@ func TestSecretsService_UseCurrentProvider(t *testing.T) {
|
||||
raw, err := ini.Load([]byte(rawCfg))
|
||||
require.NoError(t, err)
|
||||
|
||||
encryptionService := ossencryption.ProvideService()
|
||||
settings := &setting.OSSImpl{Cfg: &setting.Cfg{Raw: raw}}
|
||||
|
||||
encProvider := encryptionprovider.Provider{}
|
||||
usageStats := &usagestats.UsageStatsMock{}
|
||||
|
||||
encryptionService, err := encryptionservice.ProvideEncryptionService(encProvider, usageStats, settings)
|
||||
require.NoError(t, err)
|
||||
|
||||
features := featuremgmt.WithFeatures()
|
||||
kms := newFakeKMS(osskmsproviders.ProvideService(encryptionService, settings, features))
|
||||
secretStore := database.ProvideSecretsStore(sqlstore.InitTestDB(t))
|
||||
|
||||
Reference in New Issue
Block a user