Enable gossip encryption (#14640)
* Enable gossip encryption * Fix order * Auto-generate key * Update gorp fork to include BeginTx * Add a test for InsertIfExists And point gorp to a custom branch for now Co-authored-by: mattermod <mattermod@users.noreply.github.com>
Этот коммит содержится в:
коммит произвёл
GitHub
родитель
fc028e703a
Коммит
e3255879ba
@@ -6079,6 +6079,24 @@ func (s *OpenTracingLayerSystemStore) GetByName(name string) (*model.System, *mo
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) InsertIfExists(system *model.System) (*model.System, *model.AppError) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.InsertIfExists")
|
||||
s.Root.Store.SetContext(newCtx)
|
||||
defer func() {
|
||||
s.Root.Store.SetContext(origCtx)
|
||||
}()
|
||||
|
||||
defer span.Finish()
|
||||
resultVar0, resultVar1 := s.SystemStore.InsertIfExists(system)
|
||||
if resultVar1 != nil {
|
||||
span.LogFields(spanlog.Error(resultVar1))
|
||||
ext.Error.Set(span, true)
|
||||
}
|
||||
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *OpenTracingLayerSystemStore) PermanentDeleteByName(name string) (*model.System, *model.AppError) {
|
||||
origCtx := s.Root.Store.Context()
|
||||
span, newCtx := tracing.StartSpanWithParentByContext(s.Root.Store.Context(), "SystemStore.PermanentDeleteByName")
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
package sqlstore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"net/http"
|
||||
|
||||
"github.com/mattermost/mattermost-server/v5/model"
|
||||
@@ -86,3 +88,37 @@ func (s SqlSystemStore) PermanentDeleteByName(name string) (*model.System, *mode
|
||||
|
||||
return &system, nil
|
||||
}
|
||||
|
||||
// InsertIfExists inserts a given system value if it does not already exist. If a value
|
||||
// already exists, it returns the old one, else returns the new one.
|
||||
func (s SqlSystemStore) InsertIfExists(system *model.System) (*model.System, *model.AppError) {
|
||||
tx, err := s.GetMaster().BeginTx(context.Background(), &sql.TxOptions{
|
||||
Isolation: sql.LevelSerializable,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, model.NewAppError("SqlSystemStore.InsertIfExists", "store.sql_system.save.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
defer finalizeTransaction(tx)
|
||||
|
||||
var origSystem model.System
|
||||
if err := tx.SelectOne(&origSystem, `SELECT * FROM Systems
|
||||
WHERE Name = :Name`,
|
||||
map[string]interface{}{"Name": system.Name}); err != nil && err != sql.ErrNoRows {
|
||||
return nil, model.NewAppError("SqlSystemStore.InsertIfExists", "store.sql_system.get_by_name.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if origSystem.Value != "" {
|
||||
// Already a value exists, return that.
|
||||
return &origSystem, nil
|
||||
}
|
||||
|
||||
// Key does not exist, need to insert.
|
||||
if err := tx.Insert(system); err != nil {
|
||||
return nil, model.NewAppError("SqlSystemStore.InsertIfExists", "store.sql_system.save.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
|
||||
if err := tx.Commit(); err != nil {
|
||||
return nil, model.NewAppError("SqlSystemStore.InsertIfExists", "store.sql_system.save.commit_transaction.app_error", nil, err.Error(), http.StatusInternalServerError)
|
||||
}
|
||||
return system, nil
|
||||
}
|
||||
|
||||
@@ -418,6 +418,7 @@ type SystemStore interface {
|
||||
Get() (model.StringMap, *model.AppError)
|
||||
GetByName(name string) (*model.System, *model.AppError)
|
||||
PermanentDeleteByName(name string) (*model.System, *model.AppError)
|
||||
InsertIfExists(system *model.System) (*model.System, *model.AppError)
|
||||
}
|
||||
|
||||
type WebhookStore interface {
|
||||
|
||||
@@ -64,6 +64,31 @@ func (_m *SystemStore) GetByName(name string) (*model.System, *model.AppError) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// InsertIfExists provides a mock function with given fields: system
|
||||
func (_m *SystemStore) InsertIfExists(system *model.System) (*model.System, *model.AppError) {
|
||||
ret := _m.Called(system)
|
||||
|
||||
var r0 *model.System
|
||||
if rf, ok := ret.Get(0).(func(*model.System) *model.System); ok {
|
||||
r0 = rf(system)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*model.System)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 *model.AppError
|
||||
if rf, ok := ret.Get(1).(func(*model.System) *model.AppError); ok {
|
||||
r1 = rf(system)
|
||||
} else {
|
||||
if ret.Get(1) != nil {
|
||||
r1 = ret.Get(1).(*model.AppError)
|
||||
}
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// PermanentDeleteByName provides a mock function with given fields: name
|
||||
func (_m *SystemStore) PermanentDeleteByName(name string) (*model.System, *model.AppError) {
|
||||
ret := _m.Called(name)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package storetest
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -17,6 +18,9 @@ func TestSystemStore(t *testing.T, ss store.Store) {
|
||||
t.Run("", func(t *testing.T) { testSystemStore(t, ss) })
|
||||
t.Run("SaveOrUpdate", func(t *testing.T) { testSystemStoreSaveOrUpdate(t, ss) })
|
||||
t.Run("PermanentDeleteByName", func(t *testing.T) { testSystemStorePermanentDeleteByName(t, ss) })
|
||||
t.Run("InsertIfExists", func(t *testing.T) {
|
||||
testInsertIfExists(t, ss)
|
||||
})
|
||||
}
|
||||
|
||||
func testSystemStore(t *testing.T, ss store.Store) {
|
||||
@@ -84,3 +88,42 @@ func testSystemStorePermanentDeleteByName(t *testing.T, ss store.Store) {
|
||||
_, err = ss.System().GetByName(s2.Name)
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
|
||||
func testInsertIfExists(t *testing.T, ss store.Store) {
|
||||
t.Run("Serial", func(t *testing.T) {
|
||||
s1 := &model.System{Name: model.SYSTEM_CLUSTER_ENCRYPTION_KEY, Value: "somekey"}
|
||||
|
||||
s2, err := ss.System().InsertIfExists(s1)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, s1.Value, s2.Value)
|
||||
|
||||
s1New := &model.System{Name: model.SYSTEM_CLUSTER_ENCRYPTION_KEY, Value: "anotherKey"}
|
||||
|
||||
s3, err := ss.System().InsertIfExists(s1New)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, s1.Value, s3.Value)
|
||||
})
|
||||
|
||||
t.Run("Concurrent", func(t *testing.T) {
|
||||
var s2, s3 *model.System
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s1 := &model.System{Name: model.SYSTEM_CLUSTER_ENCRYPTION_KEY, Value: "firstKey"}
|
||||
var err *model.AppError
|
||||
s2, err = ss.System().InsertIfExists(s1)
|
||||
require.Nil(t, err)
|
||||
}()
|
||||
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
s1 := &model.System{Name: model.SYSTEM_CLUSTER_ENCRYPTION_KEY, Value: "secondKey"}
|
||||
var err *model.AppError
|
||||
s3, err = ss.System().InsertIfExists(s1)
|
||||
require.Nil(t, err)
|
||||
}()
|
||||
wg.Wait()
|
||||
assert.Equal(t, s2.Value, s3.Value)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5499,6 +5499,22 @@ func (s *TimerLayerSystemStore) GetByName(name string) (*model.System, *model.Ap
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) InsertIfExists(system *model.System) (*model.System, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
resultVar0, resultVar1 := s.SystemStore.InsertIfExists(system)
|
||||
|
||||
elapsed := float64(timemodule.Since(start)) / float64(timemodule.Second)
|
||||
if s.Root.Metrics != nil {
|
||||
success := "false"
|
||||
if resultVar1 == nil {
|
||||
success = "true"
|
||||
}
|
||||
s.Root.Metrics.ObserveStoreMethodDuration("SystemStore.InsertIfExists", success, elapsed)
|
||||
}
|
||||
return resultVar0, resultVar1
|
||||
}
|
||||
|
||||
func (s *TimerLayerSystemStore) PermanentDeleteByName(name string) (*model.System, *model.AppError) {
|
||||
start := timemodule.Now()
|
||||
|
||||
|
||||
Ссылка в новой задаче
Block a user