[MM-28692] Include config diffs in audit record for config changing API calls (#17623)

* Replace config generator

* Cleanup

* Some renaming and docs additions to add clarity

* Cleanup logging related methods

* Cleanup emitter

* Fix TestDefaultsGenerator

* Move feature flags synchronization logic out of config package

* Remove unnecessary util functions

* Simplify load/set logic

* Refine semantics and add some test to cover them

* Remove unnecessary deep copies

* Improve logic further

* Fix license header

* Review file store tests

* Fix test

* Fix test

* Avoid additional write during initialization

* More consistent naming

* Update app/feature_flags.go

Co-authored-by: Christopher Speller <crspeller@gmail.com>

* Update config/store.go

Co-authored-by: Christopher Speller <crspeller@gmail.com>

* Update config/store.go

Co-authored-by: Christopher Speller <crspeller@gmail.com>

* Update config/store.go

Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>

* Make ConfigStore.Set() return both old and new configs

* Implement config diff function

* Make app.SaveConfig return previous and current configs

* Add config diff to audit record

* Fix returned configs

* Include high level test

* Move FF synchronizer to its own package

* Remove unidiomatic use of sync.Once

* Add some comments

* Rename function

* More comment

* Save config diff in audit record for local endpoints

* Enable audit for config set/reset commands

* Improve tests output

Co-authored-by: Christopher Speller <crspeller@gmail.com>
Co-authored-by: Ibrahim Serdar Acikgoz <serdaracikgoz86@gmail.com>
Этот коммит содержится в:
Claudio Costa
2021-05-21 09:04:39 +02:00
коммит произвёл GitHub
родитель ca9d8ab0a4
Коммит e1b13c10fc
23 изменённых файлов: 841 добавлений и 136 удалений

Просмотреть файл

@@ -284,7 +284,7 @@ type AppIface interface {
// in the server and revoke them
RevokeSessionsFromAllUsers() *model.AppError
// SaveConfig replaces the active configuration, optionally notifying cluster peers.
SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError
SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError)
// SearchAllChannels returns a list of channels, the total count of the results of the search (if the paginate search option is true), and an error.
SearchAllChannels(term string, opts model.ChannelSearchOpts) (*model.ChannelListWithTeamData, int64, *model.AppError)
// SearchAllTeams returns a team list and the total count of the results

Просмотреть файл

@@ -54,7 +54,7 @@ func (s *Server) UpdateConfig(f func(*model.Config)) {
old := s.Config()
updated := old.Clone()
f(updated)
if _, err := s.configStore.Set(updated); err != nil {
if _, _, err := s.configStore.Set(updated); err != nil {
mlog.Error("Failed to update config", mlog.Err(err))
}
}
@@ -405,12 +405,13 @@ func (a *App) GetEnvironmentConfig(filter func(reflect.StructField) bool) map[st
}
// SaveConfig replaces the active configuration, optionally notifying cluster peers.
func (s *Server) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError {
oldCfg, err := s.configStore.Set(newCfg)
// It returns both the previous and current configs.
func (s *Server) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) {
oldCfg, newCfg, err := s.configStore.Set(newCfg)
if errors.Cause(err) == config.ErrReadOnlyConfiguration {
return model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, err.Error(), http.StatusForbidden)
return nil, nil, model.NewAppError("saveConfig", "ent.cluster.save_config.error", nil, err.Error(), http.StatusForbidden)
} else if err != nil {
return model.NewAppError("saveConfig", "app.save_config.app_error", nil, err.Error(), http.StatusInternalServerError)
return nil, nil, model.NewAppError("saveConfig", "app.save_config.app_error", nil, err.Error(), http.StatusInternalServerError)
}
if s.startMetrics && *s.Config().MetricsSettings.Enable {
@@ -423,19 +424,18 @@ func (s *Server) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage
}
if s.Cluster != nil {
newCfg = s.configStore.RemoveEnvironmentOverrides(newCfg)
oldCfg = s.configStore.RemoveEnvironmentOverrides(oldCfg)
err := s.Cluster.ConfigChanged(oldCfg, newCfg, sendConfigChangeClusterMessage)
err := s.Cluster.ConfigChanged(s.configStore.RemoveEnvironmentOverrides(oldCfg),
s.configStore.RemoveEnvironmentOverrides(newCfg), sendConfigChangeClusterMessage)
if err != nil {
return err
return nil, nil, err
}
}
return nil
return oldCfg, newCfg, nil
}
// SaveConfig replaces the active configuration, optionally notifying cluster peers.
func (a *App) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError {
func (a *App) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) {
return a.Srv().SaveConfig(newCfg, sendConfigChangeClusterMessage)
}

Просмотреть файл

@@ -70,7 +70,7 @@ func (s *Server) doAdvancedPermissionsMigration() {
config := s.Config()
if *config.ServiceSettings.DEPRECATED_DO_NOT_USE_AllowEditPost == model.ALLOW_EDIT_POST_ALWAYS {
*config.ServiceSettings.PostEditTimeLimit = -1
if err := s.SaveConfig(config, true); err != nil {
if _, _, err := s.SaveConfig(config, true); err != nil {
mlog.Error("Failed to update config in Advanced Permissions Phase 1 Migration.", mlog.Err(err))
}
}

Просмотреть файл

@@ -13392,7 +13392,7 @@ func (a *OpenTracingAppLayer) SaveComplianceReport(job *model.Compliance) (*mode
return resultVar0, resultVar1
}
func (a *OpenTracingAppLayer) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) *model.AppError {
func (a *OpenTracingAppLayer) SaveConfig(newCfg *model.Config, sendConfigChangeClusterMessage bool) (*model.Config, *model.Config, *model.AppError) {
origCtx := a.ctx
span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.SaveConfig")
@@ -13404,14 +13404,14 @@ func (a *OpenTracingAppLayer) SaveConfig(newCfg *model.Config, sendConfigChangeC
}()
defer span.Finish()
resultVar0 := a.app.SaveConfig(newCfg, sendConfigChangeClusterMessage)
resultVar0, resultVar1, resultVar2 := a.app.SaveConfig(newCfg, sendConfigChangeClusterMessage)
if resultVar0 != nil {
span.LogFields(spanlog.Error(resultVar0))
if resultVar2 != nil {
span.LogFields(spanlog.Error(resultVar2))
ext.Error.Set(span, true)
}
return resultVar0
return resultVar0, resultVar1, resultVar2
}
func (a *OpenTracingAppLayer) SaveReactionForPost(c *request.Context, reaction *model.Reaction) (*model.Reaction, *model.AppError) {

Просмотреть файл

@@ -402,7 +402,7 @@ func (s *Server) enablePlugin(id string) *model.AppError {
})
// This call will implicitly invoke SyncPluginsActiveState which will activate enabled plugins.
if err := s.SaveConfig(s.Config(), true); err != nil {
if _, _, err := s.SaveConfig(s.Config(), true); err != nil {
if err.Id == "ent.cluster.save_config.error" {
return model.NewAppError("EnablePlugin", "app.plugin.cluster.save_config.app_error", nil, "", http.StatusInternalServerError)
}
@@ -449,7 +449,7 @@ func (s *Server) disablePlugin(id string) *model.AppError {
s.unregisterPluginCommands(id)
// This call will implicitly invoke SyncPluginsActiveState which will deactivate disabled plugins.
if err := s.SaveConfig(s.Config(), true); err != nil {
if _, _, err := s.SaveConfig(s.Config(), true); err != nil {
return model.NewAppError("DisablePlugin", "app.plugin.config.app_error", nil, err.Error(), http.StatusInternalServerError)
}

Просмотреть файл

@@ -109,7 +109,8 @@ func (api *PluginAPI) GetUnsanitizedConfig() *model.Config {
}
func (api *PluginAPI) SaveConfig(config *model.Config) *model.AppError {
return api.app.SaveConfig(config, true)
_, _, err := api.app.SaveConfig(config, true)
return err
}
func (api *PluginAPI) GetPluginConfig() map[string]interface{} {
@@ -123,7 +124,8 @@ func (api *PluginAPI) GetPluginConfig() map[string]interface{} {
func (api *PluginAPI) SavePluginConfig(pluginConfig map[string]interface{}) *model.AppError {
cfg := api.app.GetSanitizedConfig()
cfg.PluginSettings.Plugins[api.manifest.Id] = pluginConfig
return api.app.SaveConfig(cfg, true)
_, _, err := api.app.SaveConfig(cfg, true)
return err
}
func (api *PluginAPI) GetBundlePath() (string, error) {