[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 удалений

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

@@ -12,7 +12,6 @@ import (
"github.com/mattermost/mattermost/server/public/model"
"github.com/mattermost/mattermost/server/public/shared/mlog"
"github.com/mattermost/mattermost/server/v8/channels/app"
"github.com/mattermost/mattermost/server/v8/channels/audit"
"github.com/mattermost/mattermost/server/v8/channels/utils"
"github.com/mattermost/mattermost/server/v8/platform/services/remotecluster"
)
@@ -100,8 +99,8 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque
return
}
auditRec := c.MakeAuditRecord("remoteClusterAcceptMessage", audit.Fail)
audit.AddEventParameterAuditable(auditRec, "remote_cluster_frame", &frame)
auditRec := c.MakeAuditRecord("remoteClusterAcceptMessage", model.AuditStatusFail)
model.AddEventParameterAuditableToAuditRec(auditRec, "remote_cluster_frame", &frame)
defer c.LogAuditRec(auditRec)
remoteId := c.GetRemoteID(r)
@@ -115,7 +114,7 @@ func remoteClusterAcceptMessage(c *Context, w http.ResponseWriter, r *http.Reque
c.SetInvalidRemoteIdError(frame.RemoteId)
return
}
audit.AddEventParameterAuditable(auditRec, "remote_cluster", rc)
model.AddEventParameterAuditableToAuditRec(auditRec, "remote_cluster", rc)
// pass message to Remote Cluster Service and write response
resp := service.ReceiveIncomingMsg(rc, frame.Msg)
@@ -150,8 +149,8 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque
return
}
auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", audit.Fail)
audit.AddEventParameterAuditable(auditRec, "remote_cluster_frame", &frame)
auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", model.AuditStatusFail)
model.AddEventParameterAuditableToAuditRec(auditRec, "remote_cluster_frame", &frame)
defer c.LogAuditRec(auditRec)
remoteId := c.GetRemoteID(r)
@@ -165,7 +164,7 @@ func remoteClusterConfirmInvite(c *Context, w http.ResponseWriter, r *http.Reque
c.SetInvalidRemoteIdError(frame.RemoteId)
return
}
audit.AddEventParameterAuditable(auditRec, "remote_cluster", rc)
model.AddEventParameterAuditableToAuditRec(auditRec, "remote_cluster", rc)
// check if the invitation has expired
if time.Since(model.GetTimeForMillis(rc.CreateAt)) > remotecluster.InviteExpiresAfter {
@@ -201,9 +200,9 @@ func uploadRemoteData(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("uploadRemoteData", audit.Fail)
auditRec := c.MakeAuditRecord("uploadRemoteData", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
audit.AddEventParameter(auditRec, "upload_id", c.Params.UploadId)
model.AddEventParameterToAuditRec(auditRec, "upload_id", c.Params.UploadId)
c.AppContext = c.AppContext.With(app.RequestContextWithMaster)
us, err := c.App.GetUploadSession(c.AppContext, c.Params.UploadId)
@@ -282,10 +281,10 @@ func remoteSetProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("remoteUploadProfileImage", audit.Fail)
auditRec := c.MakeAuditRecord("remoteUploadProfileImage", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
if imageArray[0] != nil {
audit.AddEventParameter(auditRec, "filename", imageArray[0].Filename)
model.AddEventParameterToAuditRec(auditRec, "filename", imageArray[0].Filename)
}
user, err := c.App.GetUser(c.Params.UserId)
@@ -302,7 +301,7 @@ func remoteSetProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
audit.AddEventParameterAuditable(auditRec, "user", user)
model.AddEventParameterAuditableToAuditRec(auditRec, "user", user)
imageData := imageArray[0]
if err := c.App.SetProfileImage(c.AppContext, c.Params.UserId, imageData); err != nil {
@@ -374,7 +373,7 @@ func createRemoteCluster(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("createRemoteCluster", audit.Fail)
auditRec := c.MakeAuditRecord("createRemoteCluster", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
var rcWithTeamAndPassword model.RemoteClusterWithPassword
@@ -408,7 +407,7 @@ func createRemoteCluster(c *Context, w http.ResponseWriter, r *http.Request) {
CreatorId: c.AppContext.Session().UserId,
}
audit.AddEventParameterAuditable(auditRec, "remotecluster", rc)
model.AddEventParameterAuditableToAuditRec(auditRec, "remotecluster", rc)
rcSaved, appErr := c.App.AddRemoteCluster(rc)
if appErr != nil {
@@ -462,7 +461,7 @@ func remoteClusterAcceptInvite(c *Context, w http.ResponseWriter, r *http.Reques
return
}
auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", audit.Fail)
auditRec := c.MakeAuditRecord("remoteClusterAcceptInvite", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
var rcAcceptInvite model.RemoteClusterAcceptInvite
@@ -481,8 +480,8 @@ func remoteClusterAcceptInvite(c *Context, w http.ResponseWriter, r *http.Reques
return
}
audit.AddEventParameter(auditRec, "name", rcAcceptInvite.Name)
audit.AddEventParameter(auditRec, "display_name", rcAcceptInvite.DisplayName)
model.AddEventParameterToAuditRec(auditRec, "name", rcAcceptInvite.Name)
model.AddEventParameterToAuditRec(auditRec, "display_name", rcAcceptInvite.DisplayName)
if rcAcceptInvite.DisplayName == "" {
rcAcceptInvite.DisplayName = rcAcceptInvite.Name
@@ -494,7 +493,7 @@ func remoteClusterAcceptInvite(c *Context, w http.ResponseWriter, r *http.Reques
return
}
audit.AddEventParameter(auditRec, "site_url", invite.SiteURL)
model.AddEventParameterToAuditRec(auditRec, "site_url", invite.SiteURL)
url := c.App.GetSiteURL()
if url == "" {
@@ -545,9 +544,9 @@ func generateRemoteClusterInvite(c *Context, w http.ResponseWriter, r *http.Requ
return
}
auditRec := c.MakeAuditRecord("generateRemoteClusterInvite", audit.Fail)
auditRec := c.MakeAuditRecord("generateRemoteClusterInvite", model.AuditStatusFail)
defer c.LogAuditRec(auditRec)
audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId)
model.AddEventParameterToAuditRec(auditRec, "remote_id", c.Params.RemoteId)
props := model.MapFromJSON(r.Body)
password := props["password"]
@@ -636,9 +635,9 @@ func patchRemoteCluster(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("patchRemoteCluster", audit.Fail)
audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId)
audit.AddEventParameterAuditable(auditRec, "remotecluster_patch", &patch)
auditRec := c.MakeAuditRecord("patchRemoteCluster", model.AuditStatusFail)
model.AddEventParameterToAuditRec(auditRec, "remote_id", c.Params.RemoteId)
model.AddEventParameterAuditableToAuditRec(auditRec, "remotecluster_patch", &patch)
defer c.LogAuditRec(auditRec)
orc, err := c.App.GetRemoteCluster(c.Params.RemoteId, false)
@@ -681,8 +680,8 @@ func deleteRemoteCluster(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
auditRec := c.MakeAuditRecord("deleteRemoteCluster", audit.Fail)
audit.AddEventParameter(auditRec, "remote_id", c.Params.RemoteId)
auditRec := c.MakeAuditRecord("deleteRemoteCluster", model.AuditStatusFail)
model.AddEventParameterToAuditRec(auditRec, "remote_id", c.Params.RemoteId)
defer c.LogAuditRec(auditRec)
orc, err := c.App.GetRemoteCluster(c.Params.RemoteId, false)