[MM-64686] Expose audit logging functionality via plugin API (#31204)

This commit exposes audit logging functionality to plugins via the plugin API, allowing plugins to create and log audit records. Additionally, it addresses a gob encoding issue that could cause plugin crashes when audit data contains nil pointers or unregistered types.
Этот коммит содержится в:
David Krauser
2025-06-25 20:37:32 -04:00
коммит произвёл GitHub
родитель efb960a160
Коммит aaa62a40ae
68 изменённых файлов: 878 добавлений и 750 удалений

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

@@ -21,7 +21,6 @@ import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/public/utils"
"github.com/mattermost/mattermost/server/v8/channels/audit"
"github.com/mattermost/mattermost/server/v8/config"
"github.com/mattermost/mattermost/server/v8/platform/services/cache"
"github.com/mattermost/mattermost/server/v8/platform/services/upgrader"
@@ -297,7 +296,7 @@ func testSiteURL(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getAudits", audit.Fail)
auditRec := c.MakeAuditRecord("getAudits", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionReadAudits) {
@@ -312,8 +311,8 @@ func getAudits(c *Context, w http.ResponseWriter, r *http.Request) {
}
auditRec.Success()
audit.AddEventParameter(auditRec, "page", c.Params.Page)
audit.AddEventParameter(auditRec, "audits_per_page", c.Params.LogsPerPage)
model.AddEventParameterToAuditRec(auditRec, "page", c.Params.Page)
model.AddEventParameterToAuditRec(auditRec, "audits_per_page", c.Params.LogsPerPage)
if err := json.NewEncoder(w).Encode(audits); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
@@ -326,7 +325,7 @@ func databaseRecycle(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("databaseRecycle", audit.Fail)
auditRec := c.MakeAuditRecord("databaseRecycle", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
c.App.RecycleDatabaseConnection(c.AppContext)
@@ -341,7 +340,7 @@ func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("invalidateCaches", audit.Fail)
auditRec := c.MakeAuditRecord("invalidateCaches", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
appErr := c.App.Srv().InvalidateAllCaches()
@@ -357,7 +356,7 @@ func invalidateCaches(c *Context, w http.ResponseWriter, r *http.Request) {
}
func queryLogs(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("queryLogs", audit.Fail)
auditRec := c.MakeAuditRecord("queryLogs", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionToAndNotRestrictedAdmin(*c.AppContext.Session(), model.PermissionGetLogs) {
@@ -400,7 +399,7 @@ func queryLogs(c *Context, w http.ResponseWriter, r *http.Request) {
}
func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getLogs", audit.Fail)
auditRec := c.MakeAuditRecord("getLogs", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionToAndNotRestrictedAdmin(*c.AppContext.Session(), model.PermissionGetLogs) {
@@ -414,8 +413,8 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
audit.AddEventParameter(auditRec, "page", c.Params.Page)
audit.AddEventParameter(auditRec, "logs_per_page", c.Params.LogsPerPage)
model.AddEventParameterToAuditRec(auditRec, "page", c.Params.Page)
model.AddEventParameterToAuditRec(auditRec, "logs_per_page", c.Params.LogsPerPage)
if _, err := w.Write([]byte(model.ArrayToJSON(lines))); err != nil {
c.Logger.Warn("Error while writing response", mlog.Err(err))
@@ -423,7 +422,7 @@ func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
}
func downloadLogs(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("downloadLogs", audit.Fail)
auditRec := c.MakeAuditRecord("downloadLogs", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionToAndNotRestrictedAdmin(*c.AppContext.Session(), model.PermissionGetLogs) {
@@ -790,9 +789,9 @@ func setServerBusy(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("setServerBusy", audit.Fail)
auditRec := c.MakeAuditRecord("setServerBusy", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
audit.AddEventParameter(auditRec, "seconds", i)
model.AddEventParameterToAuditRec(auditRec, "seconds", i)
c.App.Srv().Platform().Busy.Set(time.Second * time.Duration(i))
c.Logger.Warn("server busy state activated - non-critical services disabled", mlog.Int("seconds", i))
@@ -807,7 +806,7 @@ func clearServerBusy(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("clearServerBusy", audit.Fail)
auditRec := c.MakeAuditRecord("clearServerBusy", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
c.App.Srv().Platform().Busy.Clear()
@@ -836,7 +835,7 @@ func getServerBusyExpires(c *Context, w http.ResponseWriter, r *http.Request) {
}
func upgradeToEnterprise(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("upgradeToEnterprise", audit.Fail)
auditRec := c.MakeAuditRecord("upgradeToEnterprise", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
@@ -925,7 +924,7 @@ func upgradeToEnterpriseStatus(c *Context, w http.ResponseWriter, r *http.Reques
}
func restart(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("restartServer", audit.Fail)
auditRec := c.MakeAuditRecord("restartServer", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if !c.App.SessionHasPermissionTo(*c.AppContext.Session(), model.PermissionManageSystem) {
@@ -969,7 +968,7 @@ func getProductNotices(c *Context, w http.ResponseWriter, r *http.Request) {
}
func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("updateViewedProductNotices", audit.Fail)
auditRec := c.MakeAuditRecord("updateViewedProductNotices", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
@@ -989,7 +988,7 @@ func updateViewedProductNotices(c *Context, w http.ResponseWriter, r *http.Reque
}
func getOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
auditRec := c.MakeAuditRecord("getOnboarding", audit.Fail)
auditRec := c.MakeAuditRecord("getOnboarding", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
c.LogAudit("attempt")
@@ -1016,7 +1015,7 @@ func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("completeOnboarding", audit.Fail)
auditRec := c.MakeAuditRecord("completeOnboarding", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
onboardingRequest, err := model.CompleteOnboardingRequestFromReader(r.Body)
@@ -1024,8 +1023,8 @@ func completeOnboarding(c *Context, w http.ResponseWriter, r *http.Request) {
c.Err = model.NewAppError("completeOnboarding", "app.system.complete_onboarding_request.app_error", nil, "", http.StatusBadRequest).Wrap(err)
return
}
audit.AddEventParameter(auditRec, "install_plugin", onboardingRequest.InstallPlugins)
audit.AddEventParameterAuditable(auditRec, "onboarding_request", onboardingRequest)
model.AddEventParameterToAuditRec(auditRec, "install_plugin", onboardingRequest.InstallPlugins)
model.AddEventParameterAuditableToAuditRec(auditRec, "onboarding_request", onboardingRequest)
appErr := c.App.CompleteOnboarding(c.AppContext, onboardingRequest)
if appErr != nil {
@@ -1043,7 +1042,7 @@ func getAppliedSchemaMigrations(c *Context, w http.ResponseWriter, r *http.Reque
return
}
auditRec := c.MakeAuditRecord("getAppliedSchemaMigrations", audit.Fail)
auditRec := c.MakeAuditRecord("getAppliedSchemaMigrations", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
migrations, appErr := c.App.GetAppliedSchemaMigrations()