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

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

@@ -63,12 +63,12 @@ func (a *App) GetAuditsPage(rctx request.CTX, userID string, page int, perPage i
}
// LogAuditRec logs an audit record using default LvlAuditCLI.
func (a *App) LogAuditRec(rctx request.CTX, rec *audit.Record, err error) {
func (a *App) LogAuditRec(rctx request.CTX, rec *model.AuditRecord, err error) {
a.LogAuditRecWithLevel(rctx, rec, mlog.LvlAuditCLI, err)
}
// LogAuditRecWithLevel logs an audit record using specified Level.
func (a *App) LogAuditRecWithLevel(rctx request.CTX, rec *audit.Record, level mlog.Level, err error) {
func (a *App) LogAuditRecWithLevel(rctx request.CTX, rec *model.AuditRecord, level mlog.Level, err error) {
if rec == nil {
return
}
@@ -84,28 +84,28 @@ func (a *App) LogAuditRecWithLevel(rctx request.CTX, rec *audit.Record, level ml
}
// MakeAuditRecord creates a audit record pre-populated with defaults.
func (a *App) MakeAuditRecord(rctx request.CTX, event string, initialStatus string) *audit.Record {
func (a *App) MakeAuditRecord(rctx request.CTX, event string, initialStatus string) *model.AuditRecord {
var userID string
user, err := user.Current()
if err == nil {
userID = fmt.Sprintf("%s:%s", user.Uid, user.Username)
}
rec := &audit.Record{
rec := &model.AuditRecord{
EventName: event,
Status: initialStatus,
Meta: map[string]any{
audit.KeyAPIPath: "",
audit.KeyClusterID: a.GetClusterId(),
model.AuditKeyAPIPath: "",
model.AuditKeyClusterID: a.GetClusterId(),
},
Actor: audit.EventActor{
Actor: model.AuditEventActor{
UserId: userID,
SessionId: "",
Client: fmt.Sprintf("server %s-%s", model.BuildNumber, model.BuildHash),
IpAddress: "",
XForwardedFor: "",
},
EventData: audit.EventData{
EventData: model.AuditEventData{
Parameters: map[string]any{},
PriorState: map[string]any{},
ResultState: map[string]any{},

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

@@ -197,6 +197,21 @@ func (api *PluginAPI) GetTeamsForUser(userID string) ([]*model.Team, *model.AppE
return api.app.GetTeamsForUser(userID)
}
func (api *PluginAPI) LogAuditRec(rec *model.AuditRecord) {
api.LogAuditRecWithLevel(rec, mlog.LvlAuditCLI)
}
func (api *PluginAPI) LogAuditRecWithLevel(rec *model.AuditRecord, level mlog.Level) {
if rec == nil {
return
}
// Ensure the plugin_id is always logged with the correct ID
model.AddEventParameterToAuditRec(rec, "plugin_id", api.id)
api.app.Srv().Audit.LogRecord(level, *rec)
}
func (api *PluginAPI) CreateTeamMember(teamID, userID string) (*model.TeamMember, *model.AppError) {
return api.app.AddTeamMember(api.ctx, teamID, userID)
}

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

@@ -15,7 +15,6 @@ import (
"github.com/mattermost/mattermost/server/public/shared/request"
"github.com/mattermost/mattermost/server/v8/channels/app/platform"
"github.com/mattermost/mattermost/server/v8/channels/app/users"
"github.com/mattermost/mattermost/server/v8/channels/audit"
"github.com/mattermost/mattermost/server/v8/channels/store"
)
@@ -346,7 +345,7 @@ func (a *App) ExtendSessionExpiryIfNeeded(rctx request.CTX, session *model.Sessi
return false
}
auditRec := a.MakeAuditRecord(rctx, "extendSessionExpiry", audit.Fail)
auditRec := a.MakeAuditRecord(rctx, "extendSessionExpiry", model.AuditStatusFail)
defer a.LogAuditRec(rctx, auditRec, nil)
auditRec.AddEventPriorState(session)