From 56fb31f06f7c7e1f07a1d76fd0b973a1536b8f7d Mon Sep 17 00:00:00 2001 From: Doug Lauder Date: Wed, 22 Jul 2020 18:48:46 -0400 Subject: [PATCH] MM-22784 Advanced logging config for audit (#15076) Adds the advanced logging config for audit. Existing support for auditing to a single file remains for E0 and E10 licenses instances, and a new config item ExperimentalAuditSettings.AdvancedLoggingConfig is added that behaves like LogSettings.AdvancedLoggingConfig. Supported destinations: - file - syslog (with out without TLS) - raw TCP socket (with out without TLS) ExperimentalAuditSettings.AdvancedLoggingConfig can contain a filespec to a config file, a database DSN, or JSON. Co-authored-by: Mattermod Co-authored-by: Claudio Costa --- api4/post.go | 10 +-- app/app_iface.go | 4 +- app/audit.go | 94 ++++++++++++++-------------- app/diagnostics.go | 17 +++-- app/opentracing/opentracing_layer.go | 2 +- app/server.go | 8 ++- audit/audit.go | 25 ++++---- mlog/levels.go | 19 +++--- mlog/logr.go | 23 ++++--- model/config.go | 74 +++++++--------------- utils/logger.go | 15 ++--- web/context.go | 10 +-- 12 files changed, 144 insertions(+), 157 deletions(-) diff --git a/api4/post.go b/api4/post.go index 0f5a50dfa3..5aaf8f9f7f 100644 --- a/api4/post.go +++ b/api4/post.go @@ -45,7 +45,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) { post.UserId = c.App.Session().UserId auditRec := c.MakeAuditRecord("createPost", audit.Fail) - defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel) + defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) auditRec.AddMeta("post", post) hasPermission := false @@ -377,7 +377,7 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("deletePost", audit.Fail) - defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel) + defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) auditRec.AddMeta("post_id", c.Params.PostId) post, err := c.App.GetSinglePost(c.Params.PostId) @@ -537,7 +537,7 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("updatePost", audit.Fail) - defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel) + defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) // The post being updated in the payload must be the same one as indicated in the URL. if post.Id != c.Params.PostId { @@ -595,7 +595,7 @@ func patchPost(c *Context, w http.ResponseWriter, r *http.Request) { } auditRec := c.MakeAuditRecord("patchPost", audit.Fail) - defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel) + defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) // Updating the file_ids of a post is not a supported operation and will be ignored post.FileIds = nil @@ -660,7 +660,7 @@ func saveIsPinnedPost(c *Context, w http.ResponseWriter, r *http.Request, isPinn } auditRec := c.MakeAuditRecord("saveIsPinnedPost", audit.Fail) - defer c.LogAuditRecWithLevel(auditRec, app.RestContentLevel) + defer c.LogAuditRecWithLevel(auditRec, app.LevelContent) if !c.App.SessionHasPermissionToChannelByPost(*c.App.Session(), c.Params.PostId, model.PERMISSION_READ_CHANNEL) { c.SetPermissionError(model.PERMISSION_READ_CHANNEL) diff --git a/app/app_iface.go b/app/app_iface.go index 1f13b6e0c9..b46934d2c6 100644 --- a/app/app_iface.go +++ b/app/app_iface.go @@ -214,10 +214,10 @@ type AppIface interface { IsUsernameTaken(name string) bool // LimitedClientConfigWithComputed gets the configuration in a format suitable for sending to the client. LimitedClientConfigWithComputed() map[string]string - // LogAuditRec logs an audit record using default CLILevel. + // LogAuditRec logs an audit record using default LvlAuditCLI. LogAuditRec(rec *audit.Record, err error) // LogAuditRecWithLevel logs an audit record using specified Level. - LogAuditRecWithLevel(rec *audit.Record, level audit.Level, err error) + LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error) // MakeAuditRecord creates a audit record pre-populated with defaults. MakeAuditRecord(event string, initialStatus string) *audit.Record // MarkChanelAsUnreadFromPost will take a post and set the channel as unread from that one. diff --git a/app/audit.go b/app/audit.go index 3af111852e..deb1546bc5 100644 --- a/app/audit.go +++ b/app/audit.go @@ -9,7 +9,9 @@ import ( "net/http" "os/user" + "github.com/hashicorp/go-multierror" "github.com/mattermost/mattermost-server/v5/audit" + "github.com/mattermost/mattermost-server/v5/config" "github.com/mattermost/mattermost-server/v5/mlog" "github.com/mattermost/mattermost-server/v5/model" "github.com/mattermost/mattermost-server/v5/store" @@ -23,10 +25,10 @@ const ( ) var ( - RestLevel = audit.Level{ID: RestLevelID, Name: "audit-rest", Stacktrace: false} - RestContentLevel = audit.Level{ID: RestContentLevelID, Name: "audit-rest-content", Stacktrace: false} - RestPermsLevel = audit.Level{ID: RestPermsLevelID, Name: "audit-rest-perms", Stacktrace: false} - CLILevel = audit.Level{ID: CLILevelID, Name: "audit-cli", Stacktrace: false} + LevelAPI = mlog.LvlAuditAPI + LevelContent = mlog.LvlAuditContent + LevelPerms = mlog.LvlAuditPerms + LevelCLI = mlog.LvlAuditCLI ) func (a *App) GetAudits(userId string, limit int) (model.Audits, *model.AppError) { @@ -57,13 +59,13 @@ func (a *App) GetAuditsPage(userId string, page int, perPage int) (model.Audits, return audits, nil } -// LogAuditRec logs an audit record using default CLILevel. +// LogAuditRec logs an audit record using default LvlAuditCLI. func (a *App) LogAuditRec(rec *audit.Record, err error) { - a.LogAuditRecWithLevel(rec, CLILevel, err) + a.LogAuditRecWithLevel(rec, mlog.LvlAuditCLI, err) } // LogAuditRecWithLevel logs an audit record using specified Level. -func (a *App) LogAuditRecWithLevel(rec *audit.Record, level audit.Level, err error) { +func (a *App) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error) { if rec == nil { return } @@ -102,46 +104,13 @@ func (a *App) MakeAuditRecord(event string, initialStatus string) *audit.Record return rec } -func (s *Server) configureAudit(adt *audit.Audit) { +func (s *Server) configureAudit(adt *audit.Audit, bAllowAdvancedLogging bool) error { + var errs error + adt.OnQueueFull = s.onAuditTargetQueueFull adt.OnError = s.onAuditError - // Configure target for SysLog via TLS. - // See https://www.rsyslog.com/doc/v8-stable/tutorials/tls_cert_summary.html - if *s.Config().ExperimentalAuditSettings.SysLogEnabled { - IP := *s.Config().ExperimentalAuditSettings.SysLogIP - if IP == "" { - IP = "localhost" - } - port := *s.Config().ExperimentalAuditSettings.SysLogPort - if port <= 0 { - port = 6514 - } - maxQSize := *s.Config().ExperimentalAuditSettings.SysLogMaxQueueSize - if maxQSize <= 0 { - maxQSize = audit.DefMaxQueueSize - } - - params := &mlog.SyslogParams{ - IP: IP, - Port: port, - Cert: *s.Config().ExperimentalAuditSettings.SysLogCert, - Tag: *s.Config().ExperimentalAuditSettings.SysLogTag, - Insecure: *s.Config().ExperimentalAuditSettings.SysLogInsecure, - } - - filter := adt.MakeFilter(RestLevel, RestContentLevel, RestPermsLevel, CLILevel) - formatter := adt.MakeJSONFormatter() - target, err := mlog.NewSyslogTarget(filter, formatter, params, maxQSize) - if err != nil { - mlog.Error("cannot configure SysLogTLS audit target", mlog.Err(err)) - } else { - mlog.Debug("SysLogTLS audit target connected successfully", mlog.String("IP", IP), mlog.Int("Port", port)) - adt.AddTarget(target) - } - } - - // Configure target for rotating file output + // Configure target for rotating file output (E0, E10) if *s.Config().ExperimentalAuditSettings.FileEnabled { opts := audit.FileOptions{ Filename: *s.Config().ExperimentalAuditSettings.FileName, @@ -156,21 +125,50 @@ func (s *Server) configureAudit(adt *audit.Audit) { maxQueueSize = audit.DefMaxQueueSize } - filter := adt.MakeFilter(RestLevel, RestContentLevel, RestPermsLevel, CLILevel) + filter := adt.MakeFilter(LevelAPI, LevelContent, LevelPerms, LevelCLI) formatter := adt.MakeJSONFormatter() formatter.DisableTimestamp = false target, err := audit.NewFileTarget(filter, formatter, opts, maxQueueSize) if err != nil { - mlog.Error("cannot configure File audit target", mlog.Err(err)) + errs = multierror.Append(err) } else { mlog.Debug("File audit target created successfully", mlog.String("filename", opts.Filename)) adt.AddTarget(target) } } + + // Advanced logging for audit requires license. + dsn := *s.Config().ExperimentalAuditSettings.AdvancedLoggingConfig + if !bAllowAdvancedLogging || dsn == "" { + return errs + } + isJson := config.IsJsonMap(dsn) + cfg, err := config.NewLogConfigSrc(dsn, isJson, s.configStore) + if err != nil { + errs = multierror.Append(fmt.Errorf("invalid config for audit, %w", err)) + return errs + } + if !isJson { + mlog.Debug("Loaded audit configuration", mlog.String("filename", dsn)) + } + + for name, t := range cfg.Get() { + if len(t.Levels) == 0 { + t.Levels = mlog.MLvlAuditAll + } + target, err := mlog.NewLogrTarget(name, t) + if err != nil { + errs = multierror.Append(err) + continue + } + adt.AddTarget(target) + } + return errs } -func (s *Server) onAuditTargetQueueFull(qname string, maxQSize int) { - mlog.Warn("Audit Queue Full", mlog.String("qname", qname), mlog.Int("maxQSize", maxQSize)) +func (s *Server) onAuditTargetQueueFull(qname string, maxQSize int) bool { + mlog.Error("Audit queue full, dropping record.", mlog.String("qname", qname), mlog.Int("queueSize", maxQSize)) + return true // drop it } func (s *Server) onAuditError(err error) { diff --git a/app/diagnostics.go b/app/diagnostics.go index 2b35ea4611..6e6bbc7f67 100644 --- a/app/diagnostics.go +++ b/app/diagnostics.go @@ -405,15 +405,13 @@ func (s *Server) trackConfig() { }) s.SendDiagnostic(TRACK_CONFIG_AUDIT, map[string]interface{}{ - "syslog_enabled": *cfg.ExperimentalAuditSettings.SysLogEnabled, - "syslog_insecure": *cfg.ExperimentalAuditSettings.SysLogInsecure, - "syslog_max_queue_size": *cfg.ExperimentalAuditSettings.SysLogMaxQueueSize, - "file_enabled": *cfg.ExperimentalAuditSettings.FileEnabled, - "file_max_size_mb": *cfg.ExperimentalAuditSettings.FileMaxSizeMB, - "file_max_age_days": *cfg.ExperimentalAuditSettings.FileMaxAgeDays, - "file_max_backups": *cfg.ExperimentalAuditSettings.FileMaxBackups, - "file_compress": *cfg.ExperimentalAuditSettings.FileCompress, - "file_max_queue_size": *cfg.ExperimentalAuditSettings.FileMaxQueueSize, + "file_enabled": *cfg.ExperimentalAuditSettings.FileEnabled, + "file_max_size_mb": *cfg.ExperimentalAuditSettings.FileMaxSizeMB, + "file_max_age_days": *cfg.ExperimentalAuditSettings.FileMaxAgeDays, + "file_max_backups": *cfg.ExperimentalAuditSettings.FileMaxBackups, + "file_compress": *cfg.ExperimentalAuditSettings.FileCompress, + "file_max_queue_size": *cfg.ExperimentalAuditSettings.FileMaxQueueSize, + "advanced_logging_config": *cfg.ExperimentalAuditSettings.AdvancedLoggingConfig != "", }) s.SendDiagnostic(TRACK_CONFIG_NOTIFICATION_LOG, map[string]interface{}{ @@ -424,6 +422,7 @@ func (s *Server) trackConfig() { "file_level": *cfg.NotificationLogSettings.FileLevel, "file_json": *cfg.NotificationLogSettings.FileJson, "isdefault_file_location": isDefault(*cfg.NotificationLogSettings.FileLocation, ""), + "advanced_logging_config": *cfg.NotificationLogSettings.AdvancedLoggingConfig != "", }) s.SendDiagnostic(TRACK_CONFIG_PASSWORD, map[string]interface{}{ diff --git a/app/opentracing/opentracing_layer.go b/app/opentracing/opentracing_layer.go index f659b28f9d..10a044f339 100644 --- a/app/opentracing/opentracing_layer.go +++ b/app/opentracing/opentracing_layer.go @@ -9945,7 +9945,7 @@ func (a *OpenTracingAppLayer) LogAuditRec(rec *audit.Record, err error) { a.app.LogAuditRec(rec, err) } -func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level audit.Level, err error) { +func (a *OpenTracingAppLayer) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel, err error) { origCtx := a.ctx span, newCtx := tracing.StartSpanWithParentByContext(a.ctx, "app.LogAuditRecWithLevel") diff --git a/app/server.go b/app/server.go index 465988fca8..94b9ad4c0b 100644 --- a/app/server.go +++ b/app/server.go @@ -459,13 +459,17 @@ func NewServer(options ...Option) (*Server, error) { s.ReloadConfig() + allowAdvancedLogging := license != nil && *license.Features.AdvancedLogging + if s.Audit == nil { s.Audit = &audit.Audit{} s.Audit.Init(audit.DefMaxQueueSize) - s.configureAudit(s.Audit) + if err := s.configureAudit(s.Audit, allowAdvancedLogging); err != nil { + mlog.Error("Error configuring audit", mlog.Err(err)) + } } - if license == nil || !*license.Features.AdvancedLogging { + if !allowAdvancedLogging { timeoutCtx, cancelCtx := context.WithTimeout(context.Background(), time.Second*5) defer cancelCtx() mlog.Info("Shutting down advanced logging") diff --git a/audit/audit.go b/audit/audit.go index 0a8b6ee000..61a606612d 100644 --- a/audit/audit.go +++ b/audit/audit.go @@ -9,17 +9,16 @@ import ( "github.com/mattermost/logr" "github.com/mattermost/logr/format" + "github.com/mattermost/mattermost-server/v5/mlog" ) -type Level logr.Level - type Audit struct { lgr *logr.Logr logger logr.Logger // OnQueueFull is called on an attempt to add an audit record to a full queue. - // On return the calling goroutine will block until the audit record can be added. - OnQueueFull func(qname string, maxQueueSize int) + // Return true to drop record, or false to block until there is room in queue. + OnQueueFull func(qname string, maxQueueSize int) bool // OnError is called when an error occurs while writing an audit record. OnError func(err error) @@ -35,7 +34,7 @@ func (a *Audit) Init(maxQueueSize int) { } // MakeFilter creates a filter which only allows the specified audit levels to be output. -func (a *Audit) MakeFilter(level ...Level) *logr.CustomFilter { +func (a *Audit) MakeFilter(level ...mlog.LogLevel) *logr.CustomFilter { filter := &logr.CustomFilter{} for _, l := range level { filter.Add(logr.Level(l)) @@ -56,7 +55,7 @@ func (a *Audit) MakeJSONFormatter() *format.JSON { } // LogRecord emits an audit record with complete info. -func (a *Audit) LogRecord(level Level, rec Record) { +func (a *Audit) LogRecord(level mlog.LogLevel, rec Record) { flds := logr.Fields{} flds[KeyAPIPath] = rec.APIPath flds[KeyEvent] = rec.Event @@ -75,7 +74,7 @@ func (a *Audit) LogRecord(level Level, rec Record) { } // Log emits an audit record based on minimum required info. -func (a *Audit) Log(level Level, path string, evt string, status string, userID string, sessionID string, meta Meta) { +func (a *Audit) Log(level mlog.LogLevel, path string, evt string, status string, userID string, sessionID string, meta Meta) { a.LogRecord(level, Record{ APIPath: path, Event: evt, @@ -101,18 +100,18 @@ func (a *Audit) Shutdown() { func (a *Audit) onQueueFull(rec *logr.LogRec, maxQueueSize int) bool { if a.OnQueueFull != nil { - a.OnQueueFull("main", maxQueueSize) + return a.OnQueueFull("main", maxQueueSize) } - // block until record can be added. - return false + mlog.Error("Audit logging queue full, dropping record.", mlog.Int("queueSize", maxQueueSize)) + return true } func (a *Audit) onTargetQueueFull(target logr.Target, rec *logr.LogRec, maxQueueSize int) bool { if a.OnQueueFull != nil { - a.OnQueueFull(fmt.Sprintf("%v", target), maxQueueSize) + return a.OnQueueFull(fmt.Sprintf("%v", target), maxQueueSize) } - // block until record can be added. - return false + mlog.Error("Audit logging queue full for target, dropping record.", mlog.Any("target", target), mlog.Int("queueSize", maxQueueSize)) + return true } func (a *Audit) onLoggerError(err error) { diff --git a/mlog/levels.go b/mlog/levels.go index d6001da0e9..898e82eb52 100644 --- a/mlog/levels.go +++ b/mlog/levels.go @@ -13,20 +13,25 @@ var ( LvlDebug = LogLevel{ID: 5, Name: "debug"} LvlTrace = LogLevel{ID: 6, Name: "trace"} // used only by the logger - LvlLogError = LogLevel{ID: 11, Name: "logerror"} + LvlLogError = LogLevel{ID: 11, Name: "logerror", Stacktrace: true} ) -// Register custom (discrete) levels here... -// ! ID's must not exceed 32,768 ! +// Register custom (discrete) levels here. +// !!!!! ID's must not exceed 32,768 !!!!!! var ( // used by the audit system - LvlAuditDebug = LogLevel{ID: 100, Name: "AuditDebug"} - LvlAuditError = LogLevel{ID: 101, Name: "AuditError"} + LvlAuditAPI = LogLevel{ID: 100, Name: "audit-api"} + LvlAuditContent = LogLevel{ID: 101, Name: "audit-content"} + LvlAuditPerms = LogLevel{ID: 102, Name: "audit-permissions"} + LvlAuditCLI = LogLevel{ID: 103, Name: "audit-cli"} + // used by the TCP log target - LvlTcpLogTarget = LogLevel{ID: 105, Name: "TcpLogTarget"} + LvlTcpLogTarget = LogLevel{ID: 120, Name: "TcpLogTarget"} + + // add more here ... ) // Combinations for LogM (log multi) var ( - MLvlExample = []LogLevel{LvlAuditDebug, LvlDebug} + MLvlAuditAll = []LogLevel{LvlAuditAPI, LvlAuditContent, LvlAuditPerms, LvlAuditCLI} ) diff --git a/mlog/logr.go b/mlog/logr.go index 32ec9e3471..65248c49e1 100644 --- a/mlog/logr.go +++ b/mlog/logr.go @@ -39,30 +39,35 @@ type LogTargetCfg map[string]*LogTarget type LogrCleanup func() error func newLogr(targets LogTargetCfg) (*logr.Logger, error) { - var errs error - - lgr := logr.Logr{} - + lgr := &logr.Logr{} lgr.OnExit = func(int) {} lgr.OnPanic = func(interface{}) {} - lgr.OnLoggerError = onLoggerError lgr.OnQueueFull = onQueueFull lgr.OnTargetQueueFull = onTargetQueueFull + err := logrAddTargets(lgr, targets) + logger := lgr.NewLogger() + return &logger, err +} + +func logrAddTargets(lgr *logr.Logr, targets LogTargetCfg) error { + var errs error for name, t := range targets { - target, err := newLogrTarget(name, t) + target, err := NewLogrTarget(name, t) if err != nil { errs = multierror.Append(err) continue } lgr.AddTarget(target) } - logger := lgr.NewLogger() - return &logger, errs + return errs } -func newLogrTarget(name string, t *LogTarget) (logr.Target, error) { +// NewLogrTarget creates a `logr.Target` based on a target config. +// Can be used when parsing custom config files, or when programmatically adding +// built-in targets. Use `mlog.AddTarget` to add custom targets. +func NewLogrTarget(name string, t *LogTarget) (logr.Target, error) { formatter, err := newFormatter(name, t.Format) if err != nil { return nil, err diff --git a/model/config.go b/model/config.go index 68ed3ecaec..12419ab071 100644 --- a/model/config.go +++ b/model/config.go @@ -1117,52 +1117,17 @@ func (s *LogSettings) SetDefaults() { } type ExperimentalAuditSettings struct { - SysLogEnabled *bool `restricted:"true"` - SysLogIP *string `restricted:"true"` - SysLogPort *int `restricted:"true"` - SysLogTag *string `restricted:"true"` - SysLogCert *string `restricted:"true"` - SysLogInsecure *bool `restricted:"true"` - SysLogMaxQueueSize *int `restricted:"true"` - - FileEnabled *bool `restricted:"true"` - FileName *string `restricted:"true"` - FileMaxSizeMB *int `restricted:"true"` - FileMaxAgeDays *int `restricted:"true"` - FileMaxBackups *int `restricted:"true"` - FileCompress *bool `restricted:"true"` - FileMaxQueueSize *int `restricted:"true"` + FileEnabled *bool `restricted:"true"` + FileName *string `restricted:"true"` + FileMaxSizeMB *int `restricted:"true"` + FileMaxAgeDays *int `restricted:"true"` + FileMaxBackups *int `restricted:"true"` + FileCompress *bool `restricted:"true"` + FileMaxQueueSize *int `restricted:"true"` + AdvancedLoggingConfig *string `restricted:"true"` } func (s *ExperimentalAuditSettings) SetDefaults() { - if s.SysLogEnabled == nil { - s.SysLogEnabled = NewBool(false) - } - - if s.SysLogIP == nil { - s.SysLogIP = NewString("localhost") - } - - if s.SysLogPort == nil { - s.SysLogPort = NewInt(6514) - } - - if s.SysLogTag == nil { - s.SysLogTag = NewString("") - } - - if s.SysLogCert == nil { - s.SysLogCert = NewString("") - } - - if s.SysLogInsecure == nil { - s.SysLogInsecure = NewBool(false) - } - - if s.SysLogMaxQueueSize == nil { - s.SysLogMaxQueueSize = NewInt(1000) - } - if s.FileEnabled == nil { s.FileEnabled = NewBool(false) } @@ -1190,16 +1155,21 @@ func (s *ExperimentalAuditSettings) SetDefaults() { if s.FileMaxQueueSize == nil { s.FileMaxQueueSize = NewInt(1000) } + + if s.AdvancedLoggingConfig == nil { + s.AdvancedLoggingConfig = NewString("") + } } type NotificationLogSettings struct { - EnableConsole *bool `restricted:"true"` - ConsoleLevel *string `restricted:"true"` - ConsoleJson *bool `restricted:"true"` - EnableFile *bool `restricted:"true"` - FileLevel *string `restricted:"true"` - FileJson *bool `restricted:"true"` - FileLocation *string `restricted:"true"` + EnableConsole *bool `restricted:"true"` + ConsoleLevel *string `restricted:"true"` + ConsoleJson *bool `restricted:"true"` + EnableFile *bool `restricted:"true"` + FileLevel *string `restricted:"true"` + FileJson *bool `restricted:"true"` + FileLocation *string `restricted:"true"` + AdvancedLoggingConfig *string `restricted:"true"` } func (s *NotificationLogSettings) SetDefaults() { @@ -1230,6 +1200,10 @@ func (s *NotificationLogSettings) SetDefaults() { if s.FileJson == nil { s.FileJson = NewBool(true) } + + if s.AdvancedLoggingConfig == nil { + s.AdvancedLoggingConfig = NewString("") + } } type PasswordSettings struct { diff --git a/utils/logger.go b/utils/logger.go index 57e43f17da..8292d5eee6 100644 --- a/utils/logger.go +++ b/utils/logger.go @@ -50,13 +50,14 @@ func GetNotificationsLogFileLocation(fileLocation string) string { func GetLogSettingsFromNotificationsLogSettings(notificationLogSettings *model.NotificationLogSettings) *model.LogSettings { return &model.LogSettings{ - ConsoleJson: notificationLogSettings.ConsoleJson, - ConsoleLevel: notificationLogSettings.ConsoleLevel, - EnableConsole: notificationLogSettings.EnableConsole, - EnableFile: notificationLogSettings.EnableFile, - FileJson: notificationLogSettings.FileJson, - FileLevel: notificationLogSettings.FileLevel, - FileLocation: notificationLogSettings.FileLocation, + ConsoleJson: notificationLogSettings.ConsoleJson, + ConsoleLevel: notificationLogSettings.ConsoleLevel, + EnableConsole: notificationLogSettings.EnableConsole, + EnableFile: notificationLogSettings.EnableFile, + FileJson: notificationLogSettings.FileJson, + FileLevel: notificationLogSettings.FileLevel, + FileLocation: notificationLogSettings.FileLocation, + AdvancedLoggingConfig: notificationLogSettings.AdvancedLoggingConfig, } } diff --git a/web/context.go b/web/context.go index 0fff4a3162..9c25854d3c 100644 --- a/web/context.go +++ b/web/context.go @@ -24,13 +24,15 @@ type Context struct { siteURLHeader string } -// LogAuditRec logs an audit record using default RestLevel. +// LogAuditRec logs an audit record using default LevelAPI. func (c *Context) LogAuditRec(rec *audit.Record) { - c.LogAuditRecWithLevel(rec, app.RestLevel) + c.LogAuditRecWithLevel(rec, app.LevelAPI) } // LogAuditRec logs an audit record using specified Level. -func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level audit.Level) { +// If the context is flagged with a permissions error then `level` +// is ignored and the audit record is emitted with `LevelPerms`. +func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level mlog.LogLevel) { if rec == nil { return } @@ -38,7 +40,7 @@ func (c *Context) LogAuditRecWithLevel(rec *audit.Record, level audit.Level) { rec.AddMeta("err", c.Err.Id) rec.AddMeta("code", c.Err.StatusCode) if c.Err.Id == "api.context.permissions.app_error" { - level = app.RestPermsLevel + level = app.LevelPerms } rec.Fail() }